Group lightmap variables and put polyobj walls in a dynamic lightmap atlas

This commit is contained in:
dpjudas 2024-10-22 02:29:12 +02:00
commit dfbef085e6
10 changed files with 149 additions and 129 deletions

View file

@ -129,7 +129,7 @@ LevelMeshSurface* LevelMesh::Trace(const FVector3& start, FVector3 direction, fl
LevelMeshTileStats LevelMesh::GatherTilePixelStats()
{
LevelMeshTileStats stats;
for (const LightmapTile& tile : LightmapTiles)
for (const LightmapTile& tile : Lightmap.Tiles)
{
auto area = tile.AtlasLocation.Area();
@ -141,7 +141,7 @@ LevelMeshTileStats LevelMesh::GatherTilePixelStats()
stats.pixels.dirty += area;
}
}
stats.tiles.total += LightmapTiles.Size();
stats.tiles.total += Lightmap.Tiles.Size();
return stats;
}
@ -152,40 +152,36 @@ struct LevelMeshPlaneGroup
std::vector<LevelMeshSurface*> surfaces;
};
void LevelMesh::SetupTileTransforms()
void LevelMesh::PackStaticLightmapAtlas()
{
for (auto& tile : LightmapTiles)
{
tile.SetupTileTransform(LMTextureSize);
}
}
Lightmap.StaticAtlasPacked = true;
Lightmap.DynamicTilesStart = Lightmap.Tiles.Size();
void LevelMesh::PackLightmapAtlas(int lightmapStartIndex)
{
LMAtlasPacked = true;
for (auto& tile : Lightmap.Tiles)
{
if (tile.NeedsUpdate) // false for tiles loaded from lump
tile.SetupTileTransform(Lightmap.TextureSize);
}
std::vector<LightmapTile*> sortedTiles;
sortedTiles.reserve(LightmapTiles.Size());
for (auto& tile : LightmapTiles)
{
sortedTiles.reserve(Lightmap.Tiles.Size());
for (auto& tile : Lightmap.Tiles)
sortedTiles.push_back(&tile);
}
std::sort(sortedTiles.begin(), sortedTiles.end(), [](LightmapTile* a, LightmapTile* b) { return a->AtlasLocation.Height != b->AtlasLocation.Height ? a->AtlasLocation.Height > b->AtlasLocation.Height : a->AtlasLocation.Width > b->AtlasLocation.Width; });
// We do not need to add spacing here as this is already built into the tile size itself.
RectPacker packer(LMTextureSize, LMTextureSize, RectPacker::Spacing(0), RectPacker::Padding(0));
RectPacker packer(Lightmap.TextureSize, Lightmap.TextureSize, RectPacker::Spacing(0), RectPacker::Padding(0));
for (LightmapTile* tile : sortedTiles)
{
auto result = packer.insert(tile->AtlasLocation.Width, tile->AtlasLocation.Height);
tile->AtlasLocation.X = result.pos.x;
tile->AtlasLocation.Y = result.pos.y;
tile->AtlasLocation.ArrayIndex = lightmapStartIndex + (int)result.pageIndex;
tile->AtlasLocation.ArrayIndex = (int)result.pageIndex;
}
LMTextureCount = (int)packer.getNumPages();
Lightmap.TextureCount = (int)packer.getNumPages();
// Calculate final texture coordinates
for (int i = 0, count = Mesh.Surfaces.Size(); i < count; i++)
@ -193,61 +189,67 @@ void LevelMesh::PackLightmapAtlas(int lightmapStartIndex)
auto surface = &Mesh.Surfaces[i];
if (surface->LightmapTileIndex >= 0)
{
const LightmapTile& tile = LightmapTiles[surface->LightmapTileIndex];
const LightmapTile& tile = Lightmap.Tiles[surface->LightmapTileIndex];
for (int i = 0; i < surface->MeshLocation.NumVerts; i++)
{
auto& vertex = Mesh.Vertices[surface->MeshLocation.StartVertIndex + i];
FVector2 uv = tile.ToUV(vertex.fPos(), (float)LMTextureSize);
FVector2 uv = tile.ToUV(vertex.fPos(), (float)Lightmap.TextureSize);
vertex.lu = uv.X;
vertex.lv = uv.Y;
vertex.lindex = (float)tile.AtlasLocation.ArrayIndex;
}
}
}
}
#if 0 // Debug atlas tile locations:
float colors[30] =
void LevelMesh::ClearDynamicLightmapAtlas()
{
for (int surfIndex : Lightmap.DynamicSurfaces)
{
1.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f,
1.0f, 1.0f, 0.0f,
0.0f, 1.0f, 1.0f,
1.0f, 0.0f, 1.0f,
0.5f, 0.0f, 0.0f,
0.0f, 0.5f, 0.0f,
0.5f, 0.5f, 0.0f,
0.0f, 0.5f, 0.5f,
0.5f, 0.0f, 0.5f
};
LMTextureData.Resize(LMTextureSize * LMTextureSize * LMTextureCount * 3);
uint16_t* pixels = LMTextureData.Data();
for (LightmapTile& tile : LightmapTiles)
Mesh.Surfaces[surfIndex].LightmapTileIndex = -1;
}
Lightmap.DynamicSurfaces.Clear();
Lightmap.Tiles.Resize(Lightmap.DynamicTilesStart);
}
void LevelMesh::PackDynamicLightmapAtlas()
{
std::vector<LightmapTile*> sortedTiles;
sortedTiles.reserve(Lightmap.Tiles.Size() - Lightmap.DynamicTilesStart);
for (unsigned int i = Lightmap.DynamicTilesStart; i < Lightmap.Tiles.Size(); i++)
{
tile.NeedsUpdate = false;
Lightmap.Tiles[i].SetupTileTransform(Lightmap.TextureSize);
sortedTiles.push_back(&Lightmap.Tiles[i]);
}
int index = tile.Binding.TypeIndex;
float* color = colors + (index % 10) * 3;
std::sort(sortedTiles.begin(), sortedTiles.end(), [](LightmapTile* a, LightmapTile* b) { return a->AtlasLocation.Height != b->AtlasLocation.Height ? a->AtlasLocation.Height > b->AtlasLocation.Height : a->AtlasLocation.Width > b->AtlasLocation.Width; });
int x = tile.AtlasLocation.X;
int y = tile.AtlasLocation.Y;
int w = tile.AtlasLocation.Width;
int h = tile.AtlasLocation.Height;
for (int yy = y; yy < y + h; yy++)
// We do not need to add spacing here as this is already built into the tile size itself.
RectPacker packer(Lightmap.TextureSize, Lightmap.TextureSize, RectPacker::Spacing(0), RectPacker::Padding(0));
for (LightmapTile* tile : sortedTiles)
{
auto result = packer.insert(tile->AtlasLocation.Width, tile->AtlasLocation.Height);
tile->AtlasLocation.X = result.pos.x;
tile->AtlasLocation.Y = result.pos.y;
tile->AtlasLocation.ArrayIndex = Lightmap.TextureCount; // (int)result.pageIndex;
}
for (int surfIndex : Lightmap.DynamicSurfaces)
{
auto surface = &Mesh.Surfaces[surfIndex];
if (surface->LightmapTileIndex >= 0)
{
uint16_t* line = pixels + tile.AtlasLocation.ArrayIndex * LMTextureSize * LMTextureSize + yy * LMTextureSize * 3;
for (int xx = x; xx < x + w; xx++)
const LightmapTile& tile = Lightmap.Tiles[surface->LightmapTileIndex];
for (int i = 0; i < surface->MeshLocation.NumVerts; i++)
{
float gray = (yy - y) / (float)h;
line[xx * 3] = floatToHalf(color[0] * gray);
line[xx * 3 + 1] = floatToHalf(color[1] * gray);
line[xx * 3 + 2] = floatToHalf(color[2] * gray);
auto& vertex = Mesh.Vertices[surface->MeshLocation.StartVertIndex + i];
FVector2 uv = tile.ToUV(vertex.fPos(), (float)Lightmap.TextureSize);
vertex.lu = uv.X;
vertex.lv = uv.Y;
vertex.lindex = (float)tile.AtlasLocation.ArrayIndex;
}
}
}
for (int i = 0, count = GetSurfaceCount(); i < count; i++)
{
auto surface = GetSurface(i);
surface->AlwaysUpdate = false;
}
#endif
}

View file

@ -142,7 +142,7 @@ public:
// Indexes sorted by pipeline
TArray<uint32_t> DrawIndexes;
// GPU buffer size for collision nodes
// Acceleration structure nodes for when the GPU doesn't support rayquery
TArray<CollisionNode> Nodes;
int RootNode = 0;
} Mesh;
@ -183,20 +183,23 @@ public:
// Draw index ranges for rendering the level mesh, grouped by pipeline
std::unordered_map<int, TArray<MeshBufferRange>> DrawList[(int)LevelMeshDrawType::NumDrawTypes];
// Lightmap atlas
int LMTextureCount = 0;
int LMTextureSize = 1024;
TArray<uint16_t> LMTextureData;
// Lightmap tiles and their locations in the texture atlas
struct
{
int TextureCount = 0;
int TextureSize = 1024;
TArray<uint16_t> TextureData;
uint16_t SampleDistance = 8;
TArray<LightmapTile> Tiles;
bool StaticAtlasPacked = false;
int DynamicTilesStart = 0;
TArray<int> DynamicSurfaces;
} Lightmap;
uint16_t LightmapSampleDistance = 8;
TArray<LightmapTile> LightmapTiles;
bool LMAtlasPacked = false; // Tile sizes can't be changed anymore
uint32_t AtlasPixelCount() const { return uint32_t(LMTextureCount * LMTextureSize * LMTextureSize); }
void SetupTileTransforms();
void PackLightmapAtlas(int lightmapStartIndex);
uint32_t AtlasPixelCount() const { return uint32_t(Lightmap.TextureCount * Lightmap.TextureSize * Lightmap.TextureSize); }
void PackStaticLightmapAtlas();
void ClearDynamicLightmapAtlas();
void PackDynamicLightmapAtlas();
void AddEmptyMesh();

View file

@ -522,9 +522,9 @@ void VulkanRenderDevice::BeginFrame()
levelMeshChanged = false;
mLevelMesh->SetLevelMesh(levelMesh);
if (levelMesh && levelMesh->LMTextureCount > 0)
if (levelMesh && levelMesh->Lightmap.TextureCount > 0)
{
GetTextureManager()->CreateLightmap(levelMesh->LMTextureSize, levelMesh->LMTextureCount, std::move(levelMesh->LMTextureData));
GetTextureManager()->CreateLightmap(levelMesh->Lightmap.TextureSize, levelMesh->Lightmap.TextureCount, std::move(levelMesh->Lightmap.TextureData));
GetLightmapper()->SetLevelMesh(levelMesh);
}
}

View file

@ -3018,8 +3018,7 @@ void MapLoader::InitLevelMesh(MapData* map)
{
if (Level->lightmaps)
{
Level->levelMesh->SetupTileTransforms();
Level->levelMesh->PackLightmapAtlas(0);
Level->levelMesh->PackStaticLightmapAtlas();
}
}
}
@ -3101,11 +3100,11 @@ bool MapLoader::LoadLightmap(MapData* map)
uint8_t* data = (uint8_t*)&textureData[0];
fr.Read(data, numTexPixels * 3 * sizeof(uint16_t));
const auto textureSize = Level->levelMesh->LMTextureSize;
const auto textureSize = Level->levelMesh->Lightmap.TextureSize;
// Create lookup for finding tiles
std::map<LightmapTileBinding, LightmapTile*> levelTiles;
for (LightmapTile& tile : Level->levelMesh->LightmapTiles)
for (LightmapTile& tile : Level->levelMesh->Lightmap.Tiles)
{
levelTiles[tile.Binding] = &tile;
}
@ -3147,19 +3146,12 @@ bool MapLoader::LoadLightmap(MapData* map)
foundBindings.Push({ &entry, tile });
}
// Setup the tile transform for any tile missing in the lump (shouldn't be any, but if there are we let the lightmapper bake them)
for (auto& tile : Level->levelMesh->LightmapTiles)
{
if (tile.NeedsUpdate)
tile.SetupTileTransform(Level->levelMesh->LMTextureSize);
}
// Place all tiles in atlas textures
Level->levelMesh->PackLightmapAtlas(0);
Level->levelMesh->PackStaticLightmapAtlas();
// Start with empty lightmap textures
Level->levelMesh->LMTextureData.Resize(Level->levelMesh->LMTextureCount * textureSize * textureSize * 3);
memset(Level->levelMesh->LMTextureData.Data(), 0, Level->levelMesh->LMTextureData.Size() * sizeof(uint16_t));
Level->levelMesh->Lightmap.TextureData.Resize(Level->levelMesh->Lightmap.TextureCount * textureSize * textureSize * 3);
memset(Level->levelMesh->Lightmap.TextureData.Data(), 0, Level->levelMesh->Lightmap.TextureData.Size() * sizeof(uint16_t));
// Copy tile pixels to the texture
for (auto& binding : foundBindings)
@ -3168,7 +3160,7 @@ bool MapLoader::LoadLightmap(MapData* map)
LightmapTile* tile = binding.second;
const uint16_t* src = textureData.Data() + entry->pixelsOffset;
uint16_t* dst = &Level->levelMesh->LMTextureData[tile->AtlasLocation.ArrayIndex * textureSize * textureSize * 3];
uint16_t* dst = &Level->levelMesh->Lightmap.TextureData[tile->AtlasLocation.ArrayIndex * textureSize * textureSize * 3];
int destx = tile->AtlasLocation.X;
int desty = tile->AtlasLocation.Y;
int width = tile->AtlasLocation.Width;

View file

@ -85,13 +85,13 @@ CCMD(invalidatelightmap)
if (!RequireLightmap()) return;
int count = 0;
for (auto& tile : level.levelMesh->LightmapTiles)
for (auto& tile : level.levelMesh->Lightmap.Tiles)
{
if (!tile.NeedsUpdate)
++count;
tile.NeedsUpdate = true;
}
Printf("Marked %d out of %d tiles for update.\n", count, level.levelMesh->LightmapTiles.Size());
Printf("Marked %d out of %d tiles for update.\n", count, level.levelMesh->Lightmap.Tiles.Size());
}
CCMD(savelightmap)
@ -120,7 +120,7 @@ void DoomLevelMesh::PrintSurfaceInfo(const LevelMeshSurface* surface)
Printf("Surface %d (%p)\n Type: %d, TypeIndex: %d, ControlSector: %d\n", surfaceIndex, surface, info.Type, info.TypeIndex, info.ControlSector ? info.ControlSector->Index() : -1);
if (surface->LightmapTileIndex >= 0)
{
LightmapTile* tile = &LightmapTiles[surface->LightmapTileIndex];
LightmapTile* tile = &Lightmap.Tiles[surface->LightmapTileIndex];
Printf(" Atlas page: %d, x:%d, y:%d\n", tile->AtlasLocation.ArrayIndex, tile->AtlasLocation.X, tile->AtlasLocation.Y);
Printf(" Pixels: %dx%d (area: %d)\n", tile->AtlasLocation.Width, tile->AtlasLocation.Height, tile->AtlasLocation.Area());
Printf(" Sample dimension: %d\n", tile->SampleDimension);
@ -181,7 +181,7 @@ DoomLevelMesh::DoomLevelMesh(FLevelLocals& doomMap)
SunColor = doomMap.SunColor; // TODO keep only one copy?
SunDirection = doomMap.SunDirection;
LightmapSampleDistance = doomMap.LightmapSampleDistance;
Lightmap.SampleDistance = doomMap.LightmapSampleDistance;
// HWWall and HWFlat still looks at r_viewpoint when doing calculations,
// but we aren't rendering a specific viewpoint when this function gets called
@ -254,7 +254,8 @@ void DoomLevelMesh::BeginFrame(FLevelLocals& doomMap)
r_viewpoint.extralight = 0;
r_viewpoint.camera = nullptr;
// To do: we don't need to always do this. UpdateLevelMesh should tell us when polyobjs move.
ClearDynamicLightmapAtlas();
for (side_t* side : PolySides)
{
UpdateSide(side->Index(), SurfaceUpdateType::Full);
@ -288,8 +289,8 @@ void DoomLevelMesh::BeginFrame(FLevelLocals& doomMap)
}
FlatUpdateList.Clear();
PackDynamicLightmapAtlas();
UpdateWallPortals();
UploadDynLights(doomMap);
Collision->Update();
@ -1020,10 +1021,32 @@ void DoomLevelMesh::CreateWallSurface(side_t* side, HWWallDispatcher& disp, Mesh
sinfo.Surface->PortalIndex = (drawType == LevelMeshDrawType::Portal) ? linePortals[side->linedef->Index()] : 0;
sinfo.Surface->IsSky = (drawType == LevelMeshDrawType::Portal) ? (wallpart.portaltype == PORTALTYPE_SKY || wallpart.portaltype == PORTALTYPE_SKYBOX || wallpart.portaltype == PORTALTYPE_HORIZON) : false;
sinfo.Surface->Bounds = GetBoundsFromSurface(*sinfo.Surface);
sinfo.Surface->LightmapTileIndex = disp.Level->lightmaps ? AddSurfaceToTile(info, *sinfo.Surface, sampleDimension, !!(side->sector->Flags & SECF_LM_DYNAMIC)) : -1;
sinfo.Surface->LightList.Pos = lightlist.Start;
sinfo.Surface->LightList.Count = lightlist.Count;
if (side->Flags & WALLF_POLYOBJ) // Polyobjects gets a new tile every frame
{
LightmapTileBinding binding;
binding.Type = info.Type;
binding.TypeIndex = info.TypeIndex;
binding.ControlSector = info.ControlSector ? info.ControlSector->Index() : (int)0xffffffffUL;
LightmapTile tile;
tile.Binding = binding;
tile.Bounds = sinfo.Surface->Bounds;
tile.Plane = sinfo.Surface->Plane;
tile.SampleDimension = GetSampleDimension(sampleDimension);
tile.AlwaysUpdate = true;
sinfo.Surface->LightmapTileIndex = Lightmap.Tiles.Size();
Lightmap.Tiles.Push(tile);
Lightmap.DynamicSurfaces.Push(sinfo.Index);
}
else
{
sinfo.Surface->LightmapTileIndex = disp.Level->lightmaps ? AddSurfaceToTile(info, *sinfo.Surface, sampleDimension, !!(side->sector->Flags & SECF_LM_DYNAMIC)) : -1;
}
SetSideLightmap(sinfo.Index);
for (int i = ginfo.IndexStart / 3, end = (ginfo.IndexStart + ginfo.IndexCount) / 3; i < end; i++)
@ -1129,9 +1152,9 @@ int DoomLevelMesh::AddSurfaceToTile(const DoomSurfaceInfo& info, const LevelMesh
{
int index = it->second;
if (!LMAtlasPacked)
if (!Lightmap.StaticAtlasPacked)
{
LightmapTile& tile = LightmapTiles[index];
LightmapTile& tile = Lightmap.Tiles[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);
@ -1145,10 +1168,10 @@ int DoomLevelMesh::AddSurfaceToTile(const DoomSurfaceInfo& info, const LevelMesh
}
else
{
if (LMAtlasPacked)
if (Lightmap.StaticAtlasPacked)
return -1;
int index = LightmapTiles.Size();
int index = Lightmap.Tiles.Size();
LightmapTile tile;
tile.Binding = binding;
@ -1157,7 +1180,7 @@ int DoomLevelMesh::AddSurfaceToTile(const DoomSurfaceInfo& info, const LevelMesh
tile.SampleDimension = GetSampleDimension(sampleDimension);
tile.AlwaysUpdate = alwaysUpdate;
LightmapTiles.Push(tile);
Lightmap.Tiles.Push(tile);
bindings[binding] = index;
return index;
}
@ -1167,7 +1190,7 @@ int DoomLevelMesh::GetSampleDimension(uint16_t sampleDimension)
{
if (sampleDimension <= 0)
{
sampleDimension = LightmapSampleDistance;
sampleDimension = Lightmap.SampleDistance;
}
sampleDimension = uint16_t(max(int(roundf(float(sampleDimension) / max(1.0f / 4, float(lm_scale)))), 1));
@ -1569,7 +1592,7 @@ void DoomLevelMesh::DumpMesh(const FString& objFilename, const FString& mtlFilen
if (surface.LightmapTileIndex >= 0)
{
auto& tile = LightmapTiles[surface.LightmapTileIndex];
auto& tile = Lightmap.Tiles[surface.LightmapTileIndex];
fprintf(f, "usemtl lightmap%d\n", tile.AtlasLocation.ArrayIndex);
if (tile.AtlasLocation.ArrayIndex > highestUsedAtlasPage)
@ -1960,19 +1983,19 @@ void DoomLevelMesh::SaveLightmapLump(FLevelLocals& doomMap)
};
*/
LMTextureData.Resize(LMTextureSize * LMTextureSize * LMTextureCount * 4);
for (int arrayIndex = 0; arrayIndex < LMTextureCount; arrayIndex++)
Lightmap.TextureData.Resize(Lightmap.TextureSize * Lightmap.TextureSize * Lightmap.TextureCount * 4);
for (int arrayIndex = 0; arrayIndex < Lightmap.TextureCount; arrayIndex++)
{
screen->DownloadLightmap(arrayIndex, LMTextureData.Data() + arrayIndex * LMTextureSize * LMTextureSize * 4);
screen->DownloadLightmap(arrayIndex, Lightmap.TextureData.Data() + arrayIndex * Lightmap.TextureSize * Lightmap.TextureSize * 4);
}
// Calculate size of lump
uint32_t tileCount = 0;
uint32_t pixelCount = 0;
for (unsigned int i = 0; i < LightmapTiles.Size(); i++)
for (unsigned int i = 0; i < Lightmap.Tiles.Size(); i++)
{
LightmapTile* tile = &LightmapTiles[i];
LightmapTile* tile = &Lightmap.Tiles[i];
if (tile->AtlasLocation.ArrayIndex != -1)
{
tileCount++;
@ -1998,9 +2021,9 @@ void DoomLevelMesh::SaveLightmapLump(FLevelLocals& doomMap)
// Write tiles
uint32_t pixelsOffset = 0;
for (unsigned int i = 0; i < LightmapTiles.Size(); i++)
for (unsigned int i = 0; i < Lightmap.Tiles.Size(); i++)
{
LightmapTile* tile = &LightmapTiles[i];
LightmapTile* tile = &Lightmap.Tiles[i];
if (tile->AtlasLocation.ArrayIndex == -1)
continue;
@ -2030,19 +2053,19 @@ void DoomLevelMesh::SaveLightmapLump(FLevelLocals& doomMap)
}
// Write surface pixels
for (unsigned int i = 0; i < LightmapTiles.Size(); i++)
for (unsigned int i = 0; i < Lightmap.Tiles.Size(); i++)
{
LightmapTile* tile = &LightmapTiles[i];
LightmapTile* tile = &Lightmap.Tiles[i];
if (tile->AtlasLocation.ArrayIndex == -1)
continue;
const uint16_t* pixels = LMTextureData.Data() + tile->AtlasLocation.ArrayIndex * LMTextureSize * LMTextureSize * 4;
const uint16_t* pixels = Lightmap.TextureData.Data() + tile->AtlasLocation.ArrayIndex * Lightmap.TextureSize * Lightmap.TextureSize * 4;
int width = tile->AtlasLocation.Width;
int height = tile->AtlasLocation.Height;
for (int y = 0; y < height; y++)
{
const uint16_t* srcline = pixels + (tile->AtlasLocation.X + (tile->AtlasLocation.Y + y) * LMTextureSize) * 4;
const uint16_t* srcline = pixels + (tile->AtlasLocation.X + (tile->AtlasLocation.Y + y) * Lightmap.TextureSize) * 4;
for (int x = 0; x < width; x++)
{
lumpFile.Write16(*(srcline++));

View file

@ -246,8 +246,8 @@ static int CreateIndexedSectorVerticesLM(sector_t* sec, const secplane_t& plane,
int lightmap = sub->LightmapTiles[h].Size() > lightmapIndex ? sub->LightmapTiles[h][lightmapIndex] : -1;
if (lightmap >= 0) // tile may be missing if the subsector is degenerate triangle
{
const auto& tile = level.levelMesh->LightmapTiles[lightmap];
float textureSize = (float)level.levelMesh->LMTextureSize;
const auto& tile = level.levelMesh->Lightmap.Tiles[lightmap];
float textureSize = (float)level.levelMesh->Lightmap.TextureSize;
float lindex = (float)tile.AtlasLocation.ArrayIndex;
for (unsigned int j = 0, end = sub->numlines; j < end; j++)
{

View file

@ -427,12 +427,12 @@ void HWWall::ProcessDecal(HWDrawInfo* di, FRenderState& state, DBaseDecal *decal
if (!(decal->RenderFlags & RF_FULLBRIGHT) && lightmaptile >= 0)
{
LightmapTile* tile = &di->Level->levelMesh->LightmapTiles[lightmaptile];
LightmapTile* tile = &di->Level->levelMesh->Lightmap.Tiles[lightmaptile];
float lightmapindex = (float)tile->AtlasLocation.ArrayIndex;
for (i = 0; i < 4; i++)
{
FVector2 lightmapuv = tile->ToUV(FVector3(dv[i].x, dv[i].y, dv[i].z), di->Level->levelMesh->LMTextureSize);
FVector2 lightmapuv = tile->ToUV(FVector3(dv[i].x, dv[i].y, dv[i].z), di->Level->levelMesh->Lightmap.TextureSize);
verts.first[i].Set(dv[i].x, dv[i].z, dv[i].y, dv[i].u, dv[i].v, lightmapuv.X, lightmapuv.Y, lightmapindex);
}
}
@ -680,12 +680,12 @@ void HWDecalCreateInfo::ProcessDecal(HWDrawInfo* di, FRenderState& state, int dy
if (!(decal->RenderFlags & RF_FULLBRIGHT) && lightmaptile >= 0)
{
LightmapTile* tile = &di->Level->levelMesh->LightmapTiles[lightmaptile];
LightmapTile* tile = &di->Level->levelMesh->Lightmap.Tiles[lightmaptile];
float lightmapindex = (float)tile->AtlasLocation.ArrayIndex;
for (i = 0; i < 4; i++)
{
FVector2 lightmapuv = tile->ToUV(FVector3(dv[i].x, dv[i].y, dv[i].z), di->Level->levelMesh->LMTextureSize);
FVector2 lightmapuv = tile->ToUV(FVector3(dv[i].x, dv[i].y, dv[i].z), di->Level->levelMesh->Lightmap.TextureSize);
verts.first[i].Set(dv[i].x, dv[i].z, dv[i].y, dv[i].u, dv[i].v, lightmapuv.X, lightmapuv.Y, lightmapindex);
}
}

View file

@ -687,7 +687,7 @@ void HWDrawInfo::UpdateLightmaps()
{
if (!outer && VisibleTiles.Size() < unsigned(lm_background_updates))
{
for (auto& e : level.levelMesh->LightmapTiles)
for (auto& e : level.levelMesh->Lightmap.Tiles)
{
if (e.NeedsUpdate)
{

View file

@ -229,16 +229,16 @@ public:
void PushVisibleTile(int tileIndex)
{
if (tileIndex < 0)
return;
if (outer)
{
outer->PushVisibleTile(tileIndex);
return;
}
if (tileIndex < 0)
return;
LightmapTile* tile = &Level->levelMesh->LightmapTiles[tileIndex];
LightmapTile* tile = &Level->levelMesh->Lightmap.Tiles[tileIndex];
if (lm_always_update || tile->AlwaysUpdate)
{
tile->NeedsUpdate = true;

View file

@ -197,11 +197,11 @@ int HWWall::CreateVertices(FFlatVertex *&ptr, bool split)
{
if (lightmaptile >= 0)
{
LightmapTile* tile = &level.levelMesh->LightmapTiles[lightmaptile];
FVector2 lolft = tile->ToUV(FVector3(glseg.x1, glseg.y1, zbottom[0]), level.levelMesh->LMTextureSize);
FVector2 uplft = tile->ToUV(FVector3(glseg.x1, glseg.y1, ztop[0]), level.levelMesh->LMTextureSize);
FVector2 uprgt = tile->ToUV(FVector3(glseg.x2, glseg.y2, ztop[1]), level.levelMesh->LMTextureSize);
FVector2 lorgt = tile->ToUV(FVector3(glseg.x2, glseg.y2, zbottom[1]), level.levelMesh->LMTextureSize);
LightmapTile* tile = &level.levelMesh->Lightmap.Tiles[lightmaptile];
FVector2 lolft = tile->ToUV(FVector3(glseg.x1, glseg.y1, zbottom[0]), level.levelMesh->Lightmap.TextureSize);
FVector2 uplft = tile->ToUV(FVector3(glseg.x1, glseg.y1, ztop[0]), level.levelMesh->Lightmap.TextureSize);
FVector2 uprgt = tile->ToUV(FVector3(glseg.x2, glseg.y2, ztop[1]), level.levelMesh->Lightmap.TextureSize);
FVector2 lorgt = tile->ToUV(FVector3(glseg.x2, glseg.y2, zbottom[1]), level.levelMesh->Lightmap.TextureSize);
lightuv[LOLFT] = { lolft.X, lolft.Y };
lightuv[UPLFT] = { uplft.X, uplft.Y };
lightuv[UPRGT] = { uprgt.X, uprgt.Y };