diff --git a/src/gl/scene/gl_bsp.cpp b/src/gl/scene/gl_bsp.cpp index 8e6f8b240..24ba794db 100644 --- a/src/gl/scene/gl_bsp.cpp +++ b/src/gl/scene/gl_bsp.cpp @@ -363,9 +363,12 @@ void GLSceneDrawer::RenderThings(subsector_t * sub, sector_t * sector) continue; } } - - GLSprite sprite(this); - sprite.Process(thing, sector, false); + // If this thing is in a map section that's not in view it can't possibly be visible + if (CurrentMapSections[thing->subsector->mapsection]) + { + GLSprite sprite; + sprite.Process(gl_drawinfo, thing, sector, in_area, false); + } } for (msecnode_t *node = sec->sectorportal_thinglist; node; node = node->m_snext) @@ -382,8 +385,8 @@ void GLSceneDrawer::RenderThings(subsector_t * sub, sector_t * sector) } } - GLSprite sprite(this); - sprite.Process(thing, sector, true); + GLSprite sprite; + sprite.Process(gl_drawinfo, thing, sector, gl_drawinfo->mDrawer->in_area, true); } SetupSprite.Unclock(); } @@ -455,8 +458,8 @@ void GLSceneDrawer::DoSubsector(subsector_t * sub) for (i = ParticlesInSubsec[sub->Index()]; i != NO_PARTICLE; i = Particles[i].snext) { - GLSprite sprite(this); - sprite.ProcessParticle(&Particles[i], fakesector); + GLSprite sprite; + sprite.ProcessParticle(gl_drawinfo, &Particles[i], fakesector); } SetupSprite.Unclock(); } diff --git a/src/gl/scene/gl_drawinfo.cpp b/src/gl/scene/gl_drawinfo.cpp index c91bcdaf8..3f8446b5a 100644 --- a/src/gl/scene/gl_drawinfo.cpp +++ b/src/gl/scene/gl_drawinfo.cpp @@ -94,27 +94,6 @@ void GLDrawList::Reset() drawitems.Clear(); } - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -// Translucent polygon sorting - uses a BSP algorithm with an additional 'equal' branch - -inline double GLSprite::CalcIntersectionVertex(GLWall * w2) -{ - float ax = x1, ay=y1; - float bx = x2, by=y2; - float cx = w2->glseg.x1, cy=w2->glseg.y1; - float dx = w2->glseg.x2, dy=w2->glseg.y2; - return ((ay-cy)*(dx-cx)-(ax-cx)*(dy-cy)) / ((bx-ax)*(dy-cy)-(by-ay)*(dx-cx)); -} - - - //========================================================================== // // @@ -404,7 +383,6 @@ void GLDrawList::SortSpriteIntoPlane(SortNode * head, SortNode * sort) } } - //========================================================================== // // @@ -412,6 +390,16 @@ void GLDrawList::SortSpriteIntoPlane(SortNode * head, SortNode * sort) //========================================================================== #define MIN_EQ (0.0005f) +// Lines start-end and fdiv must intersect. +inline double CalcIntersectionVertex(GLWall *w1, GLWall * w2) +{ + float ax = w1->glseg.x1, ay = w1->glseg.y1; + float bx = w1->glseg.x2, by = w1->glseg.y2; + float cx = w2->glseg.x1, cy = w2->glseg.y1; + float dx = w2->glseg.x2, dy = w2->glseg.y2; + return ((ay - cy)*(dx - cx) - (ax - cx)*(dy - cy)) / ((bx - ax)*(dy - cy) - (by - ay)*(dx - cx)); +} + void GLDrawList::SortWallIntoWall(SortNode * head,SortNode * sort) { GLWall * wh= walls[drawitems[head->itemindex].index]; @@ -444,7 +432,7 @@ void GLDrawList::SortWallIntoWall(SortNode * head,SortNode * sort) } else { - double r=ws->CalcIntersectionVertex(wh); + double r = CalcIntersectionVertex(ws, wh); float ix=(float)(ws->glseg.x1+r*(ws->glseg.x2-ws->glseg.x1)); float iy=(float)(ws->glseg.y1+r*(ws->glseg.y2-ws->glseg.y1)); @@ -492,6 +480,19 @@ EXTERN_CVAR(Int, gl_billboard_mode) EXTERN_CVAR(Bool, gl_billboard_faces_camera) EXTERN_CVAR(Bool, gl_billboard_particles) + + +inline double CalcIntersectionVertex(GLSprite *s, GLWall * w2) +{ + float ax = s->x1, ay = s->y1; + float bx = s->x2, by = s->y2; + float cx = w2->glseg.x1, cy = w2->glseg.y1; + float dx = w2->glseg.x2, dy = w2->glseg.y2; + return ((ay - cy)*(dx - cx) - (ax - cx)*(dy - cy)) / ((bx - ax)*(dy - cy) - (by - ay)*(dx - cx)); +} + + + void GLDrawList::SortSpriteIntoWall(SortNode * head,SortNode * sort) { GLWall *wh= walls[drawitems[head->itemindex].index]; @@ -542,7 +543,7 @@ void GLDrawList::SortSpriteIntoWall(SortNode * head,SortNode * sort) } return; } - double r=ss->CalcIntersectionVertex(wh); + double r=CalcIntersectionVertex(ss, wh); float ix=(float)(ss->x1 + r * (ss->x2-ss->x1)); float iy=(float)(ss->y1 + r * (ss->y2-ss->y1)); @@ -726,7 +727,7 @@ void GLDrawList::DoDraw(int pass, int i, bool trans) { GLSprite * s= sprites[drawitems[i].index]; RenderSprite.Clock(); - s->Draw(pass); + gl_drawinfo->DrawSprite(s, pass); RenderSprite.Unclock(); } break; diff --git a/src/gl/scene/gl_drawinfo.h b/src/gl/scene/gl_drawinfo.h index 58ea61245..9f2256b7b 100644 --- a/src/gl/scene/gl_drawinfo.h +++ b/src/gl/scene/gl_drawinfo.h @@ -165,10 +165,8 @@ public: struct FDrawInfo : public HWDrawInfo { - GLSceneDrawer *mDrawer; - FDrawInfo * next; GLDrawList drawlists[GLDL_TYPES]; TArray decals[2]; // the second slot is for mirrors which get rendered in a separate pass. @@ -182,8 +180,8 @@ struct FDrawInfo : public HWDrawInfo GLDecal *AddDecal(bool onmirror) override; void AddPortal(GLWall *w, int portaltype) override; void AddFlat(GLFlat *flat, bool fog) override; + void AddSprite(GLSprite *sprite, bool translucent) override; - void ProcessActorsInPortal(FLinePortalSpan *glport) override; std::pair AllocVertices(unsigned int count) override; // Legacy GL only. @@ -222,6 +220,8 @@ struct FDrawInfo : public HWDrawInfo void DrawSubsector(GLFlat *flat, subsector_t * sub); void SetupSubsectorLights(GLFlat *flat, int pass, subsector_t * sub, int *dli); + // Sprite drawer + void DrawSprite(GLSprite *sprite, int pass); // These two may be moved to the API independent part of the renderer later. void ProcessLowerMinisegs(TArray &lowersegs) override; diff --git a/src/gl/scene/gl_portal.cpp b/src/gl/scene/gl_portal.cpp index d48550d56..25209989a 100644 --- a/src/gl/scene/gl_portal.cpp +++ b/src/gl/scene/gl_portal.cpp @@ -1060,7 +1060,7 @@ void GLLineToLinePortal::DrawContents() void GLLineToLinePortal::RenderAttached() { - gl_drawinfo->ProcessActorsInPortal(glport); + gl_drawinfo->ProcessActorsInPortal(glport, gl_drawinfo->mDrawer->in_area); } //----------------------------------------------------------------------------- diff --git a/src/gl/scene/gl_sprite.cpp b/src/gl/scene/gl_sprite.cpp index 9308ed8d4..0a42c2734 100644 --- a/src/gl/scene/gl_sprite.cpp +++ b/src/gl/scene/gl_sprite.cpp @@ -73,14 +73,6 @@ extern TArray sprites; extern TArray SpriteFrames; extern uint32_t r_renderercaps; -enum HWRenderStyle -{ - STYLEHW_Normal, // default - STYLEHW_Solid, // drawn solid (needs special treatment for sprites) - STYLEHW_NoAlphaTest, // disable alpha test -}; - - void gl_SetRenderStyle(FRenderStyle style, bool drawopaque, bool allowcolorblending) { int tm, sb, db, be; @@ -102,7 +94,7 @@ static const float LARGE_VALUE = 1e19f; // //========================================================================== -void GLSprite::CalculateVertices(FVector3 *v) +bool GLSprite::CalculateVertices(FVector3 *v) { if (actor != nullptr && (actor->renderflags & RF_SPRITETYPEMASK) == RF_FLATSPRITE) { @@ -140,14 +132,12 @@ void GLSprite::CalculateVertices(FVector3 *v) v[2] = mat * FVector3(x2, z, y1); v[3] = mat * FVector3(x1, z, y1); - glEnable(GL_POLYGON_OFFSET_FILL); - glPolygonOffset(-1.0f, -128.0f); - return; + return true; } // [BB] Billboard stuff const bool drawWithXYBillboard = ((particle && gl_billboard_particles) || (!(actor && actor->renderflags & RF_FORCEYBILLBOARD) - //&& GLRenderer->mViewActor != NULL + //&& GLRenderer->mViewActor != nullptr && (gl_billboard_mode == 1 || (actor && actor->renderflags & RF_FORCEXYBILLBOARD)))); const bool drawBillboardFacingCamera = gl_billboard_faces_camera; @@ -243,6 +233,7 @@ void GLSprite::CalculateVertices(FVector3 *v) v[2] = FVector3(x1, z2, y1); v[3] = FVector3(x2, z2, y2); } + return false; } //========================================================================== @@ -251,21 +242,22 @@ void GLSprite::CalculateVertices(FVector3 *v) // //========================================================================== -void GLSprite::Draw(int pass) +void FDrawInfo::DrawSprite(GLSprite *sprite, int pass) { if (pass == GLPASS_DECALS) return; + auto RenderStyle = sprite->RenderStyle; if (pass == GLPASS_LIGHTSONLY) { - if (modelframe) + if (sprite->modelframe) { if (RenderStyle.BlendOp != STYLEOP_Shadow) { - if (gl_lights && GLRenderer->mLightCount && mDrawer->FixedColormap == CM_DEFAULT && !fullbright) + if (gl_lights && GLRenderer->mLightCount && mDrawer->FixedColormap == CM_DEFAULT && !sprite->fullbright) { - if (!particle) + if (!sprite->particle) { - dynlightindex = gl_SetDynModelLight(gl_light_sprites ? actor : nullptr, -1); + sprite->dynlightindex = gl_SetDynModelLight(gl_light_sprites ? sprite->actor : nullptr, -1); } } } @@ -275,7 +267,7 @@ void GLSprite::Draw(int pass) bool additivefog = false; bool foglayer = false; - int rel = fullbright? 0 : getExtraLight(); + int rel = sprite->fullbright? 0 : getExtraLight(); if (pass==GLPASS_TRANSLUCENT) { @@ -289,10 +281,10 @@ void GLSprite::Draw(int pass) gl_SetRenderStyle(RenderStyle, false, // The rest of the needed checks are done inside gl_SetRenderStyle - trans > 1.f - FLT_EPSILON && gl_usecolorblending && mDrawer->FixedColormap == CM_DEFAULT && actor && - fullbright && gltexture && !gltexture->tex->GetTranslucency()); + sprite->trans > 1.f - FLT_EPSILON && gl_usecolorblending && mDrawer->FixedColormap == CM_DEFAULT && sprite->actor && + sprite->fullbright && sprite->gltexture && !sprite->gltexture->tex->GetTranslucency()); - if (hw_styleflags == STYLEHW_NoAlphaTest) + if (sprite->hw_styleflags == STYLEHW_NoAlphaTest) { gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f); } @@ -307,10 +299,10 @@ void GLSprite::Draw(int pass) float minalpha=0.1f; // fog + fuzz don't work well without some fiddling with the alpha value! - if (!Colormap.FadeColor.isBlack()) + if (!sprite->Colormap.FadeColor.isBlack()) { - float dist=Dist2(r_viewpoint.Pos.X, r_viewpoint.Pos.Y, x,y); - int fogd = hw_GetFogDensity(lightlevel, Colormap.FadeColor, Colormap.FogDensity); + float dist=Dist2(r_viewpoint.Pos.X, r_viewpoint.Pos.Y, sprite->x, sprite->y); + int fogd = hw_GetFogDensity(sprite->lightlevel, sprite->Colormap.FadeColor, sprite->Colormap.FogDensity); // this value was determined by trial and error and is scale dependent! float factor = 0.05f + exp(-fogd*dist / 62500.f); @@ -319,16 +311,16 @@ void GLSprite::Draw(int pass) } gl_RenderState.AlphaFunc(GL_GEQUAL, gl_mask_sprite_threshold); - gl_RenderState.SetColor(0.2f,0.2f,0.2f,fuzzalpha, Colormap.Desaturation); + gl_RenderState.SetColor(0.2f,0.2f,0.2f,fuzzalpha, sprite->Colormap.Desaturation); additivefog = true; - lightlist = nullptr; // the fuzz effect does not use the sector's light level so splitting is not needed. + sprite->lightlist = nullptr; // the fuzz effect does not use the sector's light level so splitting is not needed. } else if (RenderStyle.BlendOp == STYLEOP_Add && RenderStyle.DestAlpha == STYLEALPHA_One) { additivefog = true; } } - else if (modelframe == nullptr) + else if (sprite->modelframe == nullptr) { int tm, sb, db, be; @@ -341,40 +333,40 @@ void GLSprite::Draw(int pass) } if (RenderStyle.BlendOp != STYLEOP_Shadow) { - if (gl_lights && GLRenderer->mLightCount && mDrawer->FixedColormap == CM_DEFAULT && !fullbright) + if (gl_lights && GLRenderer->mLightCount && mDrawer->FixedColormap == CM_DEFAULT && !sprite->fullbright) { - if (modelframe && !particle) - dynlightindex = gl_SetDynModelLight(gl_light_sprites ? actor : NULL, dynlightindex); + if (sprite->modelframe && !sprite->particle) + sprite->dynlightindex = gl_SetDynModelLight(gl_light_sprites ? sprite->actor : nullptr, sprite->dynlightindex); else - gl_SetDynSpriteLight(gl_light_sprites ? actor : NULL, gl_light_particles ? particle : NULL); + gl_SetDynSpriteLight(gl_light_sprites ? sprite->actor : nullptr, gl_light_particles ? sprite->particle : nullptr); } - sector_t *cursec = actor ? actor->Sector : particle ? particle->subsector->sector : nullptr; + sector_t *cursec = sprite->actor ? sprite->actor->Sector : sprite->particle ? sprite->particle->subsector->sector : nullptr; if (cursec != nullptr) { - const PalEntry finalcol = fullbright - ? ThingColor - : ThingColor.Modulate(cursec->SpecialColors[sector_t::sprites]); + const PalEntry finalcol = sprite->fullbright + ? sprite->ThingColor + : sprite->ThingColor.Modulate(cursec->SpecialColors[sector_t::sprites]); gl_RenderState.SetObjectColor(finalcol); } - mDrawer->SetColor(lightlevel, rel, Colormap, trans); + mDrawer->SetColor(sprite->lightlevel, rel, sprite->Colormap, sprite->trans); } - if (Colormap.FadeColor.isBlack()) foglevel=lightlevel; + if (sprite->Colormap.FadeColor.isBlack()) sprite->foglevel = sprite->lightlevel; if (RenderStyle.Flags & STYLEF_FadeToBlack) { - Colormap.FadeColor=0; + sprite->Colormap.FadeColor=0; additivefog = true; } if (RenderStyle.BlendOp == STYLEOP_RevSub || RenderStyle.BlendOp == STYLEOP_Sub) { - if (!modelframe) + if (!sprite->modelframe) { // non-black fog with subtractive style needs special treatment - if (!Colormap.FadeColor.isBlack()) + if (!sprite->Colormap.FadeColor.isBlack()) { foglayer = true; // Due to the two-layer approach we need to force an alpha test that lets everything pass @@ -384,28 +376,29 @@ void GLSprite::Draw(int pass) else RenderStyle.BlendOp = STYLEOP_Fuzz; // subtractive with models is not going to work. } - if (!foglayer) mDrawer->SetFog(foglevel, rel, &Colormap, additivefog); + if (!foglayer) mDrawer->SetFog(sprite->foglevel, rel, &sprite->Colormap, additivefog); else { gl_RenderState.EnableFog(false); gl_RenderState.SetFog(0, 0); } - if (gltexture) gl_RenderState.SetMaterial(gltexture, CLAMP_XY, translation, OverrideShader, !!(RenderStyle.Flags & STYLEF_RedIsAlpha)); - else if (!modelframe) gl_RenderState.EnableTexture(false); + if (sprite->gltexture) gl_RenderState.SetMaterial(sprite->gltexture, CLAMP_XY, sprite->translation, sprite->OverrideShader, !!(RenderStyle.Flags & STYLEF_RedIsAlpha)); + else if (!sprite->modelframe) gl_RenderState.EnableTexture(false); //mDrawer->SetColor(lightlevel, rel, Colormap, trans); - unsigned int iter = lightlist? lightlist->Size() : 1; + unsigned int iter = sprite->lightlist? sprite->lightlist->Size() : 1; bool clipping = false; - if (lightlist || topclip != LARGE_VALUE || bottomclip != -LARGE_VALUE) + auto lightlist = sprite->lightlist; + if (lightlist || sprite->topclip != LARGE_VALUE || sprite->bottomclip != -LARGE_VALUE) { clipping = true; gl_RenderState.EnableSplit(true); } - secplane_t bottomp = { { 0, 0, -1. }, bottomclip }; - secplane_t topp = { { 0, 0, -1. }, topclip }; + secplane_t bottomp = { { 0, 0, -1. }, sprite->bottomclip }; + secplane_t topp = { { 0, 0, -1. }, sprite->topclip }; for (unsigned i = 0; i < iter; i++) { if (lightlist) @@ -414,18 +407,18 @@ void GLSprite::Draw(int pass) secplane_t *topplane = i == 0 ? &topp : &(*lightlist)[i].plane; secplane_t *lowplane = i == (*lightlist).Size() - 1 ? &bottomp : &(*lightlist)[i + 1].plane; - int thislight = (*lightlist)[i].caster != NULL ? hw_ClampLight(*(*lightlist)[i].p_lightlevel) : lightlevel; - int thisll = actor == nullptr? thislight : (uint8_t)actor->Sector->CheckSpriteGlow(thislight, actor->InterpolatedPosition(r_viewpoint.TicFrac)); + int thislight = (*lightlist)[i].caster != nullptr ? hw_ClampLight(*(*lightlist)[i].p_lightlevel) : sprite->lightlevel; + int thisll = sprite->actor == nullptr? thislight : (uint8_t)sprite->actor->Sector->CheckSpriteGlow(thislight, sprite->actor->InterpolatedPosition(r_viewpoint.TicFrac)); FColormap thiscm; - thiscm.CopyFog(Colormap); + thiscm.CopyFog(sprite->Colormap); thiscm.CopyFrom3DLight(&(*lightlist)[i]); if (level.flags3 & LEVEL3_NOCOLOREDSPRITELIGHTING) { thiscm.Decolorize(); } - mDrawer->SetColor(thisll, rel, thiscm, trans); + mDrawer->SetColor(thisll, rel, thiscm, sprite->trans); if (!foglayer) { mDrawer->SetFog(thislight, rel, &thiscm, additivefog); @@ -437,25 +430,29 @@ void GLSprite::Draw(int pass) gl_RenderState.SetSplitPlanes(topp, bottomp); } - if (!modelframe) + if (!sprite->modelframe) { gl_RenderState.Apply(); FVector3 v[4]; gl_RenderState.SetNormal(0, 0, 0); - CalculateVertices(v); + if (sprite->CalculateVertices(v)) + { + glEnable(GL_POLYGON_OFFSET_FILL); + glPolygonOffset(-1.0f, -128.0f); + } FQuadDrawer qd; - qd.Set(0, v[0][0], v[0][1], v[0][2], ul, vt); - qd.Set(1, v[1][0], v[1][1], v[1][2], ur, vt); - qd.Set(2, v[2][0], v[2][1], v[2][2], ul, vb); - qd.Set(3, v[3][0], v[3][1], v[3][2], ur, vb); + qd.Set(0, v[0][0], v[0][1], v[0][2], sprite->ul, sprite->vt); + qd.Set(1, v[1][0], v[1][1], v[1][2], sprite->ur, sprite->vt); + qd.Set(2, v[2][0], v[2][1], v[2][2], sprite->ul, sprite->vb); + qd.Set(3, v[3][0], v[3][1], v[3][2], sprite->ur, sprite->vb); qd.Render(GL_TRIANGLE_STRIP); if (foglayer) { // If we get here we know that we have colored fog and no fixed colormap. - mDrawer->SetFog(foglevel, rel, &Colormap, additivefog); + mDrawer->SetFog(sprite->foglevel, rel, &sprite->Colormap, additivefog); gl_RenderState.SetFixedColormap(CM_FOGLAYER); gl_RenderState.BlendEquation(GL_FUNC_ADD); gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -466,7 +463,7 @@ void GLSprite::Draw(int pass) } else { - gl_RenderModel(this, dynlightindex); + gl_RenderModel(sprite, sprite->dynlightindex); } } @@ -481,13 +478,13 @@ void GLSprite::Draw(int pass) gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); gl_RenderState.BlendEquation(GL_FUNC_ADD); gl_RenderState.SetTextureMode(TM_MODULATE); - if (actor != nullptr && (actor->renderflags & RF_SPRITETYPEMASK) == RF_FLATSPRITE) + if (sprite->actor != nullptr && (sprite->actor->renderflags & RF_SPRITETYPEMASK) == RF_FLATSPRITE) { glPolygonOffset(0.0f, 0.0f); glDisable(GL_POLYGON_OFFSET_FILL); } } - else if (modelframe == nullptr) + else if (sprite->modelframe == nullptr) { glPolygonOffset(0.0f, 0.0f); glDisable(GL_POLYGON_OFFSET_FILL); @@ -504,11 +501,11 @@ void GLSprite::Draw(int pass) // // //========================================================================== -inline void GLSprite::PutSprite(bool translucent) +void FDrawInfo::AddSprite(GLSprite *sprite, bool translucent) { int list; // [BB] Allow models to be drawn in the GLDL_TRANSLUCENT pass. - if (translucent || actor == nullptr || (!modelframe && (actor->renderflags & RF_SPRITETYPEMASK) != RF_WALLSPRITE)) + if (translucent || sprite->actor == nullptr || (!sprite->modelframe && (sprite->actor->renderflags & RF_SPRITETYPEMASK) != RF_WALLSPRITE)) { list = GLDL_TRANSLUCENT; } @@ -516,9 +513,9 @@ inline void GLSprite::PutSprite(bool translucent) { list = GLDL_MODELS; } - dynlightindex = -1; + sprite->dynlightindex = -1; auto newsprt = gl_drawinfo->drawlists[list].NewSprite(); - *newsprt = *this; + *newsprt = *sprite; } //========================================================================== @@ -526,9 +523,21 @@ inline void GLSprite::PutSprite(bool translucent) // // //========================================================================== -void GLSprite::SplitSprite(sector_t * frontsector, bool translucent) + +inline void GLSprite::PutSprite(HWDrawInfo *di, bool translucent) { - GLSprite copySprite(mDrawer); + di->AddSprite(this, translucent); +} + +//========================================================================== +// +// +// +//========================================================================== + +void GLSprite::SplitSprite(HWDrawInfo *di, sector_t * frontsector, bool translucent) +{ + GLSprite copySprite; double lightbottom; unsigned int i; bool put=false; @@ -536,7 +545,7 @@ void GLSprite::SplitSprite(sector_t * frontsector, bool translucent) for(i=0;ifloorplane.ZatPoint(actor); @@ -563,7 +572,7 @@ void GLSprite::SplitSprite(sector_t * frontsector, bool translucent) z1=copySprite.z2=lightbottom; vt=copySprite.vb=copySprite.vt+ (lightbottom-copySprite.z1)*(copySprite.vb-copySprite.vt)/(z2-copySprite.z1); - copySprite.PutSprite(translucent); + copySprite.PutSprite(di, translucent); put=true; } } @@ -675,7 +684,7 @@ void GLSprite::PerformSpriteClipAdjustment(AActor *thing, const DVector2 &thingp // //========================================================================== -void GLSprite::Process(AActor* thing, sector_t * sector, int thruportal) +void GLSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t in_area, int thruportal) { sector_t rs; sector_t * rendersector; @@ -696,7 +705,7 @@ void GLSprite::Process(AActor* thing, sector_t * sector, int thruportal) if (thing->renderflags & RF_INVISIBLE || !thing->RenderStyle.IsVisible(thing->Alpha)) { - if (!(thing->flags & MF_STEALTH) || !mDrawer->FixedColormap || !gl_enhanced_nightvision || thing == camera) + if (!(thing->flags & MF_STEALTH) || !di->FixedColormap || !gl_enhanced_nightvision || thing == camera) return; } @@ -708,14 +717,11 @@ void GLSprite::Process(AActor* thing, sector_t * sector, int thruportal) int spritenum = thing->sprite; DVector2 sprscale = thing->Scale; - if (thing->player != NULL) + if (thing->player != nullptr) { P_CheckPlayerSprite(thing, spritenum, sprscale); } - // If this thing is in a map section that's not in view it can't possibly be visible - if (!thruportal && !mDrawer->CurrentMapSections[thing->subsector->mapsection]) return; - // [RH] Interpolate the sprite's position to make it look smooth DVector3 thingpos = thing->InterpolatedPosition(r_viewpoint.TicFrac); if (thruportal == 1) thingpos += level.Displacements.getOffset(thing->Sector->PortalGroup, sector->PortalGroup); @@ -752,7 +758,7 @@ void GLSprite::Process(AActor* thing, sector_t * sector, int thruportal) // don't draw first frame of a player missile if (thing->flags&MF_MISSILE) { - if (!(thing->flags7 & MF7_FLYCHEAT) && thing->target == GLRenderer->mViewActor && GLRenderer->mViewActor != NULL) + if (!(thing->flags7 & MF7_FLYCHEAT) && thing->target == GLRenderer->mViewActor && GLRenderer->mViewActor != nullptr) { double speed = thing->Vel.Length(); if (speed >= thing->target->radius / 2) @@ -780,7 +786,7 @@ void GLSprite::Process(AActor* thing, sector_t * sector, int thruportal) if (sector->sectornum != thing->Sector->sectornum && !thruportal) { - rendersector = hw_FakeFlat(thing->Sector, &rs, mDrawer->in_area, false); + rendersector = hw_FakeFlat(thing->Sector, &rs, in_area, false); } else { @@ -921,7 +927,7 @@ void GLSprite::Process(AActor* thing, sector_t * sector, int thruportal) x1 = x2 = x; y1 = y2 = y; z1 = z2 = z; - gltexture = NULL; + gltexture = nullptr; } depth = FloatToFixed((x - r_viewpoint.Pos.X) * r_viewpoint.TanCos + (y - r_viewpoint.Pos.Y) * r_viewpoint.TanSin); @@ -947,16 +953,16 @@ void GLSprite::Process(AActor* thing, sector_t * sector, int thruportal) RenderStyle = thing->RenderStyle; // colormap stuff is a little more complicated here... - if (mDrawer->FixedColormap) + if (di->FixedColormap) { - if ((gl_enhanced_nv_stealth > 0 && mDrawer->FixedColormap == CM_LITE) // Infrared powerup only - || (gl_enhanced_nv_stealth == 2 && mDrawer->FixedColormap >= CM_TORCH)// Also torches + if ((gl_enhanced_nv_stealth > 0 && di->FixedColormap == CM_LITE) // Infrared powerup only + || (gl_enhanced_nv_stealth == 2 && di->FixedColormap >= CM_TORCH)// Also torches || (gl_enhanced_nv_stealth == 3)) // Any fixed colormap enhancedvision = true; Colormap.Clear(); - if (mDrawer->FixedColormap == CM_LITE) + if (di->FixedColormap == CM_LITE) { if (gl_enhanced_nightvision && (thing->IsKindOf(RUNTIME_CLASS(AInventory)) || thing->flags3&MF3_ISMONSTER || thing->flags&MF_MISSILE || thing->flags&MF_CORPSE)) @@ -970,7 +976,7 @@ void GLSprite::Process(AActor* thing, sector_t * sector, int thruportal) Colormap = rendersector->Colormap; if (fullbright) { - if (rendersector == &level.sectors[rendersector->sectornum] || mDrawer->in_area != area_below) + if (rendersector == &level.sectors[rendersector->sectornum] || in_area != area_below) // under water areas keep their color for fullbright objects { // Only make the light white but keep everything else (fog, desaturation and Boom colormap.) @@ -1088,7 +1094,7 @@ void GLSprite::Process(AActor* thing, sector_t * sector, int thruportal) actor = thing; index = GLRenderer->gl_spriteindex++; - particle = NULL; + particle = nullptr; const bool drawWithXYBillboard = (!(actor->renderflags & RF_FORCEYBILLBOARD) && (actor->renderflags & RF_SPRITETYPEMASK) == RF_FACESPRITE @@ -1102,15 +1108,15 @@ void GLSprite::Process(AActor* thing, sector_t * sector, int thruportal) // 3. any bright object // 4. any with render style shadow (which doesn't use the sector light) // 5. anything with render style reverse subtract (light effect is not what would be desired here) - if (thing->Sector->e->XFloor.lightlist.Size() != 0 && mDrawer->FixedColormap == CM_DEFAULT && !fullbright && + if (thing->Sector->e->XFloor.lightlist.Size() != 0 && di->FixedColormap == CM_DEFAULT && !fullbright && RenderStyle.BlendOp != STYLEOP_Shadow && RenderStyle.BlendOp != STYLEOP_RevSub) { if (gl.flags & RFL_NO_CLIP_PLANES) // on old hardware we are rather limited... { - lightlist = NULL; + lightlist = nullptr; if (!drawWithXYBillboard && !modelframe) { - SplitSprite(thing->Sector, hw_styleflags != STYLEHW_Solid); + SplitSprite(di, thing->Sector, hw_styleflags != STYLEHW_Solid); } } else @@ -1120,10 +1126,10 @@ void GLSprite::Process(AActor* thing, sector_t * sector, int thruportal) } else { - lightlist = NULL; + lightlist = nullptr; } - PutSprite(hw_styleflags != STYLEHW_Solid); + PutSprite(di, hw_styleflags != STYLEHW_Solid); rendered_sprites++; } @@ -1134,7 +1140,7 @@ void GLSprite::Process(AActor* thing, sector_t * sector, int thruportal) // //========================================================================== -void GLSprite::ProcessParticle (particle_t *particle, sector_t *sector)//, int shade, int fakeside) +void GLSprite::ProcessParticle (HWDrawInfo *di, particle_t *particle, sector_t *sector)//, int shade, int fakeside) { if (GLRenderer->mClipPortal) { @@ -1150,7 +1156,7 @@ void GLSprite::ProcessParticle (particle_t *particle, sector_t *sector)//, int s sector->GetCeilingLight() : sector->GetFloorLight()); foglevel = (uint8_t)clamp(sector->lightlevel, 0, 255); - if (mDrawer->FixedColormap) + if (di->FixedColormap) { Colormap.Clear(); } @@ -1191,8 +1197,8 @@ void GLSprite::ProcessParticle (particle_t *particle, sector_t *sector)//, int s ThingColor = particle->color; ThingColor.a = 255; - modelframe=NULL; - gltexture=NULL; + modelframe=nullptr; + gltexture=nullptr; topclip = LARGE_VALUE; bottomclip = -LARGE_VALUE; @@ -1253,7 +1259,7 @@ void GLSprite::ProcessParticle (particle_t *particle, sector_t *sector)//, int s depth = FloatToFixed((x - r_viewpoint.Pos.X) * r_viewpoint.TanCos + (y - r_viewpoint.Pos.Y) * r_viewpoint.TanSin); - actor=NULL; + actor=nullptr; this->particle=particle; fullbright = !!particle->bright; @@ -1261,12 +1267,12 @@ void GLSprite::ProcessParticle (particle_t *particle, sector_t *sector)//, int s if (gl_particles_style != 2 && trans>=1.0f-FLT_EPSILON) hw_styleflags = STYLEHW_Solid; else hw_styleflags = STYLEHW_NoAlphaTest; - if (sector->e->XFloor.lightlist.Size() != 0 && mDrawer->FixedColormap == CM_DEFAULT && !fullbright) + if (sector->e->XFloor.lightlist.Size() != 0 && di->FixedColormap == CM_DEFAULT && !fullbright) lightlist = §or->e->XFloor.lightlist; else - lightlist = NULL; + lightlist = nullptr; - PutSprite(hw_styleflags != STYLEHW_Solid); + PutSprite(di, hw_styleflags != STYLEHW_Solid); rendered_sprites++; } @@ -1276,7 +1282,7 @@ void GLSprite::ProcessParticle (particle_t *particle, sector_t *sector)//, int s // //========================================================================== -void FDrawInfo::ProcessActorsInPortal(FLinePortalSpan *glport) +void HWDrawInfo::ProcessActorsInPortal(FLinePortalSpan *glport, area_t in_area) { TMap processcheck; if (glport->validcount == validcount) return; // only process once per frame @@ -1318,8 +1324,8 @@ void FDrawInfo::ProcessActorsInPortal(FLinePortalSpan *glport) th->SetXYZ(newpos); th->Prev += newpos - savedpos; - GLSprite spr(mDrawer); - spr.Process(th, hw_FakeFlat(th->Sector, &fakesector, mDrawer->in_area, false), 2); + GLSprite spr; + spr.Process(this, th, hw_FakeFlat(th->Sector, &fakesector, in_area, false), in_area, 2); th->Angles.Yaw = savedangle; th->SetXYZ(savedpos); th->Prev -= newpos - savedpos; diff --git a/src/gl/scene/gl_wall.h b/src/gl/scene/gl_wall.h index 3eaa05f7f..ddad0df81 100644 --- a/src/gl/scene/gl_wall.h +++ b/src/gl/scene/gl_wall.h @@ -30,6 +30,7 @@ struct FFlatVertex; struct FLinePortalSpan; class GLSceneDrawer; struct FDynLightData; +enum area_t : int; struct FDrawInfo; struct HWDrawInfo; @@ -47,7 +48,6 @@ public: friend struct GLDrawList; friend void Mod_RenderModel(GLSprite * spr, model_t * mdl, int framenumber); - GLSceneDrawer *mDrawer; int lightlevel; uint8_t foglevel; uint8_t hw_styleflags; @@ -81,25 +81,16 @@ public: int dynlightindex; - void SplitSprite(sector_t * frontsector, bool translucent); - void SetLowerParam(); + void SplitSprite(HWDrawInfo *di, sector_t * frontsector, bool translucent); void PerformSpriteClipAdjustment(AActor *thing, const DVector2 &thingpos, float spriteheight); - void CalculateVertices(FVector3 *v); + bool CalculateVertices(FVector3 *v); public: - GLSprite(GLSceneDrawer *drawer) - { - mDrawer = drawer; - } - void Draw(int pass); - void PutSprite(bool translucent); - void Process(AActor* thing,sector_t * sector, int thruportal = false); - void ProcessParticle (particle_t *particle, sector_t *sector);//, int shade, int fakeside) - void SetThingColor(PalEntry); - - // Lines start-end and fdiv must intersect. - double CalcIntersectionVertex(GLWall * w2); + GLSprite() {} + void PutSprite(HWDrawInfo *di, bool translucent); + void Process(HWDrawInfo *di, AActor* thing,sector_t * sector, area_t in_area, int thruportal = false); + void ProcessParticle (HWDrawInfo *di, particle_t *particle, sector_t *sector);//, int shade, int fakeside) GLSprite(const GLSprite &other) { diff --git a/src/gl/scene/gl_walls_draw.cpp b/src/gl/scene/gl_walls_draw.cpp index 3d1b0dc95..1948e1761 100644 --- a/src/gl/scene/gl_walls_draw.cpp +++ b/src/gl/scene/gl_walls_draw.cpp @@ -455,7 +455,7 @@ void FDrawInfo::AddPortal(GLWall *wall, int ptype) line_t *otherside = wall->lineportal->lines[0]->mDestination; if (otherside != NULL && otherside->portalindex < level.linePortals.Size()) { - ProcessActorsInPortal(otherside->getPortal()->mGroup); + ProcessActorsInPortal(otherside->getPortal()->mGroup, mDrawer->in_area); } portal = new GLLineToLinePortal(wall->lineportal); } diff --git a/src/hwrenderer/scene/hw_drawinfo.h b/src/hwrenderer/scene/hw_drawinfo.h index c032661b5..91c6fb176 100644 --- a/src/hwrenderer/scene/hw_drawinfo.h +++ b/src/hwrenderer/scene/hw_drawinfo.h @@ -7,6 +7,7 @@ struct FLinePortalSpan; struct FFlatVertex; class GLWall; class GLFlat; +class GLSprite; struct GLDecal; //========================================================================== @@ -118,6 +119,8 @@ public: void AddCeilingStack(sector_t * sec); void ProcessSectorStacks(area_t in_area); + void ProcessActorsInPortal(FLinePortalSpan *glport, area_t in_area); + void AddOtherFloorPlane(int sector, gl_subsectorrendernode * node); void AddOtherCeilingPlane(int sector, gl_subsectorrendernode * node); @@ -130,9 +133,9 @@ public: virtual void AddPortal(GLWall *w, int portaltype) = 0; virtual void AddMirrorSurface(GLWall *w) = 0; virtual void AddFlat(GLFlat *flat, bool fog) = 0; + virtual void AddSprite(GLSprite *sprite, bool translucent) = 0; virtual GLDecal *AddDecal(bool onmirror) = 0; - virtual void ProcessActorsInPortal(FLinePortalSpan *glport) = 0; virtual std::pair AllocVertices(unsigned int count) = 0; diff --git a/src/hwrenderer/scene/hw_drawstructs.h b/src/hwrenderer/scene/hw_drawstructs.h index 0dd95cd69..a507c18db 100644 --- a/src/hwrenderer/scene/hw_drawstructs.h +++ b/src/hwrenderer/scene/hw_drawstructs.h @@ -24,6 +24,13 @@ struct FLinePortalSpan; struct FDynLightData; class VSMatrix; +enum HWRenderStyle +{ + STYLEHW_Normal, // default + STYLEHW_Solid, // drawn solid (needs special treatment for sprites) + STYLEHW_NoAlphaTest, // disable alpha test +}; + enum WallTypes { RENDERWALL_NONE, @@ -270,16 +277,6 @@ public: return -((y-glseg.y1)*(glseg.x2-glseg.x1)-(x-glseg.x1)*(glseg.y2-glseg.y1)); } - // Lines start-end and fdiv must intersect. - double CalcIntersectionVertex(GLWall * w2) - { - float ax = glseg.x1, ay=glseg.y1; - float bx = glseg.x2, by=glseg.y2; - float cx = w2->glseg.x1, cy=w2->glseg.y1; - float dx = w2->glseg.x2, dy=w2->glseg.y2; - return ((ay-cy)*(dx-cx)-(ax-cx)*(dy-cy)) / ((bx-ax)*(dy-cy)-(by-ay)*(dx-cx)); - } - }; //==========================================================================