mirror of
https://github.com/ZDoom/ZDRay.git
synced 2024-11-21 19:50:54 +00:00
Add lights
This commit is contained in:
parent
2d1c0acff2
commit
0a7108c3b1
3 changed files with 114 additions and 11 deletions
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue