- 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.
This commit is contained in:
Christoph Oelckers 2018-05-03 21:42:34 +02:00
parent 43b491ea33
commit 96ac1fa363
5 changed files with 60 additions and 50 deletions

View file

@ -464,10 +464,8 @@ void FDrawInfo::AddPortal(GLWall *wall, int ptype)
//========================================================================== //==========================================================================
void FDrawInfo::DrawDecal(GLDecal *gldecal) void FDrawInfo::DrawDecal(GLDecal *gldecal)
{ {
auto wall = gldecal->wall;
auto decal = gldecal->decal; auto decal = gldecal->decal;
auto tex = gldecal->gltexture; auto tex = gldecal->gltexture;
auto &seg = wall->seg;
// calculate dynamic light effect. // calculate dynamic light effect.
if (level.HasDynamicLights && !mDrawer->FixedColormap && gl_light_sprites) 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. // Note: This should be replaced with proper shader based lighting.
double x, y; double x, y;
float out[3]; float out[3];
decal->GetXY(seg->sidedef, x, y); decal->GetXY(decal->Side, x, y);
GetDynSpriteLight(nullptr, x, y, gldecal->zcenter, wall->sub, out); GetDynSpriteLight(nullptr, x, y, gldecal->zcenter, decal->Side->lighthead, decal->Side->sector->PortalGroup, out);
gl_RenderState.SetDynLight(out[0], out[1], out[2]); 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); 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. // for additively drawn decals we must temporarily set the fog color to black.
PalEntry fc = gl_RenderState.GetFogColor(); PalEntry fc = gl_RenderState.GetFogColor();
if (decal->RenderStyle.BlendOp == STYLEOP_Add && decal->RenderStyle.DestAlpha == STYLEALPHA_One) 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.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(); gl_RenderState.Apply();
GLRenderer->mVBO->RenderArray(GL_TRIANGLE_FAN, gldecal->vertindex, 4); GLRenderer->mVBO->RenderArray(GL_TRIANGLE_FAN, gldecal->vertindex, 4);
} }
else else
{ {
auto &lightlist = *wall->lightlist; auto &lightlist = *gldecal->lightlist;
for (unsigned k = 0; k < lightlist.Size(); k++) 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; DecalVertex *dv = gldecal->dv;
float low1 = lowplane.ZatPoint(dv[1].x, dv[1].y); 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) 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; FColormap thiscm;
thiscm.FadeColor = wall->Colormap.FadeColor; thiscm.FadeColor = gldecal->Colormap.FadeColor;
thiscm.CopyFrom3DLight(&lightlist[k]); 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(); 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.SetSplitPlanes(lightlist[k].plane, lowplane);
gl_RenderState.Apply(); gl_RenderState.Apply();
@ -554,25 +552,28 @@ void FDrawInfo::DrawDecal(GLDecal *gldecal)
//========================================================================== //==========================================================================
void FDrawInfo::DrawDecals() void FDrawInfo::DrawDecals()
{ {
GLWall *wall = nullptr; side_t *wall = nullptr;
bool splitting = false;
for (auto gldecal : decals[0]) for (auto gldecal : decals[0])
{ {
if (gldecal->wall != wall) if (gldecal->decal->Side != wall)
{ {
wall = gldecal->wall; wall = gldecal->decal->Side;
if (wall->lightlist != nullptr) if (gldecal->lightlist != nullptr)
{ {
gl_RenderState.EnableSplit(true); gl_RenderState.EnableSplit(true);
splitting = true;
} }
else else
{ {
gl_RenderState.EnableSplit(false); 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); 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); mDrawer->SetFog(wall->lightlevel, wall->rellight + getExtraLight(), &wall->Colormap, false);
for (auto gldecal : decals[1]) for (auto gldecal : decals[1])
{ {
if (gldecal->wall == wall) if (gldecal->decal->Side == wall->seg->sidedef)
{ {
DrawDecal(gldecal); DrawDecal(gldecal);
} }

View file

@ -36,7 +36,7 @@
#include "hwrenderer/utility/hw_lighting.h" #include "hwrenderer/utility/hw_lighting.h"
#include "hwrenderer/data/flatvertices.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; line_t * line = seg->linedef;
side_t * side = seg->sidedef; 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; for (i = 0; i < 4; i++) dv[i].v = vb - dv[i].v;
} }
GLDecal &gldecal = *di->AddDecal(type == RENDERWALL_MIRRORSURFACE); GLDecal *gldecal = di->AddDecal(type == RENDERWALL_MIRRORSURFACE);
gldecal.gltexture = tex; gldecal->gltexture = tex;
gldecal.wall = this; gldecal->decal = decal;
gldecal.decal = decal;
if (decal->RenderFlags & RF_FULLBRIGHT) if (decal->RenderFlags & RF_FULLBRIGHT)
{ {
gldecal.light = 255; gldecal->lightlevel = 255;
gldecal.rel = 0; gldecal->rellight = 0;
} }
else else
{ {
gldecal.light = lightlevel; gldecal->lightlevel = lightlevel;
gldecal.rel = rellight + getExtraLight(); gldecal->rellight = rellight + getExtraLight();
} }
gldecal.colormap = Colormap; gldecal->Colormap = Colormap;
if (level.flags3 & LEVEL3_NOCOLOREDSPRITELIGHTING) if (level.flags3 & LEVEL3_NOCOLOREDSPRITELIGHTING)
{ {
gldecal.colormap.Decolorize(); gldecal->Colormap.Decolorize();
} }
gldecal.a = decal->Alpha; gldecal->alpha = decal->Alpha;
gldecal.zcenter = zpos - decalheight * 0.5f; gldecal->zcenter = zpos - decalheight * 0.5f;
memcpy(gldecal.dv, dv, sizeof(dv)); gldecal->bottomplane = bottomplane;
gldecal->Normal = normal;
gldecal->lightlist = lightlist;
memcpy(gldecal->dv, dv, sizeof(dv));
auto verts = di->AllocVertices(4); auto verts = di->AllocVertices(4);
gldecal.vertindex = verts.second; gldecal->vertindex = verts.second;
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
{ {
@ -274,10 +276,14 @@ void GLWall::ProcessDecals(HWDrawInfo *di)
if (seg->sidedef != nullptr) if (seg->sidedef != nullptr)
{ {
DBaseDecal *decal = seg->sidedef->AttachedDecals; DBaseDecal *decal = seg->sidedef->AttachedDecals;
while (decal) if (decal)
{ {
ProcessDecal(di, decal); auto normal = glseg.Normal(); // calculate the normal only once per wall because it requires a square root.
decal = decal->WallNext; while (decal)
{
ProcessDecal(di, decal, normal);
decal = decal->WallNext;
}
} }
} }
} }

View file

@ -12,6 +12,7 @@ class GLSprite;
struct GLDecal; struct GLDecal;
class IShadowMap; class IShadowMap;
struct particle_t; struct particle_t;
struct FDynLightData;
//========================================================================== //==========================================================================
// //
@ -140,7 +141,7 @@ public:
void AddOtherFloorPlane(int sector, gl_subsectorrendernode * node); void AddOtherFloorPlane(int sector, gl_subsectorrendernode * node);
void AddOtherCeilingPlane(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); void GetDynSpriteLight(AActor *thing, particle_t *particle, float *out);
virtual void DrawWall(GLWall *wall, int pass) = 0; virtual void DrawWall(GLWall *wall, int pass) = 0;

View file

@ -247,7 +247,7 @@ public:
float fch1, float fch2, float ffh1, float ffh2, float fch1, float fch2, float ffh1, float ffh2,
float bch1, float bch2, float bfh1, float bfh2); 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 ProcessDecals(HWDrawInfo *di);
void CreateVertices(FFlatVertex *&ptr, bool nosplit); void CreateVertices(FFlatVertex *&ptr, bool nosplit);
@ -412,16 +412,19 @@ struct DecalVertex
struct GLDecal struct GLDecal
{ {
FMaterial *gltexture; FMaterial *gltexture;
GLWall *wall; TArray<lightlist_t> *lightlist;
DBaseDecal *decal; DBaseDecal *decal;
DecalVertex dv[4]; DecalVertex dv[4];
float zcenter; float zcenter;
unsigned int vertindex; unsigned int vertindex;
int light; FRenderStyle renderstyle;
int rel; int lightlevel;
float a; int rellight;
FColormap colormap; float alpha;
FColormap Colormap;
secplane_t bottomplane;
FVector3 Normal;
}; };

View file

@ -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; ADynamicLight *light;
float frac, lr, lg, lb; 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; out[0] = out[1] = out[2] = 0.f;
// Go through both light lists // Go through both light lists
FLightNode * node = subsec->lighthead;
while (node) while (node)
{ {
light=node->lightsource; light=node->lightsource;
@ -71,7 +70,7 @@ void HWDrawInfo::GetDynSpriteLight(AActor *self, float x, float y, float z, subs
if (level.Displacements.size > 0) if (level.Displacements.size > 0)
{ {
int fromgroup = light->Sector->PortalGroup; int fromgroup = light->Sector->PortalGroup;
int togroup = subsec->sector->PortalGroup; int togroup = portalgroup;
if (fromgroup == togroup || fromgroup == 0 || togroup == 0) goto direct; if (fromgroup == togroup || fromgroup == 0 || togroup == 0) goto direct;
DVector2 offset = level.Displacements.getOffset(fromgroup, togroup); DVector2 offset = level.Displacements.getOffset(fromgroup, togroup);
@ -132,11 +131,11 @@ void HWDrawInfo::GetDynSpriteLight(AActor *thing, particle_t *particle, float *o
{ {
if (thing != NULL) 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) 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);
} }
} }