From 1e23dcee7c186ed47f87ba0ae4d9c9b118d16086 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Sat, 28 Sep 2024 22:17:17 +0200 Subject: [PATCH] Some initial decal rendering --- src/levelmeshhelper.cpp | 21 ++-- src/levelmeshhelper.h | 25 +++-- src/playsim/a_decals.cpp | 8 +- src/rendering/hwrenderer/doom_levelmesh.cpp | 96 ++++++++++++++++--- src/rendering/hwrenderer/doom_levelmesh.h | 28 ++++-- src/rendering/hwrenderer/scene/hw_decal.cpp | 77 ++++++++++++++- .../hwrenderer/scene/hw_drawinfo.cpp | 11 +++ src/rendering/hwrenderer/scene/hw_drawinfo.h | 2 +- .../hwrenderer/scene/hw_drawlistadd.cpp | 4 +- .../hwrenderer/scene/hw_drawstructs.h | 11 ++- .../hwrenderer/scene/hw_walldispatcher.h | 7 ++ src/rendering/hwrenderer/scene/hw_walls.cpp | 33 ++++--- 12 files changed, 252 insertions(+), 71 deletions(-) diff --git a/src/levelmeshhelper.cpp b/src/levelmeshhelper.cpp index 1b1fdc6eb..d5906094a 100644 --- a/src/levelmeshhelper.cpp +++ b/src/levelmeshhelper.cpp @@ -3,20 +3,21 @@ struct NullLevelMeshUpdater : UpdateLevelMesh { - virtual void FloorHeightChanged(struct sector_t* sector) {}; - virtual void CeilingHeightChanged(struct sector_t* sector) {}; - virtual void MidTex3DHeightChanged(struct sector_t* sector) {}; + void FloorHeightChanged(sector_t* sector) override {} + void CeilingHeightChanged(sector_t* sector) override {} + void MidTex3DHeightChanged(sector_t* sector) override {} - virtual void FloorTextureChanged(struct sector_t* sector) {}; - virtual void CeilingTextureChanged(struct sector_t* sector) {}; + void FloorTextureChanged(sector_t* sector) override {} + void CeilingTextureChanged(sector_t* sector) override {} - virtual void SectorChangedOther(struct sector_t* sector) {}; + void SectorChangedOther(sector_t* sector) override {} - virtual void SideTextureChanged(struct side_t* side, int section) {}; + void SideTextureChanged(side_t* side, int section) override {} + void SideDecalsChanged(side_t* side) override {} - virtual void SectorLightChanged(struct sector_t* sector) {}; - virtual void SectorLightThinkerCreated(struct sector_t* sector, class DLighting* lightthinker) {}; - virtual void SectorLightThinkerDestroyed(struct sector_t* sector, class DLighting* lightthinker) {}; + void SectorLightChanged(sector_t* sector) override {} + void SectorLightThinkerCreated(sector_t* sector, DLighting* lightthinker) override {} + void SectorLightThinkerDestroyed(sector_t* sector, DLighting* lightthinker) override {} }; static NullLevelMeshUpdater nullUpdater; diff --git a/src/levelmeshhelper.h b/src/levelmeshhelper.h index b4e4a7d29..3ba0b2cde 100644 --- a/src/levelmeshhelper.h +++ b/src/levelmeshhelper.h @@ -2,22 +2,27 @@ // level mesh helper // this is a minimal include to keep the other source files a little bit leaner +struct sector_t; +struct side_t; +class DLighting; + struct UpdateLevelMesh { - virtual void FloorHeightChanged(struct sector_t *sector) = 0; - virtual void CeilingHeightChanged(struct sector_t *sector) = 0; - virtual void MidTex3DHeightChanged(struct sector_t *sector) = 0; + virtual void FloorHeightChanged(sector_t *sector) = 0; + virtual void CeilingHeightChanged(sector_t *sector) = 0; + virtual void MidTex3DHeightChanged(sector_t *sector) = 0; - virtual void FloorTextureChanged(struct sector_t *sector) = 0; - virtual void CeilingTextureChanged(struct sector_t *sector) = 0; + virtual void FloorTextureChanged(sector_t *sector) = 0; + virtual void CeilingTextureChanged(sector_t *sector) = 0; - virtual void SectorChangedOther(struct sector_t *sector) = 0; + virtual void SectorChangedOther(sector_t *sector) = 0; - virtual void SideTextureChanged(struct side_t *side, int section) = 0; + virtual void SideTextureChanged(side_t *side, int section) = 0; + virtual void SideDecalsChanged(side_t* side) = 0; - virtual void SectorLightChanged(struct sector_t* sector) = 0; - virtual void SectorLightThinkerCreated(struct sector_t* sector, class DLighting* lightthinker) = 0; - virtual void SectorLightThinkerDestroyed(struct sector_t* sector, class DLighting* lightthinker) = 0; + virtual void SectorLightChanged(sector_t* sector) = 0; + virtual void SectorLightThinkerCreated(sector_t* sector, DLighting* lightthinker) = 0; + virtual void SectorLightThinkerDestroyed(sector_t* sector, DLighting* lightthinker) = 0; }; extern UpdateLevelMesh* LevelMeshUpdater; diff --git a/src/playsim/a_decals.cpp b/src/playsim/a_decals.cpp index 1c0fd4712..e2878e3a5 100644 --- a/src/playsim/a_decals.cpp +++ b/src/playsim/a_decals.cpp @@ -156,7 +156,8 @@ void DBaseDecal::Remove () { if (WallPrev == nullptr) { - if (Side != nullptr) Side->AttachedDecals = WallNext; + if (Side != nullptr) + Side->AttachedDecals = WallNext; } else WallPrev->WallNext = WallNext; @@ -164,6 +165,9 @@ void DBaseDecal::Remove () WallPrev = nullptr; WallNext = nullptr; + + if (Side) + LevelMeshUpdater->SideDecalsChanged(Side); } //---------------------------------------------------------------------------- @@ -262,6 +266,8 @@ FTextureID DBaseDecal::StickToWall (side_t *wall, double x, double y, F3DFloor * else wall->AttachedDecals = this; WallNext = nullptr; + LevelMeshUpdater->SideDecalsChanged(wall); + sector_t *front, *back; line_t *line; diff --git a/src/rendering/hwrenderer/doom_levelmesh.cpp b/src/rendering/hwrenderer/doom_levelmesh.cpp index 67a36829a..c75bb2f1e 100644 --- a/src/rendering/hwrenderer/doom_levelmesh.cpp +++ b/src/rendering/hwrenderer/doom_levelmesh.cpp @@ -318,6 +318,44 @@ void DoomLevelMesh::UpdateWallPortals() } } +void DoomLevelMesh::ProcessDecals(HWDrawInfo* di, FRenderState& state) +{ + for (int sideIndex : level.levelMesh->SideDecals) + { + const auto& side = Sides[sideIndex]; + + Plane p; + if (side.Decals[0].Size() != 0 || side.Decals[1].Size() != 0) + { + if (side.FirstSurface == -1) + continue; + p.Set(Mesh.Surfaces[side.FirstSurface].Plane.XYZ(), Mesh.Surfaces[side.FirstSurface].Plane.W); + } + + for (int onmirror = 0; onmirror < 2; onmirror++) + { + for (const HWDecal& decal : side.Decals[onmirror]) + { + HWDecal* gldecal = di->AddDecal(onmirror == 1); + *gldecal = decal; + + if (di->Level->HasDynamicLights && !di->isFullbrightScene() && decal.texture != nullptr) + { + gldecal->SetupLights(di, state, lightdata, p, level.sides[sideIndex].lighthead); + } + + auto verts = state.AllocVertices(4); + for (int i = 0; i < 4; i++) + { + verts.first[i] = side.DecalVertices[decal.vertindex + i]; + } + gldecal->vertindex = verts.second; + } + } + } +} + + void DoomLevelMesh::CreateLights(FLevelLocals& doomMap) { if (LightsCreated) @@ -525,6 +563,9 @@ void DoomLevelMesh::FreeSide(FLevelLocals& doomMap, unsigned int sideIndex) Sides[sideIndex].Uniforms.Clear(); Sides[sideIndex].WallPortals.Clear(); + Sides[sideIndex].Decals[0].Clear(); + Sides[sideIndex].Decals[1].Clear(); + Sides[sideIndex].DecalVertices.Clear(); } void DoomLevelMesh::FreeFlat(FLevelLocals& doomMap, unsigned int sectorIndex) @@ -553,7 +594,7 @@ void DoomLevelMesh::FreeFlat(FLevelLocals& doomMap, unsigned int sectorIndex) Flats[sectorIndex].Uniforms.Clear(); } -void DoomLevelMesh::FloorHeightChanged(struct sector_t* sector) +void DoomLevelMesh::FloorHeightChanged(sector_t* sector) { UpdateFlat(sector->Index(), SurfaceUpdateType::Full); for (line_t* line : sector->Lines) @@ -565,7 +606,7 @@ void DoomLevelMesh::FloorHeightChanged(struct sector_t* sector) } } -void DoomLevelMesh::CeilingHeightChanged(struct sector_t* sector) +void DoomLevelMesh::CeilingHeightChanged(sector_t* sector) { UpdateFlat(sector->Index(), SurfaceUpdateType::Full); for (line_t* line : sector->Lines) @@ -577,32 +618,37 @@ void DoomLevelMesh::CeilingHeightChanged(struct sector_t* sector) } } -void DoomLevelMesh::MidTex3DHeightChanged(struct sector_t* sector) +void DoomLevelMesh::MidTex3DHeightChanged(sector_t* sector) { // UpdateFlat(sector->Index(), SurfaceUpdateType::Full); } -void DoomLevelMesh::FloorTextureChanged(struct sector_t* sector) +void DoomLevelMesh::FloorTextureChanged(sector_t* sector) { UpdateFlat(sector->Index(), SurfaceUpdateType::Full); } -void DoomLevelMesh::CeilingTextureChanged(struct sector_t* sector) +void DoomLevelMesh::CeilingTextureChanged(sector_t* sector) { UpdateFlat(sector->Index(), SurfaceUpdateType::Full); } -void DoomLevelMesh::SectorChangedOther(struct sector_t* sector) +void DoomLevelMesh::SectorChangedOther(sector_t* sector) { UpdateFlat(sector->Index(), SurfaceUpdateType::Full); } -void DoomLevelMesh::SideTextureChanged(struct side_t* side, int section) +void DoomLevelMesh::SideTextureChanged(side_t* side, int section) { UpdateSide(side->Index(), SurfaceUpdateType::Full); } -void DoomLevelMesh::SectorLightChanged(struct sector_t* sector) +void DoomLevelMesh::SideDecalsChanged(side_t* side) +{ + UpdateSide(side->Index(), SurfaceUpdateType::Full); +} + +void DoomLevelMesh::SectorLightChanged(sector_t* sector) { UpdateFlat(sector->Index(), SurfaceUpdateType::LightsOnly); for (line_t* line : sector->Lines) @@ -614,11 +660,11 @@ void DoomLevelMesh::SectorLightChanged(struct sector_t* sector) } } -void DoomLevelMesh::SectorLightThinkerCreated(struct sector_t* sector, class DLighting* lightthinker) +void DoomLevelMesh::SectorLightThinkerCreated(sector_t* sector, DLighting* lightthinker) { } -void DoomLevelMesh::SectorLightThinkerDestroyed(struct sector_t* sector, class DLighting* lightthinker) +void DoomLevelMesh::SectorLightThinkerDestroyed(sector_t* sector, DLighting* lightthinker) { } @@ -676,6 +722,30 @@ void DoomLevelMesh::CreateSide(FLevelLocals& doomMap, unsigned int sideIndex) wall.sub = sub; wall.Process(&disp, state, seg, front, back); + auto& sideBlock = Sides[sideIndex]; + + // Grab the decals generated + for (int onmirror = 0; onmirror < 2; onmirror++) + { + if (result.decals[onmirror].Size() != 0 && !sideBlock.InSideDecalsList) + { + SideDecals.Push(sideIndex); + sideBlock.InSideDecalsList = true; + } + + for (const HWDecal& decal : result.decals[onmirror]) + { + int oldvertindex = decal.vertindex; + int newvertindex = sideBlock.DecalVertices.Size(); + for (int i = 0; i < 4; i++) + { + sideBlock.DecalVertices.Push(state.mVertices[oldvertindex + i]); + } + sideBlock.Decals[onmirror].Push(decal); + sideBlock.Decals[onmirror].Last().vertindex = newvertindex; + } + } + // Part 1: solid geometry. This is set up so that there are no transparent parts state.SetDepthFunc(DF_LEqual); state.ClearDepthBias(); @@ -684,16 +754,16 @@ void DoomLevelMesh::CreateSide(FLevelLocals& doomMap, unsigned int sideIndex) state.AlphaFunc(Alpha_GEqual, 0.f); CreateWallSurface(side, disp, state, result.list, back ? LevelMeshDrawType::Masked : LevelMeshDrawType::Opaque, true, sideIndex); - if (result.portals.Size() != 0 && !Sides[sideIndex].InSidePortalsList) + if (result.portals.Size() != 0 && !sideBlock.InSidePortalsList) { // Register side having portals SidePortals.Push(sideIndex); - Sides[sideIndex].InSidePortalsList = true; + sideBlock.InSidePortalsList = true; } for (HWWall& portal : result.portals) { - Sides[sideIndex].WallPortals.Push(portal); + sideBlock.WallPortals.Push(portal); } CreateWallSurface(side, disp, state, result.portals, LevelMeshDrawType::Portal, false, sideIndex); diff --git a/src/rendering/hwrenderer/doom_levelmesh.h b/src/rendering/hwrenderer/doom_levelmesh.h index 4aeb89331..4b5b84d92 100644 --- a/src/rendering/hwrenderer/doom_levelmesh.h +++ b/src/rendering/hwrenderer/doom_levelmesh.h @@ -15,6 +15,7 @@ struct FLevelLocals; struct FPolyObj; struct HWWallDispatcher; +struct HWDrawInfo; class DoomLevelMesh; class MeshBuilder; @@ -67,7 +68,10 @@ struct SideSurfaceBlock TArray Geometries; TArray Uniforms; TArray WallPortals; + TArray Decals[2]; + TArray DecalVertices; bool InSidePortalsList = false; + bool InSideDecalsList = false; TArray DrawRanges; SurfaceUpdateType UpdateType = SurfaceUpdateType::None; }; @@ -94,6 +98,9 @@ public: void BuildSectorGroups(const FLevelLocals& doomMap); + void ProcessDecals(HWDrawInfo* drawinfo, FRenderState& state); + + TArray SideDecals; TArray SidePortals; TArray WallPortals; @@ -103,16 +110,17 @@ public: void CreateLights(FLevelLocals& doomMap); - void FloorHeightChanged(struct sector_t* sector) override; - void CeilingHeightChanged(struct sector_t* sector) override; - void MidTex3DHeightChanged(struct sector_t* sector) override; - void FloorTextureChanged(struct sector_t* sector) override; - void CeilingTextureChanged(struct sector_t* sector) override; - void SectorChangedOther(struct sector_t* sector) override; - void SideTextureChanged(struct side_t* side, int section) override; - void SectorLightChanged(struct sector_t* sector) override; - void SectorLightThinkerCreated(struct sector_t* sector, class DLighting* lightthinker) override; - void SectorLightThinkerDestroyed(struct sector_t* sector, class DLighting* lightthinker) override; + void FloorHeightChanged(sector_t* sector) override; + void CeilingHeightChanged(sector_t* sector) override; + void MidTex3DHeightChanged(sector_t* sector) override; + void FloorTextureChanged(sector_t* sector) override; + void CeilingTextureChanged(sector_t* sector) override; + void SectorChangedOther(sector_t* sector) override; + void SideTextureChanged(side_t* side, int section) override; + void SideDecalsChanged(side_t* side) override; + void SectorLightChanged(sector_t* sector) override; + void SectorLightThinkerCreated(sector_t* sector, DLighting* lightthinker) override; + void SectorLightThinkerDestroyed(sector_t* sector, DLighting* lightthinker) override; void Reset(const LevelMeshLimits& limits) override { diff --git a/src/rendering/hwrenderer/scene/hw_decal.cpp b/src/rendering/hwrenderer/scene/hw_decal.cpp index 7813531b8..912db4c7d 100644 --- a/src/rendering/hwrenderer/scene/hw_decal.cpp +++ b/src/rendering/hwrenderer/scene/hw_decal.cpp @@ -39,6 +39,9 @@ #include "flatvertices.h" #include "hw_renderstate.h" #include "texturemanager.h" +#include "hw_walldispatcher.h" +#include "hw_dynlightdata.h" +#include "a_dynlight.h" //========================================================================== // @@ -189,7 +192,7 @@ static float mix(float a, float b, float t) return a * (1.0f - t) + b * t; } -void HWWall::ProcessDecal(HWDrawInfo *di, FRenderState& state, DBaseDecal *decal, const FVector3 &normal) +void HWWall::ProcessDecal(HWWallDispatcher* di, FRenderState& state, DBaseDecal *decal, const FVector3 &normal) { line_t * line = seg->linedef; side_t * side = seg->sidedef; @@ -448,7 +451,7 @@ void HWWall::ProcessDecal(HWDrawInfo *di, FRenderState& state, DBaseDecal *decal // //========================================================================== -void HWWall::ProcessDecals(HWDrawInfo *di, FRenderState& state) +void HWWall::ProcessDecals(HWWallDispatcher* di, FRenderState& state) { if (seg->sidedef != nullptr) { @@ -465,3 +468,73 @@ void HWWall::ProcessDecals(HWDrawInfo *di, FRenderState& state) } } +//========================================================================== + +void HWDecal::SetupLights(HWDrawInfo* di, FRenderState& state, FDynLightData& lightdata, Plane p, FLightNode* node) +{ + lightdata.Clear(); + + // if (RenderStyle == STYLE_Add && !di->Level->lightadditivesurfaces) return; // no lights on additively blended surfaces. + + //float vtx[] = { glseg.x1,zbottom[0],glseg.y1, glseg.x1,ztop[0],glseg.y1, glseg.x2,ztop[1],glseg.y2, glseg.x2,zbottom[1],glseg.y2 }; + //Plane p; + // auto normal = glseg.Normal(); + // p.Set(normal, -normal.X * glseg.x1 - normal.Z * glseg.y1); + + // Iterate through all dynamic lights which touch this wall and render them + while (node) + { + if (node->lightsource->IsActive() && !node->lightsource->DontLightMap()) + { + iter_dlight++; + + DVector3 posrel = node->lightsource->PosRelative(frontsector->PortalGroup); + float x = posrel.X; + float y = posrel.Y; + float z = posrel.Z; + float dist = fabsf(p.DistToPoint(x, z, y)); + float radius = node->lightsource->GetRadius(); + //float scale = 1.0f / ((2.f * radius) - dist); + //FVector3 fn, pos; + + if (radius > 0.f && dist < radius) + { + /* + FVector3 nearPt, up, right; + + pos = { x, z, y }; + fn = p.Normal(); + + fn.GetRightUp(right, up); + + FVector3 tmpVec = fn * dist; + nearPt = pos + tmpVec; + + FVector3 t1; + int outcnt[4] = { 0,0,0,0 }; + texcoord tcs[4]; + + // do a quick check whether the light touches this polygon + for (int i = 0; i < 4; i++) + { + t1 = FVector3(&vtx[i * 3]); + FVector3 nearToVert = t1 - nearPt; + tcs[i].u = ((nearToVert | right) * scale) + 0.5f; + tcs[i].v = ((nearToVert | up) * scale) + 0.5f; + + if (tcs[i].u < 0) outcnt[0]++; + if (tcs[i].u > 1) outcnt[1]++; + if (tcs[i].v < 0) outcnt[2]++; + if (tcs[i].v > 1) outcnt[3]++; + + } + if (outcnt[0] != 4 && outcnt[1] != 4 && outcnt[2] != 4 && outcnt[3] != 4)*/ + { + draw_dlight += GetLight(lightdata, frontsector->PortalGroup, p, node->lightsource, true); + } + } + } + node = node->nextLight; + } + dynlightindex = state.UploadLights(lightdata); +} diff --git a/src/rendering/hwrenderer/scene/hw_drawinfo.cpp b/src/rendering/hwrenderer/scene/hw_drawinfo.cpp index 224cda34b..71543d30d 100644 --- a/src/rendering/hwrenderer/scene/hw_drawinfo.cpp +++ b/src/rendering/hwrenderer/scene/hw_drawinfo.cpp @@ -507,6 +507,17 @@ void HWDrawInfo::CreateScene(bool drawpsprites, FRenderState& state) } } + // Draw Decals + { + level.levelMesh->ProcessDecals(this, state); + state.SetRenderStyle(STYLE_Translucent); + state.SetDepthFunc(DF_LEqual); + DrawDecals(state, Decals[0]); + DrawDecals(state, Decals[1]); // Mirror decals - when should they be drawn? + Decals[0].Clear(); + Decals[1].Clear(); + } + // Draw sprites auto it = level.GetThinkerIterator(); AActor* thing; diff --git a/src/rendering/hwrenderer/scene/hw_drawinfo.h b/src/rendering/hwrenderer/scene/hw_drawinfo.h index 6114ec2b8..bebe4593e 100644 --- a/src/rendering/hwrenderer/scene/hw_drawinfo.h +++ b/src/rendering/hwrenderer/scene/hw_drawinfo.h @@ -327,7 +327,7 @@ public: void AddSubsectorToPortal(FSectorPortalGroup *portal, subsector_t *sub); void AddWall(HWWall *w); - void AddMirrorSurface(HWWall *w, FRenderState& state); + void AddMirrorSurface(HWWallDispatcher* di, HWWall *w, FRenderState& state); void AddFlat(HWFlat *flat, bool fog); void AddSprite(HWSprite *sprite, bool translucent); diff --git a/src/rendering/hwrenderer/scene/hw_drawlistadd.cpp b/src/rendering/hwrenderer/scene/hw_drawlistadd.cpp index a44bc4e35..bb083ff27 100644 --- a/src/rendering/hwrenderer/scene/hw_drawlistadd.cpp +++ b/src/rendering/hwrenderer/scene/hw_drawlistadd.cpp @@ -67,7 +67,7 @@ void HWDrawInfo::AddWall(HWWall *wall) // //========================================================================== -void HWDrawInfo::AddMirrorSurface(HWWall *w, FRenderState& state) +void HWDrawInfo::AddMirrorSurface(HWWallDispatcher* di, HWWall *w, FRenderState& state) { w->type = RENDERWALL_MIRRORSURFACE; auto newwall = drawlists[GLDL_TRANSLUCENTBORDER].NewWall(); @@ -87,7 +87,7 @@ void HWDrawInfo::AddMirrorSurface(HWWall *w, FRenderState& state) { newwall->SetupLights(this, state, lightdata); } - newwall->ProcessDecals(this, state); + newwall->ProcessDecals(di, state); newwall->dynlightindex = -1; // the environment map should not be affected by lights - only the decals. } diff --git a/src/rendering/hwrenderer/scene/hw_drawstructs.h b/src/rendering/hwrenderer/scene/hw_drawstructs.h index 9d62f9242..ea22d0b7e 100644 --- a/src/rendering/hwrenderer/scene/hw_drawstructs.h +++ b/src/rendering/hwrenderer/scene/hw_drawstructs.h @@ -281,8 +281,8 @@ public: float fch1, float fch2, float ffh1, float ffh2, float bch1, float bch2, float bfh1, float bfh2); - void ProcessDecal(HWDrawInfo* di, FRenderState& state, DBaseDecal* decal, const FVector3& normal); - void ProcessDecals(HWDrawInfo* di, FRenderState& state); + void ProcessDecal(HWWallDispatcher* di, FRenderState& state, DBaseDecal* decal, const FVector3& normal); + void ProcessDecals(HWWallDispatcher* di, FRenderState& state); int CreateVertices(FFlatVertex*& ptr, bool nosplit); void SplitLeftEdge(FFlatVertex*& ptr); @@ -427,8 +427,9 @@ public: void DrawSprite(HWDrawInfo *di, FRenderState &state, bool translucent); }; - - +struct FDynLightData; +struct FLightNode; +class FRenderState; struct DecalVertex { @@ -455,7 +456,7 @@ struct HWDecal FVector3 Normal; void DrawDecal(HWDrawInfo *di, FRenderState &state); - + void SetupLights(HWDrawInfo* di, FRenderState& state, FDynLightData& lightdata, Plane p, FLightNode* node); }; diff --git a/src/rendering/hwrenderer/scene/hw_walldispatcher.h b/src/rendering/hwrenderer/scene/hw_walldispatcher.h index 23d934534..1c7717d1b 100644 --- a/src/rendering/hwrenderer/scene/hw_walldispatcher.h +++ b/src/rendering/hwrenderer/scene/hw_walldispatcher.h @@ -14,6 +14,7 @@ struct HWMeshHelper TArray portals; TArray lower; TArray upper; + TArray decals[2]; }; @@ -77,4 +78,10 @@ struct HWWallDispatcher mh->portals.Push(*wal); } + HWDecal* AddDecal(bool onmirror) + { + if (di) return di->AddDecal(onmirror); + mh->decals[onmirror].Reserve(1); + return &mh->decals[onmirror].Last(); + } }; diff --git a/src/rendering/hwrenderer/scene/hw_walls.cpp b/src/rendering/hwrenderer/scene/hw_walls.cpp index 92f04b892..efc385122 100644 --- a/src/rendering/hwrenderer/scene/hw_walls.cpp +++ b/src/rendering/hwrenderer/scene/hw_walls.cpp @@ -524,24 +524,23 @@ void HWWall::PutWall(HWWallDispatcher *di, FRenderState& state, bool translucent { flags &= ~HWF_GLOW; } - - bool solid; - if (passflag[type] == 1) solid = true; - else if (type == RENDERWALL_FFBLOCK) solid = texture && !texture->isMasked(); - else solid = false; - - bool hasDecals = solid && seg->sidedef && seg->sidedef->AttachedDecals; - if (hasDecals) - { - // If we want to use the light infos for the decal we cannot delay the creation until the render pass. - if (ddi->Level->HasDynamicLights && !ddi->isFullbrightScene() && texture != nullptr) - { - SetupLights(ddi, state, lightdata); - } - ProcessDecals(ddi, state); - } } + bool solid; + if (passflag[type] == 1) solid = true; + else if (type == RENDERWALL_FFBLOCK) solid = texture && !texture->isMasked(); + else solid = false; + + bool hasDecals = solid && seg->sidedef && seg->sidedef->AttachedDecals; + if (hasDecals) + { + // If we want to use the light infos for the decal we cannot delay the creation until the render pass. + if (ddi && ddi->Level->HasDynamicLights && !ddi->isFullbrightScene() && texture != nullptr) + { + SetupLights(ddi, state, lightdata); + } + ProcessDecals(di, state); + } di->AddWall(this); @@ -631,7 +630,7 @@ void HWWall::PutPortal(HWWallDispatcher *di, FRenderState& state, int ptype, int if (gl_mirror_envmap) { // draw a reflective layer over the mirror - ddi->AddMirrorSurface(this, state); + ddi->AddMirrorSurface(di, this, state); } break;