More big beautiful porting

This commit is contained in:
Magnus Norddahl 2025-08-08 00:43:45 +02:00
commit e3cde7a9e9
12 changed files with 241 additions and 336 deletions

View file

@ -107,7 +107,7 @@ jobs:
cp -r vkdoom.app package
cp -r vktool package
elif [[ "${{ runner.os }}" == 'Linux' ]]; then
cp vkdoom vktool *.pk3 zmusic/lib/libzmusic.so package
cp vkdoom vktool *.pk3 libzmusic.so package
strip package/vkdoom
strip package/vktool
fi

View file

@ -3,6 +3,7 @@
#include "g_levellocals.h"
#include "d_event.h"
#include "v_video.h"
#include "d_net.h"
void G_SetMap(const char* mapname, int mode);
@ -36,9 +37,8 @@ void LightmapBuildCmdlet::OnCommand(FArgs args)
G_SetMap(mapname.GetChars(), 0);
for (int i = 0; i < 100; i++)
{
#ifdef NEEDS_BIG_BEAUTIFUL_MERGE_PORTING
D_SingleTick();
#endif
TryRunTics(1);
if (gameaction == ga_nothing)
break;
}
@ -126,9 +126,7 @@ void LightmapDeleteCmdlet::OnCommand(FArgs args)
G_SetMap(mapname.GetChars(), 0);
for (int i = 0; i < 100; i++)
{
#ifdef NEEDS_BIG_BEAUTIFUL_MERGE_PORTING
D_SingleTick();
#endif
TryRunTics(1);
if (gameaction == ga_nothing)
break;
}

View file

@ -2145,7 +2145,7 @@ static void CalculateNetStabilityBuffer(int diff)
//
// TryRunTics
//
void TryRunTics()
void TryRunTics(int forceRunTics)
{
GC::CheckGC();
@ -2154,23 +2154,28 @@ void TryRunTics()
ToggleFullscreen = false;
AddCommandString("toggle vid_fullscreen");
}
bool doWait = (cl_capfps || pauseext || (!netgame && r_NoInterpolate && !M_IsAnimated()));
if (vid_dontdowait && (vid_maxfps > 0 || vid_vsync))
doWait = false;
if (!netgame && !AppActive && vid_lowerinbackground)
doWait = true;
// Get the full number of tics the client can run.
if (doWait)
EnterTic = I_WaitForTic(LastEnterTic);
else
EnterTic = I_GetTime();
const int startCommand = ClientTic;
int totalTics = EnterTic - LastEnterTic;
if (totalTics > 1 && singletics)
totalTics = 1;
int totalTics = forceRunTics;
if (totalTics == 0)
{
bool doWait = (cl_capfps || pauseext || (!netgame && r_NoInterpolate && !M_IsAnimated()));
if (vid_dontdowait && (vid_maxfps > 0 || vid_vsync))
doWait = false;
if (!netgame && !AppActive && vid_lowerinbackground)
doWait = true;
// Get the full number of tics the client can run.
if (doWait)
EnterTic = I_WaitForTic(LastEnterTic);
else
EnterTic = I_GetTime();
totalTics = EnterTic - LastEnterTic;
if (totalTics > 1 && singletics)
totalTics = 1;
}
// Listen for other clients and send out data as needed. This is also
// needed for singleplayer! But is instead handled entirely through local

View file

@ -136,7 +136,7 @@ void NetUpdate(int tics);
void D_QuitNetGame (void);
//? how many ticks to run?
void TryRunTics (void);
void TryRunTics(int forceRunTics = 0);
// [RH] Functions for making and using special "ticcmds"
void Net_NewClientTic();

View file

@ -647,12 +647,10 @@ void FDynamicLight::CollectWithinRadius(const DVector3 &opos, FSection *section,
auto pos = collected_ss[i].pos;
section = collected_ss[i].sect;
AddLightNode(section, NULL);
if(markTiles)
{
if (markTiles)
LevelMeshUpdater->SectorLightListChanged(section->sector);
}
AddLightNode(section, NULL);
auto processSide = [&](side_t *sidedef, const vertex_t *v1, const vertex_t *v2)
{
@ -664,12 +662,10 @@ void FDynamicLight::CollectWithinRadius(const DVector3 &opos, FSection *section,
{
linedef->validcount = ::validcount;
AddLightNode(NULL, sidedef);
if(markTiles)
{
if (markTiles)
LevelMeshUpdater->SideLightListChanged(sidedef);
}
AddLightNode(NULL, sidedef);
}
else if (linedef->sidedef[0] == sidedef && linedef->sidedef[1] == nullptr)
{
@ -771,6 +767,8 @@ void FDynamicLight::CollectWithinRadius(const DVector3 &opos, FSection *section,
void FDynamicLight::LinkLight()
{
UnlinkLight();
if (radius>0)
{
// passing in radius*radius allows us to do a distance check without any calls to sqrt
@ -779,38 +777,7 @@ void FDynamicLight::LinkLight()
dl_validcount++;
::validcount++;
CollectWithinRadius(Pos, sect, float(radius*radius));
}
#ifdef NEEDS_BIG_BEAUTIFUL_MERGE_PORTING
bool markTiles = ((Trace() || lm_dynlights) && Level->levelMesh);
if(markTiles)
{
node = touching_sides;
while (node)
{
if (node->lightsource == nullptr)
{
LevelMeshUpdater->SideLightListChanged(node->targLine);
node = DeleteLightNode(node);
}
else
node = node->nextTarget;
}
node = touching_sector;
while (node)
{
if (node->lightsource == nullptr)
{
LevelMeshUpdater->SectorLightListChanged(node->targSection->sector);
node = DeleteLightNode(node);
}
else
node = node->nextTarget;
}
}
#endif
}
@ -821,25 +788,6 @@ void FDynamicLight::LinkLight()
//==========================================================================
void FDynamicLight::UnlinkLight ()
{
#ifdef NEEDS_BIG_BEAUTIFUL_MERGE_PORTING
bool markTiles = ((Trace() || lm_dynlights) && Level->levelMesh);
if(markTiles)
{
while (touching_sides)
{
LevelMeshUpdater->SideLightListChanged(touching_sides->targLine);
touching_sides = DeleteLightNode(touching_sides);
}
while (touching_sector)
{
LevelMeshUpdater->SectorLightListChanged(touching_sector->targSection->sector);
touching_sector = DeleteLightNode(touching_sector);
}
}
#endif
TMap<side_t *, side_t *>::Iterator wit(touchlists.wall_tlist);
TMap<side_t *, side_t *>::Pair *wpair;
while (wit.NextPair(wpair))
@ -850,6 +798,7 @@ void FDynamicLight::UnlinkLight ()
auto wallLightList = Level->lightlists.wall_dlist.CheckKey(sidedef);
if (wallLightList)
{
LevelMeshUpdater->SideLightListChanged(sidedef);
wallLightList->Remove(this);
}
}
@ -864,6 +813,7 @@ void FDynamicLight::UnlinkLight ()
auto flatLightList = Level->lightlists.flat_dlist.CheckKey(sec);
if (flatLightList)
{
LevelMeshUpdater->SectorLightListChanged(sec->sector);
flatLightList->Remove(this);
}
}

View file

@ -650,9 +650,7 @@ void DoomLevelMesh::AddSidesToDrawLists(const TArray<int>& sides, LevelMeshDrawL
int dynlightindex = -1;
if (di->Level->HasDynamicLights && !di->isFullbrightScene() && decals[0].texture != nullptr && !lm_dynlights)
{
#ifdef NEEDS_BIG_BEAUTIFUL_MERGE_PORTING
dynlightindex = decals[0].SetupLights(di, state, lightdata, level.sides[sideIndex].lighthead);
#endif
dynlightindex = decals[0].SetupLights(di, state, lightdata, &level.sides[sideIndex]);
}
for (const HWDecalCreateInfo& info : decals)
@ -1048,18 +1046,21 @@ void DoomLevelMesh::UpdateLightShadows(sector_t* sector)
{
for (FSection& section : level.sections.SectionsForSector(sector))
{
#ifdef NEEDS_BIG_BEAUTIFUL_MERGE_PORTING
FLightNode* cur = section.lighthead;
while (cur)
auto flatLightList = level.lightlists.flat_dlist.CheckKey(&section);
if (flatLightList)
{
FDynamicLight* light = cur->lightsource;
if (light && light->IsActive() && (light->Trace() || lm_dynlights))
TMap<FDynamicLight*, std::unique_ptr<FLightNode>>::Iterator it(*flatLightList);
TMap<FDynamicLight*, std::unique_ptr<FLightNode>>::Pair* pair;
while (it.NextPair(pair))
{
UpdateLightShadows(light);
auto node = pair->Value.get();
FDynamicLight* light = node->lightsource;
if (light && light->IsActive() && (light->Trace() || lm_dynlights))
{
UpdateLightShadows(light);
}
}
cur = cur->nextLight;
}
#endif
}
}
@ -1185,16 +1186,12 @@ void DoomLevelMesh::UpdateSideLightList(FLevelLocals& doomMap, unsigned int side
return;
FreeLightList(sideBlock.Lights.Start, sideBlock.Lights.Count);
#ifdef NEEDS_BIG_BEAUTIFUL_MERGE_PORTING
sideBlock.Lights = CreateLightList(sub->section->lighthead, sub->sector->PortalGroup);
#endif
sideBlock.Lights = CreateLightList(sub->section, nullptr, sub->sector->PortalGroup);
}
else
{
FreeLightList(sideBlock.Lights.Start, sideBlock.Lights.Count);
#ifdef NEEDS_BIG_BEAUTIFUL_MERGE_PORTING
sideBlock.Lights = CreateLightList(side->lighthead, side->sector->PortalGroup);
#endif
sideBlock.Lights = CreateLightList(nullptr, side, side->sector->PortalGroup);
}
int surf = Sides[sideIndex].FirstSurface;
@ -1222,9 +1219,7 @@ void DoomLevelMesh::UpdateFlatLightList(FLevelLocals& doomMap, unsigned int sect
sector_t* sector = &doomMap.sectors[sectorIndex];
for (FSection& section : doomMap.sections.SectionsForSector(sectorIndex))
{
#ifdef NEEDS_BIG_BEAUTIFUL_MERGE_PORTING
Flats[sectorIndex].Lights.Push(CreateLightList(section.lighthead, section.sector->PortalGroup));
#endif
Flats[sectorIndex].Lights.Push(CreateLightList(&section, nullptr, section.sector->PortalGroup));
}
int surf = Flats[sectorIndex].FirstSurface;
@ -1318,36 +1313,51 @@ void DoomLevelMesh::UpdateFlat(unsigned int sectorIndex, SurfaceUpdateType updat
}
}
LightListAllocInfo DoomLevelMesh::CreateLightList(FLightNode* node, int portalgroup)
LightListAllocInfo DoomLevelMesh::CreateLightList(FSection* section, side_t* side, int portalgroup)
{
int lightcount = 0;
FLightNode* cur = node;
while (cur)
auto srcLightList = section ? level.lightlists.flat_dlist.CheckKey(section) : level.lightlists.wall_dlist.CheckKey(side);
if (srcLightList)
{
FDynamicLight* light = cur->lightsource;
if (light && light->IsActive() && (light->Trace() || lm_dynlights) && GetLightIndex(light, portalgroup) >= 0)
TMap<FDynamicLight*, std::unique_ptr<FLightNode>>::Iterator it(*srcLightList);
TMap<FDynamicLight*, std::unique_ptr<FLightNode>>::Pair* pair;
while (it.NextPair(pair))
{
lightcount++;
auto node = pair->Value.get();
if (!node) continue;
FDynamicLight* light = node->lightsource;
if (light && light->IsActive() && (light->Trace() || lm_dynlights) && GetLightIndex(light, portalgroup) >= 0)
{
lightcount++;
}
}
cur = cur->nextLight;
}
LightListAllocInfo info = AllocLightList(lightcount);
int32_t* lightList = GetLightList(info);
int i = 0;
cur = node;
while (cur)
if (srcLightList)
{
FDynamicLight* light = cur->lightsource;
if (light && light->IsActive() && (light->Trace() || lm_dynlights))
int32_t* lightList = GetLightList(info);
int i = 0;
TMap<FDynamicLight*, std::unique_ptr<FLightNode>>::Iterator it(*srcLightList);
TMap<FDynamicLight*, std::unique_ptr<FLightNode>>::Pair* pair;
while (it.NextPair(pair))
{
int lightindex = GetLightIndex(light, portalgroup);
if (lightindex >= 0)
auto node = pair->Value.get();
if (!node) continue;
FDynamicLight* light = node->lightsource;
if (light && light->IsActive() && (light->Trace() || lm_dynlights))
{
lightList[i++] = lightindex;
int lightindex = GetLightIndex(light, portalgroup);
if (lightindex >= 0)
{
lightList[i++] = lightindex;
}
}
}
cur = cur->nextLight;
}
return info;
}
@ -1382,9 +1392,7 @@ void DoomLevelMesh::CreateSide(FLevelLocals& doomMap, unsigned int sideIndex)
{
if (!lightlistCreated)
{
#ifdef NEEDS_BIG_BEAUTIFUL_MERGE_PORTING
sideBlock.Lights = CreateLightList(sub->section->lighthead, sub->sector->PortalGroup);
#endif
sideBlock.Lights = CreateLightList(sub->section, nullptr, sub->sector->PortalGroup);
lightlistCreated = true;
}
@ -1399,9 +1407,7 @@ void DoomLevelMesh::CreateSide(FLevelLocals& doomMap, unsigned int sideIndex)
}
else
{
#ifdef NEEDS_BIG_BEAUTIFUL_MERGE_PORTING
sideBlock.Lights = CreateLightList(side->lighthead, side->sector->PortalGroup);
#endif
sideBlock.Lights = CreateLightList(nullptr, side, side->sector->PortalGroup);
subsector_t* sub = seg->Subsector;
sector_t* front = side->sector;
@ -1493,11 +1499,7 @@ void DoomLevelMesh::CreateFlat(FLevelLocals& doomMap, unsigned int sectorIndex)
int lightlistSection = 0;
for (FSection& section : doomMap.sections.SectionsForSector(sectorIndex))
{
#ifdef NEEDS_BIG_BEAUTIFUL_MERGE_PORTING
Flats[sectorIndex].Lights.Push(CreateLightList(section.lighthead, section.sector->PortalGroup));
#else
Flats[sectorIndex].Lights.Push({});
#endif
Flats[sectorIndex].Lights.Push(CreateLightList(&section, nullptr, section.sector->PortalGroup));
const auto& lightlist = Flats[sectorIndex].Lights.Last();
HWFlatMeshHelper result;

View file

@ -244,7 +244,7 @@ private:
void CreatePortals(FLevelLocals& doomMap);
LightListAllocInfo CreateLightList(FLightNode* node, int portalgroup);
LightListAllocInfo CreateLightList(FSection* section, side_t* side, int portalgroup);
int GetLightIndex(FDynamicLight* light, int portalgroup);
void UpdateLight(FDynamicLight* light);
void CopyToMeshLight(FDynamicLight* light, LevelMeshLight& meshlight, int portalgroup);

View file

@ -751,7 +751,7 @@ void HWWall::ProcessDecals(HWWallDispatcher* di, FRenderState& state)
//==========================================================================
int HWDecalCreateInfo::SetupLights(HWDrawInfo* di, FRenderState& state, FDynLightData& lightdata, FLightNode* node) const
int HWDecalCreateInfo::SetupLights(HWDrawInfo* di, FRenderState& state, FDynLightData& lightdata, side_t* side) const
{
lightdata.Clear();
@ -762,58 +762,66 @@ int HWDecalCreateInfo::SetupLights(HWDrawInfo* di, FRenderState& state, FDynLigh
p.Set(normal, -normal.X * glseg.x1 - normal.Z * glseg.y1);
// Iterate through all dynamic lights which touch this wall and render them
while (node)
auto wallLightList = di->Level->lightlists.wall_dlist.CheckKey(side);
if (wallLightList)
{
if (node->lightsource->IsActive() && !node->lightsource->DontLightMap())
TMap<FDynamicLight*, std::unique_ptr<FLightNode>>::Iterator it(*wallLightList);
TMap<FDynamicLight*, std::unique_ptr<FLightNode>>::Pair* pair;
while (it.NextPair(pair))
{
iter_dlight++;
DVector3 posrel = node->lightsource->PosRelative(frontsector->PortalGroup);
float x = posrel.X;
float y = posrel.Y;
float z = posrel.Z;
float dist = fabsf(p.DistToPoint(x, z, y));
float radius = node->lightsource->GetRadius();
float scale = 1.0f / ((2.f * radius) - dist);
FVector3 fn, pos;
if (radius > 0.f && dist < radius)
auto node = pair->Value.get();
if (!node) continue;
if (node->lightsource->IsActive() && !node->lightsource->DontLightMap())
{
FVector3 nearPt, up, right;
iter_dlight++;
pos = { x, z, y };
fn = p.Normal();
DVector3 posrel = node->lightsource->PosRelative(frontsector->PortalGroup);
float x = posrel.X;
float y = posrel.Y;
float z = posrel.Z;
float dist = fabsf(p.DistToPoint(x, z, y));
float radius = node->lightsource->GetRadius();
float scale = 1.0f / ((2.f * radius) - dist);
FVector3 fn, pos;
fn.GetRightUp(right, up);
FVector3 tmpVec = fn * dist;
nearPt = pos + tmpVec;
FVector3 t1;
int outcnt[4] = { 0,0,0,0 };
texcoord tcs[4];
// do a quick check whether the light touches this polygon
for (int i = 0; i < 4; i++)
if (radius > 0.f && dist < radius)
{
t1 = FVector3(&vtx[i * 3]);
FVector3 nearToVert = t1 - nearPt;
tcs[i].u = ((nearToVert | right) * scale) + 0.5f;
tcs[i].v = ((nearToVert | up) * scale) + 0.5f;
FVector3 nearPt, up, right;
if (tcs[i].u < 0) outcnt[0]++;
if (tcs[i].u > 1) outcnt[1]++;
if (tcs[i].v < 0) outcnt[2]++;
if (tcs[i].v > 1) outcnt[3]++;
pos = { x, z, y };
fn = p.Normal();
}
if (outcnt[0] != 4 && outcnt[1] != 4 && outcnt[2] != 4 && outcnt[3] != 4)
{
draw_dlight += GetLight(lightdata, frontsector->PortalGroup, p, node->lightsource, true);
fn.GetRightUp(right, up);
FVector3 tmpVec = fn * dist;
nearPt = pos + tmpVec;
FVector3 t1;
int outcnt[4] = { 0,0,0,0 };
texcoord tcs[4];
// do a quick check whether the light touches this polygon
for (int i = 0; i < 4; i++)
{
t1 = FVector3(&vtx[i * 3]);
FVector3 nearToVert = t1 - nearPt;
tcs[i].u = ((nearToVert | right) * scale) + 0.5f;
tcs[i].v = ((nearToVert | up) * scale) + 0.5f;
if (tcs[i].u < 0) outcnt[0]++;
if (tcs[i].u > 1) outcnt[1]++;
if (tcs[i].v < 0) outcnt[2]++;
if (tcs[i].v > 1) outcnt[3]++;
}
if (outcnt[0] != 4 && outcnt[1] != 4 && outcnt[2] != 4 && outcnt[3] != 4)
{
draw_dlight += GetLight(lightdata, frontsector->PortalGroup, p, node->lightsource, true);
}
}
}
}
node = node->nextLight;
}
return state.UploadLights(lightdata);
}

View file

@ -466,7 +466,7 @@ struct HWDecal
struct HWDecalCreateInfo
{
void ProcessDecal(HWDrawInfo* di, FRenderState& state, int dynlightindex) const;
int SetupLights(HWDrawInfo* di, FRenderState& state, FDynLightData& lightdata, FLightNode* node) const;
int SetupLights(HWDrawInfo* di, FRenderState& state, FDynLightData& lightdata, side_t* side) const;
DBaseDecal* decal;
FVector3 normal;

View file

@ -131,25 +131,23 @@ float inverseSquareAttenuation(float dist, float radius, float strength, float l
return mix(((b * b) / (dist * dist + 1.0f) * strength), clamp((radius - dist) / radius, 0.0f, 1.0f), linearity);
}
void HWDrawInfo::GetDynSpriteLight(AActor *self, sun_trace_cache_t * traceCache, double x, double y, double z, FSection *sec, int portalgroup, float *out, bool fullbright)
void HWDrawInfo::GetDynSpriteLight(AActor* self, sun_trace_cache_t* traceCache, double x, double y, double z, FSection* sec, int portalgroup, float* out, bool fullbright)
{
FDynamicLight *light;
FDynamicLight* light;
float frac, lr, lg, lb;
float radius;
out[0] = out[1] = out[2] = 0.f;
if (fullbright || get_gl_spritelight() > 0)
return;
#ifdef NEEDS_BIG_BEAUTIFUL_MERGE_PORTING
ActorTraceStaticLight staticLight(self);
if (ActorTraceStaticLight::TraceSunVisibility(x, y, z, traceCache, (self ? staticLight.ActorMoved : traceCache ? traceCache->Pos != DVector3(x, y, z) : false)))
{
if(!self && traceCache)
if (!self && traceCache)
{
traceCache->Pos = DVector3(x, y, z);
}
@ -164,69 +162,19 @@ void HWDrawInfo::GetDynSpriteLight(AActor *self, sun_trace_cache_t * traceCache,
if (flatLightList)
{
TMap<FDynamicLight *, std::unique_ptr<FLightNode>>::Iterator it(*flatLightList);
TMap<FDynamicLight *, std::unique_ptr<FLightNode>>::Pair *pair;
TMap<FDynamicLight*, std::unique_ptr<FLightNode>>::Iterator it(*flatLightList);
TMap<FDynamicLight*, std::unique_ptr<FLightNode>>::Pair* pair;
while (it.NextPair(pair))
{
auto node = pair->Value.get();
if (!node) continue;
light=node->lightsource;
light = node->lightsource;
if (light->ShouldLightActor(self))
{
float dist;
FVector3 L;
<<<<<<< HEAD
DVector2 offset = Level->Displacements.getOffset(fromgroup, togroup);
L = FVector3(x - (float)(light->X() + offset.X), y - (float)(light->Y() + offset.Y), z - (float)light->Z());
}
else
{
direct:
L = FVector3(x - (float)light->X(), y - (float)light->Y(), z - (float)light->Z());
}
dist = (float)L.LengthSquared();
radius = light->GetRadius();
if (radius > 0 && dist < radius * radius)
{
dist = sqrtf(dist); // only calculate the square root if we really need it.
if (light->IsSpot() || light->TraceActors())
L *= -1.0f / dist;
if (staticLight.TraceLightVisbility(node, L, dist, light->updated))
{
if(level.info->lightattenuationmode == ELightAttenuationMode::INVERSE_SQUARE)
{
frac = (inverseSquareAttenuation(std::max(dist, sqrt(radius) * 2), radius, light->GetStrength(), light->GetLinearity()));
}
else
{
frac = 1.0f - (dist / radius);
}
if (light->IsSpot())
{
DAngle negPitch = -*light->pPitch;
DAngle Angle = light->target->Angles.Yaw;
double xyLen = negPitch.Cos();
double spotDirX = -Angle.Cos() * xyLen;
double spotDirY = -Angle.Sin() * xyLen;
double spotDirZ = -negPitch.Sin();
double cosDir = L.X * spotDirX + L.Y * spotDirY + L.Z * spotDirZ;
frac *= (float)smoothstep(light->pSpotOuterAngle->Cos(), light->pSpotInnerAngle->Cos(), cosDir);
}
if (frac > 0 && (!light->shadowmapped || (self && light->TraceActors()) || screen->mShadowMap->ShadowTest(light->Pos, { x, y, z })))
{
lr = light->GetRed() / 255.0f;
lg = light->GetGreen() / 255.0f;
lb = light->GetBlue() / 255.0f;
=======
// This is a performance critical section of code where we cannot afford to let the compiler decide whether to inline the function or not.
// This will do the calculations explicitly rather than calling one of AActor's utility functions.
if (Level->Displacements.size > 0)
@ -247,63 +195,73 @@ void HWDrawInfo::GetDynSpriteLight(AActor *self, sun_trace_cache_t * traceCache,
dist = (float)L.LengthSquared();
radius = light->GetRadius();
if (dist < radius * radius)
if (radius > 0 && dist < radius * radius)
{
dist = sqrtf(dist); // only calculate the square root if we really need it.
frac = 1.0f - (dist / radius);
if (light->IsSpot())
{
if (light->IsSpot() || light->TraceActors())
L *= -1.0f / dist;
DAngle negPitch = -*light->pPitch;
DAngle Angle = light->target->Angles.Yaw;
double xyLen = negPitch.Cos();
double spotDirX = -Angle.Cos() * xyLen;
double spotDirY = -Angle.Sin() * xyLen;
double spotDirZ = -negPitch.Sin();
double cosDir = L.X * spotDirX + L.Y * spotDirY + L.Z * spotDirZ;
frac *= (float)smoothstep(light->pSpotOuterAngle->Cos(), light->pSpotInnerAngle->Cos(), cosDir);
}
if (frac > 0 && (!light->shadowmapped || (light->GetRadius() > 0 && screen->mShadowMap.ShadowTest(light->Pos, { x, y, z }))))
if (staticLight.TraceLightVisbility(node, L, dist, light->updated))
{
lr = light->GetRed() / 255.0f;
lg = light->GetGreen() / 255.0f;
lb = light->GetBlue() / 255.0f;
>>>>>>> gzdoom/master
if (light->target && (light->target->renderflags2 & RF2_LIGHTMULTALPHA))
if (level.info->lightattenuationmode == ELightAttenuationMode::INVERSE_SQUARE)
{
float alpha = (float)light->target->Alpha;
lr *= alpha;
lg *= alpha;
lb *= alpha;
frac = (inverseSquareAttenuation(std::max(dist, sqrt(radius) * 2), radius, light->GetStrength(), light->GetLinearity()));
}
else
{
frac = 1.0f - (dist / radius);
}
// Get GLDEFS intensity
lr *= light->GetLightDefIntensity();
lg *= light->GetLightDefIntensity();
lb *= light->GetLightDefIntensity();
if (light->IsSubtractive())
if (light->IsSpot())
{
float bright = (float)FVector3(lr, lg, lb).Length();
FVector3 lightColor(lr, lg, lb);
lr = (bright - lr) * -1;
lg = (bright - lg) * -1;
lb = (bright - lb) * -1;
DAngle negPitch = -*light->pPitch;
DAngle Angle = light->target->Angles.Yaw;
double xyLen = negPitch.Cos();
double spotDirX = -Angle.Cos() * xyLen;
double spotDirY = -Angle.Sin() * xyLen;
double spotDirZ = -negPitch.Sin();
double cosDir = L.X * spotDirX + L.Y * spotDirY + L.Z * spotDirZ;
frac *= (float)smoothstep(light->pSpotOuterAngle->Cos(), light->pSpotInnerAngle->Cos(), cosDir);
}
out[0] += lr * frac;
out[1] += lg * frac;
out[2] += lb * frac;
if (frac > 0 && (!light->shadowmapped || (self && light->TraceActors()) || screen->mShadowMap->ShadowTest(light->Pos, { x, y, z })))
{
lr = light->GetRed() / 255.0f;
lg = light->GetGreen() / 255.0f;
lb = light->GetBlue() / 255.0f;
if (light->target && (light->target->renderflags2 & RF2_LIGHTMULTALPHA))
{
float alpha = (float)light->target->Alpha;
lr *= alpha;
lg *= alpha;
lb *= alpha;
}
// Get GLDEFS intensity
lr *= light->GetLightDefIntensity();
lg *= light->GetLightDefIntensity();
lb *= light->GetLightDefIntensity();
if (light->IsSubtractive())
{
float bright = (float)FVector3(lr, lg, lb).Length();
FVector3 lightColor(lr, lg, lb);
lr = (bright - lr) * -1;
lg = (bright - lg) * -1;
lb = (bright - lb) * -1;
}
out[0] += lr * frac;
out[1] += lg * frac;
out[2] += lb * frac;
}
}
}
}
}
}
#endif
}
void HWDrawInfo::GetDynSpriteLight(AActor *thing, particle_t *particle, sun_trace_cache_t * traceCache, float *out)
@ -323,8 +281,6 @@ void HWDrawInfo::GetDynSpriteLightList(AActor *self, double x, double y, double
{
modellightdata.Clear();
#ifdef NEEDS_BIG_BEAUTIFUL_MERGE_PORTING
if (self && (self->flags5 & MF5_BRIGHT))
return;
@ -355,73 +311,48 @@ void HWDrawInfo::GetDynSpriteLightList(AActor *self, double x, double y, double
{
auto section = subsector->section;
if (section->validcount == dl_validcount) return; // already done from a previous subsector.
FLightNode * node = section->lighthead;
while (node) // check all lights touching a subsector
auto flatLightList = level.lightlists.flat_dlist.CheckKey(subsector->section);
if (flatLightList)
{
<<<<<<< HEAD
FDynamicLight *light = node->lightsource;
if (light->ShouldLightActor(self))
{
int group = subsector->sector->PortalGroup;
DVector3 pos = light->PosRelative(group);
float radius = (float)(light->GetRadius() + actorradius);
double dx = pos.X - x;
double dy = pos.Y - y;
double dz = pos.Z - z;
double distSquared = dx * dx + dy * dy + dz * dz;
if (distSquared < radius * radius) // Light and actor touches
TMap<FDynamicLight*, std::unique_ptr<FLightNode>>::Iterator it(*flatLightList);
TMap<FDynamicLight*, std::unique_ptr<FLightNode>>::Pair* pair;
while (it.NextPair(pair))
{ // check all lights touching a subsector
auto node = pair->Value.get();
if (!node) continue;
FDynamicLight* light = node->lightsource;
if (light->ShouldLightActor(self))
{
unsigned index = addedLights.SortedFind(light, false);
if(index == addedLights.Size() || addedLights[index] != light) // Check if we already added this light from a different subsector (use binary search instead of linear search)
int group = subsector->sector->PortalGroup;
DVector3 pos = light->PosRelative(group);
float radius = (float)(light->GetRadius() + actorradius);
double dx = pos.X - x;
double dy = pos.Y - y;
double dz = pos.Z - z;
double distSquared = dx * dx + dy * dy + dz * dz;
if (distSquared < radius * radius) // Light and actor touches
{
FVector3 L(dx, dy, dz);
float dist = sqrtf(distSquared);
if (gl_spritelight == 0 && light->TraceActors())
L *= 1.0f / dist;
unsigned index = addedLights.SortedFind(light, false);
if (index == addedLights.Size() || addedLights[index] != light) // Check if we already added this light from a different subsector (use binary search instead of linear search)
{
FVector3 L(dx, dy, dz);
float dist = sqrtf(distSquared);
if (gl_spritelight == 0 && light->TraceActors())
L *= 1.0f / dist;
if (gl_spritelight > 0 || staticLight.TraceLightVisbility(node, L, dist, light->updated))
{
AddLightToList(modellightdata, group, light, true, gl_spritelight > 0);
=======
auto section = subsector->section;
if (section->validcount == dl_validcount) return; // already done from a previous subsector.
auto flatLightList = self->Level->lightlists.flat_dlist.CheckKey(subsector->section);
if (flatLightList)
{
TMap<FDynamicLight *, std::unique_ptr<FLightNode>>::Iterator it(*flatLightList);
TMap<FDynamicLight *, std::unique_ptr<FLightNode>>::Pair *pair;
while (it.NextPair(pair))
{ // check all lights touching a subsector
auto node = pair->Value.get();
if (!node) continue;
FDynamicLight *light = node->lightsource;
if (light->ShouldLightActor(self))
{
int group = subsector->sector->PortalGroup;
DVector3 pos = light->PosRelative(group);
float radius = (float)(light->GetRadius() + actorradius);
double dx = pos.X - x;
double dy = pos.Y - y;
double dz = pos.Z - z;
double distSquared = dx * dx + dy * dy + dz * dz;
if (distSquared < radius * radius) // Light and actor touches
{
if (std::find(addedLights.begin(), addedLights.end(), light) == addedLights.end()) // Check if we already added this light from a different subsector
if (gl_spritelight > 0 || staticLight.TraceLightVisbility(node, L, dist, light->updated))
{
AddLightToList(modellightdata, group, light, true);
addedLights.Push(light);
AddLightToList(modellightdata, group, light, true, gl_spritelight > 0);
}
>>>>>>> gzdoom/master
}
addedLights.Insert(index, light);
addedLights.Insert(index, light);
}
}
}
}
node = node->nextLight;
}
});
#endif
}
void HWDrawInfo::GetDynSpriteLightList(AActor *thing, particle_t *particle, sun_trace_cache_t * traceCache, FDynLightData &modellightdata, bool isModel)

View file

@ -25,6 +25,9 @@ layout(set = 1, binding = 0, std140) uniform readonly ViewpointUBO
float SunIntensity;
vec3 uCameraNormal;
float uThickFogDistance;
float uThickFogMultiplier;
};
layout(set = 1, binding = 1, std140) uniform readonly MatricesUBO

View file

@ -156,6 +156,10 @@ vec3 AmbientOcclusionColor()
fogdist = max(16.0, distance(pixelpos.xyz, uCameraPos.xyz));
else
fogdist = max(16.0, pixelpos.w);
if (uThickFogDistance > 0.0 && fogdist > uThickFogDistance)
fogdist = fogdist + uThickFogMultiplier * (fogdist - uThickFogDistance);
float fogfactor = exp2 (uFogDensity * fogdist);
vec4 color = vec4(mix(uFogColor.rgb, vec3(0.0), fogfactor), 0.0);
@ -198,6 +202,10 @@ vec4 ProcessLightMode(Material material)
fogdist = max(16.0, distance(pixelpos.xyz, uCameraPos.xyz));
else
fogdist = max(16.0, pixelpos.w);
if (uThickFogDistance > 0.0 && fogdist > uThickFogDistance)
fogdist = fogdist + uThickFogMultiplier * (fogdist - uThickFogDistance);
float fogfactor = exp2 (uFogDensity * fogdist);
return vec4(uFogColor.rgb, (1.0 - fogfactor) * material.Base.a * 0.75 * vColor.a);