Make the light list part of the level mesh

This commit is contained in:
Magnus Norddahl 2024-02-26 15:57:32 +01:00
commit 68f9fee55b
11 changed files with 195 additions and 156 deletions

View file

@ -34,7 +34,6 @@ public:
virtual LevelMeshSurface* GetSurface(int index) { return nullptr; }
virtual unsigned int GetSurfaceIndex(const LevelMeshSurface* surface) const { return 0xffffffff; }
virtual int GetSurfaceCount() { return 0; }
virtual int AddSurfaceLights(const LevelMeshSurface* surface, LevelMeshLight* list, int listMaxSize) { return 0; }
LevelMeshSurface* Trace(const FVector3& start, FVector3 direction, float maxDist);
@ -55,6 +54,10 @@ public:
// Surface info
TArray<SurfaceUniforms> Uniforms;
TArray<FMaterialState> Materials;
TArray<int32_t> LightIndexes;
// Lights
TArray<LevelMeshLight> Lights;
// Index data
TArray<uint32_t> Indexes;
@ -68,6 +71,8 @@ public:
int MaxUniforms = 0;
int MaxSurfaceIndexes = 0;
int MaxNodes = 0;
int MaxLights = 0;
int MaxLightIndexes = 0;
} Mesh;
std::unique_ptr<TriangleMeshShape> Collision;

View file

@ -36,8 +36,7 @@ struct LevelMeshSurface
// Light list location in the lightmapper GPU buffers
struct
{
int Pos = -1;
int Pos = 0;
int Count = 0;
int ResetCounter = -1;
} LightList;
};

View file

@ -55,6 +55,8 @@ void VkLevelMesh::Reset()
deletelist->Add(std::move(UniformsBuffer));
deletelist->Add(std::move(SurfaceIndexBuffer));
deletelist->Add(std::move(PortalBuffer));
deletelist->Add(std::move(LightBuffer));
deletelist->Add(std::move(LightIndexBuffer));
deletelist->Add(std::move(StaticBLAS.ScratchBuffer));
deletelist->Add(std::move(StaticBLAS.AccelStructBuffer));
deletelist->Add(std::move(StaticBLAS.AccelStruct));
@ -173,6 +175,8 @@ void VkLevelMesh::UploadMeshes(bool dynamicOnly)
Locations.UniformIndexes.Push({ 0, (int)Mesh->Mesh.UniformIndexes.Size() });
Locations.Uniforms.Push({ 0, (int)Mesh->Mesh.Uniforms.Size() });
Locations.Portals.Push({ 0, (int)Mesh->Portals.Size() });
Locations.Light.Push({ 0, (int)Mesh->Mesh.Lights.Size() });
Locations.LightIndex.Push({ 0, (int)Mesh->Mesh.LightIndexes.Size() });
}
VkLevelMeshUploader uploader(this);
@ -242,6 +246,18 @@ void VkLevelMesh::CreateBuffers()
.Size(Mesh->Portals.Size() * sizeof(PortalInfo))
.DebugName("PortalBuffer")
.Create(fb->GetDevice());
LightBuffer = BufferBuilder()
.Usage(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT)
.Size(Mesh->Mesh.MaxLights * sizeof(LightInfo))
.DebugName("LightBuffer")
.Create(fb->GetDevice());
LightIndexBuffer = BufferBuilder()
.Usage(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT)
.Size(Mesh->Mesh.MaxLightIndexes * sizeof(int32_t))
.DebugName("LightIndexBuffer")
.Create(fb->GetDevice());
}
VkLevelMesh::BLAS VkLevelMesh::CreateBLAS(bool preferFastBuild, int indexOffset, int indexCount)
@ -455,9 +471,11 @@ void VkLevelMeshUploader::Upload()
UploadRanges(Mesh->Locations.UniformIndexes, Mesh->Mesh->Mesh.UniformIndexes.Data(), Mesh->UniformIndexBuffer.get());
UploadRanges(Mesh->Locations.Index, Mesh->Mesh->Mesh.Indexes.Data(), Mesh->IndexBuffer.get());
UploadRanges(Mesh->Locations.SurfaceIndex, Mesh->Mesh->Mesh.SurfaceIndexes.Data(), Mesh->SurfaceIndexBuffer.get());
UploadRanges(Mesh->Locations.LightIndex, Mesh->Mesh->Mesh.LightIndexes.Data(), Mesh->LightIndexBuffer.get());
UploadSurfaces();
UploadUniforms();
UploadPortals();
UploadLights();
EndTransfer(transferBufferSize);
ClearRanges();
@ -473,6 +491,8 @@ void VkLevelMeshUploader::ClearRanges()
Mesh->Locations.UniformIndexes.clear();
Mesh->Locations.Uniforms.clear();
Mesh->Locations.Portals.clear();
Mesh->Locations.Light.clear();
Mesh->Locations.LightIndex.clear();
}
void VkLevelMeshUploader::BeginTransfer(size_t transferBufferSize)
@ -635,6 +655,33 @@ void VkLevelMeshUploader::UploadPortals()
}
}
void VkLevelMeshUploader::UploadLights()
{
for (const MeshBufferRange& range : Mesh->Locations.Light)
{
LightInfo* lights = (LightInfo*)(data + datapos);
for (int i = 0, count = range.Size; i < count; i++)
{
const auto& light = Mesh->Mesh->Mesh.Lights[range.Offset + i];
LightInfo info;
info.Origin = SwapYZ(light.Origin);
info.RelativeOrigin = SwapYZ(light.RelativeOrigin);
info.Radius = light.Radius;
info.Intensity = light.Intensity;
info.InnerAngleCos = light.InnerAngleCos;
info.OuterAngleCos = light.OuterAngleCos;
info.SpotDir = SwapYZ(light.SpotDir);
info.Color = light.Color;
*(lights++) = info;
}
size_t copysize = range.Size * sizeof(LightInfo);
if (copysize > 0)
cmdbuffer->copyBuffer(transferBuffer.get(), Mesh->LightBuffer.get(), datapos, range.Offset * sizeof(LightInfo), copysize);
datapos += copysize;
}
}
size_t VkLevelMeshUploader::GetTransferSize()
{
// Figure out how much memory we need to transfer it to the GPU
@ -648,5 +695,7 @@ size_t VkLevelMeshUploader::GetTransferSize()
for (const MeshBufferRange& range : Mesh->Locations.Surface) transferBufferSize += range.Size * sizeof(SurfaceInfo);
for (const MeshBufferRange& range : Mesh->Locations.Uniforms) transferBufferSize += range.Size * sizeof(SurfaceUniforms);
for (const MeshBufferRange& range : Mesh->Locations.Portals) transferBufferSize += range.Size * sizeof(PortalInfo);
for (const MeshBufferRange& range : Mesh->Locations.LightIndex) transferBufferSize += range.Size * sizeof(int32_t);
for (const MeshBufferRange& range : Mesh->Locations.Light) transferBufferSize += range.Size * sizeof(LightInfo);
return transferBufferSize;
}

View file

@ -42,6 +42,24 @@ struct PortalInfo
VSMatrix transformation;
};
struct LightInfo
{
FVector3 Origin;
float Padding0;
FVector3 RelativeOrigin;
float Padding1;
float Radius;
float Intensity;
float InnerAngleCos;
float OuterAngleCos;
FVector3 SpotDir;
float Padding2;
FVector3 Color;
float Padding3;
};
static_assert(sizeof(LightInfo) == sizeof(float) * 20);
struct MeshBufferRange
{
int Offset = 0;
@ -65,6 +83,8 @@ public:
VulkanBuffer* GetSurfaceBuffer() { return SurfaceBuffer.get(); }
VulkanBuffer* GetUniformsBuffer() { return UniformsBuffer.get(); }
VulkanBuffer* GetPortalBuffer() { return PortalBuffer.get(); }
VulkanBuffer* GetLightBuffer() { return LightBuffer.get(); }
VulkanBuffer* GetLightIndexBuffer() { return LightIndexBuffer.get(); }
LevelMesh* GetMesh() { return Mesh; }
@ -107,6 +127,8 @@ private:
TArray<MeshBufferRange> UniformIndexes;
TArray<MeshBufferRange> Uniforms;
TArray<MeshBufferRange> Portals;
TArray<MeshBufferRange> Light;
TArray<MeshBufferRange> LightIndex;
} Locations;
std::unique_ptr<VulkanBuffer> VertexBuffer;
@ -116,6 +138,8 @@ private:
std::unique_ptr<VulkanBuffer> SurfaceBuffer;
std::unique_ptr<VulkanBuffer> UniformsBuffer;
std::unique_ptr<VulkanBuffer> PortalBuffer;
std::unique_ptr<VulkanBuffer> LightBuffer;
std::unique_ptr<VulkanBuffer> LightIndexBuffer;
std::unique_ptr<VulkanBuffer> NodeBuffer;
@ -151,6 +175,7 @@ private:
void UploadSurfaces();
void UploadUniforms();
void UploadPortals();
void UploadLights();
template<typename T>
void UploadRanges(const TArray<MeshBufferRange>& ranges, const T* srcbuffer, VulkanBuffer* destbuffer);

View file

@ -38,7 +38,6 @@ VkLightmapper::VkLightmapper(VulkanRenderDevice* fb) : fb(fb)
try
{
CreateUniformBuffer();
CreateLightBuffer();
CreateTileBuffer();
CreateDrawIndexedBuffer();
@ -63,8 +62,6 @@ VkLightmapper::~VkLightmapper()
void VkLightmapper::ReleaseResources()
{
if (lights.Buffer)
lights.Buffer->Unmap();
if (copytiles.Buffer)
copytiles.Buffer->Unmap();
if (drawindexed.CommandsBuffer)
@ -85,8 +82,6 @@ void VkLightmapper::SetLevelMesh(LevelMesh* level)
void VkLightmapper::BeginFrame()
{
lights.Pos = 0;
lights.ResetCounter++;
drawindexed.Pos = 0;
}
@ -200,42 +195,8 @@ void VkLightmapper::Render()
{
LevelMeshSurface* surface = mesh->GetSurface(surfaceIndex);
pc.SurfaceIndex = surfaceIndex;
if (surface->LightList.ResetCounter != 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.
buffersFull = true;
break;
}
surface->LightList.Pos = lights.Pos;
surface->LightList.Count = lightCount;
surface->LightList.ResetCounter = lights.ResetCounter;
LightInfo* lightinfo = &lights.Lights[lights.Pos];
for (int i = 0; i < lightCount; i++)
{
const LevelMeshLight* light = &templightlist[i];
lightinfo->Origin = SwapYZ(light->Origin);
lightinfo->RelativeOrigin = SwapYZ(light->RelativeOrigin);
lightinfo->Radius = light->Radius;
lightinfo->Intensity = light->Intensity;
lightinfo->InnerAngleCos = light->InnerAngleCos;
lightinfo->OuterAngleCos = light->OuterAngleCos;
lightinfo->SpotDir = SwapYZ(light->SpotDir);
lightinfo->Color = light->Color;
lightinfo++;
}
lights.Pos += lightCount;
}
pc.LightStart = surface->LightList.Pos;
pc.LightEnd = pc.LightStart + surface->LightList.Count;
pc.LightEnd = surface->LightList.Pos + surface->LightList.Count;
VkDrawIndexedIndirectCommand cmd;
cmd.indexCount = surface->MeshLocation.NumElements;
@ -680,7 +641,8 @@ void VkLightmapper::CreateRaytracePipeline()
.AddBinding(2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT)
.AddBinding(3, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT)
.AddBinding(4, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT)
.AddBinding(5, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT)
.AddBinding(5, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT)
.AddBinding(6, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT)
.DebugName("raytrace.descriptorSetLayout0")
.Create(fb->GetDevice());
@ -748,7 +710,7 @@ void VkLightmapper::CreateRaytracePipeline()
raytrace.descriptorPool0 = DescriptorPoolBuilder()
.AddPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1)
.AddPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 5)
.AddPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 6)
.MaxSets(1)
.DebugName("raytrace.descriptorPool0")
.Create(fb->GetDevice());
@ -801,9 +763,10 @@ void VkLightmapper::UpdateAccelStructDescriptors()
.AddBuffer(raytrace.descriptorSet0.get(), 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, uniforms.Buffer.get(), 0, sizeof(Uniforms))
.AddBuffer(raytrace.descriptorSet0.get(), 1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetSurfaceIndexBuffer())
.AddBuffer(raytrace.descriptorSet0.get(), 2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetSurfaceBuffer())
.AddBuffer(raytrace.descriptorSet0.get(), 3, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, lights.Buffer.get())
.AddBuffer(raytrace.descriptorSet0.get(), 4, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetPortalBuffer())
.AddBuffer(raytrace.descriptorSet0.get(), 5, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, drawindexed.ConstantsBuffer.get(), 0, drawindexed.BufferSize * sizeof(LightmapRaytracePC))
.AddBuffer(raytrace.descriptorSet0.get(), 3, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetLightBuffer())
.AddBuffer(raytrace.descriptorSet0.get(), 4, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetLightIndexBuffer())
.AddBuffer(raytrace.descriptorSet0.get(), 5, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetPortalBuffer())
.AddBuffer(raytrace.descriptorSet0.get(), 6, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, drawindexed.ConstantsBuffer.get(), 0, drawindexed.BufferSize * sizeof(LightmapRaytracePC))
.Execute(fb->GetDevice());
}
@ -1075,25 +1038,6 @@ void VkLightmapper::CreateUniformBuffer()
.Create(fb->GetDevice());
}
void VkLightmapper::CreateLightBuffer()
{
size_t size = sizeof(LightInfo) * lights.BufferSize;
lights.Buffer = BufferBuilder()
.Usage(
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
VMA_MEMORY_USAGE_UNKNOWN, VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT)
.MemoryType(
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)
.Size(size)
.DebugName("LightmapLightBuffer")
.Create(fb->GetDevice());
lights.Lights = (LightInfo*)lights.Buffer->Map(0, size);
lights.Pos = 0;
}
void VkLightmapper::CreateTileBuffer()
{
size_t size = sizeof(CopyTileInfo) * copytiles.BufferSize;

View file

@ -79,22 +79,6 @@ struct LightmapBakeImage
uint16_t maxY = 0;
};
struct LightInfo
{
FVector3 Origin;
float Padding0;
FVector3 RelativeOrigin;
float Padding1;
float Radius;
float Intensity;
float InnerAngleCos;
float OuterAngleCos;
FVector3 SpotDir;
float Padding2;
FVector3 Color;
float Padding3;
};
struct SelectedTile
{
LightmapTile* Tile = nullptr;
@ -103,8 +87,6 @@ struct SelectedTile
bool Rendered = false;
};
static_assert(sizeof(LightInfo) == sizeof(float) * 20);
struct CopyTileInfo
{
int SrcPosX;
@ -147,7 +129,6 @@ private:
void CreateBlurPipeline();
void CreateCopyPipeline();
void CreateUniformBuffer();
void CreateLightBuffer();
void CreateTileBuffer();
void CreateDrawIndexedBuffer();
void CreateBakeImage();
@ -180,15 +161,6 @@ private:
VkDeviceSize StructStride = sizeof(Uniforms);
} uniforms;
struct
{
const int BufferSize = 2 * 1024 * 1024;
std::unique_ptr<VulkanBuffer> Buffer;
LightInfo* Lights = nullptr;
int Pos = 0;
int ResetCounter = 0;
} lights;
struct
{
const int BufferSize = 100'000;

View file

@ -289,6 +289,13 @@ public:
bool swapped;
bool explicitpitch;
// Locations in the level mesh light list. Ends with index = 0 or all entries used
enum { max_levelmesh_entries = 4 };
struct
{
int index;
int portalgroup;
} levelmesh[max_levelmesh_entries];
};

View file

@ -175,10 +175,101 @@ DoomLevelMesh::DoomLevelMesh(FLevelLocals& doomMap)
Mesh.MaxUniforms = std::max(Mesh.Uniforms.size() * 2, (size_t)10000);
Mesh.MaxSurfaceIndexes = std::max(Mesh.SurfaceIndexes.size() * 2, (size_t)10000);
Mesh.MaxNodes = std::max(Collision->get_nodes().size() * 2, (size_t)10000);
Mesh.MaxLights = 100'000;
Mesh.MaxLightIndexes = 4 * 1024 * 1024;
}
void DoomLevelMesh::CreateLights(FLevelLocals& doomMap)
{
if (Mesh.Lights.Size() != 0)
return;
for (DoomLevelMeshSurface& surface : Surfaces)
{
surface.LightList.Pos = Mesh.LightIndexes.Size();
surface.LightList.Count = 0;
std::pair<FLightNode*, int> nodePortalGroup = GetSurfaceLightNode(&surface);
FLightNode* node = nodePortalGroup.first;
int portalgroup = nodePortalGroup.second;
if (!node)
continue;
int listpos = 0;
while (node)
{
FDynamicLight* light = node->lightsource;
if (light && light->Trace())
{
int lightindex = GetLightIndex(light, portalgroup);
if (lightindex >= 0)
{
Mesh.LightIndexes.Push(lightindex);
surface.LightList.Count++;
}
}
node = node->nextLight;
}
}
}
int DoomLevelMesh::GetLightIndex(FDynamicLight* light, int portalgroup)
{
int index;
for (index = 0; index < FDynamicLight::max_levelmesh_entries && light->levelmesh[index].index != 0; index++)
{
if (light->levelmesh[index].portalgroup == portalgroup)
return light->levelmesh[index].index - 1;
}
if (index == FDynamicLight::max_levelmesh_entries)
return 0;
DVector3 pos = light->PosRelative(portalgroup);
LevelMeshLight meshlight;
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;
int lightindex = Mesh.Lights.Size();
light->levelmesh[index].index = lightindex + 1;
light->levelmesh[index].portalgroup = portalgroup;
Mesh.Lights.Push(meshlight);
return lightindex;
}
void DoomLevelMesh::BeginFrame(FLevelLocals& doomMap)
{
CreateLights(doomMap);
#if 0
static_cast<DoomLevelSubmesh*>(DynamicMesh.get())->Update(doomMap);
if (doomMap.lightmaps)
@ -196,63 +287,6 @@ bool DoomLevelMesh::TraceSky(const FVector3& start, FVector3 direction, float di
return surface && surface->IsSky;
}
int DoomLevelMesh::AddSurfaceLights(const LevelMeshSurface* surface, LevelMeshLight* list, int listMaxSize)
{
std::pair<FLightNode*, int> nodePortalGroup = GetSurfaceLightNode(static_cast<const DoomLevelMeshSurface*>(surface));
FLightNode* node = nodePortalGroup.first;
int portalgroup = nodePortalGroup.second;
if (!node)
return 0;
int listpos = 0;
while (node && listpos < listMaxSize)
{
FDynamicLight* light = node->lightsource;
if (light && light->Trace())
{
DVector3 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;
}
std::pair<FLightNode*, int> DoomLevelMesh::GetSurfaceLightNode(const DoomLevelMeshSurface* doomsurf)
{
FLightNode* node = nullptr;

View file

@ -49,7 +49,6 @@ public:
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(); }
int AddSurfaceLights(const LevelMeshSurface* surface, LevelMeshLight* list, int listMaxSize) override;
void BeginFrame(FLevelLocals& doomMap);
bool TraceSky(const FVector3& start, FVector3 direction, float dist);
@ -65,6 +64,8 @@ public:
TArray<int> sectorPortals[2]; // index is sector+plane, value is index into the portal list
TArray<int> linePortals; // index is linedef, value is index into the portal list
void CreateLights(FLevelLocals& doomMap);
private:
void CreateSurfaces(FLevelLocals& doomMap);
@ -89,6 +90,8 @@ private:
void CreatePortals(FLevelLocals& doomMap);
std::pair<FLightNode*, int> GetSurfaceLightNode(const DoomLevelMeshSurface* doomsurf);
int GetLightIndex(FDynamicLight* light, int portalgroup);
TArray<SideSurfaceRange> Sides;
TArray<FlatSurfaceRange> Flats;
std::map<LightmapTileBinding, int> bindings;

View file

@ -41,7 +41,8 @@ struct LightInfo
layout(set = 0, binding = 1) buffer SurfaceIndexBuffer { uint surfaceIndices[]; };
layout(set = 0, binding = 2) buffer SurfaceBuffer { SurfaceInfo surfaces[]; };
layout(set = 0, binding = 3) buffer LightBuffer { LightInfo lights[]; };
layout(set = 0, binding = 4) buffer PortalBuffer { PortalInfo portals[]; };
layout(set = 0, binding = 4) buffer LightIndexBuffer { int lightIndexes[]; };
layout(set = 0, binding = 5) buffer PortalBuffer { PortalInfo portals[]; };
struct LightmapRaytracePC
{
@ -61,4 +62,4 @@ struct LightmapRaytracePC
float TileHeight;
};
layout(std430, set = 0, binding = 5) buffer ConstantsBuffer { LightmapRaytracePC constants[]; };
layout(std430, set = 0, binding = 6) buffer ConstantsBuffer { LightmapRaytracePC constants[]; };

View file

@ -30,7 +30,7 @@ void main()
for (uint j = LightStart; j < LightEnd; j++)
{
incoming += TraceLight(origin, normal, lights[j], SurfaceIndex);
incoming += TraceLight(origin, normal, lights[lightIndexes[j]], SurfaceIndex);
}
#if defined(USE_AO)