Add lights

This commit is contained in:
Magnus Norddahl 2023-10-17 18:29:27 +02:00
parent 2d1c0acff2
commit 0a7108c3b1
3 changed files with 114 additions and 11 deletions

View file

@ -5,6 +5,7 @@
#include "framework/binfile.h" #include "framework/binfile.h"
#include <algorithm> #include <algorithm>
#include <map> #include <map>
#include <set>
extern float lm_scale; extern float lm_scale;
@ -13,16 +14,42 @@ DoomLevelMesh::DoomLevelMesh(FLevel& doomMap, int samples, int lmdims)
SunColor = doomMap.defaultSunColor; // TODO keep only one copy? SunColor = doomMap.defaultSunColor; // TODO keep only one copy?
SunDirection = doomMap.defaultSunDirection; SunDirection = doomMap.defaultSunDirection;
printf(" Building level mesh\n");
StaticMesh = std::make_unique<DoomLevelSubmesh>(); StaticMesh = std::make_unique<DoomLevelSubmesh>();
static_cast<DoomLevelSubmesh*>(StaticMesh.get())->CreateStatic(doomMap); static_cast<DoomLevelSubmesh*>(StaticMesh.get())->CreateStatic(doomMap);
static_cast<DoomLevelSubmesh*>(StaticMesh.get())->PackLightmapAtlas(0); static_cast<DoomLevelSubmesh*>(StaticMesh.get())->PackLightmapAtlas(0);
static_cast<DoomLevelSubmesh*>(StaticMesh.get())->BindLightmapSurfacesToGeometry(doomMap); static_cast<DoomLevelSubmesh*>(StaticMesh.get())->BindLightmapSurfacesToGeometry(doomMap);
BuildLightLists(doomMap);
} }
int DoomLevelMesh::AddSurfaceLights(const LevelMeshSurface* surface, LevelMeshLight* list, int listMaxSize) int DoomLevelMesh::AddSurfaceLights(const LevelMeshSurface* surface, LevelMeshLight* list, int listMaxSize)
{ {
return 0; const DoomLevelMeshSurface* doomsurface = static_cast<const DoomLevelMeshSurface*>(surface);
int listpos = 0;
for (ThingLight* light : doomsurface->LightList)
{
if (listpos == listMaxSize)
break;
LevelMeshLight& meshlight = list[listpos++];
meshlight.Origin = light->LightOrigin();
meshlight.RelativeOrigin = light->LightRelativeOrigin();
meshlight.Radius = light->LightRadius();
meshlight.Intensity = light->intensity;
meshlight.InnerAngleCos = light->innerAngleCos;
meshlight.OuterAngleCos = light->outerAngleCos;
meshlight.SpotDir = light->SpotDir();
meshlight.Color = light->rgb;
/*if (light->sector)
meshlight.SectorGroup = static_cast<DoomLevelSubmesh*>(StaticMesh.get())->sectorGroup[light->sector->Index()];
else*/
meshlight.SectorGroup = 0;
}
return listpos;
} }
void DoomLevelMesh::DumpMesh(const FString& objFilename, const FString& mtlFilename) const void DoomLevelMesh::DumpMesh(const FString& objFilename, const FString& mtlFilename) const
@ -202,6 +229,73 @@ void DoomLevelMesh::AddLightmapLump(FLevel& doomMap, FWadWriter& wadFile)
zout.Write(buffer.data(), (int)(ptrdiff_t)(lumpFile.BufferAt() - lumpFile.Buffer())); zout.Write(buffer.data(), (int)(ptrdiff_t)(lumpFile.BufferAt() - lumpFile.Buffer()));
} }
void DoomLevelMesh::PropagateLight(FLevel& doomMap, ThingLight* light, int recursiveDepth)
{
if (recursiveDepth > 32)
return;
auto submesh = static_cast<DoomLevelSubmesh*>(StaticMesh.get());
SphereShape sphere;
sphere.center = light->LightRelativeOrigin();
sphere.radius = light->LightRadius();
//std::set<Portal, RecursivePortalComparator> portalsToErase;
for (int triangleIndex : TriangleMeshShape::find_all_hits(submesh->Collision.get(), &sphere))
{
DoomLevelMeshSurface* surface = &submesh->Surfaces[submesh->MeshSurfaceIndexes[triangleIndex]];
// skip any surface which isn't physically connected to the sector group in which the light resides
//if (light->sectorGroup == surface->sectorGroup)
{
/*if (surface->portalIndex >= 0)
{
auto portal = portals[surface->portalIndex].get();
if (touchedPortals.insert(*portal).second)
{
auto fakeLight = std::make_unique<ThingLight>(*light);
fakeLight->relativePosition.emplace(portal->TransformPosition(light->LightRelativeOrigin()));
fakeLight->sectorGroup = portal->targetSectorGroup;
PropagateLight(doomMap, fakeLight.get(), recursiveDepth + 1);
portalsToErase.insert(*portal);
portalLights.push_back(std::move(fakeLight));
}
}*/
// Add light to the list if it isn't already there
bool found = false;
for (ThingLight* light2 : surface->LightList)
{
if (light2 == light)
{
found = true;
break;
}
}
if (!found)
surface->LightList.push_back(light);
}
}
/*for (auto& portal : portalsToErase)
{
touchedPortals.erase(portal);
}*/
}
void DoomLevelMesh::BuildLightLists(FLevel& doomMap)
{
for (unsigned i = 0; i < doomMap.ThingLights.Size(); ++i)
{
printf(" Building light lists: %u / %u\r", i, doomMap.ThingLights.Size());
PropagateLight(doomMap, &doomMap.ThingLights[i]);
}
printf(" Building light lists: %u / %u\n", doomMap.ThingLights.Size(), doomMap.ThingLights.Size());
}
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
void DoomLevelSubmesh::CreateStatic(FLevel& doomMap) void DoomLevelSubmesh::CreateStatic(FLevel& doomMap)

View file

@ -14,8 +14,18 @@ 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(FLevel& doomMap, FWadWriter& out); void AddLightmapLump(FLevel& doomMap, FWadWriter& out);
private:
void BuildLightLists(FLevel& doomMap);
void PropagateLight(FLevel& doomMap, ThingLight* light, int recursiveDepth = 0);
// Portal to portals[] index
//std::map<Portal, int, IdenticalPortalComparator> portalCache;
// Portal lights
//std::vector<std::unique_ptr<ThingLight>> portalLights;
//std::set<Portal, RecursivePortalComparator> touchedPortals;
}; };
enum DoomLevelMeshSurfaceType enum DoomLevelMeshSurfaceType
@ -38,6 +48,8 @@ struct DoomLevelMeshSurface : public LevelMeshSurface
IntSector* ControlSector = nullptr; IntSector* ControlSector = nullptr;
float* TexCoords = nullptr; float* TexCoords = nullptr;
std::vector<ThingLight*> LightList;
}; };
class DoomLevelSubmesh : public LevelSubmesh class DoomLevelSubmesh : public LevelSubmesh

View file

@ -32,26 +32,22 @@ void GPURaytracer::Raytrace(DoomLevelMesh* mesh)
QueryPerformanceCounter(&s); QueryPerformanceCounter(&s);
#endif #endif
printf(" Ray tracing in progress\n");
printf(" [");
try try
{ {
auto raytrace = mDevice->GetRaytrace(); auto raytrace = mDevice->GetRaytrace();
auto lightmap = mDevice->GetLightmap(); auto lightmap = mDevice->GetLightmap();
auto submesh = mesh->StaticMesh.get(); auto submesh = mesh->StaticMesh.get();
printf(" Map uses %u lightmap textures\n", submesh->LMTextureCount);
mDevice->GetTextureManager()->CreateLightmap(submesh->LMTextureSize, submesh->LMTextureCount); mDevice->GetTextureManager()->CreateLightmap(submesh->LMTextureSize, submesh->LMTextureCount);
printf(".");
raytrace->SetLevelMesh(mesh); raytrace->SetLevelMesh(mesh);
lightmap->SetLevelMesh(mesh); lightmap->SetLevelMesh(mesh);
// Keep baking until all surfaces have been processed // Keep baking until all surfaces have been processed
while (true) while (true)
{ {
printf(".");
raytrace->BeginFrame(); raytrace->BeginFrame();
lightmap->BeginFrame(); lightmap->BeginFrame();
@ -68,12 +64,14 @@ void GPURaytracer::Raytrace(DoomLevelMesh* mesh)
if (surfaces.Size() == 0) if (surfaces.Size() == 0)
break; break;
printf(" Ray tracing surfaces: %u / %u\r", submesh->GetSurfaceCount() - surfaces.Size(), submesh->GetSurfaceCount());
lightmap->Raytrace(surfaces); lightmap->Raytrace(surfaces);
mDevice->GetCommands()->SubmitAndWait(); mDevice->GetCommands()->SubmitAndWait();
} }
printf("."); printf(" Ray tracing surfaces: %u / %u\n", submesh->GetSurfaceCount(), submesh->GetSurfaceCount());
submesh->LMTextureData.Resize(submesh->LMTextureSize * submesh->LMTextureSize * submesh->LMTextureCount * 4); submesh->LMTextureData.Resize(submesh->LMTextureSize * submesh->LMTextureSize * submesh->LMTextureCount * 4);
for (int arrayIndex = 0; arrayIndex < submesh->LMTextureCount; arrayIndex++) for (int arrayIndex = 0; arrayIndex < submesh->LMTextureCount; arrayIndex++)
@ -83,10 +81,9 @@ void GPURaytracer::Raytrace(DoomLevelMesh* mesh)
} }
catch (...) catch (...)
{ {
printf("]\n"); printf("\n");
throw; throw;
} }
printf("]\n");
#ifdef WIN32 #ifdef WIN32
LARGE_INTEGER e, f; LARGE_INTEGER e, f;