Retrieve the light list on the fly rather than try to sync it

This commit is contained in:
Magnus Norddahl 2023-09-22 16:35:50 +02:00 committed by Christoph Oelckers
parent 2549b0fa57
commit ad97b5408a
7 changed files with 81 additions and 27 deletions

View file

@ -90,10 +90,8 @@ struct LevelMeshSurface
//
inline uint32_t Area() const { return texWidth * texHeight; }
// Touching light sources
std::vector<const LevelMeshLight*> LightList;
int LightListPos = -1;
int LightListCount = 0;
int LightListResetCounter = -1;
};
@ -209,7 +207,7 @@ public:
virtual unsigned int GetSurfaceIndex(const LevelMeshSurface* surface) const { return 0xffffffff; }
virtual int GetSurfaceCount() { return 0; }
virtual void UpdateLightLists() { }
virtual int AddSurfaceLights(const LevelMeshSurface* surface, LevelMeshLight* list, int listMaxSize) { return 0; }
TArray<LevelMeshSmoothingGroup> SmoothingGroups;
TArray<LevelMeshPortal> Portals;

View file

@ -30,6 +30,8 @@ VkLightmap::VkLightmap(VulkanRenderDevice* fb) : fb(fb)
{
useRayQuery = fb->GetDevice()->PhysicalDevice.Features.RayQuery.rayQuery;
templightlist.Resize(128);
CreateUniformBuffer();
CreateLightBuffer();
CreateTileBuffer();
@ -158,11 +160,11 @@ void VkLightmap::Render()
auto& selectedSurface = selectedSurfaces[i];
LevelMeshSurface* targetSurface = selectedSurface.Surface;
if (targetSurface->LightList.empty() && (targetSurface->plane.XYZ() | mesh->SunDirection) < 0.0f) // No lights, no sun
/*if (targetSurface->LightList.empty() && (targetSurface->plane.XYZ() | mesh->SunDirection) < 0.0f) // No lights, no sun
{
selectedSurface.Rendered = true;
continue;
}
}*/
LightmapRaytracePC pc;
pc.TileX = (float)selectedSurface.X;
@ -193,10 +195,10 @@ void VkLightmap::Render()
// Paint all surfaces visible in the tile
for (LevelMeshSurface* surface : targetSurface->tileSurfaces)
{
int lightCount = (int)surface->LightList.size();
if (surface->LightListResetCounter != lights.ResetCounter)
{
int lightCount = mesh->AddSurfaceLights(surface, templightlist.Data(), (int)templightlist.Size());
if (lights.Pos + lightCount > lights.BufferSize)
{
// Our light buffer is full. Postpone the rest.
@ -205,11 +207,13 @@ void VkLightmap::Render()
}
surface->LightListPos = lights.Pos;
surface->LightListCount = lightCount;
surface->LightListResetCounter = lights.ResetCounter;
LightInfo* lightinfo = &lights.Lights[lights.Pos];
for (const LevelMeshLight* light : surface->LightList)
for (int i = 0; i < lightCount; i++)
{
const LevelMeshLight* light = &templightlist[i];
lightinfo->Origin = light->Origin;
lightinfo->RelativeOrigin = light->RelativeOrigin;
lightinfo->Radius = light->Radius;
@ -225,7 +229,7 @@ void VkLightmap::Render()
}
pc.LightStart = surface->LightListPos;
pc.LightEnd = pc.LightStart + lightCount;
pc.LightEnd = pc.LightStart + surface->LightListCount;
cmdbuffer->pushConstants(raytrace.pipelineLayout.get(), VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(LightmapRaytracePC), &pc);
cmdbuffer->drawIndexed(surface->numElements, 1, surface->startElementIndex, 0, 0);
}

View file

@ -159,6 +159,7 @@ private:
TArray<SelectedSurface> selectedSurfaces;
TArray<TArray<SelectedSurface*>> copylists;
TArray<LevelMeshLight> templightlist;
struct
{

View file

@ -483,7 +483,6 @@ void VulkanRenderDevice::BeginFrame()
if (levelMesh && levelMesh->GetSurfaceCount() > 0)
{
levelMesh->UpdateLightLists();
GetTextureManager()->CreateLightmap(levelMesh->LMTextureSize, levelMesh->LMTextureCount, std::move(levelMesh->LMTextureData));
GetLightmap()->SetLevelMesh(levelMesh);
}

View file

@ -363,6 +363,72 @@ void DoomLevelMesh::CreatePortals()
}
}
int DoomLevelMesh::AddSurfaceLights(const LevelMeshSurface* surface, LevelMeshLight* list, int listMaxSize)
{
const DoomLevelMeshSurface* doomsurf = static_cast<const DoomLevelMeshSurface*>(surface);
FLightNode* node = nullptr;
if (doomsurf->Type == ST_FLOOR || doomsurf->Type == ST_CEILING)
{
node = doomsurf->Subsector->section->lighthead;
}
else if (doomsurf->Type == ST_MIDDLESIDE || doomsurf->Type == ST_UPPERSIDE || doomsurf->Type == ST_LOWERSIDE)
{
node = doomsurf->Side->lighthead;
}
if (!node)
return 0;
int listpos = 0;
while (node && listpos < listMaxSize)
{
FDynamicLight* light = node->lightsource;
if (light && light->Trace())
{
DVector3 pos = light->Pos; //light->PosRelative(portalgroup);
LevelMeshLight& meshlight = list[listpos++];
meshlight.Origin = { (float)pos.X, (float)pos.Y, (float)pos.Z };
meshlight.RelativeOrigin = meshlight.Origin;
meshlight.Radius = (float)light->GetRadius();
meshlight.Intensity = (float)light->target->Alpha;
if (light->IsSpot())
{
meshlight.InnerAngleCos = (float)light->pSpotInnerAngle->Cos();
meshlight.OuterAngleCos = (float)light->pSpotOuterAngle->Cos();
DAngle negPitch = -*light->pPitch;
DAngle Angle = light->target->Angles.Yaw;
double xzLen = negPitch.Cos();
meshlight.SpotDir.X = float(-Angle.Cos() * xzLen);
meshlight.SpotDir.Y = float(-Angle.Sin() * xzLen);
meshlight.SpotDir.Z = float(-negPitch.Sin());
}
else
{
meshlight.InnerAngleCos = -1.0f;
meshlight.OuterAngleCos = -1.0f;
meshlight.SpotDir.X = 0.0f;
meshlight.SpotDir.Y = 0.0f;
meshlight.SpotDir.Z = 0.0f;
}
meshlight.Color.X = light->GetRed() * (1.0f / 255.0f);
meshlight.Color.Y = light->GetGreen() * (1.0f / 255.0f);
meshlight.Color.Z = light->GetBlue() * (1.0f / 255.0f);
if (light->Sector)
meshlight.SectorGroup = sectorGroup[light->Sector->Index()];
else
meshlight.SectorGroup = 0;
}
node = node->nextLight;
}
return listpos;
}
#if 0
void DoomLevelMesh::PropagateLight(const LevelMeshLight* light, std::set<LevelMeshPortal, RecursivePortalComparator>& touchedPortals, int lightPropagationRecursiveDepth)
{
if (++lightPropagationRecursiveDepth > 32) // TODO is this too much?
@ -495,11 +561,7 @@ void DoomLevelMesh::CreateLightList()
PropagateLight(Lights[i].get(), touchedPortals, 0);
}
}
void DoomLevelMesh::UpdateLightLists()
{
CreateLightList(); // full recreation
}
#endif
void DoomLevelMesh::BindLightmapSurfacesToGeometry(FLevelLocals& doomMap)
{

View file

@ -39,13 +39,12 @@ public:
return surface && surface->bSky;
}
void UpdateLightLists() override;
int AddSurfaceLights(const LevelMeshSurface* surface, LevelMeshLight* list, int listMaxSize) override;
LevelMeshSurface* GetSurface(int index) override { return &Surfaces[index]; }
unsigned int GetSurfaceIndex(const LevelMeshSurface* surface) const override { return (unsigned int)(ptrdiff_t)(static_cast<const DoomLevelMeshSurface*>(surface) - Surfaces.Data()); }
int GetSurfaceCount() override { return Surfaces.Size(); }
TArray<DoomLevelMeshSurface> Surfaces;
std::vector<std::unique_ptr<LevelMeshLight>> Lights;
TArray<FVector2> LightmapUvs;
@ -72,9 +71,6 @@ private:
void SetSideLightmap(DoomLevelMeshSurface* surface);
void SetupLightmapUvs(FLevelLocals& doomMap);
void PropagateLight(const LevelMeshLight* light, std::set<LevelMeshPortal, RecursivePortalComparator>& touchedPortals, int lightPropagationRecursiveDepth);
void CreateLightList();
static bool IsTopSideSky(sector_t* frontsector, sector_t* backsector, side_t* side);
static bool IsTopSideVisible(side_t* side);

View file

@ -429,12 +429,6 @@ void HWDrawInfo::UpdateLightmaps()
}
}
}
if (lm_always_update) // To do: this is stupid, but it lets us see the move for now!
{
//level.levelMesh->UpdateLightLists();
}
screen->UpdateLightmaps(VisibleSurfaces);
}