Split level mesh surface from lightmap tiles as we have multiple surfaces per tile
This commit is contained in:
parent
421b8532ff
commit
48b6a7ec46
19 changed files with 446 additions and 597 deletions
|
|
@ -55,11 +55,11 @@ LevelMeshSurface* LevelMesh::Trace(const FVector3& start, FVector3 direction, fl
|
|||
return hitSurface; // I hit something
|
||||
}
|
||||
|
||||
LevelMeshSurfaceStats LevelMesh::GatherSurfacePixelStats()
|
||||
LevelMeshTileStats LevelMesh::GatherTilePixelStats()
|
||||
{
|
||||
LevelMeshSurfaceStats stats;
|
||||
StaticMesh->GatherSurfacePixelStats(stats);
|
||||
DynamicMesh->GatherSurfacePixelStats(stats);
|
||||
LevelMeshTileStats stats;
|
||||
StaticMesh->GatherTilePixelStats(stats);
|
||||
DynamicMesh->GatherTilePixelStats(stats);
|
||||
return stats;
|
||||
}
|
||||
|
||||
|
|
@ -94,98 +94,96 @@ void LevelSubmesh::UpdateCollision()
|
|||
Collision = std::make_unique<TriangleMeshShape>(Mesh.Vertices.Data(), Mesh.Vertices.Size(), Mesh.Indexes.Data(), Mesh.Indexes.Size());
|
||||
}
|
||||
|
||||
void LevelSubmesh::GatherSurfacePixelStats(LevelMeshSurfaceStats& stats)
|
||||
void LevelSubmesh::GatherTilePixelStats(LevelMeshTileStats& stats)
|
||||
{
|
||||
int count = GetSurfaceCount();
|
||||
for (int i = 0; i < count; ++i)
|
||||
for (const LightmapTile& tile : LightmapTiles)
|
||||
{
|
||||
const auto* surface = GetSurface(i);
|
||||
auto area = surface->AtlasTile.Area();
|
||||
auto area = tile.AtlasLocation.Area();
|
||||
|
||||
stats.pixels.total += area;
|
||||
|
||||
if (surface->NeedsUpdate)
|
||||
if (tile.NeedsUpdate)
|
||||
{
|
||||
stats.surfaces.dirty++;
|
||||
stats.tiles.dirty++;
|
||||
stats.pixels.dirty += area;
|
||||
}
|
||||
if (surface->IsSky)
|
||||
{
|
||||
stats.surfaces.sky++;
|
||||
stats.pixels.sky += area;
|
||||
}
|
||||
}
|
||||
stats.surfaces.total += count;
|
||||
stats.tiles.total += LightmapTiles.Size();
|
||||
}
|
||||
|
||||
struct LevelMeshPlaneGroup
|
||||
{
|
||||
FVector4 plane = FVector4(0, 0, 1, 0);
|
||||
int sectorGroup = 0;
|
||||
std::vector<LevelMeshSurface*> surfaces;
|
||||
};
|
||||
|
||||
void LevelSubmesh::BuildTileSurfaceLists()
|
||||
{
|
||||
// Smoothing group surface is to be rendered with
|
||||
TArray<LevelMeshSmoothingGroup> SmoothingGroups;
|
||||
TArray<int> SmoothingGroupIndexes(GetSurfaceCount());
|
||||
// Plane group surface is to be rendered with
|
||||
TArray<LevelMeshPlaneGroup> PlaneGroups;
|
||||
TArray<int> PlaneGroupIndexes(GetSurfaceCount());
|
||||
|
||||
for (int i = 0, count = GetSurfaceCount(); i < count; i++)
|
||||
{
|
||||
auto surface = GetSurface(i);
|
||||
|
||||
// Is this surface in the same plane as an existing smoothing group?
|
||||
int smoothingGroupIndex = -1;
|
||||
// Is this surface in the same plane as an existing plane group?
|
||||
int planeGroupIndex = -1;
|
||||
|
||||
for (size_t j = 0; j < SmoothingGroups.Size(); j++)
|
||||
for (size_t j = 0; j < PlaneGroups.Size(); j++)
|
||||
{
|
||||
if (surface->SectorGroup == SmoothingGroups[j].sectorGroup)
|
||||
if (surface->SectorGroup == PlaneGroups[j].sectorGroup)
|
||||
{
|
||||
float direction = SmoothingGroups[j].plane.XYZ() | surface->Plane.XYZ();
|
||||
float direction = PlaneGroups[j].plane.XYZ() | surface->Plane.XYZ();
|
||||
if (direction >= 0.9999f && direction <= 1.001f)
|
||||
{
|
||||
auto point = (surface->Plane.XYZ() * surface->Plane.W);
|
||||
auto planeDistance = (SmoothingGroups[j].plane.XYZ() | point) - SmoothingGroups[j].plane.W;
|
||||
auto planeDistance = (PlaneGroups[j].plane.XYZ() | point) - PlaneGroups[j].plane.W;
|
||||
|
||||
float dist = std::abs(planeDistance);
|
||||
if (dist <= 0.01f)
|
||||
{
|
||||
smoothingGroupIndex = (int)j;
|
||||
planeGroupIndex = (int)j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Surface is in a new plane. Create a smoothing group for it
|
||||
if (smoothingGroupIndex == -1)
|
||||
// Surface is in a new plane. Create a plane group for it
|
||||
if (planeGroupIndex == -1)
|
||||
{
|
||||
smoothingGroupIndex = SmoothingGroups.Size();
|
||||
planeGroupIndex = PlaneGroups.Size();
|
||||
|
||||
LevelMeshSmoothingGroup group;
|
||||
LevelMeshPlaneGroup group;
|
||||
group.plane = surface->Plane;
|
||||
group.sectorGroup = surface->SectorGroup;
|
||||
SmoothingGroups.Push(group);
|
||||
PlaneGroups.Push(group);
|
||||
}
|
||||
|
||||
SmoothingGroups[smoothingGroupIndex].surfaces.push_back(surface);
|
||||
SmoothingGroupIndexes.Push(smoothingGroupIndex);
|
||||
PlaneGroups[planeGroupIndex].surfaces.push_back(surface);
|
||||
PlaneGroupIndexes.Push(planeGroupIndex);
|
||||
}
|
||||
|
||||
for (auto& tile : LightmapTiles)
|
||||
tile.Surfaces.Clear();
|
||||
|
||||
for (int i = 0, count = GetSurfaceCount(); i < count; i++)
|
||||
{
|
||||
auto targetSurface = GetSurface(i);
|
||||
targetSurface->TileSurfaces.Clear();
|
||||
for (LevelMeshSurface* surface : SmoothingGroups[SmoothingGroupIndexes[i]].surfaces)
|
||||
LevelMeshSurface* targetSurface = GetSurface(i);
|
||||
if (targetSurface->LightmapTileIndex < 0)
|
||||
continue;
|
||||
LightmapTile* tile = &LightmapTiles[targetSurface->LightmapTileIndex];
|
||||
for (LevelMeshSurface* surface : PlaneGroups[PlaneGroupIndexes[i]].surfaces)
|
||||
{
|
||||
FVector2 minUV = ToUV(surface->Bounds.min, targetSurface);
|
||||
FVector2 maxUV = ToUV(surface->Bounds.max, targetSurface);
|
||||
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
|
||||
|
||||
targetSurface->TileSurfaces.Push(surface);
|
||||
tile->Surfaces.Push(surface);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FVector2 LevelSubmesh::ToUV(const FVector3& vert, const LevelMeshSurface* targetSurface)
|
||||
{
|
||||
FVector3 localPos = vert - targetSurface->TileTransform.TranslateWorldToLocal;
|
||||
float u = (1.0f + (localPos | targetSurface->TileTransform.ProjLocalToU)) / (targetSurface->AtlasTile.Width + 2);
|
||||
float v = (1.0f + (localPos | targetSurface->TileTransform.ProjLocalToV)) / (targetSurface->AtlasTile.Height + 2);
|
||||
return FVector2(u, v);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,12 +7,13 @@
|
|||
#include "flatvertices.h"
|
||||
#include "hw_levelmeshlight.h"
|
||||
#include "hw_levelmeshportal.h"
|
||||
#include "hw_lightmaptile.h"
|
||||
#include "hw_levemeshsurface.h"
|
||||
#include "hw_materialstate.h"
|
||||
#include "hw_surfaceuniforms.h"
|
||||
#include <memory>
|
||||
|
||||
struct LevelMeshSurfaceStats;
|
||||
struct LevelMeshTileStats;
|
||||
|
||||
struct LevelSubmeshDrawRange
|
||||
{
|
||||
|
|
@ -48,19 +49,21 @@ public:
|
|||
|
||||
// Lightmap atlas
|
||||
int LMTextureCount = 0;
|
||||
int LMTextureSize = 0;
|
||||
int LMTextureSize = 1024;
|
||||
TArray<uint16_t> LMTextureData;
|
||||
|
||||
uint16_t LightmapSampleDistance = 16;
|
||||
|
||||
TArray<LightmapTile> LightmapTiles;
|
||||
|
||||
uint32_t AtlasPixelCount() const { return uint32_t(LMTextureCount * LMTextureSize * LMTextureSize); }
|
||||
|
||||
void UpdateCollision();
|
||||
void GatherSurfacePixelStats(LevelMeshSurfaceStats& stats);
|
||||
void GatherTilePixelStats(LevelMeshTileStats& stats);
|
||||
void BuildTileSurfaceLists();
|
||||
|
||||
private:
|
||||
FVector2 ToUV(const FVector3& vert, const LevelMeshSurface* targetSurface);
|
||||
FVector2 ToUV(const FVector3& vert, const LightmapTile* tile);
|
||||
};
|
||||
|
||||
class LevelMesh
|
||||
|
|
@ -76,7 +79,7 @@ public:
|
|||
|
||||
LevelMeshSurface* Trace(const FVector3& start, FVector3 direction, float maxDist);
|
||||
|
||||
LevelMeshSurfaceStats GatherSurfacePixelStats();
|
||||
LevelMeshTileStats GatherTilePixelStats();
|
||||
|
||||
// Map defaults
|
||||
FVector3 SunDirection = FVector3(0.0f, 0.0f, -1.0f);
|
||||
|
|
@ -85,12 +88,12 @@ public:
|
|||
TArray<LevelMeshPortal> Portals;
|
||||
};
|
||||
|
||||
struct LevelMeshSurfaceStats
|
||||
struct LevelMeshTileStats
|
||||
{
|
||||
struct Stats
|
||||
{
|
||||
uint32_t total = 0, dirty = 0, sky = 0;
|
||||
uint32_t total = 0, dirty = 0;
|
||||
};
|
||||
|
||||
Stats surfaces, pixels;
|
||||
Stats tiles, pixels;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
class LevelSubmesh;
|
||||
class FGameTexture;
|
||||
struct LevelMeshSurface;
|
||||
|
||||
struct LevelMeshSurface
|
||||
{
|
||||
|
|
@ -22,21 +23,10 @@ struct LevelMeshSurface
|
|||
unsigned int NumElements = 0;
|
||||
} MeshLocation;
|
||||
|
||||
BBox Bounds;
|
||||
FVector4 Plane = FVector4(0.0f, 0.0f, 1.0f, 0.0f);
|
||||
int LightmapTileIndex = -1;
|
||||
|
||||
// Surface location in lightmap texture
|
||||
struct
|
||||
{
|
||||
int X = 0;
|
||||
int Y = 0;
|
||||
int Width = 0;
|
||||
int Height = 0;
|
||||
int ArrayIndex = 0;
|
||||
uint32_t Area() const { return Width * Height; }
|
||||
} AtlasTile;
|
||||
|
||||
// True if the surface needs to be rendered into the lightmap texture before it can be used
|
||||
bool NeedsUpdate = true;
|
||||
bool AlwaysUpdate = false;
|
||||
|
||||
FGameTexture* Texture = nullptr;
|
||||
|
|
@ -46,20 +36,6 @@ struct LevelMeshSurface
|
|||
int PortalIndex = 0;
|
||||
int SectorGroup = 0;
|
||||
|
||||
BBox Bounds;
|
||||
uint16_t SampleDimension = 0;
|
||||
|
||||
// Calculate world coordinates to UV coordinates
|
||||
struct
|
||||
{
|
||||
FVector3 TranslateWorldToLocal = { 0.0f, 0.0f, 0.0f };
|
||||
FVector3 ProjLocalToU = { 0.0f, 0.0f, 0.0f };
|
||||
FVector3 ProjLocalToV = { 0.0f, 0.0f, 0.0f };
|
||||
} TileTransform;
|
||||
|
||||
// Surfaces that are visible within the lightmap tile
|
||||
TArray<LevelMeshSurface*> TileSurfaces;
|
||||
|
||||
// Light list location in the lightmapper GPU buffers
|
||||
struct
|
||||
{
|
||||
|
|
@ -68,10 +44,3 @@ struct LevelMeshSurface
|
|||
int ResetCounter = -1;
|
||||
} LightList;
|
||||
};
|
||||
|
||||
struct LevelMeshSmoothingGroup
|
||||
{
|
||||
FVector4 plane = FVector4(0, 0, 1, 0);
|
||||
int sectorGroup = 0;
|
||||
std::vector<LevelMeshSurface*> surfaces;
|
||||
};
|
||||
|
|
|
|||
64
src/common/rendering/hwrenderer/data/hw_lightmaptile.h
Normal file
64
src/common/rendering/hwrenderer/data/hw_lightmaptile.h
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "tarray.h"
|
||||
#include "vectors.h"
|
||||
#include "bounds.h"
|
||||
|
||||
struct LevelMeshSurface;
|
||||
|
||||
struct LightmapTileBinding
|
||||
{
|
||||
uint32_t Type = 0;
|
||||
uint32_t TypeIndex = 0;
|
||||
uint32_t ControlSector = 0xffffffff;
|
||||
|
||||
bool operator<(const LightmapTileBinding& other) const
|
||||
{
|
||||
if (TypeIndex != other.TypeIndex) return TypeIndex < other.TypeIndex;
|
||||
if (ControlSector != other.ControlSector) return ControlSector < other.ControlSector;
|
||||
return Type < other.Type;
|
||||
}
|
||||
};
|
||||
|
||||
struct LightmapTile
|
||||
{
|
||||
// Surface location in lightmap texture
|
||||
struct
|
||||
{
|
||||
int X = 0;
|
||||
int Y = 0;
|
||||
int Width = 0;
|
||||
int Height = 0;
|
||||
int ArrayIndex = 0;
|
||||
uint32_t Area() const { return Width * Height; }
|
||||
} AtlasLocation;
|
||||
|
||||
// Calculate world coordinates to UV coordinates
|
||||
struct
|
||||
{
|
||||
FVector3 TranslateWorldToLocal = { 0.0f, 0.0f, 0.0f };
|
||||
FVector3 ProjLocalToU = { 0.0f, 0.0f, 0.0f };
|
||||
FVector3 ProjLocalToV = { 0.0f, 0.0f, 0.0f };
|
||||
} Transform;
|
||||
|
||||
LightmapTileBinding Binding;
|
||||
|
||||
// Surfaces that are visible within the lightmap tile
|
||||
TArray<LevelMeshSurface*> Surfaces;
|
||||
|
||||
BBox Bounds;
|
||||
uint16_t SampleDimension = 0;
|
||||
FVector4 Plane = FVector4(0.0f, 0.0f, 1.0f, 0.0f);
|
||||
|
||||
// True if the tile needs to be rendered into the lightmap texture before it can be used
|
||||
bool NeedsUpdate = true;
|
||||
|
||||
FVector2 ToUV(const FVector3& vert) const
|
||||
{
|
||||
FVector3 localPos = vert - Transform.TranslateWorldToLocal;
|
||||
float u = (1.0f + (localPos | Transform.ProjLocalToU)) / (AtlasLocation.Width + 2);
|
||||
float v = (1.0f + (localPos | Transform.ProjLocalToV)) / (AtlasLocation.Height + 2);
|
||||
return FVector2(u, v);
|
||||
}
|
||||
};
|
||||
|
|
@ -139,7 +139,7 @@ public:
|
|||
virtual bool IsPoly() { return false; }
|
||||
virtual bool CompileNextShader() { return true; }
|
||||
virtual void SetLevelMesh(LevelMesh *mesh) { }
|
||||
virtual void UpdateLightmaps(const TArray<LevelMeshSurface*>& surfaces) {}
|
||||
virtual void UpdateLightmaps(const TArray<LightmapTile*>& tiles) {}
|
||||
|
||||
virtual DCanvas* GetCanvas() { return nullptr; }
|
||||
|
||||
|
|
|
|||
|
|
@ -640,7 +640,6 @@ void VkLevelMeshUploader::UploadSurfaces()
|
|||
SurfaceInfo info;
|
||||
info.Normal = FVector3(surface->Plane.X, surface->Plane.Z, surface->Plane.Y);
|
||||
info.PortalIndex = surface->PortalIndex;
|
||||
info.SamplingDistance = (float)surface->SampleDimension;
|
||||
info.Sky = surface->IsSky;
|
||||
info.Alpha = surface->Alpha;
|
||||
if (surface->Texture)
|
||||
|
|
|
|||
|
|
@ -31,10 +31,10 @@ struct SurfaceInfo
|
|||
{
|
||||
FVector3 Normal;
|
||||
float Sky;
|
||||
float SamplingDistance;
|
||||
uint32_t PortalIndex;
|
||||
int32_t TextureIndex;
|
||||
float Alpha;
|
||||
float Padding;
|
||||
};
|
||||
|
||||
struct PortalInfo
|
||||
|
|
|
|||
|
|
@ -92,16 +92,16 @@ void VkLightmapper::BeginFrame()
|
|||
drawindexed.Pos = 0;
|
||||
}
|
||||
|
||||
void VkLightmapper::Raytrace(const TArray<LevelMeshSurface*>& surfaces)
|
||||
void VkLightmapper::Raytrace(const TArray<LightmapTile*>& tiles)
|
||||
{
|
||||
if (mesh && surfaces.Size() > 0)
|
||||
if (mesh && tiles.Size() > 0)
|
||||
{
|
||||
lightmapRaytraceLast.active = true;
|
||||
|
||||
lightmapRaytraceLast.ResetAndClock();
|
||||
|
||||
SelectSurfaces(surfaces);
|
||||
if (selectedSurfaces.Size() > 0)
|
||||
SelectTiles(tiles);
|
||||
if (selectedTiles.Size() > 0)
|
||||
{
|
||||
fb->GetCommands()->PushGroup(fb->GetCommands()->GetTransferCommands(), "lightmap.total");
|
||||
|
||||
|
|
@ -119,36 +119,36 @@ void VkLightmapper::Raytrace(const TArray<LevelMeshSurface*>& surfaces)
|
|||
}
|
||||
}
|
||||
|
||||
void VkLightmapper::SelectSurfaces(const TArray<LevelMeshSurface*>& surfaces)
|
||||
void VkLightmapper::SelectTiles(const TArray<LightmapTile*>& tiles)
|
||||
{
|
||||
bakeImage.maxX = 0;
|
||||
bakeImage.maxY = 0;
|
||||
selectedSurfaces.Clear();
|
||||
selectedTiles.Clear();
|
||||
|
||||
const int spacing = 5; // Note: the spacing is here to avoid that the resolve sampler finds data from other surface tiles
|
||||
RectPacker packer(bakeImageSize - spacing, bakeImageSize - spacing, RectPacker::Spacing(spacing));
|
||||
|
||||
for (int i = 0, count = surfaces.Size(); i < count; i++)
|
||||
for (int i = 0, count = tiles.Size(); i < count; i++)
|
||||
{
|
||||
LevelMeshSurface* surface = surfaces[i];
|
||||
LightmapTile* tile = tiles[i];
|
||||
|
||||
if (!surface->NeedsUpdate)
|
||||
if (!tile->NeedsUpdate)
|
||||
continue;
|
||||
|
||||
// Only grab surfaces until our bake texture is full
|
||||
auto result = packer.insert(surface->AtlasTile.Width + 2, surface->AtlasTile.Height + 2);
|
||||
auto result = packer.insert(tile->AtlasLocation.Width + 2, tile->AtlasLocation.Height + 2);
|
||||
if (result.pageIndex == 0)
|
||||
{
|
||||
SelectedSurface selected;
|
||||
selected.Surface = surface;
|
||||
SelectedTile selected;
|
||||
selected.Tile = tile;
|
||||
selected.X = result.pos.x + 1;
|
||||
selected.Y = result.pos.y + 1;
|
||||
selectedSurfaces.Push(selected);
|
||||
selectedTiles.Push(selected);
|
||||
|
||||
bakeImage.maxX = std::max<uint16_t>(bakeImage.maxX, uint16_t(selected.X + surface->AtlasTile.Width + spacing));
|
||||
bakeImage.maxY = std::max<uint16_t>(bakeImage.maxY, uint16_t(selected.Y + surface->AtlasTile.Height + spacing));
|
||||
bakeImage.maxX = std::max<uint16_t>(bakeImage.maxX, uint16_t(selected.X + tile->AtlasLocation.Width + spacing));
|
||||
bakeImage.maxY = std::max<uint16_t>(bakeImage.maxY, uint16_t(selected.Y + tile->AtlasLocation.Height + spacing));
|
||||
|
||||
surface->NeedsUpdate = false;
|
||||
tile->NeedsUpdate = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -180,35 +180,40 @@ void VkLightmapper::Render()
|
|||
viewport.height = (float)bakeImageSize;
|
||||
cmdbuffer->setViewport(0, 1, &viewport);
|
||||
|
||||
for (int i = 0, count = selectedSurfaces.Size(); i < count; i++)
|
||||
{
|
||||
auto& selectedSurface = selectedSurfaces[i];
|
||||
LevelMeshSurface* targetSurface = selectedSurface.Surface;
|
||||
int dynamicSurfaceIndexOffset = mesh->StaticMesh->GetSurfaceCount();
|
||||
int dynamicFirstIndexOffset = mesh->StaticMesh->Mesh.Indexes.Size();
|
||||
LevelSubmesh* staticMesh = mesh->StaticMesh.get();
|
||||
|
||||
int surfaceIndexOffset = 0;
|
||||
int firstIndexOffset = 0;
|
||||
if (targetSurface->Submesh != mesh->StaticMesh.get())
|
||||
{
|
||||
surfaceIndexOffset = mesh->StaticMesh->GetSurfaceCount();
|
||||
firstIndexOffset = mesh->StaticMesh->Mesh.Indexes.Size();
|
||||
}
|
||||
for (int i = 0, count = selectedTiles.Size(); i < count; i++)
|
||||
{
|
||||
auto& selectedTile = selectedTiles[i];
|
||||
LightmapTile* targetTile = selectedTile.Tile;
|
||||
|
||||
LightmapRaytracePC pc;
|
||||
pc.TileX = (float)selectedSurface.X;
|
||||
pc.TileY = (float)selectedSurface.Y;
|
||||
pc.SurfaceIndex = surfaceIndexOffset + targetSurface->Submesh->GetSurfaceIndex(targetSurface);
|
||||
pc.TileX = (float)selectedTile.X;
|
||||
pc.TileY = (float)selectedTile.Y;
|
||||
pc.TextureSize = (float)bakeImageSize;
|
||||
pc.TileWidth = (float)targetSurface->AtlasTile.Width;
|
||||
pc.TileHeight = (float)targetSurface->AtlasTile.Height;
|
||||
pc.WorldToLocal = SwapYZ(targetSurface->TileTransform.TranslateWorldToLocal);
|
||||
pc.ProjLocalToU = SwapYZ(targetSurface->TileTransform.ProjLocalToU);
|
||||
pc.ProjLocalToV = SwapYZ(targetSurface->TileTransform.ProjLocalToV);
|
||||
pc.TileWidth = (float)targetTile->AtlasLocation.Width;
|
||||
pc.TileHeight = (float)targetTile->AtlasLocation.Height;
|
||||
pc.WorldToLocal = SwapYZ(targetTile->Transform.TranslateWorldToLocal);
|
||||
pc.ProjLocalToU = SwapYZ(targetTile->Transform.ProjLocalToU);
|
||||
pc.ProjLocalToV = SwapYZ(targetTile->Transform.ProjLocalToV);
|
||||
|
||||
bool buffersFull = false;
|
||||
|
||||
// Paint all surfaces visible in the tile
|
||||
for (LevelMeshSurface* surface : targetSurface->TileSurfaces)
|
||||
for (LevelMeshSurface* surface : targetTile->Surfaces)
|
||||
{
|
||||
int surfaceIndexOffset = 0;
|
||||
int firstIndexOffset = 0;
|
||||
if (surface->Submesh != staticMesh)
|
||||
{
|
||||
surfaceIndexOffset = dynamicSurfaceIndexOffset;
|
||||
firstIndexOffset = dynamicFirstIndexOffset;
|
||||
}
|
||||
|
||||
pc.SurfaceIndex = surfaceIndexOffset + surface->Submesh->GetSurfaceIndex(surface);
|
||||
|
||||
if (surface->LightList.ResetCounter != lights.ResetCounter)
|
||||
{
|
||||
int lightCount = mesh->AddSurfaceLights(surface, templightlist.Data(), (int)templightlist.Size());
|
||||
|
|
@ -272,13 +277,13 @@ void VkLightmapper::Render()
|
|||
{
|
||||
while (i < count)
|
||||
{
|
||||
selectedSurfaces[i].Surface->NeedsUpdate = true;
|
||||
selectedTiles[i].Tile->NeedsUpdate = true;
|
||||
i++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
selectedSurface.Rendered = true;
|
||||
selectedTile.Rendered = true;
|
||||
}
|
||||
|
||||
#ifdef USE_DRAWINDIRECT
|
||||
|
|
@ -407,19 +412,19 @@ void VkLightmapper::CopyResult()
|
|||
uint32_t pixels = 0;
|
||||
lastSurfaceCount = 0;
|
||||
for (auto& list : copylists) list.Clear();
|
||||
for (int i = 0, count = selectedSurfaces.Size(); i < count; i++)
|
||||
for (int i = 0, count = selectedTiles.Size(); i < count; i++)
|
||||
{
|
||||
auto& selected = selectedSurfaces[i];
|
||||
auto& selected = selectedTiles[i];
|
||||
if (selected.Rendered)
|
||||
{
|
||||
unsigned int pageIndex = (unsigned int)selected.Surface->AtlasTile.ArrayIndex;
|
||||
unsigned int pageIndex = (unsigned int)selected.Tile->AtlasLocation.ArrayIndex;
|
||||
if (pageIndex >= copylists.Size())
|
||||
{
|
||||
copylists.Resize(pageIndex + 1);
|
||||
}
|
||||
copylists[pageIndex].Push(&selected);
|
||||
|
||||
pixels += selected.Surface->AtlasTile.Area();
|
||||
pixels += selected.Tile->AtlasLocation.Area();
|
||||
lastSurfaceCount++;
|
||||
}
|
||||
}
|
||||
|
|
@ -484,17 +489,17 @@ void VkLightmapper::CopyResult()
|
|||
|
||||
// Copy the tile positions into a storage buffer for the vertex shader to read
|
||||
start = pos;
|
||||
for (SelectedSurface* selected : list)
|
||||
for (SelectedTile* selected : list)
|
||||
{
|
||||
LevelMeshSurface* surface = selected->Surface;
|
||||
LightmapTile* tile = selected->Tile;
|
||||
|
||||
CopyTileInfo* copyinfo = ©tiles.Tiles[pos++];
|
||||
copyinfo->SrcPosX = selected->X;
|
||||
copyinfo->SrcPosY = selected->Y;
|
||||
copyinfo->DestPosX = surface->AtlasTile.X;
|
||||
copyinfo->DestPosY = surface->AtlasTile.Y;
|
||||
copyinfo->TileWidth = surface->AtlasTile.Width;
|
||||
copyinfo->TileHeight = surface->AtlasTile.Height;
|
||||
copyinfo->DestPosX = tile->AtlasLocation.X;
|
||||
copyinfo->DestPosY = tile->AtlasLocation.Y;
|
||||
copyinfo->TileWidth = tile->AtlasLocation.Width;
|
||||
copyinfo->TileHeight = tile->AtlasLocation.Height;
|
||||
}
|
||||
|
||||
// Draw the tiles. One instance per tile.
|
||||
|
|
|
|||
|
|
@ -95,9 +95,9 @@ struct LightInfo
|
|||
float Padding3;
|
||||
};
|
||||
|
||||
struct SelectedSurface
|
||||
struct SelectedTile
|
||||
{
|
||||
LevelMeshSurface* Surface = nullptr;
|
||||
LightmapTile* Tile = nullptr;
|
||||
int X = -1;
|
||||
int Y = -1;
|
||||
bool Rendered = false;
|
||||
|
|
@ -126,13 +126,13 @@ public:
|
|||
~VkLightmapper();
|
||||
|
||||
void BeginFrame();
|
||||
void Raytrace(const TArray<LevelMeshSurface*>& surfaces);
|
||||
void Raytrace(const TArray<LightmapTile*>& surfaces);
|
||||
void SetLevelMesh(LevelMesh* level);
|
||||
|
||||
private:
|
||||
void ReleaseResources();
|
||||
|
||||
void SelectSurfaces(const TArray<LevelMeshSurface*>& surfaces);
|
||||
void SelectTiles(const TArray<LightmapTile*>& surfaces);
|
||||
void UploadUniforms();
|
||||
void Render();
|
||||
void Resolve();
|
||||
|
|
@ -165,8 +165,8 @@ private:
|
|||
|
||||
bool useRayQuery = true;
|
||||
|
||||
TArray<SelectedSurface> selectedSurfaces;
|
||||
TArray<TArray<SelectedSurface*>> copylists;
|
||||
TArray<SelectedTile> selectedTiles;
|
||||
TArray<TArray<SelectedTile*>> copylists;
|
||||
TArray<LevelMeshLight> templightlist;
|
||||
|
||||
struct
|
||||
|
|
|
|||
|
|
@ -553,9 +553,9 @@ void VulkanRenderDevice::SetLevelMesh(LevelMesh* mesh)
|
|||
levelMeshChanged = true;
|
||||
}
|
||||
|
||||
void VulkanRenderDevice::UpdateLightmaps(const TArray<LevelMeshSurface*>& surfaces)
|
||||
void VulkanRenderDevice::UpdateLightmaps(const TArray<LightmapTile*>& tiles)
|
||||
{
|
||||
GetLightmapper()->Raytrace(surfaces);
|
||||
GetLightmapper()->Raytrace(tiles);
|
||||
}
|
||||
|
||||
void VulkanRenderDevice::SetShadowMaps(const TArray<float>& lights, hwrenderer::LevelAABBTree* tree, bool newTree)
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ public:
|
|||
void AmbientOccludeScene(float m5) override;
|
||||
void SetSceneRenderTarget(bool useSSAO) override;
|
||||
void SetLevelMesh(LevelMesh* mesh) override;
|
||||
void UpdateLightmaps(const TArray<LevelMeshSurface*>& surfaces) override;
|
||||
void UpdateLightmaps(const TArray<LightmapTile*>& tiles) override;
|
||||
void SetShadowMaps(const TArray<float>& lights, hwrenderer::LevelAABBTree* tree, bool newTree) override;
|
||||
void SetSaveBuffers(bool yes) override;
|
||||
void ImageTransitionScene(bool unknown) override;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue