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

View file

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

View file

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

View file

@ -483,7 +483,6 @@ void VulkanRenderDevice::BeginFrame()
if (levelMesh && levelMesh->GetSurfaceCount() > 0) if (levelMesh && levelMesh->GetSurfaceCount() > 0)
{ {
levelMesh->UpdateLightLists();
GetTextureManager()->CreateLightmap(levelMesh->LMTextureSize, levelMesh->LMTextureCount, std::move(levelMesh->LMTextureData)); GetTextureManager()->CreateLightmap(levelMesh->LMTextureSize, levelMesh->LMTextureCount, std::move(levelMesh->LMTextureData));
GetLightmap()->SetLevelMesh(levelMesh); 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) void DoomLevelMesh::PropagateLight(const LevelMeshLight* light, std::set<LevelMeshPortal, RecursivePortalComparator>& touchedPortals, int lightPropagationRecursiveDepth)
{ {
if (++lightPropagationRecursiveDepth > 32) // TODO is this too much? if (++lightPropagationRecursiveDepth > 32) // TODO is this too much?
@ -495,11 +561,7 @@ void DoomLevelMesh::CreateLightList()
PropagateLight(Lights[i].get(), touchedPortals, 0); PropagateLight(Lights[i].get(), touchedPortals, 0);
} }
} }
#endif
void DoomLevelMesh::UpdateLightLists()
{
CreateLightList(); // full recreation
}
void DoomLevelMesh::BindLightmapSurfacesToGeometry(FLevelLocals& doomMap) void DoomLevelMesh::BindLightmapSurfacesToGeometry(FLevelLocals& doomMap)
{ {

View file

@ -39,13 +39,12 @@ public:
return surface && surface->bSky; 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]; } 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()); } 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(); } int GetSurfaceCount() override { return Surfaces.Size(); }
TArray<DoomLevelMeshSurface> Surfaces; TArray<DoomLevelMeshSurface> Surfaces;
std::vector<std::unique_ptr<LevelMeshLight>> Lights; std::vector<std::unique_ptr<LevelMeshLight>> Lights;
TArray<FVector2> LightmapUvs; TArray<FVector2> LightmapUvs;
@ -72,9 +71,6 @@ private:
void SetSideLightmap(DoomLevelMeshSurface* surface); void SetSideLightmap(DoomLevelMeshSurface* surface);
void SetupLightmapUvs(FLevelLocals& doomMap); 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 IsTopSideSky(sector_t* frontsector, sector_t* backsector, side_t* side);
static bool IsTopSideVisible(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); screen->UpdateLightmaps(VisibleSurfaces);
} }