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 <algorithm>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
extern float lm_scale;
|
||||
|
||||
|
@ -13,16 +14,42 @@ DoomLevelMesh::DoomLevelMesh(FLevel& doomMap, int samples, int lmdims)
|
|||
SunColor = doomMap.defaultSunColor; // TODO keep only one copy?
|
||||
SunDirection = doomMap.defaultSunDirection;
|
||||
|
||||
printf(" Building level mesh\n");
|
||||
|
||||
StaticMesh = std::make_unique<DoomLevelSubmesh>();
|
||||
|
||||
static_cast<DoomLevelSubmesh*>(StaticMesh.get())->CreateStatic(doomMap);
|
||||
static_cast<DoomLevelSubmesh*>(StaticMesh.get())->PackLightmapAtlas(0);
|
||||
static_cast<DoomLevelSubmesh*>(StaticMesh.get())->BindLightmapSurfacesToGeometry(doomMap);
|
||||
|
||||
BuildLightLists(doomMap);
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -202,6 +229,73 @@ void DoomLevelMesh::AddLightmapLump(FLevel& doomMap, FWadWriter& wadFile)
|
|||
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)
|
||||
|
|
|
@ -14,8 +14,18 @@ public:
|
|||
|
||||
int AddSurfaceLights(const LevelMeshSurface* surface, LevelMeshLight* list, int listMaxSize) override;
|
||||
void DumpMesh(const FString& objFilename, const FString& mtlFilename) const;
|
||||
|
||||
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
|
||||
|
@ -38,6 +48,8 @@ struct DoomLevelMeshSurface : public LevelMeshSurface
|
|||
IntSector* ControlSector = nullptr;
|
||||
|
||||
float* TexCoords = nullptr;
|
||||
|
||||
std::vector<ThingLight*> LightList;
|
||||
};
|
||||
|
||||
class DoomLevelSubmesh : public LevelSubmesh
|
||||
|
|
|
@ -32,26 +32,22 @@ void GPURaytracer::Raytrace(DoomLevelMesh* mesh)
|
|||
QueryPerformanceCounter(&s);
|
||||
#endif
|
||||
|
||||
printf(" Ray tracing in progress\n");
|
||||
printf(" [");
|
||||
|
||||
try
|
||||
{
|
||||
auto raytrace = mDevice->GetRaytrace();
|
||||
auto lightmap = mDevice->GetLightmap();
|
||||
auto submesh = mesh->StaticMesh.get();
|
||||
|
||||
printf(" Map uses %u lightmap textures\n", submesh->LMTextureCount);
|
||||
|
||||
mDevice->GetTextureManager()->CreateLightmap(submesh->LMTextureSize, submesh->LMTextureCount);
|
||||
|
||||
printf(".");
|
||||
raytrace->SetLevelMesh(mesh);
|
||||
lightmap->SetLevelMesh(mesh);
|
||||
|
||||
// Keep baking until all surfaces have been processed
|
||||
while (true)
|
||||
{
|
||||
printf(".");
|
||||
|
||||
raytrace->BeginFrame();
|
||||
lightmap->BeginFrame();
|
||||
|
||||
|
@ -68,12 +64,14 @@ void GPURaytracer::Raytrace(DoomLevelMesh* mesh)
|
|||
if (surfaces.Size() == 0)
|
||||
break;
|
||||
|
||||
printf(" Ray tracing surfaces: %u / %u\r", submesh->GetSurfaceCount() - surfaces.Size(), submesh->GetSurfaceCount());
|
||||
|
||||
lightmap->Raytrace(surfaces);
|
||||
|
||||
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);
|
||||
for (int arrayIndex = 0; arrayIndex < submesh->LMTextureCount; arrayIndex++)
|
||||
|
@ -83,10 +81,9 @@ void GPURaytracer::Raytrace(DoomLevelMesh* mesh)
|
|||
}
|
||||
catch (...)
|
||||
{
|
||||
printf("]\n");
|
||||
printf("\n");
|
||||
throw;
|
||||
}
|
||||
printf("]\n");
|
||||
|
||||
#ifdef WIN32
|
||||
LARGE_INTEGER e, f;
|
||||
|
|
Loading…
Reference in a new issue