From 20c234b90f20b86f042d17e876d85398c4a1f239 Mon Sep 17 00:00:00 2001 From: Gene Date: Sat, 5 Apr 2025 22:01:31 -0700 Subject: [PATCH 1/5] Scrap dlight lighthead link lists --- src/g_level.cpp | 3 + src/g_levellocals.h | 10 + src/gamedata/r_defs.h | 1 - src/playsim/a_dynlight.cpp | 213 ++++++++---------- src/playsim/a_dynlight.h | 7 + src/r_data/r_sections.cpp | 1 - src/r_data/r_sections.h | 1 - src/rendering/hwrenderer/scene/hw_drawinfo.h | 2 +- .../hwrenderer/scene/hw_drawstructs.h | 2 +- src/rendering/hwrenderer/scene/hw_flats.cpp | 50 ++-- .../hwrenderer/scene/hw_renderhacks.cpp | 31 +-- .../hwrenderer/scene/hw_spritelight.cpp | 167 +++++++------- src/rendering/hwrenderer/scene/hw_walls.cpp | 162 ++++++++----- src/rendering/swrenderer/line/r_walldraw.cpp | 46 +++- .../swrenderer/plane/r_visibleplane.cpp | 43 ++-- .../swrenderer/plane/r_visibleplane.h | 2 +- .../swrenderer/scene/r_opaque_pass.cpp | 8 +- src/rendering/swrenderer/things/r_sprite.cpp | 66 +++--- 18 files changed, 469 insertions(+), 346 deletions(-) diff --git a/src/g_level.cpp b/src/g_level.cpp index 38b6e5feb79..f7c448407a2 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -623,6 +623,9 @@ void G_InitNew (const char *mapname, bool bTitleLevel) primaryLevel->totaltime = 0; primaryLevel->spawnindex = 0; + primaryLevel->lightlists.wall_dlist.clear(); + primaryLevel->lightlists.flat_dlist.clear(); + if (!multiplayer || !deathmatch) { InitPlayerClasses (); diff --git a/src/g_levellocals.h b/src/g_levellocals.h index 2bb55f33237..bbc313f4980 100644 --- a/src/g_levellocals.h +++ b/src/g_levellocals.h @@ -35,6 +35,8 @@ #pragma once +#include + #include "doomdata.h" #include "g_level.h" #include "r_defs.h" @@ -58,6 +60,12 @@ #include "doom_levelmesh.h" #include "p_visualthinker.h" +struct FGlobalDLightLists +{ + std::unordered_map> flat_dlist; + std::unordered_map> wall_dlist; +}; + //============================================================================ // // This is used to mark processed portals for some collection functions. @@ -745,6 +753,8 @@ struct FLevelLocals bool notexturefill; int ImpactDecalCount; + FGlobalDLightLists lightlists; + FDynamicLight *lights; DVisualThinker* VisualThinkerHead = nullptr; diff --git a/src/gamedata/r_defs.h b/src/gamedata/r_defs.h index 663f3aa388d..93531b55528 100644 --- a/src/gamedata/r_defs.h +++ b/src/gamedata/r_defs.h @@ -1268,7 +1268,6 @@ struct side_t int16_t TierLights[3]; // per-tier light levels uint16_t Flags; int UDMFIndex; // needed to access custom UDMF fields which are stored in loading order. - FLightNode * lighthead; // all dynamic lights that may affect this wall LightmapSurface* lightmap; seg_t **segs; // all segs belonging to this sidedef in ascending order. Used for precise rendering int numsegs; diff --git a/src/playsim/a_dynlight.cpp b/src/playsim/a_dynlight.cpp index 79d8fe768be..2548614a953 100644 --- a/src/playsim/a_dynlight.cpp +++ b/src/playsim/a_dynlight.cpp @@ -95,6 +95,7 @@ static FDynamicLight *GetLight(FLevelLocals *Level) ret->mShadowmapIndex = 1024; ret->Level = Level; ret->Pos.X = -10000000; // not a valid coordinate. + if (!ret->touchlists) ret->touchlists = new FDynamicLightTouchLists; return ret; } @@ -249,6 +250,7 @@ void FDynamicLight::Tick() if (!target) { // How did we get here? :? + UnlinkLight(); ReleaseLight(); return; } @@ -416,83 +418,6 @@ void FDynamicLight::UpdateLocation() } } -//============================================================================= -// -// These have been copied from the secnode code and modified for the light links -// -// P_AddSecnode() searches the current list to see if this sector is -// already there. If not, it adds a sector node at the head of the list of -// sectors this object appears in. This is called when creating a list of -// nodes that will get linked in later. Returns a pointer to the new node. -// -//============================================================================= - -FLightNode * AddLightNode(FLightNode ** thread, void * linkto, FDynamicLight * light, FLightNode *& nextnode) -{ - FLightNode * node; - - node = nextnode; - while (node) - { - if (node->targ==linkto) // Already have a node for this sector? - { - node->lightsource = light; // Yes. Setting m_thing says 'keep it'. - return(nextnode); - } - node = node->nextTarget; - } - - // Couldn't find an existing node for this sector. Add one at the head - // of the list. - - node = new FLightNode; - - node->targ = linkto; - node->lightsource = light; - - node->prevTarget = &nextnode; - node->nextTarget = nextnode; - - if (nextnode) nextnode->prevTarget = &node->nextTarget; - - // Add new node at head of sector thread starting at s->touching_thinglist - - node->prevLight = thread; - node->nextLight = *thread; - if (node->nextLight) node->nextLight->prevLight=&node->nextLight; - *thread = node; - return(node); -} - - -//============================================================================= -// -// P_DelSecnode() deletes a sector node from the list of -// sectors this object appears in. Returns a pointer to the next node -// on the linked list, or nullptr. -// -//============================================================================= - -static FLightNode * DeleteLightNode(FLightNode * node) -{ - FLightNode * tn; // next node on thing thread - - if (node) - { - - *node->prevTarget = node->nextTarget; - if (node->nextTarget) node->nextTarget->prevTarget=node->prevTarget; - - *node->prevLight = node->nextLight; - if (node->nextLight) node->nextLight->prevLight=node->prevLight; - - // Return this node to the freelist - tn=node->nextTarget; - delete node; - return(tn); - } - return(nullptr); -} @@ -550,7 +475,38 @@ void FDynamicLight::CollectWithinRadius(const DVector3 &opos, FSection *section, auto pos = collected_ss[i].pos; section = collected_ss[i].sect; - touching_sector = AddLightNode(§ion->lighthead, section, this, touching_sector); + auto updateFlatTList = [&](FSection *sec) + { + touchlists->flat_tlist.try_emplace(sec, sec); + }; + auto updateWallTList = [&](side_t *sidedef) + { + touchlists->wall_tlist.try_emplace(sidedef, sidedef); + }; + + FLightNode * node = new FLightNode; + node->targ = section; + node->lightsource = this; + + auto flatLightList = Level->lightlists.flat_dlist.find(section); + if (flatLightList != Level->lightlists.flat_dlist.end()) + { + auto ret = flatLightList->second.try_emplace(this, node); + if (ret.second) + { + updateFlatTList(section); + } + else + { + delete node; + } + } + else + { + std::unordered_map u = { {this, node} }; + Level->lightlists.flat_dlist.try_emplace(section, u); + updateFlatTList(section); + } auto processSide = [&](side_t *sidedef, const vertex_t *v1, const vertex_t *v2) @@ -562,7 +518,30 @@ void FDynamicLight::CollectWithinRadius(const DVector3 &opos, FSection *section, if ((pos.Y - v1->fY()) * (v2->fX() - v1->fX()) + (v1->fX() - pos.X) * (v2->fY() - v1->fY()) <= 0) { linedef->validcount = ::validcount; - touching_sides = AddLightNode(&sidedef->lighthead, sidedef, this, touching_sides); + + FLightNode * node = new FLightNode; + node->targ = sidedef; + node->lightsource = this; + + auto wallLightList = Level->lightlists.wall_dlist.find(sidedef); + if (wallLightList != Level->lightlists.wall_dlist.end()) + { + auto ret = wallLightList->second.try_emplace(this, node); + if (ret.second) + { + updateWallTList(sidedef); + } + else + { + delete node; + } + } + else + { + std::unordered_map u = { {this, node} }; + Level->lightlists.wall_dlist.try_emplace(sidedef, u); + updateWallTList(sidedef); + } } else if (linedef->sidedef[0] == sidedef && linedef->sidedef[1] == nullptr) { @@ -664,22 +643,6 @@ void FDynamicLight::CollectWithinRadius(const DVector3 &opos, FSection *section, void FDynamicLight::LinkLight() { - // mark the old light nodes - FLightNode * node; - - node = touching_sides; - while (node) - { - node->lightsource = nullptr; - node = node->nextTarget; - } - node = touching_sector; - while (node) - { - node->lightsource = nullptr; - node = node->nextTarget; - } - if (radius>0) { // passing in radius*radius allows us to do a distance check without any calls to sqrt @@ -690,31 +653,6 @@ void FDynamicLight::LinkLight() CollectWithinRadius(Pos, sect, float(radius*radius)); } - - // Now delete any nodes that won't be used. These are the ones where - // m_thing is still nullptr. - - node = touching_sides; - while (node) - { - if (node->lightsource == nullptr) - { - node = DeleteLightNode(node); - } - else - node = node->nextTarget; - } - - node = touching_sector; - while (node) - { - if (node->lightsource == nullptr) - { - node = DeleteLightNode(node); - } - else - node = node->nextTarget; - } } @@ -725,8 +663,39 @@ void FDynamicLight::LinkLight() //========================================================================== void FDynamicLight::UnlinkLight () { - while (touching_sides) touching_sides = DeleteLightNode(touching_sides); - while (touching_sector) touching_sector = DeleteLightNode(touching_sector); + for (auto iter = touchlists->wall_tlist.begin(); iter != touchlists->wall_tlist.end(); iter++) + { + auto sidedef = iter->second; + if (!sidedef) continue; + + auto wallLightList = Level->lightlists.wall_dlist.find(sidedef); + if (wallLightList != Level->lightlists.wall_dlist.end()) + { + auto light = wallLightList->second.find(this); + if (light != wallLightList->second.end()) + { + delete light->second; + wallLightList->second.erase(light); + } + } + } + for (auto iter = touchlists->flat_tlist.begin(); iter != touchlists->flat_tlist.end(); iter++) + { + auto sec = iter->second; + if (!sec) continue; + + auto flatLightList = Level->lightlists.flat_dlist.find(sec); + if (flatLightList != Level->lightlists.flat_dlist.end()) + { + auto light = flatLightList->second.find(this); + if (light != flatLightList->second.end()) + { + delete light->second; + flatLightList->second.erase(light); + } + } + } + delete touchlists; shadowmapped = false; } diff --git a/src/playsim/a_dynlight.h b/src/playsim/a_dynlight.h index 0aee31790f6..9127cfd21c9 100644 --- a/src/playsim/a_dynlight.h +++ b/src/playsim/a_dynlight.h @@ -195,6 +195,12 @@ struct FLightNode }; }; +struct FDynamicLightTouchLists +{ + std::unordered_map flat_tlist; + std::unordered_map wall_tlist; +}; + struct FDynamicLight { friend class FLightDefaults; @@ -286,6 +292,7 @@ struct FDynamicLight bool swapped; bool explicitpitch; + FDynamicLightTouchLists *touchlists; }; diff --git a/src/r_data/r_sections.cpp b/src/r_data/r_sections.cpp index c4149248284..ebed5e3acfd 100644 --- a/src/r_data/r_sections.cpp +++ b/src/r_data/r_sections.cpp @@ -712,7 +712,6 @@ class FSectionCreator dest.sector = &Level->sectors[group.groupedSections[0].section->sectorindex]; dest.mapsection = (short)group.groupedSections[0].section->mapsection; dest.hacked = false; - dest.lighthead = nullptr; dest.validcount = 0; dest.segments.Set(&output.allLines[numsegments], group.segments.Size()); dest.sides.Set(&output.allSides[numsides], group.sideMap.CountUsed()); diff --git a/src/r_data/r_sections.h b/src/r_data/r_sections.h index fd13a80e7a5..d844d2d1827 100644 --- a/src/r_data/r_sections.h +++ b/src/r_data/r_sections.h @@ -113,7 +113,6 @@ struct FSection TArrayView sides; // contains all sidedefs, including the internal ones that do not make up the outer shape. TArrayView subsectors; // contains all subsectors making up this section sector_t *sector; - FLightNode *lighthead; // Light nodes (blended and additive) BoundingRect bounds; int vertexindex; // This is relative to the start of the entire sector's vertex plane data because it needs to be used with different sources. int vertexcount; diff --git a/src/rendering/hwrenderer/scene/hw_drawinfo.h b/src/rendering/hwrenderer/scene/hw_drawinfo.h index e4cbeb98eb9..f134eddd130 100644 --- a/src/rendering/hwrenderer/scene/hw_drawinfo.h +++ b/src/rendering/hwrenderer/scene/hw_drawinfo.h @@ -290,7 +290,7 @@ struct HWDrawInfo void AddOtherFloorPlane(int sector, gl_subsectorrendernode * node); void AddOtherCeilingPlane(int sector, gl_subsectorrendernode * node); - void GetDynSpriteLight(AActor *self, float x, float y, float z, FLightNode *node, int portalgroup, float *out); + void GetDynSpriteLight(AActor *self, float x, float y, float z, FSection *sec, int portalgroup, float *out); void GetDynSpriteLight(AActor *thing, particle_t *particle, float *out); void PreparePlayerSprites(sector_t * viewsector, area_t in_area); diff --git a/src/rendering/hwrenderer/scene/hw_drawstructs.h b/src/rendering/hwrenderer/scene/hw_drawstructs.h index 903806c67de..77d72f7db76 100644 --- a/src/rendering/hwrenderer/scene/hw_drawstructs.h +++ b/src/rendering/hwrenderer/scene/hw_drawstructs.h @@ -333,7 +333,7 @@ class HWFlat int dynlightindex; void CreateSkyboxVertices(FFlatVertex *buffer); - void SetupLights(HWDrawInfo *di, FLightNode *head, FDynLightData &lightdata, int portalgroup); + void SetupLights(HWDrawInfo *di, FDynLightData &lightdata, int portalgroup); void PutFlat(HWDrawInfo *di, bool fog = false); void Process(HWDrawInfo *di, sector_t * model, int whichplane, bool notexture); diff --git a/src/rendering/hwrenderer/scene/hw_flats.cpp b/src/rendering/hwrenderer/scene/hw_flats.cpp index 317ba939969..3839accadf6 100644 --- a/src/rendering/hwrenderer/scene/hw_flats.cpp +++ b/src/rendering/hwrenderer/scene/hw_flats.cpp @@ -148,7 +148,7 @@ void HWFlat::CreateSkyboxVertices(FFlatVertex *vert) // //========================================================================== -void HWFlat::SetupLights(HWDrawInfo *di, FLightNode * node, FDynLightData &lightdata, int portalgroup) +void HWFlat::SetupLights(HWDrawInfo *di, FDynLightData &lightdata, int portalgroup) { Plane p; @@ -158,29 +158,35 @@ void HWFlat::SetupLights(HWDrawInfo *di, FLightNode * node, FDynLightData &light dynlightindex = -1; return; // no lights on additively blended surfaces. } - while (node) - { - FDynamicLight * light = node->lightsource; - if (!light->IsActive() || light->DontLightMap()) - { - node = node->nextLight; - continue; - } - iter_dlightf++; + auto flatLightList = di->Level->lightlists.flat_dlist.find(section); - // we must do the side check here because gl_GetLight needs the correct plane orientation - // which we don't have for Legacy-style 3D-floors - double planeh = plane.plane.ZatPoint(light->Pos); - if ((planehZ() && ceiling) || (planeh>light->Z() && !ceiling)) + if (flatLightList != di->Level->lightlists.flat_dlist.end()) + { + for (auto nodeIterator = flatLightList->second.begin(); nodeIterator != flatLightList->second.end(); nodeIterator++) { - node = node->nextLight; - continue; - } + auto node = nodeIterator->second; + if (!node) continue; + + FDynamicLight * light = node->lightsource; + + if (!light->IsActive() || light->DontLightMap()) + { + continue; + } + iter_dlightf++; + + // we must do the side check here because gl_GetLight needs the correct plane orientation + // which we don't have for Legacy-style 3D-floors + double planeh = plane.plane.ZatPoint(light->Pos); + if ((planehZ() && ceiling) || (planeh>light->Z() && !ceiling)) + { + continue; + } - p.Set(plane.plane.Normal(), plane.plane.fD()); - draw_dlightf += GetLight(lightdata, portalgroup, p, light, false); - node = node->nextLight; + p.Set(plane.plane.Normal(), plane.plane.fD()); + draw_dlightf += GetLight(lightdata, portalgroup, p, light, false); + } } dynlightindex = screen->mLights->UploadLights(lightdata); @@ -196,7 +202,7 @@ void HWFlat::DrawSubsectors(HWDrawInfo *di, FRenderState &state) { if (di->Level->HasDynamicLights && screen->BuffersArePersistent() && !di->isFullbrightScene()) { - SetupLights(di, section->lighthead, lightdata, sector->PortalGroup); + SetupLights(di, lightdata, sector->PortalGroup); } state.SetLightIndex(dynlightindex); @@ -399,7 +405,7 @@ inline void HWFlat::PutFlat(HWDrawInfo *di, bool fog) { if (di->Level->HasDynamicLights && texture != nullptr && !di->isFullbrightScene() && !(hacktype & (SSRF_PLANEHACK|SSRF_FLOODHACK)) ) { - SetupLights(di, section->lighthead, lightdata, sector->PortalGroup); + SetupLights(di, lightdata, sector->PortalGroup); } } di->AddFlat(this, fog); diff --git a/src/rendering/hwrenderer/scene/hw_renderhacks.cpp b/src/rendering/hwrenderer/scene/hw_renderhacks.cpp index 6cb22175240..c4c65fd18ba 100644 --- a/src/rendering/hwrenderer/scene/hw_renderhacks.cpp +++ b/src/rendering/hwrenderer/scene/hw_renderhacks.cpp @@ -115,23 +115,28 @@ int HWDrawInfo::SetupLightsForOtherPlane(subsector_t * sub, FDynLightData &light { Plane p; - FLightNode * node = sub->section->lighthead; - lightdata.Clear(); - while (node) - { - FDynamicLight * light = node->lightsource; - if (!light->IsActive()) + auto flatLightList = Level->lightlists.flat_dlist.find(sub->section); + + if (flatLightList != Level->lightlists.flat_dlist.end()) + { + for (auto nodeIterator = flatLightList->second.begin(); nodeIterator != flatLightList->second.end(); nodeIterator++) { - node = node->nextLight; - continue; - } - iter_dlightf++; + auto node = nodeIterator->second; + if (!node) continue; - p.Set(plane->Normal(), plane->fD()); - draw_dlightf += GetLight(lightdata, sub->sector->PortalGroup, p, light, true); - node = node->nextLight; + FDynamicLight * light = node->lightsource; + + if (!light->IsActive()) + { + continue; + } + iter_dlightf++; + + p.Set(plane->Normal(), plane->fD()); + draw_dlightf += GetLight(lightdata, sub->sector->PortalGroup, p, light, true); + } } return screen->mLights->UploadLights(lightdata); diff --git a/src/rendering/hwrenderer/scene/hw_spritelight.cpp b/src/rendering/hwrenderer/scene/hw_spritelight.cpp index ca67296d7da..a7a92f03316 100644 --- a/src/rendering/hwrenderer/scene/hw_spritelight.cpp +++ b/src/rendering/hwrenderer/scene/hw_spritelight.cpp @@ -107,7 +107,7 @@ LightProbe* FindLightProbe(FLevelLocals* level, float x, float y, float z) // //========================================================================== -void HWDrawInfo::GetDynSpriteLight(AActor *self, float x, float y, float z, FLightNode *node, int portalgroup, float *out) +void HWDrawInfo::GetDynSpriteLight(AActor *self, float x, float y, float z, FSection *sec, int portalgroup, float *out) { FDynamicLight *light; float frac, lr, lg, lb; @@ -124,83 +124,90 @@ void HWDrawInfo::GetDynSpriteLight(AActor *self, float x, float y, float z, FLig } // Go through both light lists - while (node) + auto flatLightList = Level->lightlists.flat_dlist.find(sec); + + if (flatLightList != Level->lightlists.flat_dlist.end()) { - light=node->lightsource; - if (light->ShouldLightActor(self)) + for (auto nodeIterator = flatLightList->second.begin(); nodeIterator != flatLightList->second.end(); nodeIterator++) { - float dist; - FVector3 L; - - // This is a performance critical section of code where we cannot afford to let the compiler decide whether to inline the function or not. - // This will do the calculations explicitly rather than calling one of AActor's utility functions. - if (Level->Displacements.size > 0) - { - int fromgroup = light->Sector->PortalGroup; - int togroup = portalgroup; - if (fromgroup == togroup || fromgroup == 0 || togroup == 0) goto direct; + auto node = nodeIterator->second; + if (!node) continue; - DVector2 offset = Level->Displacements.getOffset(fromgroup, togroup); - L = FVector3(x - (float)(light->X() + offset.X), y - (float)(light->Y() + offset.Y), z - (float)light->Z()); - } - else + light=node->lightsource; + if (light->ShouldLightActor(self)) { - direct: - L = FVector3(x - (float)light->X(), y - (float)light->Y(), z - (float)light->Z()); - } - - dist = (float)L.LengthSquared(); - radius = light->GetRadius(); + float dist; + FVector3 L; - if (dist < radius * radius) - { - dist = sqrtf(dist); // only calculate the square root if we really need it. - - frac = 1.0f - (dist / radius); + // This is a performance critical section of code where we cannot afford to let the compiler decide whether to inline the function or not. + // This will do the calculations explicitly rather than calling one of AActor's utility functions. + if (Level->Displacements.size > 0) + { + int fromgroup = light->Sector->PortalGroup; + int togroup = portalgroup; + if (fromgroup == togroup || fromgroup == 0 || togroup == 0) goto direct; - if (light->IsSpot()) + DVector2 offset = Level->Displacements.getOffset(fromgroup, togroup); + L = FVector3(x - (float)(light->X() + offset.X), y - (float)(light->Y() + offset.Y), z - (float)light->Z()); + } + else { - L *= -1.0f / dist; - DAngle negPitch = -*light->pPitch; - DAngle Angle = light->target->Angles.Yaw; - double xyLen = negPitch.Cos(); - double spotDirX = -Angle.Cos() * xyLen; - double spotDirY = -Angle.Sin() * xyLen; - double spotDirZ = -negPitch.Sin(); - double cosDir = L.X * spotDirX + L.Y * spotDirY + L.Z * spotDirZ; - frac *= (float)smoothstep(light->pSpotOuterAngle->Cos(), light->pSpotInnerAngle->Cos(), cosDir); + direct: + L = FVector3(x - (float)light->X(), y - (float)light->Y(), z - (float)light->Z()); } - if (frac > 0 && (!light->shadowmapped || (light->GetRadius() > 0 && screen->mShadowMap.ShadowTest(light->Pos, { x, y, z })))) + dist = (float)L.LengthSquared(); + radius = light->GetRadius(); + + if (dist < radius * radius) { - lr = light->GetRed() / 255.0f; - lg = light->GetGreen() / 255.0f; - lb = light->GetBlue() / 255.0f; + dist = sqrtf(dist); // only calculate the square root if we really need it. - if (light->target) + frac = 1.0f - (dist / radius); + + if (light->IsSpot()) { - float alpha = (float)light->target->Alpha; - lr *= alpha; - lg *= alpha; - lb *= alpha; + L *= -1.0f / dist; + DAngle negPitch = -*light->pPitch; + DAngle Angle = light->target->Angles.Yaw; + double xyLen = negPitch.Cos(); + double spotDirX = -Angle.Cos() * xyLen; + double spotDirY = -Angle.Sin() * xyLen; + double spotDirZ = -negPitch.Sin(); + double cosDir = L.X * spotDirX + L.Y * spotDirY + L.Z * spotDirZ; + frac *= (float)smoothstep(light->pSpotOuterAngle->Cos(), light->pSpotInnerAngle->Cos(), cosDir); } - if (light->IsSubtractive()) + if (frac > 0 && (!light->shadowmapped || (light->GetRadius() > 0 && screen->mShadowMap.ShadowTest(light->Pos, { x, y, z })))) { - float bright = (float)FVector3(lr, lg, lb).Length(); - FVector3 lightColor(lr, lg, lb); - lr = (bright - lr) * -1; - lg = (bright - lg) * -1; - lb = (bright - lb) * -1; - } + lr = light->GetRed() / 255.0f; + lg = light->GetGreen() / 255.0f; + lb = light->GetBlue() / 255.0f; + + if (light->target) + { + float alpha = (float)light->target->Alpha; + lr *= alpha; + lg *= alpha; + lb *= alpha; + } - out[0] += lr * frac; - out[1] += lg * frac; - out[2] += lb * frac; + if (light->IsSubtractive()) + { + float bright = (float)FVector3(lr, lg, lb).Length(); + FVector3 lightColor(lr, lg, lb); + lr = (bright - lr) * -1; + lg = (bright - lg) * -1; + lb = (bright - lb) * -1; + } + + out[0] += lr * frac; + out[1] += lg * frac; + out[2] += lb * frac; + } } } } - node = node->nextLight; } } @@ -208,11 +215,11 @@ void HWDrawInfo::GetDynSpriteLight(AActor *thing, particle_t *particle, float *o { if (thing != NULL) { - GetDynSpriteLight(thing, (float)thing->X(), (float)thing->Y(), (float)thing->Center(), thing->section->lighthead, thing->Sector->PortalGroup, out); + GetDynSpriteLight(thing, (float)thing->X(), (float)thing->Y(), (float)thing->Center(), thing->section, thing->Sector->PortalGroup, out); } else if (particle != NULL) { - GetDynSpriteLight(NULL, (float)particle->Pos.X, (float)particle->Pos.Y, (float)particle->Pos.Z, particle->subsector->section->lighthead, particle->subsector->sector->PortalGroup, out); + GetDynSpriteLight(NULL, (float)particle->Pos.X, (float)particle->Pos.Y, (float)particle->Pos.Z, particle->subsector->section, particle->subsector->sector->PortalGroup, out); } } @@ -241,29 +248,33 @@ void hw_GetDynModelLight(AActor *self, FDynLightData &modellightdata) { auto section = subsector->section; if (section->validcount == dl_validcount) return; // already done from a previous subsector. - FLightNode * node = section->lighthead; - while (node) // check all lights touching a subsector + auto flatLightList = self->Level->lightlists.flat_dlist.find(subsector->section); + if (flatLightList != self->Level->lightlists.flat_dlist.end()) { - FDynamicLight *light = node->lightsource; - if (light->ShouldLightActor(self)) - { - int group = subsector->sector->PortalGroup; - DVector3 pos = light->PosRelative(group); - float radius = (float)(light->GetRadius() + actorradius); - double dx = pos.X - x; - double dy = pos.Y - y; - double dz = pos.Z - z; - double distSquared = dx * dx + dy * dy + dz * dz; - if (distSquared < radius * radius) // Light and actor touches + for (auto nodeIterator = flatLightList->second.begin(); nodeIterator != flatLightList->second.end(); nodeIterator++) + { // check all lights touching a subsector + auto node = nodeIterator->second; + if (!node) continue; + FDynamicLight *light = node->lightsource; + if (light->ShouldLightActor(self)) { - if (std::find(addedLights.begin(), addedLights.end(), light) == addedLights.end()) // Check if we already added this light from a different subsector + int group = subsector->sector->PortalGroup; + DVector3 pos = light->PosRelative(group); + float radius = (float)(light->GetRadius() + actorradius); + double dx = pos.X - x; + double dy = pos.Y - y; + double dz = pos.Z - z; + double distSquared = dx * dx + dy * dy + dz * dz; + if (distSquared < radius * radius) // Light and actor touches { - AddLightToList(modellightdata, group, light, true); - addedLights.Push(light); + if (std::find(addedLights.begin(), addedLights.end(), light) == addedLights.end()) // Check if we already added this light from a different subsector + { + AddLightToList(modellightdata, group, light, true); + addedLights.Push(light); + } } } } - node = node->nextLight; } }); } diff --git a/src/rendering/hwrenderer/scene/hw_walls.cpp b/src/rendering/hwrenderer/scene/hw_walls.cpp index 527c02c0de2..ea81f1fc77a 100644 --- a/src/rendering/hwrenderer/scene/hw_walls.cpp +++ b/src/rendering/hwrenderer/scene/hw_walls.cpp @@ -424,76 +424,134 @@ void HWWall::SetupLights(HWDrawInfo*di, FDynLightData &lightdata) auto normal = glseg.Normal(); p.Set(normal, -normal.X * glseg.x1 - normal.Z * glseg.y1); - FLightNode *node; - if (seg->sidedef == NULL) - { - node = NULL; - } - else if (!(seg->sidedef->Flags & WALLF_POLYOBJ)) - { - node = seg->sidedef->lighthead; - } - else if (sub) + if ((seg->sidedef->Flags & WALLF_POLYOBJ) && sub) { // Polobject segs cannot be checked per sidedef so use the subsector instead. - node = sub->section->lighthead; - } - else node = NULL; + auto flatLightList = di->Level->lightlists.flat_dlist.find(sub->section); - // Iterate through all dynamic lights which touch this wall and render them - while (node) - { - if (node->lightsource->IsActive() && !node->lightsource->DontLightMap()) + if (flatLightList != di->Level->lightlists.flat_dlist.end()) { - iter_dlight++; - - DVector3 posrel = node->lightsource->PosRelative(seg->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) + for (auto nodeIterator = flatLightList->second.begin(); nodeIterator != flatLightList->second.end(); nodeIterator++) { - FVector3 nearPt, up, right; + auto node = nodeIterator->second; + if (!node) continue; + + if (node->lightsource->IsActive() && !node->lightsource->DontLightMap()) + { + iter_dlight++; + + DVector3 posrel = node->lightsource->PosRelative(seg->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(); + pos = { x, z, y }; + fn = p.Normal(); - fn.GetRightUp(right, up); + fn.GetRightUp(right, up); - FVector3 tmpVec = fn * dist; - nearPt = pos + tmpVec; + FVector3 tmpVec = fn * dist; + nearPt = pos + tmpVec; - FVector3 t1; - int outcnt[4]={0,0,0,0}; - texcoord tcs[4]; + 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; + // 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 (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, seg->frontsector->PortalGroup, p, node->lightsource, true); + } + } } - if (outcnt[0]!=4 && outcnt[1]!=4 && outcnt[2]!=4 && outcnt[3]!=4) + } + } + } + else + { + auto wallLightList = di->Level->lightlists.wall_dlist.find(seg->sidedef); + + if (wallLightList != di->Level->lightlists.wall_dlist.end()) + { + for (auto nodeIterator = wallLightList->second.begin(); nodeIterator != wallLightList->second.end(); nodeIterator++) + { + auto node = nodeIterator->second; + if (!node) continue; + + if (node->lightsource->IsActive() && !node->lightsource->DontLightMap()) { - draw_dlight += GetLight(lightdata, seg->frontsector->PortalGroup, p, node->lightsource, true); + iter_dlight++; + + DVector3 posrel = node->lightsource->PosRelative(seg->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, seg->frontsector->PortalGroup, p, node->lightsource, true); + } + } } } } - node = node->nextLight; } + dynlightindex = screen->mLights->UploadLights(lightdata); } diff --git a/src/rendering/swrenderer/line/r_walldraw.cpp b/src/rendering/swrenderer/line/r_walldraw.cpp index bd7ae48c4a9..d96b6b21eeb 100644 --- a/src/rendering/swrenderer/line/r_walldraw.cpp +++ b/src/rendering/swrenderer/line/r_walldraw.cpp @@ -209,11 +209,55 @@ namespace swrenderer FLightNode* RenderWallPart::GetLightList() { + while (light_list) + { + // Clear out the wall part light list + FLightNode *next = nullptr; + if (light_list->nextLight) next = light_list->nextLight; + delete light_list; + if (next) light_list = next; + } + CameraLight* cameraLight = CameraLight::Instance(); if ((cameraLight->FixedLightLevel() >= 0) || cameraLight->FixedColormap()) return nullptr; // [SP] Don't draw dynlights if invul/lightamp active else if (curline && curline->sidedef) - return curline->sidedef->lighthead; + { + auto Level = curline->Subsector->sector->Level; + auto wallLightList = Level->lightlists.wall_dlist.find(curline->sidedef); + if (wallLightList != Level->lightlists.wall_dlist.end()) + { + for (auto nodeIterator = wallLightList->second.begin(); nodeIterator != wallLightList->second.end(); nodeIterator++) + { + auto node = nodeIterator->second; + if (!node) continue; + + if (node->lightsource->IsActive()) + { + bool found = false; + FLightNode *light_node = light_list; + while (light_node) + { + if (light_node->lightsource == node->lightsource) + { + found = true; + break; + } + light_node = light_node->nextLight; + } + if (!found) + { + FLightNode *newlight = new FLightNode; + newlight->nextLight = light_list; + newlight->lightsource = node->lightsource; + light_list = newlight; + } + } + } + } + + return light_list; + } else return nullptr; } diff --git a/src/rendering/swrenderer/plane/r_visibleplane.cpp b/src/rendering/swrenderer/plane/r_visibleplane.cpp index c8517cac42a..8a0624992ce 100644 --- a/src/rendering/swrenderer/plane/r_visibleplane.cpp +++ b/src/rendering/swrenderer/plane/r_visibleplane.cpp @@ -66,7 +66,7 @@ namespace swrenderer fillshort(top, viewwidth, 0x7fff); } - void VisiblePlane::AddLights(RenderThread *thread, FLightNode *node) + void VisiblePlane::AddLights(RenderThread *thread, FSection *sec) { if (!r_dynlights) return; @@ -75,30 +75,37 @@ namespace swrenderer if (cameraLight->FixedColormap() != NULL || cameraLight->FixedLightLevel() >= 0) return; // [SP] no dynlights if invul or lightamp - while (node) + auto Level = sec->sector->Level; + auto flatLightList = Level->lightlists.flat_dlist.find(sec); + if (flatLightList != Level->lightlists.flat_dlist.end()) { - if (node->lightsource->IsActive() && (height.PointOnSide(node->lightsource->Pos) > 0)) + for (auto nodeIterator = flatLightList->second.begin(); nodeIterator != flatLightList->second.end(); nodeIterator++) { - bool found = false; - VisiblePlaneLight *light_node = lights; - while (light_node) + auto node = nodeIterator->second; + if (!node) continue; + + if (node->lightsource->IsActive() && (height.PointOnSide(node->lightsource->Pos) > 0)) { - if (light_node->lightsource == node->lightsource) + bool found = false; + VisiblePlaneLight *light_node = lights; + while (light_node) { - found = true; - break; + if (light_node->lightsource == node->lightsource) + { + found = true; + break; + } + light_node = light_node->next; + } + if (!found) + { + VisiblePlaneLight *newlight = thread->FrameMemory->NewObject(); + newlight->next = lights; + newlight->lightsource = node->lightsource; + lights = newlight; } - light_node = light_node->next; - } - if (!found) - { - VisiblePlaneLight *newlight = thread->FrameMemory->NewObject(); - newlight->next = lights; - newlight->lightsource = node->lightsource; - lights = newlight; } } - node = node->nextLight; } } diff --git a/src/rendering/swrenderer/plane/r_visibleplane.h b/src/rendering/swrenderer/plane/r_visibleplane.h index fcb5c6786c3..3189a5d67ee 100644 --- a/src/rendering/swrenderer/plane/r_visibleplane.h +++ b/src/rendering/swrenderer/plane/r_visibleplane.h @@ -46,7 +46,7 @@ namespace swrenderer { VisiblePlane(RenderThread *thread); - void AddLights(RenderThread *thread, FLightNode *node); + void AddLights(RenderThread *thread, FSection *sec); void Render(RenderThread *thread, fixed_t alpha, bool additive, bool masked); VisiblePlane *next = nullptr; // Next visplane in hash chain -- killough diff --git a/src/rendering/swrenderer/scene/r_opaque_pass.cpp b/src/rendering/swrenderer/scene/r_opaque_pass.cpp index f9424464417..49904e6bbf2 100644 --- a/src/rendering/swrenderer/scene/r_opaque_pass.cpp +++ b/src/rendering/swrenderer/scene/r_opaque_pass.cpp @@ -561,7 +561,7 @@ namespace swrenderer Fake3DOpaque::Normal, 0); - ceilingplane->AddLights(Thread, sub->section->lighthead); + ceilingplane->AddLights(Thread, sub->section); } int adjusted_floorlightlevel = floorlightlevel; @@ -601,7 +601,7 @@ namespace swrenderer Fake3DOpaque::Normal, 0); - floorplane->AddLights(Thread, sub->section->lighthead); + floorplane->AddLights(Thread, sub->section); } Add3DFloorPlanes(sub, frontsector, basecolormap, foggy, adjusted_ceilinglightlevel, adjusted_floorlightlevel); @@ -738,7 +738,7 @@ namespace swrenderer Fake3DOpaque::FakeFloor, fakeAlpha); - floorplane3d->AddLights(Thread, sub->section->lighthead); + floorplane3d->AddLights(Thread, sub->section); FakeDrawLoop(sub, &tempsec, floorplane3d, nullptr, Fake3DOpaque::FakeFloor); } @@ -806,7 +806,7 @@ namespace swrenderer Fake3DOpaque::FakeCeiling, fakeAlpha); - ceilingplane3d->AddLights(Thread, sub->section->lighthead); + ceilingplane3d->AddLights(Thread, sub->section); FakeDrawLoop(sub, &tempsec, nullptr, ceilingplane3d, Fake3DOpaque::FakeCeiling); } diff --git a/src/rendering/swrenderer/things/r_sprite.cpp b/src/rendering/swrenderer/things/r_sprite.cpp index b05a6744801..513faa6b586 100644 --- a/src/rendering/swrenderer/things/r_sprite.cpp +++ b/src/rendering/swrenderer/things/r_sprite.cpp @@ -208,42 +208,48 @@ namespace swrenderer float lit_red = 0; float lit_green = 0; float lit_blue = 0; - auto node = vis->section->lighthead; - while (node != nullptr) + auto Level = vis->sector->Level; + auto flatLightList = Level->lightlists.flat_dlist.find(vis->section); + if (flatLightList != Level->lightlists.flat_dlist.end()) { - FDynamicLight *light = node->lightsource; - if (light->ShouldLightActor(thing)) + for (auto nodeIterator = flatLightList->second.begin(); nodeIterator != flatLightList->second.end(); nodeIterator++) { - float lx = (float)(light->X() - thing->X()); - float ly = (float)(light->Y() - thing->Y()); - float lz = (float)(light->Z() - thing->Center()); - float LdotL = lx * lx + ly * ly + lz * lz; - float radius = node->lightsource->GetRadius(); - if (radius * radius >= LdotL) + auto node = nodeIterator->second; + if (!node) continue; + + FDynamicLight *light = node->lightsource; + if (light->ShouldLightActor(thing)) { - float distance = sqrt(LdotL); - float attenuation = 1.0f - distance / radius; - if (attenuation > 0.0f) - { - float red = light->GetRed() * (1.0f / 255.0f); - float green = light->GetGreen() * (1.0f / 255.0f); - float blue = light->GetBlue() * (1.0f / 255.0f); - /*if (light->IsSubtractive()) - { - float bright = FVector3(lr, lg, lb).Length(); - FVector3 lightColor(lr, lg, lb); - red = (bright - lr) * -1; - green = (bright - lg) * -1; - blue = (bright - lb) * -1; - }*/ - - lit_red += red * attenuation; - lit_green += green * attenuation; - lit_blue += blue * attenuation; + float lx = (float)(light->X() - thing->X()); + float ly = (float)(light->Y() - thing->Y()); + float lz = (float)(light->Z() - thing->Center()); + float LdotL = lx * lx + ly * ly + lz * lz; + float radius = node->lightsource->GetRadius(); + if (radius * radius >= LdotL) + { + float distance = sqrt(LdotL); + float attenuation = 1.0f - distance / radius; + if (attenuation > 0.0f) + { + float red = light->GetRed() * (1.0f / 255.0f); + float green = light->GetGreen() * (1.0f / 255.0f); + float blue = light->GetBlue() * (1.0f / 255.0f); + /*if (light->IsSubtractive()) + { + float bright = FVector3(lr, lg, lb).Length(); + FVector3 lightColor(lr, lg, lb); + red = (bright - lr) * -1; + green = (bright - lg) * -1; + blue = (bright - lb) * -1; + }*/ + + lit_red += red * attenuation; + lit_green += green * attenuation; + lit_blue += blue * attenuation; + } } } } - node = node->nextLight; } lit_red = clamp(lit_red * 255.0f, 0.0f, 255.0f); lit_green = clamp(lit_green * 255.0f, 0.0f, 255.0f); From 4fb4e1859452c4d9dbec4d9235593d2ac4edea9d Mon Sep 17 00:00:00 2001 From: Gene Date: Sun, 6 Apr 2025 22:05:49 -0700 Subject: [PATCH 2/5] Don't inline AddLightNode --- src/playsim/a_dynlight.cpp | 127 +++++++++++++++++++++---------------- src/playsim/a_dynlight.h | 1 + 2 files changed, 73 insertions(+), 55 deletions(-) diff --git a/src/playsim/a_dynlight.cpp b/src/playsim/a_dynlight.cpp index 2548614a953..2bfcd393dd2 100644 --- a/src/playsim/a_dynlight.cpp +++ b/src/playsim/a_dynlight.cpp @@ -418,6 +418,76 @@ void FDynamicLight::UpdateLocation() } } +//============================================================================= +// +// Attempts to emplace the light node in the unordered_map +// +//============================================================================= + +void FDynamicLight::AddLightNode(FSection *section, side_t *sidedef) +{ + auto updateFlatTList = [&](FSection *sec) + { + touchlists->flat_tlist.try_emplace(sec, sec); + }; + auto updateWallTList = [&](side_t *sidedef) + { + touchlists->wall_tlist.try_emplace(sidedef, sidedef); + }; + + FLightNode * node = new FLightNode; + node->lightsource = this; + + if (section) + { + node->targ = section; + + auto flatLightList = Level->lightlists.flat_dlist.find(section); + if (flatLightList != Level->lightlists.flat_dlist.end()) + { + auto ret = flatLightList->second.try_emplace(this, node); + if (ret.second) + { + updateFlatTList(section); + } + else + { + delete node; + } + } + else + { + std::unordered_map u = { {this, node} }; + Level->lightlists.flat_dlist.try_emplace(section, u); + updateFlatTList(section); + } + } + else if (sidedef) + { + node->targ = sidedef; + + auto wallLightList = Level->lightlists.wall_dlist.find(sidedef); + if (wallLightList != Level->lightlists.wall_dlist.end()) + { + auto ret = wallLightList->second.try_emplace(this, node); + if (ret.second) + { + updateWallTList(sidedef); + } + else + { + delete node; + } + } + else + { + std::unordered_map u = { {this, node} }; + Level->lightlists.wall_dlist.try_emplace(sidedef, u); + updateWallTList(sidedef); + } + } +} + @@ -475,38 +545,7 @@ void FDynamicLight::CollectWithinRadius(const DVector3 &opos, FSection *section, auto pos = collected_ss[i].pos; section = collected_ss[i].sect; - auto updateFlatTList = [&](FSection *sec) - { - touchlists->flat_tlist.try_emplace(sec, sec); - }; - auto updateWallTList = [&](side_t *sidedef) - { - touchlists->wall_tlist.try_emplace(sidedef, sidedef); - }; - - FLightNode * node = new FLightNode; - node->targ = section; - node->lightsource = this; - - auto flatLightList = Level->lightlists.flat_dlist.find(section); - if (flatLightList != Level->lightlists.flat_dlist.end()) - { - auto ret = flatLightList->second.try_emplace(this, node); - if (ret.second) - { - updateFlatTList(section); - } - else - { - delete node; - } - } - else - { - std::unordered_map u = { {this, node} }; - Level->lightlists.flat_dlist.try_emplace(section, u); - updateFlatTList(section); - } + AddLightNode(section, NULL); auto processSide = [&](side_t *sidedef, const vertex_t *v1, const vertex_t *v2) @@ -519,29 +558,7 @@ void FDynamicLight::CollectWithinRadius(const DVector3 &opos, FSection *section, { linedef->validcount = ::validcount; - FLightNode * node = new FLightNode; - node->targ = sidedef; - node->lightsource = this; - - auto wallLightList = Level->lightlists.wall_dlist.find(sidedef); - if (wallLightList != Level->lightlists.wall_dlist.end()) - { - auto ret = wallLightList->second.try_emplace(this, node); - if (ret.second) - { - updateWallTList(sidedef); - } - else - { - delete node; - } - } - else - { - std::unordered_map u = { {this, node} }; - Level->lightlists.wall_dlist.try_emplace(sidedef, u); - updateWallTList(sidedef); - } + AddLightNode(NULL, sidedef); } else if (linedef->sidedef[0] == sidedef && linedef->sidedef[1] == nullptr) { diff --git a/src/playsim/a_dynlight.h b/src/playsim/a_dynlight.h index 9127cfd21c9..a305278c2ac 100644 --- a/src/playsim/a_dynlight.h +++ b/src/playsim/a_dynlight.h @@ -251,6 +251,7 @@ struct FDynamicLight void Tick(); void UpdateLocation(); + void AddLightNode(FSection *section, side_t *sidedef); void LinkLight(); void UnlinkLight(); void ReleaseLight(); From 81165facf2bd8a2939e9da772ac898de4156f82c Mon Sep 17 00:00:00 2001 From: Gene Date: Mon, 7 Apr 2025 00:13:11 -0700 Subject: [PATCH 3/5] Actually null the pointer --- src/playsim/a_dynlight.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/playsim/a_dynlight.cpp b/src/playsim/a_dynlight.cpp index 2bfcd393dd2..4cd278b925c 100644 --- a/src/playsim/a_dynlight.cpp +++ b/src/playsim/a_dynlight.cpp @@ -713,6 +713,7 @@ void FDynamicLight::UnlinkLight () } } delete touchlists; + touchlists = nullptr; shadowmapped = false; } From c5b7123e0e8def39168859f44cecf98f41d28b15 Mon Sep 17 00:00:00 2001 From: Gene Date: Mon, 7 Apr 2025 04:19:53 -0700 Subject: [PATCH 4/5] Use range-based for loops --- src/playsim/a_dynlight.cpp | 8 ++++---- src/rendering/hwrenderer/scene/hw_flats.cpp | 4 ++-- src/rendering/hwrenderer/scene/hw_renderhacks.cpp | 4 ++-- src/rendering/hwrenderer/scene/hw_spritelight.cpp | 8 ++++---- src/rendering/hwrenderer/scene/hw_walls.cpp | 8 ++++---- src/rendering/swrenderer/line/r_walldraw.cpp | 4 ++-- src/rendering/swrenderer/plane/r_visibleplane.cpp | 4 ++-- src/rendering/swrenderer/things/r_sprite.cpp | 4 ++-- 8 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/playsim/a_dynlight.cpp b/src/playsim/a_dynlight.cpp index 4cd278b925c..c82d70688b5 100644 --- a/src/playsim/a_dynlight.cpp +++ b/src/playsim/a_dynlight.cpp @@ -680,9 +680,9 @@ void FDynamicLight::LinkLight() //========================================================================== void FDynamicLight::UnlinkLight () { - for (auto iter = touchlists->wall_tlist.begin(); iter != touchlists->wall_tlist.end(); iter++) + for (const auto& [key, value] : touchlists->wall_tlist) { - auto sidedef = iter->second; + auto sidedef = value; if (!sidedef) continue; auto wallLightList = Level->lightlists.wall_dlist.find(sidedef); @@ -696,9 +696,9 @@ void FDynamicLight::UnlinkLight () } } } - for (auto iter = touchlists->flat_tlist.begin(); iter != touchlists->flat_tlist.end(); iter++) + for (const auto& [key, value] : touchlists->flat_tlist) { - auto sec = iter->second; + auto sec = value; if (!sec) continue; auto flatLightList = Level->lightlists.flat_dlist.find(sec); diff --git a/src/rendering/hwrenderer/scene/hw_flats.cpp b/src/rendering/hwrenderer/scene/hw_flats.cpp index 3839accadf6..5e612446407 100644 --- a/src/rendering/hwrenderer/scene/hw_flats.cpp +++ b/src/rendering/hwrenderer/scene/hw_flats.cpp @@ -163,9 +163,9 @@ void HWFlat::SetupLights(HWDrawInfo *di, FDynLightData &lightdata, int portalgro if (flatLightList != di->Level->lightlists.flat_dlist.end()) { - for (auto nodeIterator = flatLightList->second.begin(); nodeIterator != flatLightList->second.end(); nodeIterator++) + for (const auto& [key, value] : flatLightList->second) { - auto node = nodeIterator->second; + auto node = value; if (!node) continue; FDynamicLight * light = node->lightsource; diff --git a/src/rendering/hwrenderer/scene/hw_renderhacks.cpp b/src/rendering/hwrenderer/scene/hw_renderhacks.cpp index c4c65fd18ba..3ba12a14cb3 100644 --- a/src/rendering/hwrenderer/scene/hw_renderhacks.cpp +++ b/src/rendering/hwrenderer/scene/hw_renderhacks.cpp @@ -121,9 +121,9 @@ int HWDrawInfo::SetupLightsForOtherPlane(subsector_t * sub, FDynLightData &light if (flatLightList != Level->lightlists.flat_dlist.end()) { - for (auto nodeIterator = flatLightList->second.begin(); nodeIterator != flatLightList->second.end(); nodeIterator++) + for (const auto& [key, value] : flatLightList->second) { - auto node = nodeIterator->second; + auto node = value; if (!node) continue; FDynamicLight * light = node->lightsource; diff --git a/src/rendering/hwrenderer/scene/hw_spritelight.cpp b/src/rendering/hwrenderer/scene/hw_spritelight.cpp index a7a92f03316..b204bc3b835 100644 --- a/src/rendering/hwrenderer/scene/hw_spritelight.cpp +++ b/src/rendering/hwrenderer/scene/hw_spritelight.cpp @@ -128,9 +128,9 @@ void HWDrawInfo::GetDynSpriteLight(AActor *self, float x, float y, float z, FSec if (flatLightList != Level->lightlists.flat_dlist.end()) { - for (auto nodeIterator = flatLightList->second.begin(); nodeIterator != flatLightList->second.end(); nodeIterator++) + for (const auto& [key, value] : flatLightList->second) { - auto node = nodeIterator->second; + auto node = value; if (!node) continue; light=node->lightsource; @@ -251,9 +251,9 @@ void hw_GetDynModelLight(AActor *self, FDynLightData &modellightdata) auto flatLightList = self->Level->lightlists.flat_dlist.find(subsector->section); if (flatLightList != self->Level->lightlists.flat_dlist.end()) { - for (auto nodeIterator = flatLightList->second.begin(); nodeIterator != flatLightList->second.end(); nodeIterator++) + for (const auto& [key, value] : flatLightList->second) { // check all lights touching a subsector - auto node = nodeIterator->second; + auto node = value; if (!node) continue; FDynamicLight *light = node->lightsource; if (light->ShouldLightActor(self)) diff --git a/src/rendering/hwrenderer/scene/hw_walls.cpp b/src/rendering/hwrenderer/scene/hw_walls.cpp index ea81f1fc77a..dfcb561be34 100644 --- a/src/rendering/hwrenderer/scene/hw_walls.cpp +++ b/src/rendering/hwrenderer/scene/hw_walls.cpp @@ -431,9 +431,9 @@ void HWWall::SetupLights(HWDrawInfo*di, FDynLightData &lightdata) if (flatLightList != di->Level->lightlists.flat_dlist.end()) { - for (auto nodeIterator = flatLightList->second.begin(); nodeIterator != flatLightList->second.end(); nodeIterator++) + for (const auto& [key, value] : flatLightList->second) { - auto node = nodeIterator->second; + auto node = value; if (!node) continue; if (node->lightsource->IsActive() && !node->lightsource->DontLightMap()) @@ -494,9 +494,9 @@ void HWWall::SetupLights(HWDrawInfo*di, FDynLightData &lightdata) if (wallLightList != di->Level->lightlists.wall_dlist.end()) { - for (auto nodeIterator = wallLightList->second.begin(); nodeIterator != wallLightList->second.end(); nodeIterator++) + for (const auto& [key, value] : wallLightList->second) { - auto node = nodeIterator->second; + auto node = value; if (!node) continue; if (node->lightsource->IsActive() && !node->lightsource->DontLightMap()) diff --git a/src/rendering/swrenderer/line/r_walldraw.cpp b/src/rendering/swrenderer/line/r_walldraw.cpp index d96b6b21eeb..6859db8dd48 100644 --- a/src/rendering/swrenderer/line/r_walldraw.cpp +++ b/src/rendering/swrenderer/line/r_walldraw.cpp @@ -227,9 +227,9 @@ namespace swrenderer auto wallLightList = Level->lightlists.wall_dlist.find(curline->sidedef); if (wallLightList != Level->lightlists.wall_dlist.end()) { - for (auto nodeIterator = wallLightList->second.begin(); nodeIterator != wallLightList->second.end(); nodeIterator++) + for (const auto& [key, value] : wallLightList->second) { - auto node = nodeIterator->second; + auto node = value; if (!node) continue; if (node->lightsource->IsActive()) diff --git a/src/rendering/swrenderer/plane/r_visibleplane.cpp b/src/rendering/swrenderer/plane/r_visibleplane.cpp index 8a0624992ce..c47be2e7213 100644 --- a/src/rendering/swrenderer/plane/r_visibleplane.cpp +++ b/src/rendering/swrenderer/plane/r_visibleplane.cpp @@ -79,9 +79,9 @@ namespace swrenderer auto flatLightList = Level->lightlists.flat_dlist.find(sec); if (flatLightList != Level->lightlists.flat_dlist.end()) { - for (auto nodeIterator = flatLightList->second.begin(); nodeIterator != flatLightList->second.end(); nodeIterator++) + for (const auto& [key, value] : flatLightList->second) { - auto node = nodeIterator->second; + auto node = value; if (!node) continue; if (node->lightsource->IsActive() && (height.PointOnSide(node->lightsource->Pos) > 0)) diff --git a/src/rendering/swrenderer/things/r_sprite.cpp b/src/rendering/swrenderer/things/r_sprite.cpp index 513faa6b586..ca7666a49d5 100644 --- a/src/rendering/swrenderer/things/r_sprite.cpp +++ b/src/rendering/swrenderer/things/r_sprite.cpp @@ -212,9 +212,9 @@ namespace swrenderer auto flatLightList = Level->lightlists.flat_dlist.find(vis->section); if (flatLightList != Level->lightlists.flat_dlist.end()) { - for (auto nodeIterator = flatLightList->second.begin(); nodeIterator != flatLightList->second.end(); nodeIterator++) + for (const auto& [key, value] : flatLightList->second) { - auto node = nodeIterator->second; + auto node = value; if (!node) continue; FDynamicLight *light = node->lightsource; From 7f8bb0cdff7d535ed2be21122de7ebf747cff815 Mon Sep 17 00:00:00 2001 From: Gene Date: Mon, 7 Apr 2025 13:25:14 -0700 Subject: [PATCH 5/5] Only allocate when needed --- src/playsim/a_dynlight.cpp | 39 +++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/src/playsim/a_dynlight.cpp b/src/playsim/a_dynlight.cpp index c82d70688b5..876f47629d3 100644 --- a/src/playsim/a_dynlight.cpp +++ b/src/playsim/a_dynlight.cpp @@ -435,28 +435,27 @@ void FDynamicLight::AddLightNode(FSection *section, side_t *sidedef) touchlists->wall_tlist.try_emplace(sidedef, sidedef); }; - FLightNode * node = new FLightNode; - node->lightsource = this; - if (section) { - node->targ = section; - auto flatLightList = Level->lightlists.flat_dlist.find(section); if (flatLightList != Level->lightlists.flat_dlist.end()) { - auto ret = flatLightList->second.try_emplace(this, node); - if (ret.second) + if (flatLightList->second.find(this) == flatLightList->second.end()) { + FLightNode * node = new FLightNode; + node->lightsource = this; + node->targ = section; + + flatLightList->second.try_emplace(this, node); updateFlatTList(section); } - else - { - delete node; - } } else { + FLightNode * node = new FLightNode; + node->lightsource = this; + node->targ = section; + std::unordered_map u = { {this, node} }; Level->lightlists.flat_dlist.try_emplace(section, u); updateFlatTList(section); @@ -464,23 +463,25 @@ void FDynamicLight::AddLightNode(FSection *section, side_t *sidedef) } else if (sidedef) { - node->targ = sidedef; - auto wallLightList = Level->lightlists.wall_dlist.find(sidedef); if (wallLightList != Level->lightlists.wall_dlist.end()) { - auto ret = wallLightList->second.try_emplace(this, node); - if (ret.second) + if (wallLightList->second.find(this) == wallLightList->second.end()) { + FLightNode * node = new FLightNode; + node->lightsource = this; + node->targ = sidedef; + + wallLightList->second.try_emplace(this, node); updateWallTList(sidedef); } - else - { - delete node; - } } else { + FLightNode * node = new FLightNode; + node->lightsource = this; + node->targ = sidedef; + std::unordered_map u = { {this, node} }; Level->lightlists.wall_dlist.try_emplace(sidedef, u); updateWallTList(sidedef);