remove linked lists entirely from lights

This commit is contained in:
Ricardo Luís Vaz Silva 2025-08-07 18:32:38 -03:00
commit 773c534896
10 changed files with 53 additions and 119 deletions

View file

@ -405,7 +405,7 @@ public:
// exact = false returns the closest match, to be used for, ex., insertions, exact = true returns Size() when no match, like Find does
unsigned int SortedFind(const T& item, bool exact = true) const
{
unsigned int index = (std::lower_bound(begin(), end(), item) - begin());
unsigned int index = (unsigned int)(std::lower_bound(begin(), end(), item) - begin());
if(exact)
{
return (index < Count && Array[index] == item) ? index : Count;

View file

@ -76,31 +76,12 @@ CCMD(listlights)
if (dl->target)
{
FTextureID spr = sprites[dl->target->sprite].GetSpriteFrame(dl->target->frame, 0, nullAngle, nullptr);
Printf(", frame = %s ", TexMan.GetGameTexture(spr)->GetName().GetChars());
Printf(", frame = %s\n", TexMan.GetGameTexture(spr)->GetName().GetChars());
}
FLightNode * node;
node=dl->touching_sides;
while (node)
{
walls++;
allwalls++;
node = node->nextTarget;
}
node = dl->touching_sector;
while (node)
{
allsectors++;
sectors++;
node = node->nextTarget;
}
/*
Printf("- %d walls, %d sectors\n", walls, sectors);
*/
}
Printf("%i dynamic lights, %d shadowmapped, %d walls, %d sectors\n\n\n", i, shadowcount, allwalls, allsectors);

View file

@ -61,6 +61,7 @@
struct FGlobalDLightLists
{
//TODO add TSet and switch from TMap to TSet
TArray<TMap<FDynamicLight*, std::unique_ptr<FLightNode>>> flat_dlist;
TArray<TMap<FDynamicLight*, std::unique_ptr<FLightNode>>> wall_dlist;
};

View file

@ -447,7 +447,6 @@ void FDynamicLight::AddLightNode(FSection *section, side_t *sidedef)
{
FLightNode * node = new FLightNode;
node->lightsource = this;
node->targ = section;
flatLightList.TryEmplace(this, node);
touchlists.flat_tlist.SortedAddUnique(section);
@ -466,7 +465,6 @@ void FDynamicLight::AddLightNode(FSection *section, side_t *sidedef)
{
FLightNode * node = new FLightNode;
node->lightsource = this;
node->targ = sidedef;
wallLightList.TryEmplace(this, node);
touchlists.wall_tlist.SortedAddUnique(sidedef);

View file

@ -184,17 +184,7 @@ protected:
struct FLightNode
{
FLightNode ** prevTarget;
FLightNode * nextTarget;
FLightNode ** prevLight;
FLightNode * nextLight;
FDynamicLight * lightsource;
union
{
side_t * targLine;
subsector_t * targSubsector;
void * targ;
};
};
struct FDynamicLightTouchLists
@ -281,8 +271,7 @@ public:
sector_t *Sector;
FLevelLocals *Level;
TObjPtr<AActor *> target;
FLightNode * touching_sides;
FLightNode * touching_sector;
float radius; // The maximum size the light can be with its current settings.
float m_currentRadius; // The current light size.
int m_tickCount;

View file

@ -241,46 +241,48 @@ namespace swrenderer
drawerargs.dc_num_lights = 0;
// Setup lights for column
FLightNode* cur_node = drawerargs.LightList();
while (cur_node)
if(drawerargs.LightList())
{
if (cur_node->lightsource->IsActive())
TMap<FDynamicLight *, std::unique_ptr<FLightNode>>::Iterator it(*drawerargs.LightList());
TMap<FDynamicLight *, std::unique_ptr<FLightNode>>::Pair *pair;
while (it.NextPair(pair))
{
double lightX = cur_node->lightsource->X() - wallargs.ViewpointPos.X;
double lightY = cur_node->lightsource->Y() - wallargs.ViewpointPos.Y;
double lightZ = cur_node->lightsource->Z() - wallargs.ViewpointPos.Z;
float lx = (float)(lightX * wallargs.Sin - lightY * wallargs.Cos) - drawerargs.dc_viewpos.X;
float ly = (float)(lightX * wallargs.TanCos + lightY * wallargs.TanSin) - drawerargs.dc_viewpos.Y;
float lz = (float)lightZ;
// Precalculate the constant part of the dot here so the drawer doesn't have to.
bool is_point_light = cur_node->lightsource->IsAttenuated();
float lconstant = lx * lx + ly * ly;
float nlconstant = is_point_light ? lx * drawerargs.dc_normal.X + ly * drawerargs.dc_normal.Y : 0.0f;
// Include light only if it touches this column
float radius = cur_node->lightsource->GetRadius();
if (radius * radius >= lconstant && nlconstant >= 0.0f)
auto cur_node = pair->Value.get();
if (cur_node->lightsource->IsActive())
{
uint32_t red = cur_node->lightsource->GetRed();
uint32_t green = cur_node->lightsource->GetGreen();
uint32_t blue = cur_node->lightsource->GetBlue();
double lightX = cur_node->lightsource->X() - wallargs.ViewpointPos.X;
double lightY = cur_node->lightsource->Y() - wallargs.ViewpointPos.Y;
double lightZ = cur_node->lightsource->Z() - wallargs.ViewpointPos.Z;
auto& light = drawerargs.dc_lights[drawerargs.dc_num_lights++];
light.x = lconstant;
light.y = nlconstant;
light.z = lz;
light.radius = 256.0f / cur_node->lightsource->GetRadius();
light.color = (red << 16) | (green << 8) | blue;
float lx = (float)(lightX * wallargs.Sin - lightY * wallargs.Cos) - drawerargs.dc_viewpos.X;
float ly = (float)(lightX * wallargs.TanCos + lightY * wallargs.TanSin) - drawerargs.dc_viewpos.Y;
float lz = (float)lightZ;
if (drawerargs.dc_num_lights == WallColumnDrawerArgs::MAX_DRAWER_LIGHTS)
break;
// Precalculate the constant part of the dot here so the drawer doesn't have to.
bool is_point_light = cur_node->lightsource->IsAttenuated();
float lconstant = lx * lx + ly * ly;
float nlconstant = is_point_light ? lx * drawerargs.dc_normal.X + ly * drawerargs.dc_normal.Y : 0.0f;
// Include light only if it touches this column
float radius = cur_node->lightsource->GetRadius();
if (radius * radius >= lconstant && nlconstant >= 0.0f)
{
uint32_t red = cur_node->lightsource->GetRed();
uint32_t green = cur_node->lightsource->GetGreen();
uint32_t blue = cur_node->lightsource->GetBlue();
auto& light = drawerargs.dc_lights[drawerargs.dc_num_lights++];
light.x = lconstant;
light.y = nlconstant;
light.z = lz;
light.radius = 256.0f / cur_node->lightsource->GetRadius();
light.color = (red << 16) | (green << 8) | blue;
if (drawerargs.dc_num_lights == WallColumnDrawerArgs::MAX_DRAWER_LIGHTS)
break;
}
}
}
cur_node = cur_node->nextLight;
}
}

View file

@ -86,7 +86,7 @@ namespace swrenderer
ShadeConstants ColormapConstants() const { return wallargs->ColormapConstants(); }
fixed_t Light() const { return LIGHTSCALE(mLight, mShade); }
FLightNode* LightList() const { return wallargs->lightlist; }
TMap<FDynamicLight*, std::unique_ptr<FLightNode>>* LightList() const { return wallargs->lightlist; }
const WallDrawerArgs* wallargs;

View file

@ -207,60 +207,23 @@ namespace swrenderer
drawerargs.DrawWall(Thread);
}
FLightNode* RenderWallPart::GetLightList()
TMap<FDynamicLight*, std::unique_ptr<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)
{
auto Level = curline->Subsector->sector->Level;
if (Level->lightlists.wall_dlist.SSize() > curline->sidedef->Index())
{
TMap<FDynamicLight *, std::unique_ptr<FLightNode>>::Iterator it(Level->lightlists.wall_dlist[curline->sidedef->Index()]);
TMap<FDynamicLight *, std::unique_ptr<FLightNode>>::Pair *pair;
while (it.NextPair(pair))
{
auto node = pair->Value.get();
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 &Level->lightlists.wall_dlist[curline->sidedef->Index()];
}
return light_list;
}
else
return nullptr;
return nullptr;
}
}

View file

@ -62,7 +62,7 @@ namespace swrenderer
private:
void ProcessStripedWall(const short *uwal, const short *dwal, const ProjectedWallTexcoords& texcoords);
void ProcessNormalWall(const short *uwal, const short *dwal, const ProjectedWallTexcoords& texcoords);
FLightNode* GetLightList();
TMap<FDynamicLight*, std::unique_ptr<FLightNode>>* GetLightList();
RenderThread* Thread = nullptr;
@ -76,7 +76,7 @@ namespace swrenderer
ProjectedWallLight mLight;
FLightNode *light_list = nullptr;
TMap<FDynamicLight*, std::unique_ptr<FLightNode>> *light_list = nullptr;
bool mask = false;
bool additive = false;
fixed_t alpha = 0;

View file

@ -31,7 +31,7 @@ namespace swrenderer
short* dwal;
FWallCoords WallC;
ProjectedWallTexcoords texcoords;
FLightNode* lightlist = nullptr;
TMap<FDynamicLight*, std::unique_ptr<FLightNode>>* lightlist = nullptr;
float lightpos;
float lightstep;