From 68f9fee55b8f0bfcda6c32b6804fb58fca18f55d Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Mon, 26 Feb 2024 15:57:32 +0100 Subject: [PATCH] Make the light list part of the level mesh --- .../rendering/hwrenderer/data/hw_levelmesh.h | 7 +- .../hwrenderer/data/hw_levelmeshsurface.h | 3 +- src/common/rendering/vulkan/vk_levelmesh.cpp | 49 ++++++ src/common/rendering/vulkan/vk_levelmesh.h | 25 +++ .../rendering/vulkan/vk_lightmapper.cpp | 72 +-------- src/common/rendering/vulkan/vk_lightmapper.h | 28 ---- src/playsim/a_dynlight.h | 7 + src/rendering/hwrenderer/doom_levelmesh.cpp | 148 +++++++++++------- src/rendering/hwrenderer/doom_levelmesh.h | 5 +- .../shaders/lightmap/binding_lightmapper.glsl | 5 +- .../shaders/lightmap/frag_raytrace.glsl | 2 +- 11 files changed, 195 insertions(+), 156 deletions(-) diff --git a/src/common/rendering/hwrenderer/data/hw_levelmesh.h b/src/common/rendering/hwrenderer/data/hw_levelmesh.h index 994405f31..ef3987f09 100644 --- a/src/common/rendering/hwrenderer/data/hw_levelmesh.h +++ b/src/common/rendering/hwrenderer/data/hw_levelmesh.h @@ -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 Uniforms; TArray Materials; + TArray LightIndexes; + + // Lights + TArray Lights; // Index data TArray 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 Collision; diff --git a/src/common/rendering/hwrenderer/data/hw_levelmeshsurface.h b/src/common/rendering/hwrenderer/data/hw_levelmeshsurface.h index c933a6647..5dae14107 100644 --- a/src/common/rendering/hwrenderer/data/hw_levelmeshsurface.h +++ b/src/common/rendering/hwrenderer/data/hw_levelmeshsurface.h @@ -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; }; diff --git a/src/common/rendering/vulkan/vk_levelmesh.cpp b/src/common/rendering/vulkan/vk_levelmesh.cpp index 59f81d7f6..c79fcf338 100644 --- a/src/common/rendering/vulkan/vk_levelmesh.cpp +++ b/src/common/rendering/vulkan/vk_levelmesh.cpp @@ -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; } diff --git a/src/common/rendering/vulkan/vk_levelmesh.h b/src/common/rendering/vulkan/vk_levelmesh.h index 873d4ce04..84e2302ca 100644 --- a/src/common/rendering/vulkan/vk_levelmesh.h +++ b/src/common/rendering/vulkan/vk_levelmesh.h @@ -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 UniformIndexes; TArray Uniforms; TArray Portals; + TArray Light; + TArray LightIndex; } Locations; std::unique_ptr VertexBuffer; @@ -116,6 +138,8 @@ private: std::unique_ptr SurfaceBuffer; std::unique_ptr UniformsBuffer; std::unique_ptr PortalBuffer; + std::unique_ptr LightBuffer; + std::unique_ptr LightIndexBuffer; std::unique_ptr NodeBuffer; @@ -151,6 +175,7 @@ private: void UploadSurfaces(); void UploadUniforms(); void UploadPortals(); + void UploadLights(); template void UploadRanges(const TArray& ranges, const T* srcbuffer, VulkanBuffer* destbuffer); diff --git a/src/common/rendering/vulkan/vk_lightmapper.cpp b/src/common/rendering/vulkan/vk_lightmapper.cpp index ed90fa130..068bec389 100644 --- a/src/common/rendering/vulkan/vk_lightmapper.cpp +++ b/src/common/rendering/vulkan/vk_lightmapper.cpp @@ -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; diff --git a/src/common/rendering/vulkan/vk_lightmapper.h b/src/common/rendering/vulkan/vk_lightmapper.h index f8e14fab5..4be81c65c 100644 --- a/src/common/rendering/vulkan/vk_lightmapper.h +++ b/src/common/rendering/vulkan/vk_lightmapper.h @@ -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 Buffer; - LightInfo* Lights = nullptr; - int Pos = 0; - int ResetCounter = 0; - } lights; - struct { const int BufferSize = 100'000; diff --git a/src/playsim/a_dynlight.h b/src/playsim/a_dynlight.h index 938292a95..fdc80e09a 100644 --- a/src/playsim/a_dynlight.h +++ b/src/playsim/a_dynlight.h @@ -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]; }; diff --git a/src/rendering/hwrenderer/doom_levelmesh.cpp b/src/rendering/hwrenderer/doom_levelmesh.cpp index 70d5ea9c3..d4f4a3dcf 100644 --- a/src/rendering/hwrenderer/doom_levelmesh.cpp +++ b/src/rendering/hwrenderer/doom_levelmesh.cpp @@ -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 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(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 nodePortalGroup = GetSurfaceLightNode(static_cast(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 DoomLevelMesh::GetSurfaceLightNode(const DoomLevelMeshSurface* doomsurf) { FLightNode* node = nullptr; diff --git a/src/rendering/hwrenderer/doom_levelmesh.h b/src/rendering/hwrenderer/doom_levelmesh.h index 5cc00db90..f5341ab92 100644 --- a/src/rendering/hwrenderer/doom_levelmesh.h +++ b/src/rendering/hwrenderer/doom_levelmesh.h @@ -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(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 sectorPortals[2]; // index is sector+plane, value is index into the portal list TArray 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 GetSurfaceLightNode(const DoomLevelMeshSurface* doomsurf); + int GetLightIndex(FDynamicLight* light, int portalgroup); + TArray Sides; TArray Flats; std::map bindings; diff --git a/wadsrc/static/shaders/lightmap/binding_lightmapper.glsl b/wadsrc/static/shaders/lightmap/binding_lightmapper.glsl index a0e02ae50..866134122 100644 --- a/wadsrc/static/shaders/lightmap/binding_lightmapper.glsl +++ b/wadsrc/static/shaders/lightmap/binding_lightmapper.glsl @@ -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[]; }; diff --git a/wadsrc/static/shaders/lightmap/frag_raytrace.glsl b/wadsrc/static/shaders/lightmap/frag_raytrace.glsl index 172e59d74..344b79fb0 100644 --- a/wadsrc/static/shaders/lightmap/frag_raytrace.glsl +++ b/wadsrc/static/shaders/lightmap/frag_raytrace.glsl @@ -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)