From 285fbfe299d0662f51c8becf1745779929b40ec7 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Tue, 19 Sep 2023 01:17:03 +0200 Subject: [PATCH] Only find the tile surfaces once Only upload the lights once per surface participating in the baking --- .../rendering/hwrenderer/data/hw_levelmesh.h | 6 ++ .../vulkan/accelstructs/vk_lightmap.cpp | 93 +++++++++++-------- .../vulkan/accelstructs/vk_lightmap.h | 6 +- 3 files changed, 60 insertions(+), 45 deletions(-) diff --git a/src/common/rendering/hwrenderer/data/hw_levelmesh.h b/src/common/rendering/hwrenderer/data/hw_levelmesh.h index ba21a8c38..f5cfd9303 100644 --- a/src/common/rendering/hwrenderer/data/hw_levelmesh.h +++ b/src/common/rendering/hwrenderer/data/hw_levelmesh.h @@ -76,6 +76,9 @@ struct LevelMeshSurface // Smoothing group surface is to be rendered with int smoothingGroupIndex = -1; + // Surfaces that are visible within the lightmap tile + TArray tileSurfaces; + // // Utility/Info // @@ -83,6 +86,9 @@ struct LevelMeshSurface // Touching light sources std::vector LightList; + + int LightListPos = -1; + int LightListResetCounter = -1; }; inline float IsInFrontOfPlane(const FVector4& plane, const FVector3& point) diff --git a/src/common/rendering/vulkan/accelstructs/vk_lightmap.cpp b/src/common/rendering/vulkan/accelstructs/vk_lightmap.cpp index 9855377a0..42a3f536e 100644 --- a/src/common/rendering/vulkan/accelstructs/vk_lightmap.cpp +++ b/src/common/rendering/vulkan/accelstructs/vk_lightmap.cpp @@ -61,6 +61,7 @@ void VkLightmap::SetLevelMesh(LevelMesh* level) void VkLightmap::BeginFrame() { lights.Pos = 0; + lights.ResetCounter++; } void VkLightmap::Raytrace(const TArray& surfaces) @@ -157,55 +158,67 @@ void VkLightmap::RenderBakeImage() continue; } + LightmapPushConstants pc; + pc.TileX = (float)selectedSurface.X; + pc.TileY = (float)selectedSurface.Y; + pc.SurfaceIndex = mesh->GetSurfaceIndex(targetSurface); + pc.TextureSize = (float)bakeImageSize; + pc.TileWidth = (float)targetSurface->texWidth; + pc.TileHeight = (float)targetSurface->texHeight; + pc.WorldToLocal = targetSurface->translateWorldToLocal; + pc.ProjLocalToU = targetSurface->projLocalToU; + pc.ProjLocalToV = targetSurface->projLocalToV; + bool buffersFull = false; - // Paint all surfaces part of the smoothing group into the surface - for (LevelMeshSurface* surface : mesh->SmoothingGroups[targetSurface->smoothingGroupIndex].surfaces) + if (targetSurface->tileSurfaces.Size() == 0) // To do: move this to where we set up the smoothing groups as we don't need the groups after this step { - FVector2 minUV = ToUV(surface->bounds.min, targetSurface); - FVector2 maxUV = ToUV(surface->bounds.max, targetSurface); - if (surface != targetSurface && (maxUV.X < 0.0f || maxUV.Y < 0.0f || minUV.X > 1.0f || minUV.Y > 1.0f)) - continue; // Bounding box not visible + for (LevelMeshSurface* surface : mesh->SmoothingGroups[targetSurface->smoothingGroupIndex].surfaces) + { + FVector2 minUV = ToUV(surface->bounds.min, targetSurface); + FVector2 maxUV = ToUV(surface->bounds.max, targetSurface); + if (surface != targetSurface && (maxUV.X < 0.0f || maxUV.Y < 0.0f || minUV.X > 1.0f || minUV.Y > 1.0f)) + continue; // Bounding box not visible + targetSurface->tileSurfaces.Push(surface); + } + } + + // Paint all surfaces visible in the tile + for (LevelMeshSurface* surface : targetSurface->tileSurfaces) + { int lightCount = (int)surface->LightList.size(); - if (lights.Pos + lightCount > lights.BufferSize) + if (surface->LightListResetCounter != lights.ResetCounter) { - // Our light buffer is full. Postpone the rest. - buffersFull = true; - break; + if (lights.Pos + lightCount > lights.BufferSize) + { + // Our light buffer is full. Postpone the rest. + buffersFull = true; + break; + } + + surface->LightListPos = lights.Pos; + + LightInfo* lightinfo = &lights.Lights[lights.Pos]; + for (const LevelMeshLight* light : surface->LightList) + { + lightinfo->Origin = light->Origin; + lightinfo->RelativeOrigin = light->RelativeOrigin; + lightinfo->Radius = light->Radius; + lightinfo->Intensity = light->Intensity; + lightinfo->InnerAngleCos = light->InnerAngleCos; + lightinfo->OuterAngleCos = light->OuterAngleCos; + lightinfo->SpotDir = light->SpotDir; + lightinfo->Color = light->Color; + lightinfo++; + } + + lights.Pos += lightCount; } - int firstLight = lights.Pos; - lights.Pos += lightCount; - - LightInfo* lightinfo = &lights.Lights[firstLight]; - for (const LevelMeshLight* light : surface->LightList) - { - lightinfo->Origin = light->Origin; - lightinfo->RelativeOrigin = light->RelativeOrigin; - lightinfo->Radius = light->Radius; - lightinfo->Intensity = light->Intensity; - lightinfo->InnerAngleCos = light->InnerAngleCos; - lightinfo->OuterAngleCos = light->OuterAngleCos; - lightinfo->SpotDir = light->SpotDir; - lightinfo->Color = light->Color; - lightinfo++; - } - - LightmapPushConstants pc; - pc.LightStart = firstLight; - pc.LightEnd = firstLight + lightCount; - pc.TileX = (float)selectedSurface.X; - pc.TileY = (float)selectedSurface.Y; - pc.SurfaceIndex = mesh->GetSurfaceIndex(targetSurface); - pc.TextureSize = (float)bakeImageSize; - pc.TileWidth = (float)targetSurface->texWidth; - pc.TileHeight = (float)targetSurface->texHeight; - pc.WorldToLocal = targetSurface->translateWorldToLocal; - pc.ProjLocalToU = targetSurface->projLocalToU; - pc.ProjLocalToV = targetSurface->projLocalToV; - + pc.LightStart = surface->LightListPos; + pc.LightEnd = pc.LightStart + lightCount; fb->GetCommands()->GetTransferCommands()->pushConstants(raytrace.pipelineLayout.get(), VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(LightmapPushConstants), &pc); fb->GetCommands()->GetTransferCommands()->drawIndexed(surface->numElements, 1, surface->startElementIndex, 0, 0); } diff --git a/src/common/rendering/vulkan/accelstructs/vk_lightmap.h b/src/common/rendering/vulkan/accelstructs/vk_lightmap.h index b3ff45d81..5e5d7e25e 100644 --- a/src/common/rendering/vulkan/accelstructs/vk_lightmap.h +++ b/src/common/rendering/vulkan/accelstructs/vk_lightmap.h @@ -65,11 +65,6 @@ struct LightmapBakeImage uint16_t maxY = 0; }; -struct SceneVertex -{ - FVector3 Position; -}; - struct LightInfo { FVector3 Origin; @@ -152,6 +147,7 @@ private: std::unique_ptr Buffer; LightInfo* Lights = nullptr; int Pos = 0; + int ResetCounter = 0; } lights; struct