Add ZDRay light intensity support

This commit is contained in:
RaveYard 2023-09-06 15:15:58 +02:00 committed by Magnus Norddahl
commit c05ef67679
4 changed files with 133 additions and 64 deletions

View file

@ -174,19 +174,138 @@ void DoomLevelMesh::CreatePortals()
}
}
void DoomLevelMesh::UpdateLightLists()
void DoomLevelMesh::PropagateLight(const LevelMeshLight* light, std::set<LevelMeshPortal, RecursivePortalComparator>& touchedPortals, int lightPropagationRecursiveDepth)
{
for (auto& surface : Surfaces)
if (++lightPropagationRecursiveDepth > 32) // TODO is this too much?
{
if (surface.Type == ST_FLOOR || surface.Type == ST_CEILING)
return;
}
SphereShape sphere;
sphere.center = FVector3(light->RelativeOrigin);
sphere.radius = light->Radius;
std::set<LevelMeshPortal, RecursivePortalComparator> portalsToErase;
for (int triangleIndex : TriangleMeshShape::find_all_hits(Collision.get(), &sphere))
{
auto& surface = Surfaces[MeshSurfaceIndexes[triangleIndex]];
// TODO skip any surface which isn't physically connected to the sector group in which the light resides
//if (light-> == surface.sectorGroup)
{
CreateLightList(&surface, surface.Subsector->section->lighthead, surface.Subsector->sector->PortalGroup);
}
else
{
CreateLightList(&surface, surface.Side->lighthead, surface.Side->sector->PortalGroup);
if (surface.portalIndex >= 0)
{
auto& portal = Portals[surface.portalIndex];
if (touchedPortals.insert(portal).second)
{
auto newLight = std::make_unique<LevelMeshLight>(*light);
auto fakeLight = newLight.get();
Lights.push_back(std::move(newLight));
fakeLight->RelativeOrigin = portal.TransformPosition(light->RelativeOrigin);
//fakeLight->sectorGroup = portal->targetSectorGroup;
PropagateLight(fakeLight, touchedPortals, lightPropagationRecursiveDepth);
portalsToErase.insert(portal);
}
}
// Add light to the list if it isn't already there
// TODO in order for this to work the light list be fed from global light buffer? Or just somehow de-duplicate portals?
bool found = false;
for (const LevelMeshLight* light2 : surface.LightList)
{
if (light2 == light)
{
found = true;
break;
}
}
if (!found)
surface.LightList.push_back(light);
}
}
for (auto& portal : portalsToErase)
{
touchedPortals.erase(portal); // Dear me: I wonder what was the reason for all of this.
}
}
void DoomLevelMesh::CreateLightList()
{
std::set<FDynamicLight*> lightList; // bit silly ain't it?
Lights.clear();
for (auto& surface : Surfaces)
{
surface.LightList.clear();
if (surface.Type == ST_FLOOR || surface.Type == ST_CEILING)
{
auto node = surface.Subsector->section->lighthead;
while (node)
{
FDynamicLight* light = node->lightsource;
if (light->Trace())
{
if (lightList.insert(light).second)
{
DVector3 pos = light->Pos; //light->PosRelative(portalgroup);
LevelMeshLight meshlight;
meshlight.Origin = { (float)pos.X, (float)pos.Y, (float)pos.Z };
meshlight.RelativeOrigin = meshlight.Origin;
meshlight.Radius = (float)light->GetRadius();
meshlight.Intensity = light->target->Alpha;
if (light->IsSpot())
{
meshlight.InnerAngleCos = (float)light->pSpotInnerAngle->Cos();
meshlight.OuterAngleCos = (float)light->pSpotOuterAngle->Cos();
DAngle negPitch = -*light->pPitch;
DAngle Angle = light->target->Angles.Yaw;
double xzLen = negPitch.Cos();
meshlight.SpotDir.X = float(-Angle.Cos() * xzLen);
meshlight.SpotDir.Y = float(-negPitch.Sin());
meshlight.SpotDir.Z = float(-Angle.Sin() * xzLen);
}
else
{
meshlight.InnerAngleCos = -1.0f;
meshlight.OuterAngleCos = -1.0f;
meshlight.SpotDir.X = 0.0f;
meshlight.SpotDir.Y = 0.0f;
meshlight.SpotDir.Z = 0.0f;
}
meshlight.Color.X = light->GetRed() * (1.0f / 255.0f);
meshlight.Color.Y = light->GetGreen() * (1.0f / 255.0f);
meshlight.Color.Z = light->GetBlue() * (1.0f / 255.0f);
Lights.push_back(std::make_unique<LevelMeshLight>(meshlight));
}
}
node = node->nextLight;
}
}
}
std::set<LevelMeshPortal, RecursivePortalComparator> touchedPortals;
touchedPortals.insert(Portals[0]);
for (int i = 0, count = Lights.size(); i < count; ++i) // The array expands as the lights are duplicated/propagated
{
PropagateLight(Lights[i].get(), touchedPortals, 0);
}
}
void DoomLevelMesh::UpdateLightLists()
{
CreateLightList(); // full recreation
}
void DoomLevelMesh::BindLightmapSurfacesToGeometry(FLevelLocals& doomMap)
@ -296,58 +415,6 @@ void DoomLevelMesh::SetSideLightmap(DoomLevelMeshSurface* surface)
}
}
void DoomLevelMesh::CreateLightList(DoomLevelMeshSurface* surface, FLightNode* node, int portalgroup)
{
surface->LightListBuffer.clear();
surface->LightList.clear();
while (node)
{
FDynamicLight* light = node->lightsource;
if (light->Trace())
{
DVector3 pos = light->PosRelative(portalgroup);
LevelMeshLight meshlight;
meshlight.Origin = { (float)pos.X, (float)pos.Y, (float)pos.Z };
meshlight.RelativeOrigin = meshlight.Origin; // ?? what is the difference between this and Origin?
meshlight.Radius = (float)light->GetRadius();
meshlight.Intensity = light->target->Alpha;
if (light->IsSpot())
{
meshlight.InnerAngleCos = (float)light->pSpotInnerAngle->Cos();
meshlight.OuterAngleCos = (float)light->pSpotOuterAngle->Cos();
DAngle negPitch = -*light->pPitch;
DAngle Angle = light->target->Angles.Yaw;
double xzLen = negPitch.Cos();
meshlight.SpotDir.X = float(-Angle.Cos() * xzLen);
meshlight.SpotDir.Y = float(-negPitch.Sin());
meshlight.SpotDir.Z = float(-Angle.Sin() * xzLen);
}
else
{
meshlight.InnerAngleCos = -1.0f;
meshlight.OuterAngleCos = -1.0f;
meshlight.SpotDir.X = 0.0f;
meshlight.SpotDir.Y = 0.0f;
meshlight.SpotDir.Z = 0.0f;
}
meshlight.Color.X = light->GetRed() * (1.0f / 255.0f);
meshlight.Color.Y = light->GetGreen() * (1.0f / 255.0f);
meshlight.Color.Z = light->GetBlue() * (1.0f / 255.0f);
surface->LightListBuffer.push_back(meshlight);
}
node = node->nextLight;
}
for (auto& silly : surface->LightListBuffer)
surface->LightList.push_back(&silly);
}
void DoomLevelMesh::CreateSideSurfaces(FLevelLocals &doomMap, side_t *side)
{
sector_t *front;