Fix deactivated lightmap light not working

This commit is contained in:
Magnus Norddahl 2025-05-11 17:57:44 +02:00
commit bfb37a89c3
7 changed files with 61 additions and 4 deletions

View file

@ -227,7 +227,7 @@ public:
// Lightmap tiles and their locations in the texture atlas
struct
{
int TextureCount = 0;
int TextureCount = 10; // To do: remove all the limits and instead resize GPU resources if they are exhausted. Too difficult to calculate it all up front.
int TextureSize = 1024;
TArray<uint16_t> TextureData;
uint16_t SampleDistance = 8;

View file

@ -26,6 +26,14 @@ struct LightmapTileBinding
}
};
enum TileUpdatePolicy
{
MapChanges,
AlwaysUltraQuality,
Always,
MapChangesUltraQuality
};
struct LightmapTile
{
// Surface location in lightmap texture

View file

@ -88,6 +88,16 @@ void UpdateLevelMesh::SectorLightThinkerDestroyed(sector_t* sector, DLighting* l
PropagateCorrelations(this, &UpdateLevelMesh::OnSectorLightThinkerDestroyed, sector, lightthinker);
}
void UpdateLevelMesh::SectorLightListChanged(sector_t* sector)
{
OnSectorLightListChanged(sector);
}
void UpdateLevelMesh::SideLightListChanged(side_t* side)
{
OnSideLightListChanged(side);
}
struct NullLevelMeshUpdater : UpdateLevelMesh
{
void OnFloorHeightChanged(sector_t* sector) override {}
@ -105,6 +115,9 @@ struct NullLevelMeshUpdater : UpdateLevelMesh
void OnSectorLightChanged(sector_t* sector) override {}
void OnSectorLightThinkerCreated(sector_t* sector, DLighting* lightthinker) override {}
void OnSectorLightThinkerDestroyed(sector_t* sector, DLighting* lightthinker) override {}
void OnSectorLightListChanged(sector_t* sector) override {}
void OnSideLightListChanged(side_t* side) override {}
};
static NullLevelMeshUpdater nullUpdater;

View file

@ -24,7 +24,10 @@ struct UpdateLevelMesh
void SectorLightChanged(sector_t* sector);
void SectorLightThinkerCreated(sector_t* sector, DLighting* lightthinker);
void SectorLightThinkerDestroyed(sector_t* sector, DLighting* lightthinker);
void SectorLightListChanged(sector_t* sector);
void SideLightListChanged(side_t* side);
//raw
virtual void OnFloorHeightChanged(sector_t *sector) = 0;
virtual void OnCeilingHeightChanged(sector_t *sector) = 0;
@ -41,6 +44,9 @@ struct UpdateLevelMesh
virtual void OnSectorLightChanged(sector_t* sector) = 0;
virtual void OnSectorLightThinkerCreated(sector_t* sector, DLighting* lightthinker) = 0;
virtual void OnSectorLightThinkerDestroyed(sector_t* sector, DLighting* lightthinker) = 0;
virtual void OnSectorLightListChanged(sector_t* sector) = 0;
virtual void OnSideLightListChanged(side_t* side) = 0;
};
extern UpdateLevelMesh* LevelMeshUpdater;

View file

@ -95,6 +95,7 @@ static void MarkTilesForUpdate(FLevelLocals * Level, FLightNode * touching_sides
{
while(touching_sides)
{
LevelMeshUpdater->SideLightListChanged(touching_sides->targLine);
MarkTilesForUpdate(Level, touching_sides->targLine->LightmapTiles);
touching_sides = touching_sides->nextTarget;
@ -102,6 +103,7 @@ static void MarkTilesForUpdate(FLevelLocals * Level, FLightNode * touching_sides
while(touching_sector)
{
LevelMeshUpdater->SectorLightListChanged(touching_sector->targSection->sector);
for(subsector_t * ss : touching_sector->targSection->subsectors)
{
MarkTilesForUpdate(Level, ss->LightmapTiles[0]);

View file

@ -706,22 +706,48 @@ void DoomLevelMesh::OnSectorLightThinkerDestroyed(sector_t* sector, DLighting* l
{
}
void DoomLevelMesh::OnSectorLightListChanged(sector_t* sector)
{
// To do: we don't have to recreate the entire surface. Updating just the light list would do.
UpdateFlat(sector->Index(), SurfaceUpdateType::Full);
}
void DoomLevelMesh::OnSideLightListChanged(side_t* side)
{
// To do: we don't have to recreate the entire surface. Updating just the light list would do.
UpdateSide(side->Index(), SurfaceUpdateType::Full);
}
void DoomLevelMesh::UpdateSide(unsigned int sideIndex, SurfaceUpdateType updateType)
{
if (Sides[sideIndex].UpdateType == SurfaceUpdateType::None)
SurfaceUpdateType value = Sides[sideIndex].UpdateType;
if (value == SurfaceUpdateType::None)
{
// First update request
SideUpdateList.Push(sideIndex);
Sides[sideIndex].UpdateType = updateType;
}
else if (value != updateType)
{
// Upgrade to full update if we get multiple upgrade requests of different types
Sides[sideIndex].UpdateType = SurfaceUpdateType::Full;
}
}
void DoomLevelMesh::UpdateFlat(unsigned int sectorIndex, SurfaceUpdateType updateType)
{
if (Flats[sectorIndex].UpdateType == SurfaceUpdateType::None)
SurfaceUpdateType value = Flats[sectorIndex].UpdateType;
if (value == SurfaceUpdateType::None)
{
// First update request
FlatUpdateList.Push(sectorIndex);
Flats[sectorIndex].UpdateType = updateType;
}
else if (value != updateType)
{
// Upgrade to full update if we get multiple upgrade requests of different types
Flats[sectorIndex].UpdateType = SurfaceUpdateType::Full;
}
}
LightListAllocInfo DoomLevelMesh::CreateLightList(FLightNode* node, int portalgroup)

View file

@ -125,6 +125,8 @@ public:
void OnSectorLightChanged(sector_t* sector) override;
void OnSectorLightThinkerCreated(sector_t* sector, DLighting* lightthinker) override;
void OnSectorLightThinkerDestroyed(sector_t* sector, DLighting* lightthinker) override;
void OnSectorLightListChanged(sector_t* sector) override;
void OnSideLightListChanged(side_t* side) override;
void Reset(const LevelMeshLimits& limits) override
{