From 96ac1fa3633a2703b98b95d1bb004562021a1628 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 3 May 2018 21:42:34 +0200 Subject: [PATCH] - changed GLDecal to work without a pointer to the generating GLWall. Although this is currently safe there is no guarantee that future refactorings will keep the current draw lists, so it's better if GLDecal used its own copy of the data. --- src/gl/scene/gl_walls_draw.cpp | 41 ++++++++++++------------ src/hwrenderer/scene/hw_decal.cpp | 42 ++++++++++++++----------- src/hwrenderer/scene/hw_drawinfo.h | 3 +- src/hwrenderer/scene/hw_drawstructs.h | 15 +++++---- src/hwrenderer/scene/hw_spritelight.cpp | 9 +++--- 5 files changed, 60 insertions(+), 50 deletions(-) diff --git a/src/gl/scene/gl_walls_draw.cpp b/src/gl/scene/gl_walls_draw.cpp index bd0388722..a03e53150 100644 --- a/src/gl/scene/gl_walls_draw.cpp +++ b/src/gl/scene/gl_walls_draw.cpp @@ -464,10 +464,8 @@ void FDrawInfo::AddPortal(GLWall *wall, int ptype) //========================================================================== void FDrawInfo::DrawDecal(GLDecal *gldecal) { - auto wall = gldecal->wall; auto decal = gldecal->decal; auto tex = gldecal->gltexture; - auto &seg = wall->seg; // calculate dynamic light effect. if (level.HasDynamicLights && !mDrawer->FixedColormap && gl_light_sprites) @@ -475,8 +473,8 @@ void FDrawInfo::DrawDecal(GLDecal *gldecal) // Note: This should be replaced with proper shader based lighting. double x, y; float out[3]; - decal->GetXY(seg->sidedef, x, y); - GetDynSpriteLight(nullptr, x, y, gldecal->zcenter, wall->sub, out); + decal->GetXY(decal->Side, x, y); + GetDynSpriteLight(nullptr, x, y, gldecal->zcenter, decal->Side->lighthead, decal->Side->sector->PortalGroup, out); gl_RenderState.SetDynLight(out[0], out[1], out[2]); } @@ -495,7 +493,7 @@ void FDrawInfo::DrawDecal(GLDecal *gldecal) else gl_RenderState.AlphaFunc(GL_GREATER, 0.f); - mDrawer->SetColor(gldecal->light, gldecal->rel, gldecal->colormap, gldecal->a); + mDrawer->SetColor(gldecal->lightlevel, gldecal->rellight, gldecal->Colormap, gldecal->alpha); // for additively drawn decals we must temporarily set the fog color to black. PalEntry fc = gl_RenderState.GetFogColor(); if (decal->RenderStyle.BlendOp == STYLEOP_Add && decal->RenderStyle.DestAlpha == STYLEALPHA_One) @@ -503,20 +501,20 @@ void FDrawInfo::DrawDecal(GLDecal *gldecal) gl_RenderState.SetFog(0, -1); } - gl_RenderState.SetNormal(wall->glseg.Normal()); + gl_RenderState.SetNormal(gldecal->Normal); - if (wall->lightlist == nullptr) + if (gldecal->lightlist == nullptr) { gl_RenderState.Apply(); GLRenderer->mVBO->RenderArray(GL_TRIANGLE_FAN, gldecal->vertindex, 4); } else { - auto &lightlist = *wall->lightlist; + auto &lightlist = *gldecal->lightlist; for (unsigned k = 0; k < lightlist.Size(); k++) { - secplane_t &lowplane = k == lightlist.Size() - 1 ? wall->bottomplane : lightlist[k + 1].plane; + secplane_t &lowplane = k == lightlist.Size() - 1 ? gldecal->bottomplane : lightlist[k + 1].plane; DecalVertex *dv = gldecal->dv; float low1 = lowplane.ZatPoint(dv[1].x, dv[1].y); @@ -524,13 +522,13 @@ void FDrawInfo::DrawDecal(GLDecal *gldecal) if (low1 < dv[1].z || low2 < dv[2].z) { - int thisll = lightlist[k].caster != NULL ? hw_ClampLight(*lightlist[k].p_lightlevel) : wall->lightlevel; + int thisll = lightlist[k].caster != NULL ? hw_ClampLight(*lightlist[k].p_lightlevel) : gldecal->lightlevel; FColormap thiscm; - thiscm.FadeColor = wall->Colormap.FadeColor; + thiscm.FadeColor = gldecal->Colormap.FadeColor; thiscm.CopyFrom3DLight(&lightlist[k]); - mDrawer->SetColor(thisll, gldecal->rel, thiscm, gldecal->a); + mDrawer->SetColor(thisll, gldecal->rellight, thiscm, gldecal->alpha); if (level.flags3 & LEVEL3_NOCOLOREDSPRITELIGHTING) thiscm.Decolorize(); - mDrawer->SetFog(thisll, gldecal->rel, &thiscm, wall->RenderStyle == STYLE_Add); + mDrawer->SetFog(thisll, gldecal->rellight, &thiscm, false); gl_RenderState.SetSplitPlanes(lightlist[k].plane, lowplane); gl_RenderState.Apply(); @@ -554,25 +552,28 @@ void FDrawInfo::DrawDecal(GLDecal *gldecal) //========================================================================== void FDrawInfo::DrawDecals() { - GLWall *wall = nullptr; + side_t *wall = nullptr; + bool splitting = false; for (auto gldecal : decals[0]) { - if (gldecal->wall != wall) + if (gldecal->decal->Side != wall) { - wall = gldecal->wall; - if (wall->lightlist != nullptr) + wall = gldecal->decal->Side; + if (gldecal->lightlist != nullptr) { gl_RenderState.EnableSplit(true); + splitting = true; } else { gl_RenderState.EnableSplit(false); - mDrawer->SetFog(wall->lightlevel, wall->rellight + getExtraLight(), &wall->Colormap, false); + splitting = false; + mDrawer->SetFog(gldecal->lightlevel, gldecal->rellight, &gldecal->Colormap, false); } } DrawDecal(gldecal); } - if (wall && wall->lightlist != nullptr) gl_RenderState.EnableSplit(false); + if (splitting) gl_RenderState.EnableSplit(false); } //========================================================================== @@ -585,7 +586,7 @@ void FDrawInfo::DrawDecalsForMirror(GLWall *wall) mDrawer->SetFog(wall->lightlevel, wall->rellight + getExtraLight(), &wall->Colormap, false); for (auto gldecal : decals[1]) { - if (gldecal->wall == wall) + if (gldecal->decal->Side == wall->seg->sidedef) { DrawDecal(gldecal); } diff --git a/src/hwrenderer/scene/hw_decal.cpp b/src/hwrenderer/scene/hw_decal.cpp index 423d11276..fca5b9ef3 100644 --- a/src/hwrenderer/scene/hw_decal.cpp +++ b/src/hwrenderer/scene/hw_decal.cpp @@ -36,7 +36,7 @@ #include "hwrenderer/utility/hw_lighting.h" #include "hwrenderer/data/flatvertices.h" -void GLWall::ProcessDecal(HWDrawInfo *di, DBaseDecal *decal) +void GLWall::ProcessDecal(HWDrawInfo *di, DBaseDecal *decal, const FVector3 &normal) { line_t * line = seg->linedef; side_t * side = seg->sidedef; @@ -228,35 +228,37 @@ void GLWall::ProcessDecal(HWDrawInfo *di, DBaseDecal *decal) for (i = 0; i < 4; i++) dv[i].v = vb - dv[i].v; } - GLDecal &gldecal = *di->AddDecal(type == RENDERWALL_MIRRORSURFACE); - gldecal.gltexture = tex; - gldecal.wall = this; - gldecal.decal = decal; + GLDecal *gldecal = di->AddDecal(type == RENDERWALL_MIRRORSURFACE); + gldecal->gltexture = tex; + gldecal->decal = decal; if (decal->RenderFlags & RF_FULLBRIGHT) { - gldecal.light = 255; - gldecal.rel = 0; + gldecal->lightlevel = 255; + gldecal->rellight = 0; } else { - gldecal.light = lightlevel; - gldecal.rel = rellight + getExtraLight(); + gldecal->lightlevel = lightlevel; + gldecal->rellight = rellight + getExtraLight(); } - gldecal.colormap = Colormap; + gldecal->Colormap = Colormap; if (level.flags3 & LEVEL3_NOCOLOREDSPRITELIGHTING) { - gldecal.colormap.Decolorize(); + gldecal->Colormap.Decolorize(); } - gldecal.a = decal->Alpha; - gldecal.zcenter = zpos - decalheight * 0.5f; - memcpy(gldecal.dv, dv, sizeof(dv)); + gldecal->alpha = decal->Alpha; + gldecal->zcenter = zpos - decalheight * 0.5f; + gldecal->bottomplane = bottomplane; + gldecal->Normal = normal; + gldecal->lightlist = lightlist; + memcpy(gldecal->dv, dv, sizeof(dv)); auto verts = di->AllocVertices(4); - gldecal.vertindex = verts.second; + gldecal->vertindex = verts.second; for (i = 0; i < 4; i++) { @@ -274,10 +276,14 @@ void GLWall::ProcessDecals(HWDrawInfo *di) if (seg->sidedef != nullptr) { DBaseDecal *decal = seg->sidedef->AttachedDecals; - while (decal) + if (decal) { - ProcessDecal(di, decal); - decal = decal->WallNext; + auto normal = glseg.Normal(); // calculate the normal only once per wall because it requires a square root. + while (decal) + { + ProcessDecal(di, decal, normal); + decal = decal->WallNext; + } } } } diff --git a/src/hwrenderer/scene/hw_drawinfo.h b/src/hwrenderer/scene/hw_drawinfo.h index 38218c46d..2914a7a9c 100644 --- a/src/hwrenderer/scene/hw_drawinfo.h +++ b/src/hwrenderer/scene/hw_drawinfo.h @@ -12,6 +12,7 @@ class GLSprite; struct GLDecal; class IShadowMap; struct particle_t; +struct FDynLightData; //========================================================================== // @@ -140,7 +141,7 @@ public: void AddOtherFloorPlane(int sector, gl_subsectorrendernode * node); void AddOtherCeilingPlane(int sector, gl_subsectorrendernode * node); - void GetDynSpriteLight(AActor *self, float x, float y, float z, subsector_t * subsec, float *out); + void GetDynSpriteLight(AActor *self, float x, float y, float z, FLightNode *node, int portalgroup, float *out); void GetDynSpriteLight(AActor *thing, particle_t *particle, float *out); virtual void DrawWall(GLWall *wall, int pass) = 0; diff --git a/src/hwrenderer/scene/hw_drawstructs.h b/src/hwrenderer/scene/hw_drawstructs.h index 5407512ce..b70db68fb 100644 --- a/src/hwrenderer/scene/hw_drawstructs.h +++ b/src/hwrenderer/scene/hw_drawstructs.h @@ -247,7 +247,7 @@ public: float fch1, float fch2, float ffh1, float ffh2, float bch1, float bch2, float bfh1, float bfh2); - void ProcessDecal(HWDrawInfo *di, DBaseDecal *decal); + void ProcessDecal(HWDrawInfo *di, DBaseDecal *decal, const FVector3 &normal); void ProcessDecals(HWDrawInfo *di); void CreateVertices(FFlatVertex *&ptr, bool nosplit); @@ -412,16 +412,19 @@ struct DecalVertex struct GLDecal { FMaterial *gltexture; - GLWall *wall; + TArray *lightlist; DBaseDecal *decal; DecalVertex dv[4]; float zcenter; unsigned int vertindex; - int light; - int rel; - float a; - FColormap colormap; + FRenderStyle renderstyle; + int lightlevel; + int rellight; + float alpha; + FColormap Colormap; + secplane_t bottomplane; + FVector3 Normal; }; diff --git a/src/hwrenderer/scene/hw_spritelight.cpp b/src/hwrenderer/scene/hw_spritelight.cpp index 21037adfc..cd3e8a293 100644 --- a/src/hwrenderer/scene/hw_spritelight.cpp +++ b/src/hwrenderer/scene/hw_spritelight.cpp @@ -49,7 +49,7 @@ T smoothstep(const T edge0, const T edge1, const T x) // //========================================================================== -void HWDrawInfo::GetDynSpriteLight(AActor *self, float x, float y, float z, subsector_t * subsec, float *out) +void HWDrawInfo::GetDynSpriteLight(AActor *self, float x, float y, float z, FLightNode *node, int portalgroup, float *out) { ADynamicLight *light; float frac, lr, lg, lb; @@ -57,7 +57,6 @@ void HWDrawInfo::GetDynSpriteLight(AActor *self, float x, float y, float z, subs out[0] = out[1] = out[2] = 0.f; // Go through both light lists - FLightNode * node = subsec->lighthead; while (node) { light=node->lightsource; @@ -71,7 +70,7 @@ void HWDrawInfo::GetDynSpriteLight(AActor *self, float x, float y, float z, subs if (level.Displacements.size > 0) { int fromgroup = light->Sector->PortalGroup; - int togroup = subsec->sector->PortalGroup; + int togroup = portalgroup; if (fromgroup == togroup || fromgroup == 0 || togroup == 0) goto direct; DVector2 offset = level.Displacements.getOffset(fromgroup, togroup); @@ -132,11 +131,11 @@ void HWDrawInfo::GetDynSpriteLight(AActor *thing, particle_t *particle, float *o { if (thing != NULL) { - GetDynSpriteLight(thing, thing->X(), thing->Y(), thing->Center(), thing->subsector, out); + GetDynSpriteLight(thing, thing->X(), thing->Y(), thing->Center(), thing->subsector->lighthead, thing->Sector->PortalGroup, out); } else if (particle != NULL) { - GetDynSpriteLight(NULL, particle->Pos.X, particle->Pos.Y, particle->Pos.Z, particle->subsector, out); + GetDynSpriteLight(NULL, particle->Pos.X, particle->Pos.Y, particle->Pos.Z, particle->subsector->lighthead, particle->subsector->sector->PortalGroup, out); } }