diff --git a/.github/workflows/continuous_integration.yml b/.github/workflows/continuous_integration.yml index 7055a2c86..074f372f5 100644 --- a/.github/workflows/continuous_integration.yml +++ b/.github/workflows/continuous_integration.yml @@ -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 diff --git a/src/commandlets/lightmapcmd.cpp b/src/commandlets/lightmapcmd.cpp index 7bb22f32d..1915fd648 100644 --- a/src/commandlets/lightmapcmd.cpp +++ b/src/commandlets/lightmapcmd.cpp @@ -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; } diff --git a/src/d_net.cpp b/src/d_net.cpp index 0b41136e7..fe6e3727d 100644 --- a/src/d_net.cpp +++ b/src/d_net.cpp @@ -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 diff --git a/src/d_net.h b/src/d_net.h index 11e847bd9..b4431bd7b 100644 --- a/src/d_net.h +++ b/src/d_net.h @@ -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(); diff --git a/src/playsim/a_dynlight.cpp b/src/playsim/a_dynlight.cpp index 12a8618f6..00724de8c 100644 --- a/src/playsim/a_dynlight.cpp +++ b/src/playsim/a_dynlight.cpp @@ -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::Iterator wit(touchlists.wall_tlist); TMap::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); } } diff --git a/src/rendering/hwrenderer/doom_levelmesh.cpp b/src/rendering/hwrenderer/doom_levelmesh.cpp index f9f1694a7..19aa2c93f 100644 --- a/src/rendering/hwrenderer/doom_levelmesh.cpp +++ b/src/rendering/hwrenderer/doom_levelmesh.cpp @@ -650,9 +650,7 @@ void DoomLevelMesh::AddSidesToDrawLists(const TArray& 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(§ion); + if (flatLightList) { - FDynamicLight* light = cur->lightsource; - if (light && light->IsActive() && (light->Trace() || lm_dynlights)) + TMap>::Iterator it(*flatLightList); + TMap>::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(§ion, 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>::Iterator it(*srcLightList); + TMap>::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>::Iterator it(*srcLightList); + TMap>::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(§ion, nullptr, section.sector->PortalGroup)); const auto& lightlist = Flats[sectorIndex].Lights.Last(); HWFlatMeshHelper result; diff --git a/src/rendering/hwrenderer/doom_levelmesh.h b/src/rendering/hwrenderer/doom_levelmesh.h index 6fe993616..73ffc1aed 100644 --- a/src/rendering/hwrenderer/doom_levelmesh.h +++ b/src/rendering/hwrenderer/doom_levelmesh.h @@ -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); diff --git a/src/rendering/hwrenderer/scene/hw_decal.cpp b/src/rendering/hwrenderer/scene/hw_decal.cpp index 90dc5946a..bfd092262 100644 --- a/src/rendering/hwrenderer/scene/hw_decal.cpp +++ b/src/rendering/hwrenderer/scene/hw_decal.cpp @@ -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>::Iterator it(*wallLightList); + TMap>::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); } diff --git a/src/rendering/hwrenderer/scene/hw_drawstructs.h b/src/rendering/hwrenderer/scene/hw_drawstructs.h index 7efb28cb8..35a1c8ff1 100644 --- a/src/rendering/hwrenderer/scene/hw_drawstructs.h +++ b/src/rendering/hwrenderer/scene/hw_drawstructs.h @@ -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; diff --git a/src/rendering/hwrenderer/scene/hw_spritelight.cpp b/src/rendering/hwrenderer/scene/hw_spritelight.cpp index 6bb424d4b..32512cd83 100644 --- a/src/rendering/hwrenderer/scene/hw_spritelight.cpp +++ b/src/rendering/hwrenderer/scene/hw_spritelight.cpp @@ -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>::Iterator it(*flatLightList); - TMap>::Pair *pair; + TMap>::Iterator it(*flatLightList); + TMap>::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>::Iterator it(*flatLightList); + TMap>::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>::Iterator it(*flatLightList); - TMap>::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) diff --git a/wadsrc/static/shaders/scene/binding_rsbuffers.glsl b/wadsrc/static/shaders/scene/binding_rsbuffers.glsl index fddf898a2..52878817c 100644 --- a/wadsrc/static/shaders/scene/binding_rsbuffers.glsl +++ b/wadsrc/static/shaders/scene/binding_rsbuffers.glsl @@ -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 diff --git a/wadsrc/static/shaders/scene/lightmode.glsl b/wadsrc/static/shaders/scene/lightmode.glsl index 9f01d6734..470da100c 100644 --- a/wadsrc/static/shaders/scene/lightmode.glsl +++ b/wadsrc/static/shaders/scene/lightmode.glsl @@ -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);