diff --git a/src/common/rendering/hwrenderer/data/hw_levelmesh.cpp b/src/common/rendering/hwrenderer/data/hw_levelmesh.cpp index 78ca51cc8..243f23fa1 100644 --- a/src/common/rendering/hwrenderer/data/hw_levelmesh.cpp +++ b/src/common/rendering/hwrenderer/data/hw_levelmesh.cpp @@ -148,75 +148,6 @@ struct LevelMeshPlaneGroup std::vector surfaces; }; -void LevelMesh::BuildTileSurfaceLists() -{ - // Plane group surface is to be rendered with - TArray PlaneGroups; - TArray PlaneGroupIndexes(Mesh.Surfaces.Size()); - - for (int i = 0, count = Mesh.Surfaces.Size(); i < count; i++) - { - auto surface = &Mesh.Surfaces[i]; - - // Is this surface in the same plane as an existing plane group? - int planeGroupIndex = -1; - - for (size_t j = 0; j < PlaneGroups.Size(); j++) - { - if (surface->SectorGroup == PlaneGroups[j].sectorGroup) - { - float direction = PlaneGroups[j].plane.XYZ() | surface->Plane.XYZ(); - if (direction >= 0.999f && direction <= 1.01f) - { - auto point = (surface->Plane.XYZ() * surface->Plane.W); - auto planeDistance = (PlaneGroups[j].plane.XYZ() | point) - PlaneGroups[j].plane.W; - - float dist = std::abs(planeDistance); - if (dist <= 0.1f) - { - planeGroupIndex = (int)j; - break; - } - } - } - } - - // Surface is in a new plane. Create a plane group for it - if (planeGroupIndex == -1) - { - planeGroupIndex = PlaneGroups.Size(); - - LevelMeshPlaneGroup group; - group.plane = surface->Plane; - group.sectorGroup = surface->SectorGroup; - PlaneGroups.Push(group); - } - - PlaneGroups[planeGroupIndex].surfaces.push_back(surface); - PlaneGroupIndexes.Push(planeGroupIndex); - } - - for (auto& tile : LightmapTiles) - tile.Surfaces.Clear(); - - for (int i = 0, count = Mesh.Surfaces.Size(); i < count; i++) - { - LevelMeshSurface* targetSurface = &Mesh.Surfaces[i]; - if (targetSurface->LightmapTileIndex < 0) - continue; - LightmapTile* tile = &LightmapTiles[targetSurface->LightmapTileIndex]; - for (LevelMeshSurface* surface : PlaneGroups[PlaneGroupIndexes[i]].surfaces) - { - FVector2 minUV = tile->ToUV(surface->Bounds.min); - FVector2 maxUV = tile->ToUV(surface->Bounds.max); - if (surface != targetSurface && (maxUV.X < 0.0f || maxUV.Y < 0.0f || minUV.X > 1.0f || minUV.Y > 1.0f)) - continue; // Bounding box not visible - - tile->Surfaces.Push((unsigned int)(ptrdiff_t)(surface - Mesh.Surfaces.Data())); - } - } -} - void LevelMesh::SetupTileTransforms() { for (auto& tile : LightmapTiles) @@ -227,6 +158,8 @@ void LevelMesh::SetupTileTransforms() void LevelMesh::PackLightmapAtlas(int lightmapStartIndex) { + LMAtlasPacked = true; + std::vector sortedTiles; sortedTiles.reserve(LightmapTiles.Size()); diff --git a/src/common/rendering/hwrenderer/data/hw_levelmesh.h b/src/common/rendering/hwrenderer/data/hw_levelmesh.h index b9cba5d75..9957f4a33 100644 --- a/src/common/rendering/hwrenderer/data/hw_levelmesh.h +++ b/src/common/rendering/hwrenderer/data/hw_levelmesh.h @@ -103,6 +103,8 @@ public: // Sets the sizes of all the GPU buffers and empties the mesh virtual void Reset(const LevelMeshLimits& limits); + virtual void GetVisibleSurfaces(LightmapTile* tile, TArray& outSurfaces) { } + // Data placed in GPU buffers struct { @@ -171,6 +173,7 @@ public: uint16_t LightmapSampleDistance = 16; TArray LightmapTiles; + bool LMAtlasPacked = false; // Tile sizes can't be changed anymore uint32_t AtlasPixelCount() const { return uint32_t(LMTextureCount * LMTextureSize * LMTextureSize); } diff --git a/src/common/rendering/hwrenderer/data/hw_lightmaptile.h b/src/common/rendering/hwrenderer/data/hw_lightmaptile.h index 2793252ac..7f803f5a8 100644 --- a/src/common/rendering/hwrenderer/data/hw_lightmaptile.h +++ b/src/common/rendering/hwrenderer/data/hw_lightmaptile.h @@ -44,9 +44,6 @@ struct LightmapTile LightmapTileBinding Binding; - // Surfaces that are visible within the lightmap tile - TArray Surfaces; - BBox Bounds; uint16_t SampleDimension = 0; FVector4 Plane = FVector4(0.0f, 0.0f, 1.0f, 0.0f); diff --git a/src/common/rendering/vulkan/vk_lightmapper.cpp b/src/common/rendering/vulkan/vk_lightmapper.cpp index c569ce742..9e0d2e9b0 100644 --- a/src/common/rendering/vulkan/vk_lightmapper.cpp +++ b/src/common/rendering/vulkan/vk_lightmapper.cpp @@ -194,7 +194,10 @@ void VkLightmapper::Render() bool buffersFull = false; // Paint all surfaces visible in the tile - for (int surfaceIndex : targetTile->Surfaces) + + visibleSurfaces.Clear(); + mesh->GetVisibleSurfaces(targetTile, visibleSurfaces); + for (int surfaceIndex : visibleSurfaces) { LevelMeshSurface* surface = &mesh->Mesh.Surfaces[surfaceIndex]; pc.SurfaceIndex = surfaceIndex; diff --git a/src/common/rendering/vulkan/vk_lightmapper.h b/src/common/rendering/vulkan/vk_lightmapper.h index ac2944cf8..2cfd75502 100644 --- a/src/common/rendering/vulkan/vk_lightmapper.h +++ b/src/common/rendering/vulkan/vk_lightmapper.h @@ -149,6 +149,8 @@ private: TArray selectedTiles; TArray> copylists; + TArray visibleSurfaces; + struct { std::unique_ptr Buffer; diff --git a/src/rendering/hwrenderer/doom_levelmesh.cpp b/src/rendering/hwrenderer/doom_levelmesh.cpp index 7e1bfc46c..523297313 100644 --- a/src/rendering/hwrenderer/doom_levelmesh.cpp +++ b/src/rendering/hwrenderer/doom_levelmesh.cpp @@ -171,8 +171,6 @@ DoomLevelMesh::DoomLevelMesh(FLevelLocals& doomMap) CreatePortals(doomMap); CreateSurfaces(doomMap); - BuildTileSurfaceLists(); - UpdateCollision(); Mesh.MaxNodes = std::max(Collision->get_nodes().size() * 2, (size_t)10000); @@ -921,19 +919,25 @@ int DoomLevelMesh::AddSurfaceToTile(const DoomSurfaceInfo& info, const LevelMesh { int index = it->second; - LightmapTile& tile = LightmapTiles[index]; - tile.Bounds.min.X = std::min(tile.Bounds.min.X, surf.Bounds.min.X); - tile.Bounds.min.Y = std::min(tile.Bounds.min.Y, surf.Bounds.min.Y); - tile.Bounds.min.Z = std::min(tile.Bounds.min.Z, surf.Bounds.min.Z); - tile.Bounds.max.X = std::max(tile.Bounds.max.X, surf.Bounds.max.X); - tile.Bounds.max.Y = std::max(tile.Bounds.max.Y, surf.Bounds.max.Y); - tile.Bounds.max.Z = std::max(tile.Bounds.max.Z, surf.Bounds.max.Z); - tile.AlwaysUpdate = tile.AlwaysUpdate || alwaysUpdate; + if (!LMAtlasPacked) + { + LightmapTile& tile = LightmapTiles[index]; + tile.Bounds.min.X = std::min(tile.Bounds.min.X, surf.Bounds.min.X); + tile.Bounds.min.Y = std::min(tile.Bounds.min.Y, surf.Bounds.min.Y); + tile.Bounds.min.Z = std::min(tile.Bounds.min.Z, surf.Bounds.min.Z); + tile.Bounds.max.X = std::max(tile.Bounds.max.X, surf.Bounds.max.X); + tile.Bounds.max.Y = std::max(tile.Bounds.max.Y, surf.Bounds.max.Y); + tile.Bounds.max.Z = std::max(tile.Bounds.max.Z, surf.Bounds.max.Z); + tile.AlwaysUpdate = tile.AlwaysUpdate || alwaysUpdate; + } return index; } else { + if (LMAtlasPacked) + return -1; + int index = LightmapTiles.Size(); LightmapTile tile; @@ -1237,6 +1241,45 @@ BBox DoomLevelMesh::GetBoundsFromSurface(const LevelMeshSurface& surface) const return bounds; } +void DoomLevelMesh::GetVisibleSurfaces(LightmapTile* tile, TArray& outSurfaces) +{ + if (tile->Binding.Type == ST_MIDDLESIDE || tile->Binding.Type == ST_UPPERSIDE || tile->Binding.Type == ST_LOWERSIDE) + { + int sideIndex = tile->Binding.TypeIndex; + int surf = Sides[sideIndex].FirstSurface; + while (surf != -1) + { + const auto& sinfo = DoomSurfaceInfos[surf]; + if (sinfo.Type == tile->Binding.Type) + { + outSurfaces.Push(surf); + } + surf = sinfo.NextSurface; + } + } + else if (tile->Binding.Type == ST_CEILING || tile->Binding.Type == ST_FLOOR) + { + int subsectorIndex = tile->Binding.TypeIndex; + int sectorIndex = level.subsectors[subsectorIndex].sector->Index(); + int surf = Flats[sectorIndex].FirstSurface; + while (surf != -1) + { + const auto& sinfo = DoomSurfaceInfos[surf]; + int controlSector = sinfo.ControlSector ? sinfo.ControlSector->Index() : (int)0xffffffffUL; + if (sinfo.Type == tile->Binding.Type && controlSector == tile->Binding.ControlSector) + { + FVector2 minUV = tile->ToUV(Mesh.Surfaces[surf].Bounds.min); + FVector2 maxUV = tile->ToUV(Mesh.Surfaces[surf].Bounds.max); + if (!(maxUV.X < 0.0f || maxUV.Y < 0.0f || minUV.X > 1.0f || minUV.Y > 1.0f)) + { + outSurfaces.Push(surf); + } + } + surf = sinfo.NextSurface; + } + } +} + void DoomLevelMesh::DumpMesh(const FString& objFilename, const FString& mtlFilename) const { auto f = fopen(objFilename.GetChars(), "w"); diff --git a/src/rendering/hwrenderer/doom_levelmesh.h b/src/rendering/hwrenderer/doom_levelmesh.h index d8eacde39..75f4edfe1 100644 --- a/src/rendering/hwrenderer/doom_levelmesh.h +++ b/src/rendering/hwrenderer/doom_levelmesh.h @@ -113,6 +113,8 @@ public: DoomSurfaceInfos.Resize(limits.MaxSurfaces); } + void GetVisibleSurfaces(LightmapTile* tile, TArray& outSurfaces) override; + struct Stats { int FlatsUpdated = 0; @@ -159,7 +161,6 @@ private: void SortDrawLists(); TArray DoomSurfaceInfos; - TArray> PolyDoomSurfaceInfos; TArray Sides; TArray Flats;