Save lightmap lump

This commit is contained in:
Magnus Norddahl 2023-10-16 16:46:35 +02:00
parent df010a5643
commit 7c1acb5075
6 changed files with 50 additions and 69 deletions

View file

@ -941,8 +941,7 @@ void FProcessor::WriteUDMF(FWadWriter &out)
if (LightmapMesh) if (LightmapMesh)
{ {
LightmapMesh->AddLightmapLump(out); LightmapMesh->AddLightmapLump(Level, out);
//LightmapMesh->Export("level.obj");
} }
out.CreateLabel("ENDMAP"); out.CreateLabel("ENDMAP");

View file

@ -2,6 +2,7 @@
#include "doom_levelmesh.h" #include "doom_levelmesh.h"
#include "level/level.h" #include "level/level.h"
#include "framework/halffloat.h" #include "framework/halffloat.h"
#include "framework/binfile.h"
#include <algorithm> #include <algorithm>
#include <map> #include <map>
@ -27,7 +28,7 @@ void DoomLevelMesh::DumpMesh(const FString& objFilename, const FString& mtlFilen
static_cast<DoomLevelSubmesh*>(StaticMesh.get())->DumpMesh(objFilename, mtlFilename); static_cast<DoomLevelSubmesh*>(StaticMesh.get())->DumpMesh(objFilename, mtlFilename);
} }
void DoomLevelMesh::AddLightmapLump(FWadWriter& wadFile) void DoomLevelMesh::AddLightmapLump(FLevel& doomMap, FWadWriter& wadFile)
{ {
/* /*
// LIGHTMAP V2 pseudo-C specification: // LIGHTMAP V2 pseudo-C specification:
@ -62,20 +63,15 @@ void DoomLevelMesh::AddLightmapLump(FWadWriter& wadFile)
for (unsigned int i = 0; i < submesh->Surfaces.Size(); i++) for (unsigned int i = 0; i < submesh->Surfaces.Size(); i++)
{ {
DoomLevelMeshSurface* surface = &submesh->Surfaces[i]; DoomLevelMeshSurface* surface = &submesh->Surfaces[i];
if (surface->atlasPageIndex != -1) if (surface->AtlasTile.ArrayIndex != -1)
{ {
surfaceCount++; surfaceCount++;
pixelCount += surface->Area(); pixelCount += surface->Area();
uvCount += surface->verts.size(); uvCount += surface->numVerts;
if (surface->Area() != surf.texPixels.size())
{
printf("Error: Surface area does not match the pixel count.\n");
}
} }
} }
printf(" Writing %u surfaces out of %llu\n", surfaceCount, surfaces.size()); printf(" Writing %u surfaces out of %llu\n", surfaceCount, (size_t)submesh->Surfaces.Size());
const int version = 2; const int version = 2;
@ -118,23 +114,23 @@ void DoomLevelMesh::AddLightmapLump(FWadWriter& wadFile)
{ {
DoomLevelMeshSurface* surface = &submesh->Surfaces[i]; DoomLevelMeshSurface* surface = &submesh->Surfaces[i];
if (surface->atlasPageIndex == -1) if (surface->AtlasTile.ArrayIndex == -1)
continue; continue;
lumpFile.Write32(surface->Type); lumpFile.Write32(surface->Type);
lumpFile.Write32(surface->TypeIndex); lumpFile.Write32(surface->TypeIndex);
lumpFile.Write32(surface->ControlSector ? uint32_t(surface->ControlSector - &map->Sectors[0]) : 0xffffffff); lumpFile.Write32(surface->ControlSector ? uint32_t(surface->ControlSector->Index(doomMap)) : 0xffffffff);
lumpFile.Write16(uint16_t(surface->texWidth)); lumpFile.Write16(uint16_t(surface->AtlasTile.Width));
lumpFile.Write16(uint16_t(surface->texHeight)); lumpFile.Write16(uint16_t(surface->AtlasTile.Height));
lumpFile.Write32(pixelsOffset * 3); lumpFile.Write32(pixelsOffset * 3);
lumpFile.Write32(surface->lightUV.size()); lumpFile.Write32(surface->numVerts);
lumpFile.Write32(uvOffset); lumpFile.Write32(uvOffset);
pixelsOffset += surface->Area(); pixelsOffset += surface->Area();
uvOffset += surface->lightUV.size(); uvOffset += (uint32_t)surface->numVerts;
} }
if (debug) if (debug)
@ -147,19 +143,22 @@ void DoomLevelMesh::AddLightmapLump(FWadWriter& wadFile)
{ {
DoomLevelMeshSurface* surface = &submesh->Surfaces[i]; DoomLevelMeshSurface* surface = &submesh->Surfaces[i];
if (surface->atlasPageIndex == -1) if (surface->AtlasTile.ArrayIndex == -1)
continue; continue;
if (debug) const uint16_t* pixels = submesh->LMTextureData.Data() + surface->AtlasTile.ArrayIndex * submesh->LMTextureSize * submesh->LMTextureSize * 4;
int width = surface->AtlasTile.Width;
int height = surface->AtlasTile.Height;
for (int y = 0; y < height; y++)
{ {
printf("Surface %llu contains %llu pixels\n", i, surface->texPixels.size()); const uint16_t* srcline = pixels + (surface->AtlasTile.X + (surface->AtlasTile.Y + y) * submesh->LMTextureSize) * 4;
for (int x = 0; x < width; x++)
{
lumpFile.Write16(*(srcline++));
lumpFile.Write16(*(srcline++));
lumpFile.Write16(*(srcline++));
srcline++;
} }
for (const auto& pixel : surface->texPixels)
{
lumpFile.Write16(floatToHalf(clamp(pixel.r, 0.0f, 65000.0f)));
lumpFile.Write16(floatToHalf(clamp(pixel.g, 0.0f, 65000.0f)));
lumpFile.Write16(floatToHalf(clamp(pixel.b, 0.0f, 65000.0f)));
} }
} }
@ -173,45 +172,32 @@ void DoomLevelMesh::AddLightmapLump(FWadWriter& wadFile)
{ {
DoomLevelMeshSurface* surface = &submesh->Surfaces[i]; DoomLevelMeshSurface* surface = &submesh->Surfaces[i];
if (surface->atlasPageIndex == -1) if (surface->AtlasTile.ArrayIndex == -1)
continue; continue;
if (debug) if (debug)
{ {
printf("Surface %llu contains %llu UVs\n", i, surface->verts.size()); printf("Surface %u contains %u UVs\n", i, surface->numVerts);
} }
// as of V2 LIGHTMAP version: internal lightmapper uses ZDRay order triangle strips in its internal representation. It will convert from triangle strips to triangle fan on its own. // as of V2 LIGHTMAP version: internal lightmapper uses ZDRay order triangle strips in its internal representation. It will convert from triangle strips to triangle fan on its own.
int count = surface->verts.size(); float offsetU = surface->AtlasTile.X / (float)submesh->LMTextureSize;
if (surface->type == ST_FLOOR || surface->type == ST_CEILING) float offsetV = surface->AtlasTile.Y / (float)submesh->LMTextureSize;
float scaleU = surface->AtlasTile.Width / (float)submesh->LMTextureSize;
float scaleV = surface->AtlasTile.Height / (float)submesh->LMTextureSize;
FVector2* texcoords = (FVector2*)surface->TexCoords;
for (int j = 0, count = surface->numVerts; j < count; j++)
{ {
for (int j = 0; j < count; j++) lumpFile.WriteFloat((texcoords[j].X - offsetU) * scaleU);
{ lumpFile.WriteFloat((texcoords[j].Y - offsetV) * scaleV);
lumpFile.WriteFloat(surface->lightUV[j].x);
lumpFile.WriteFloat(surface->lightUV[j].y);
}
}
else
{
lumpFile.WriteFloat(surface->lightUV[0].x);
lumpFile.WriteFloat(surface->lightUV[0].y);
lumpFile.WriteFloat(surface->lightUV[1].x);
lumpFile.WriteFloat(surface->lightUV[1].y);
lumpFile.WriteFloat(surface->lightUV[2].x);
lumpFile.WriteFloat(surface->lightUV[2].y);
lumpFile.WriteFloat(surface->lightUV[3].x);
lumpFile.WriteFloat(surface->lightUV[3].y);
} }
} }
// Compress and store in lump // Compress and store in lump
ZLibOut zout(wadFile); ZLibOut zout(wadFile);
wadFile.StartWritingLump("LIGHTMAP"); wadFile.StartWritingLump("LIGHTMAP");
zout.Write(buffer.data(), lumpFile.BufferAt() - lumpFile.Buffer()); zout.Write(buffer.data(), (int)(ptrdiff_t)(lumpFile.BufferAt() - lumpFile.Buffer()));
} }
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
@ -1150,12 +1136,10 @@ void DoomLevelSubmesh::DumpMesh(const FString& objFilename, const FString& mtlFi
fprintf(f, "v %f %f %f\n", v.X * scale, v.Z * scale, -v.Y * scale); fprintf(f, "v %f %f %f\n", v.X * scale, v.Z * scale, -v.Y * scale);
} }
{
for (const auto& uv : LightmapUvs) for (const auto& uv : LightmapUvs)
{ {
fprintf(f, "vt %f %f\n", uv.X, uv.Y); fprintf(f, "vt %f %f\n", uv.X, uv.Y);
} }
}
auto name = [](DoomLevelMeshSurfaceType type) -> const char* { auto name = [](DoomLevelMeshSurfaceType type) -> const char* {
switch (type) switch (type)

View file

@ -15,7 +15,7 @@ public:
int AddSurfaceLights(const LevelMeshSurface* surface, LevelMeshLight* list, int listMaxSize) override; int AddSurfaceLights(const LevelMeshSurface* surface, LevelMeshLight* list, int listMaxSize) override;
void DumpMesh(const FString& objFilename, const FString& mtlFilename) const; void DumpMesh(const FString& objFilename, const FString& mtlFilename) const;
void AddLightmapLump(FWadWriter& out); void AddLightmapLump(FLevel& doomMap, FWadWriter& out);
}; };
enum DoomLevelMeshSurfaceType enum DoomLevelMeshSurfaceType
@ -55,7 +55,6 @@ public:
void BindLightmapSurfacesToGeometry(FLevel& doomMap); void BindLightmapSurfacesToGeometry(FLevel& doomMap);
void PackLightmapAtlas(int lightmapStartIndex); void PackLightmapAtlas(int lightmapStartIndex);
void CreatePortals(FLevel& doomMap); void CreatePortals(FLevel& doomMap);
void DisableLightmaps() { Surfaces.Clear(); } // Temp hack that disables lightmapping
TArray<DoomLevelMeshSurface> Surfaces; TArray<DoomLevelMeshSurface> Surfaces;
TArray<FVector2> LightmapUvs; TArray<FVector2> LightmapUvs;

View file

@ -39,8 +39,9 @@ void GPURaytracer::Raytrace(DoomLevelMesh* mesh)
{ {
auto raytrace = mDevice->GetRaytrace(); auto raytrace = mDevice->GetRaytrace();
auto lightmap = mDevice->GetLightmap(); auto lightmap = mDevice->GetLightmap();
auto submesh = mesh->StaticMesh.get();
// mDevice->GetTextureManager()->CreateLightmap(mesh->LMTextureSize, mesh->LMTextureCount); mDevice->GetTextureManager()->CreateLightmap(submesh->LMTextureSize, submesh->LMTextureCount);
printf("."); printf(".");
raytrace->SetLevelMesh(mesh); raytrace->SetLevelMesh(mesh);
@ -49,16 +50,15 @@ void GPURaytracer::Raytrace(DoomLevelMesh* mesh)
lightmap->BeginFrame(); lightmap->BeginFrame();
printf("."); printf(".");
// lightmap->Raytrace(surfaces); //lightmap->Raytrace(surfaces);
printf("."); printf(".");
/*
TArray<uint16_t> buffer; submesh->LMTextureData.Resize(submesh->LMTextureSize * submesh->LMTextureSize * submesh->LMTextureCount * 4);
for (int arrayIndex = 0; arrayIndex < mesh->LMTextureCount; arrayIndex++) for (int arrayIndex = 0; arrayIndex < submesh->LMTextureCount; arrayIndex++)
{ {
mDevice->GetTextureManager()->DownloadLightmap(arrayIndex, buffer); mDevice->GetTextureManager()->DownloadLightmap(arrayIndex, submesh->LMTextureData.Data() + arrayIndex * submesh->LMTextureSize * submesh->LMTextureSize * 4);
} }
*/
} }
catch (...) catch (...)
{ {

View file

@ -116,10 +116,9 @@ void VkTextureManager::CreateLightmap(int newLMTextureSize, int newLMTextureCoun
.Execute(fb->GetCommands()->GetTransferCommands(), 0, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); .Execute(fb->GetCommands()->GetTransferCommands(), 0, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
} }
void VkTextureManager::DownloadLightmap(int arrayIndex, TArray<uint16_t>& buffer) void VkTextureManager::DownloadLightmap(int arrayIndex, uint16_t* buffer)
{ {
unsigned int totalSize = LMTextureSize * LMTextureSize; unsigned int totalSize = LMTextureSize * LMTextureSize * 4;
buffer.Resize(totalSize);
auto stagingBuffer = BufferBuilder() auto stagingBuffer = BufferBuilder()
.Size(totalSize * sizeof(uint16_t)) .Size(totalSize * sizeof(uint16_t))
@ -150,7 +149,7 @@ void VkTextureManager::DownloadLightmap(int arrayIndex, TArray<uint16_t>& buffer
fb->GetCommands()->SubmitAndWait(); fb->GetCommands()->SubmitAndWait();
uint16_t* srcdata = (uint16_t*)stagingBuffer->Map(0, totalSize * sizeof(uint16_t)); uint16_t* srcdata = (uint16_t*)stagingBuffer->Map(0, totalSize * sizeof(uint16_t));
memcpy(buffer.Data(), srcdata, totalSize * sizeof(uint16_t)); memcpy(buffer, srcdata, totalSize * sizeof(uint16_t));
stagingBuffer->Unmap(); stagingBuffer->Unmap();
} }

View file

@ -113,7 +113,7 @@ public:
VkTextureManager(VulkanRenderDevice* fb); VkTextureManager(VulkanRenderDevice* fb);
void CreateLightmap(int newLMTextureSize, int newLMTextureCount); void CreateLightmap(int newLMTextureSize, int newLMTextureCount);
void DownloadLightmap(int arrayIndex, TArray<uint16_t>& buffer); void DownloadLightmap(int arrayIndex, uint16_t* buffer);
VkTextureImage Lightmap; VkTextureImage Lightmap;
int LMTextureSize = 0; int LMTextureSize = 0;