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); } }