mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-25 21:41:03 +00:00
Initial implementation for lightmap lump loading
This commit is contained in:
parent
2b4db4c601
commit
537cd7790d
10 changed files with 354 additions and 35 deletions
|
@ -192,11 +192,12 @@ public:
|
|||
|
||||
virtual void UpdateLightLists() { }
|
||||
|
||||
TArray<LevelMeshSmoothingGroup> SmoothingGroups; // TODO fill
|
||||
TArray<LevelMeshPortal> Portals; // TODO fill
|
||||
TArray<LevelMeshSmoothingGroup> SmoothingGroups;
|
||||
TArray<LevelMeshPortal> Portals;
|
||||
|
||||
int LMTextureCount = 0;
|
||||
int LMTextureSize = 0;
|
||||
TArray<uint16_t> LMTextureData; // TODO better place for this?
|
||||
|
||||
FVector3 SunDirection = FVector3(0.0f, 0.0f, -1.0f);
|
||||
FVector3 SunColor = FVector3(0.0f, 0.0f, 0.0f);
|
||||
|
|
|
@ -189,17 +189,17 @@ void VkTextureManager::CreateLightmap()
|
|||
SetLightmap(1, 1, data);
|
||||
}
|
||||
|
||||
void VkTextureManager::CreateLightmap(int newLMTextureSize, int newLMTextureCount)
|
||||
void VkTextureManager::CreateLightmap(int newLMTextureSize, int newLMTextureCount, TArray<uint16_t>&& newPixelData)
|
||||
{
|
||||
if (LMTextureSize == newLMTextureSize && LMTextureCount == newLMTextureCount)
|
||||
return;
|
||||
|
||||
LMTextureSize = newLMTextureSize;
|
||||
LMTextureCount = newLMTextureCount;
|
||||
|
||||
int w = LMTextureSize;
|
||||
int h = LMTextureSize;
|
||||
int count = LMTextureCount;
|
||||
|
||||
int w = newLMTextureSize;
|
||||
int h = newLMTextureSize;
|
||||
int count = newLMTextureCount;
|
||||
int pixelsize = 8;
|
||||
|
||||
Lightmap.Reset(fb);
|
||||
|
@ -219,6 +219,47 @@ void VkTextureManager::CreateLightmap(int newLMTextureSize, int newLMTextureCoun
|
|||
|
||||
auto cmdbuffer = fb->GetCommands()->GetTransferCommands();
|
||||
|
||||
if (newPixelData.Size() >= w * h * count * 3)
|
||||
{
|
||||
assert(newPixelData.Size() == w * h * count * 3);
|
||||
|
||||
int totalSize = w * h * count * pixelsize;
|
||||
|
||||
auto stagingBuffer = BufferBuilder()
|
||||
.Size(totalSize)
|
||||
.Usage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY)
|
||||
.DebugName("VkHardwareTexture.mStagingBuffer")
|
||||
.Create(fb->GetDevice());
|
||||
|
||||
uint16_t one = 0x3c00; // half-float 1.0
|
||||
const uint16_t* src = newPixelData.Data();
|
||||
uint16_t* data = (uint16_t*)stagingBuffer->Map(0, totalSize);
|
||||
for (int i = w * h * count; i > 0; i--)
|
||||
{
|
||||
*(data++) = *(src++);
|
||||
*(data++) = *(src++);
|
||||
*(data++) = *(src++);
|
||||
*(data++) = one;
|
||||
}
|
||||
stagingBuffer->Unmap();
|
||||
|
||||
VkImageTransition()
|
||||
.AddImage(&Lightmap, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true, 0, count)
|
||||
.Execute(cmdbuffer);
|
||||
|
||||
VkBufferImageCopy region = {};
|
||||
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
region.imageSubresource.layerCount = count;
|
||||
region.imageExtent.depth = 1;
|
||||
region.imageExtent.width = w;
|
||||
region.imageExtent.height = h;
|
||||
cmdbuffer->copyBufferToImage(stagingBuffer->buffer, Lightmap.Image->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
|
||||
|
||||
fb->GetCommands()->TransferDeleteList->Add(std::move(stagingBuffer));
|
||||
|
||||
newPixelData.Clear();
|
||||
}
|
||||
|
||||
VkImageTransition()
|
||||
.AddImage(&Lightmap, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false, 0, count)
|
||||
.Execute(cmdbuffer);
|
||||
|
|
|
@ -23,7 +23,7 @@ public:
|
|||
|
||||
void BeginFrame();
|
||||
|
||||
void CreateLightmap(int LMTextureSize, int LMTextureCount);
|
||||
void CreateLightmap(int newLMTextureSize, int newLMTextureCount, TArray<uint16_t>&& newPixelData);
|
||||
void SetLightmap(int LMTextureSize, int LMTextureCount, const TArray<uint16_t>& LMTextureData);
|
||||
|
||||
VkTextureImage* GetTexture(const PPTextureType& type, PPTexture* tex);
|
||||
|
|
|
@ -474,7 +474,7 @@ void VulkanRenderDevice::BeginFrame()
|
|||
if (levelMesh && levelMesh->GetSurfaceCount() > 0)
|
||||
{
|
||||
levelMesh->UpdateLightLists();
|
||||
GetTextureManager()->CreateLightmap(levelMesh->LMTextureSize, levelMesh->LMTextureCount);
|
||||
GetTextureManager()->CreateLightmap(levelMesh->LMTextureSize, levelMesh->LMTextureCount, std::move(levelMesh->LMTextureData));
|
||||
GetLightmap()->SetLevelMesh(levelMesh);
|
||||
|
||||
#if 0 // full lightmap generation
|
||||
|
|
|
@ -93,6 +93,7 @@ enum
|
|||
|
||||
CVAR (Bool, genblockmap, false, CVAR_SERVERINFO|CVAR_GLOBALCONFIG);
|
||||
CVAR (Bool, gennodes, false, CVAR_SERVERINFO|CVAR_GLOBALCONFIG);
|
||||
CVAR (Bool, genlightmaps, true, CVAR_GLOBALCONFIG);
|
||||
|
||||
inline bool P_LoadBuildMap(uint8_t *mapdata, size_t len, FMapThing **things, int *numthings)
|
||||
{
|
||||
|
@ -2938,7 +2939,7 @@ void MapLoader::CalcIndices()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void MapLoader::InitLevelMesh()
|
||||
void MapLoader::InitLevelMesh(MapData* map)
|
||||
{
|
||||
// Propagate sample distance where it isn't yet set
|
||||
for (auto& line : Level->lines)
|
||||
|
@ -2960,9 +2961,281 @@ void MapLoader::InitLevelMesh()
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Last chance to make up our mind whether to use lightmaps or not
|
||||
if (!Level->lightmaps)
|
||||
{
|
||||
if (map->Size(ML_LIGHTMAP))
|
||||
{
|
||||
Level->lightmaps = true;
|
||||
Printf(PRINT_HIGH, "InitLevelMesh: The level contains LIGHTMAP, but no ZDRayInfo thing was detected in the level.\n");
|
||||
}
|
||||
|
||||
Level->lightmaps = *genlightmaps;
|
||||
}
|
||||
|
||||
// Levelmesh and lightmap binding/loading
|
||||
Level->levelMesh = new DoomLevelMesh(*Level);
|
||||
Level->lightmaps = true;
|
||||
|
||||
if (Level->lightmaps)
|
||||
{
|
||||
LoadLightmap(map);
|
||||
Level->levelMesh->BindLightmapSurfacesToGeometry(*Level);
|
||||
}
|
||||
else
|
||||
{
|
||||
Level->levelMesh->Surfaces.Clear(); // Temp hack that disables lightmapping
|
||||
}
|
||||
}
|
||||
|
||||
void MapLoader::LoadLightmap(MapData* map)
|
||||
{
|
||||
if (!map->Size(ML_LIGHTMAP))
|
||||
return;
|
||||
|
||||
FileReader fr;
|
||||
if (!fr.OpenDecompressor(map->Reader(ML_LIGHTMAP), -1, FileSys::METHOD_ZLIB, false, true))
|
||||
return;
|
||||
|
||||
int version = fr.ReadInt32();
|
||||
if (version == 0)
|
||||
{
|
||||
Printf(PRINT_HIGH, "LoadLightmap: This is an old unsupported alpha version of the lightmap lump. Please rebuild the map with a newer version of zdray.\n");
|
||||
return;
|
||||
}
|
||||
if (version != 1)
|
||||
{
|
||||
Printf(PRINT_HIGH, "LoadLightmap: unsupported lightmap lump version\n");
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t textureSize = fr.ReadUInt16();
|
||||
uint16_t numTextures = fr.ReadUInt16();
|
||||
uint32_t numSurfaces = fr.ReadUInt32();
|
||||
uint32_t numTexCoords = fr.ReadUInt32();
|
||||
uint32_t numSubsectors = fr.ReadUInt32();
|
||||
uint32_t numTexBytes = numTextures * textureSize * textureSize * 3 * 2;
|
||||
if (numSurfaces == 0 || numTexCoords == 0 || numTexBytes == 0)
|
||||
return;
|
||||
|
||||
float sunDir[3], sunColor[3];
|
||||
fr.Read(sunDir, sizeof(float) * 3);
|
||||
fr.Read(sunColor, sizeof(float) * 3);
|
||||
Level->SunDirection = FVector3(sunDir);
|
||||
Level->SunColor = FVector3(sunColor);
|
||||
|
||||
/*if (numSubsectors != Level->subsectors.Size())
|
||||
{
|
||||
Printf(PRINT_HIGH, "LoadLightmap: subsector count for level doesn't match (%d in wad vs %d in engine)\n", (int)numSubsectors, (int)Level->subsectors.Size());
|
||||
}*/
|
||||
|
||||
//Level->LMTexCoords.Resize(numTexCoords * 2);
|
||||
|
||||
// Allocate room for all surfaces
|
||||
|
||||
#if 0
|
||||
unsigned int allSurfaces = 0;
|
||||
|
||||
for (unsigned int i = 0; i < Level->sides.Size(); i++)
|
||||
allSurfaces += 4 + Level->sides[i].sector->e->XFloor.ffloors.Size();
|
||||
|
||||
for (unsigned int i = 0; i < Level->subsectors.Size(); i++)
|
||||
allSurfaces += 2 + Level->subsectors[i].sector->e->XFloor.ffloors.Size() * 2;
|
||||
|
||||
Level->LMSurfaces.Resize(allSurfaces);
|
||||
memset(&Level->LMSurfaces[0], 0, sizeof(LightmapSurface) * allSurfaces);
|
||||
|
||||
// Link the surfaces to sectors, sides and their 3D floors
|
||||
|
||||
unsigned int offset = 0;
|
||||
for (unsigned int i = 0; i < Level->sides.Size(); i++)
|
||||
{
|
||||
auto& side = Level->sides[i];
|
||||
side.lightmap = &Level->LMSurfaces[offset];
|
||||
offset += 4 + side.sector->e->XFloor.ffloors.Size();
|
||||
}
|
||||
for (unsigned int i = 0; i < Level->subsectors.Size(); i++)
|
||||
{
|
||||
auto& subsector = Level->subsectors[i];
|
||||
unsigned int count = 1 + subsector.sector->e->XFloor.ffloors.Size();
|
||||
subsector.lightmap[0] = &Level->LMSurfaces[offset];
|
||||
subsector.lightmap[1] = &Level->LMSurfaces[offset + count];
|
||||
offset += count * 2;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool errors = false;
|
||||
|
||||
// Load the surfaces we have lightmap data for
|
||||
|
||||
// TODO more optimized way:
|
||||
auto findSurfaceIndex = [&](int type, int index, const sector_t* sec) {
|
||||
const auto& surfaces = Level->levelMesh->Surfaces;
|
||||
for (unsigned i = 0, count = surfaces.Size(); i < count; ++i)
|
||||
{
|
||||
if (surfaces[i].Type == type && surfaces[i].typeIndex == index && sec == surfaces[i].ControlSector)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return 0xffffffff;
|
||||
};
|
||||
|
||||
TArray<DoomLevelMeshSurface> zdraySurfaces;
|
||||
|
||||
for (uint32_t i = 0; i < numSurfaces; i++)
|
||||
{
|
||||
LevelMeshSurfaceType type = (LevelMeshSurfaceType)fr.ReadUInt32();
|
||||
uint32_t typeIndex = fr.ReadUInt32();
|
||||
uint32_t controlSectorIndex = fr.ReadUInt32();
|
||||
uint32_t lightmapNum = fr.ReadUInt32();
|
||||
uint32_t firstTexCoord = fr.ReadUInt32();
|
||||
|
||||
auto controlSector = controlSectorIndex < Level->sectors.Size() ? &Level->sectors[controlSectorIndex] : nullptr;
|
||||
|
||||
// Check against the internal levelmesh
|
||||
|
||||
if (i >= Level->levelMesh->Surfaces.Size())
|
||||
{
|
||||
errors = true;
|
||||
if (*developer >= 1)
|
||||
{
|
||||
Printf(PRINT_HIGH, "Lightmap lump surface index %d is out of bounds\n", i);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
auto levelSurface = &Level->levelMesh->Surfaces[i];
|
||||
|
||||
if (levelSurface->Type != type || levelSurface->typeIndex != typeIndex || levelSurface->ControlSector != controlSector)
|
||||
{
|
||||
auto internalIndex = findSurfaceIndex(type, typeIndex, controlSector);
|
||||
|
||||
if (internalIndex < Level->levelMesh->Surfaces.Size())
|
||||
{
|
||||
levelSurface = &Level->levelMesh->Surfaces[internalIndex];
|
||||
}
|
||||
else
|
||||
{
|
||||
errors = true;
|
||||
if (*developer >= 1)
|
||||
{
|
||||
Printf(PRINT_HIGH, "Lightmap lump surface %d mismatch. Couldn't find surface type:%d, typeindex:%d, controlsector:%d\n", i, type, typeIndex, controlSectorIndex);
|
||||
}
|
||||
// TODO detailed printout
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
DoomLevelMeshSurface surface;
|
||||
|
||||
surface.startUvIndex = firstTexCoord;
|
||||
surface.typeIndex = typeIndex;
|
||||
surface.ControlSector = controlSector;
|
||||
surface.Type = type;
|
||||
surface.numVerts = levelSurface->numVerts;
|
||||
surface.atlasPageIndex = lightmapNum;
|
||||
|
||||
|
||||
zdraySurfaces.Push(surface);
|
||||
|
||||
#if 0
|
||||
if (type == ST_CEILING || type == ST_FLOOR)
|
||||
{
|
||||
surface.Subsector = &Level->subsectors[typeIndex];
|
||||
surface.Subsector->firstline->sidedef->sector->HasLightmaps = true;
|
||||
SetSubsectorLightmap(surface);
|
||||
}
|
||||
else if (type != ST_NULL)
|
||||
{
|
||||
surface.Side = &Level->sides[typeIndex];
|
||||
SetSideLightmap(surface);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Load texture coordinates
|
||||
TArray<FVector2> zdrayUvs;
|
||||
zdrayUvs.Resize(numTexCoords);
|
||||
fr.Read(&zdrayUvs[0], numTexCoords * 2 * sizeof(float));
|
||||
|
||||
// Load lightmap textures
|
||||
Level->levelMesh->LMTextureData.Resize(Level->levelMesh->LMTextureCount* Level->levelMesh->LMTextureSize * Level->levelMesh->LMTextureSize * 3);
|
||||
|
||||
TArray<uint16_t> textureData;
|
||||
textureData.Resize((numTexBytes + 1) / 2);
|
||||
uint8_t* data = (uint8_t*)&textureData[0];
|
||||
fr.Read(data, numTexBytes);
|
||||
|
||||
// Remap the ZDRay atlas into internal lightmapper
|
||||
for (auto& surface : zdraySurfaces)
|
||||
{
|
||||
auto& realSurface = Level->levelMesh->Surfaces[findSurfaceIndex(surface.Type, surface.typeIndex, surface.ControlSector)];
|
||||
|
||||
// what are the pixel boundaries in the atlas?
|
||||
BBox bbox;
|
||||
for (int i = 0; i < surface.numVerts; ++i)
|
||||
{
|
||||
auto& uv = zdrayUvs[surface.startUvIndex + i];
|
||||
bbox.AddPoint(FVector3(uv.X, uv.Y, 0));
|
||||
}
|
||||
|
||||
// calculate pixel positions
|
||||
int srcMinX = (int)floorf(bbox.min.X * textureSize - 1.0f);
|
||||
int srcMinY = (int)floorf(bbox.min.Y * textureSize - 1.0f);
|
||||
int srcMaxX = (int)ceilf(bbox.max.X * textureSize + 1.0f);
|
||||
int srcMaxY = (int)ceilf(bbox.max.Y * textureSize + 1.0f);
|
||||
int srcPage = surface.atlasPageIndex;
|
||||
int srcW = srcMaxX - srcMinX;
|
||||
int srcH = srcMaxY - srcMinY;
|
||||
|
||||
// Now let's check
|
||||
|
||||
int dstX = realSurface.atlasX;
|
||||
int dstY = realSurface.atlasY;
|
||||
int dstPage = realSurface.atlasPageIndex;
|
||||
|
||||
// Sanity checks
|
||||
if (srcMinX < 0 || srcMinY < 0 || dstX < 0 || dstY < 0 || srcMaxX >= textureSize || srcMaxY >= textureSize || dstX + srcW >= textureSize || dstY + srcH >= textureSize || srcPage >= numTextures || dstPage >= Level->levelMesh->LMTextureCount)
|
||||
{
|
||||
errors = true;
|
||||
if (*developer >= 1)
|
||||
{
|
||||
Printf("Can't remap lightmap surface ((%d, %d), (%d, %d), %d) -> ((%d, %d), (%d, %d), %d)\n", srcMinX, srcMinY, srcMaxX, srcMaxY, srcPage, dstX, dstY, dstX + srcW, dstY + srcH, dstPage);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// copy pixels
|
||||
uint16_t* src = &textureData[0];
|
||||
uint16_t* dst = &Level->levelMesh->LMTextureData[0];
|
||||
|
||||
for (int y = srcMinY, y2 = dstY; y < srcMaxY; ++y, ++y2)
|
||||
{
|
||||
for (int x = srcMinX, x2 = dstX; x < srcMaxX; ++x, ++x2)
|
||||
{
|
||||
int index = (x + y * textureSize + srcPage * textureSize * textureSize) * 3;
|
||||
int dstIndex = (x2 + y2 * textureSize + dstPage * textureSize * textureSize) * 3;
|
||||
|
||||
dst[dstIndex] = src[index];
|
||||
dst[dstIndex + 1] = src[index + 1];
|
||||
dst[dstIndex + 2] = src[index + 2];
|
||||
}
|
||||
}
|
||||
|
||||
realSurface.needsUpdate = false; // this surface is good
|
||||
}
|
||||
|
||||
if (errors && developer <= 0)
|
||||
{
|
||||
Printf(PRINT_HIGH, "Pre-calculated LIGHTMAP surfaces do not match current level surfaces. Restart this level with 'developer 1' for further details.\nPerhaps you forget to rebuild lightmaps after modifying the map?");
|
||||
}
|
||||
#if 0
|
||||
// Apply compression predictor
|
||||
for (uint32_t i = 1; i < numTexBytes; i++)
|
||||
data[i] += data[i - 1];
|
||||
#endif
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -2979,6 +3252,7 @@ void MapLoader::LoadLevel(MapData *map, const char *lumpname, int position)
|
|||
Level->SunColor = FVector3(1.f, 1.f, 1.f);
|
||||
Level->SunDirection = FVector3(0.45f, 0.3f, 0.9f);
|
||||
Level->LightmapSampleDistance = 16;
|
||||
Level->lightmaps = false;
|
||||
|
||||
// note: most of this ordering is important
|
||||
ForceNodeBuild = gennodes;
|
||||
|
@ -3258,7 +3532,7 @@ void MapLoader::LoadLevel(MapData *map, const char *lumpname, int position)
|
|||
// set up world state
|
||||
SpawnSpecials();
|
||||
|
||||
InitLevelMesh();
|
||||
InitLevelMesh(map);
|
||||
|
||||
// disable reflective planes on sloped sectors.
|
||||
for (auto &sec : Level->sectors)
|
||||
|
|
|
@ -304,7 +304,8 @@ public:
|
|||
void SetSlopes();
|
||||
void CopySlopes();
|
||||
|
||||
void InitLevelMesh();
|
||||
void InitLevelMesh(MapData* map);
|
||||
void LoadLightmap(MapData* map);
|
||||
|
||||
void LoadLevel(MapData *map, const char *lumpname, int position);
|
||||
|
||||
|
|
|
@ -835,6 +835,7 @@ public:
|
|||
|
||||
auto pc = pitch.Cos();
|
||||
Level->SunDirection = -FVector3 { pc * angle.Cos(), pc * angle.Sin(), -pitch.Sin() }; // [RaveYard]: is there a dedicated function for this?
|
||||
Level->lightmaps = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -95,18 +95,8 @@ DoomLevelMesh::DoomLevelMesh(FLevelLocals &doomMap)
|
|||
}
|
||||
|
||||
SetupLightmapUvs();
|
||||
BindLightmapSurfacesToGeometry(doomMap);
|
||||
|
||||
Collision = std::make_unique<TriangleMeshShape>(MeshVertices.Data(), MeshVertices.Size(), MeshElements.Data(), MeshElements.Size());
|
||||
|
||||
// Runtime stuff
|
||||
for (auto& surface : Surfaces)
|
||||
{
|
||||
if ((surface.Type == ST_FLOOR || surface.Type == ST_CEILING) && surface.ControlSector)
|
||||
{
|
||||
XFloorToSurface[surface.Subsector->sector].Push(&surface);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DoomLevelMesh::CreatePortals()
|
||||
|
@ -382,6 +372,15 @@ void DoomLevelMesh::BindLightmapSurfacesToGeometry(FLevelLocals& doomMap)
|
|||
SetSideLightmap(&surface);
|
||||
}
|
||||
}
|
||||
|
||||
// Runtime helper
|
||||
for (auto& surface : Surfaces)
|
||||
{
|
||||
if ((surface.Type == ST_FLOOR || surface.Type == ST_CEILING) && surface.ControlSector)
|
||||
{
|
||||
XFloorToSurface[surface.Subsector->sector].Push(&surface);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DoomLevelMesh::SetSubsectorLightmap(DoomLevelMeshSurface* surface)
|
||||
|
|
|
@ -29,6 +29,7 @@ public:
|
|||
|
||||
void CreatePortals();
|
||||
void DumpMesh(const FString& objFilename, const FString& mtlFilename) const;
|
||||
void BindLightmapSurfacesToGeometry(FLevelLocals& doomMap);
|
||||
|
||||
bool TraceSky(const FVector3& start, FVector3 direction, float dist)
|
||||
{
|
||||
|
@ -58,7 +59,6 @@ private:
|
|||
void CreateFloorSurface(FLevelLocals &doomMap, subsector_t *sub, sector_t *sector, int typeIndex, bool is3DFloor);
|
||||
void CreateSideSurfaces(FLevelLocals &doomMap, side_t *side);
|
||||
|
||||
void BindLightmapSurfacesToGeometry(FLevelLocals& doomMap);
|
||||
void SetSubsectorLightmap(DoomLevelMeshSurface* surface);
|
||||
void SetSideLightmap(DoomLevelMeshSurface* surface);
|
||||
|
||||
|
|
|
@ -504,25 +504,27 @@ void HWFlat::ProcessSector(HWDrawInfo *di, FRenderState& state, sector_t * front
|
|||
//
|
||||
// Lightmaps
|
||||
//
|
||||
|
||||
for (int i = 0, count = sector->subsectorcount; i < count; ++i)
|
||||
if (level.lightmaps)
|
||||
{
|
||||
for (int plane = 0; plane < 2; ++plane)
|
||||
for (int i = 0, count = sector->subsectorcount; i < count; ++i)
|
||||
{
|
||||
if (auto lightmap = sector->subsectors[i]->lightmap[plane][0])
|
||||
for (int plane = 0; plane < 2; ++plane)
|
||||
{
|
||||
state.PushVisibleSurface(lightmap);
|
||||
if (auto lightmap = sector->subsectors[i]->lightmap[plane][0])
|
||||
{
|
||||
state.PushVisibleSurface(lightmap);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (auto subsectors = sector->Level->levelMesh->XFloorToSurface.CheckKey(sector))
|
||||
{
|
||||
for (auto* surface : *subsectors)
|
||||
if (auto subsectors = sector->Level->levelMesh->XFloorToSurface.CheckKey(sector))
|
||||
{
|
||||
if (surface)
|
||||
for (auto* surface : *subsectors)
|
||||
{
|
||||
state.PushVisibleSurface(surface);
|
||||
if (surface)
|
||||
{
|
||||
state.PushVisibleSurface(surface);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue