diff --git a/src/common/rendering/hwrenderer/data/hw_levelmesh.cpp b/src/common/rendering/hwrenderer/data/hw_levelmesh.cpp index 39ff02cc5..6b8a74021 100644 --- a/src/common/rendering/hwrenderer/data/hw_levelmesh.cpp +++ b/src/common/rendering/hwrenderer/data/hw_levelmesh.cpp @@ -103,7 +103,7 @@ void LevelSubmesh::GatherSurfacePixelStats(LevelMeshSurfaceStats& stats) stats.pixels.total += area; - if (surface->needsUpdate) + if (surface->NeedsUpdate) { stats.surfaces.dirty++; stats.pixels.dirty += area; diff --git a/src/common/rendering/hwrenderer/data/hw_levelmesh.h b/src/common/rendering/hwrenderer/data/hw_levelmesh.h index eeaaf16db..d8e287bf2 100644 --- a/src/common/rendering/hwrenderer/data/hw_levelmesh.h +++ b/src/common/rendering/hwrenderer/data/hw_levelmesh.h @@ -53,7 +53,8 @@ struct LevelMeshSurface } AtlasTile; // True if the surface needs to be rendered into the lightmap texture before it can be used - bool needsUpdate = true; + bool NeedsUpdate = true; + bool AlwaysUpdate = false; FTextureID texture = FNullTextureID(); float alpha = 1.0; diff --git a/src/common/rendering/vulkan/accelstructs/vk_lightmap.cpp b/src/common/rendering/vulkan/accelstructs/vk_lightmap.cpp index c5aefac18..63dac338d 100644 --- a/src/common/rendering/vulkan/accelstructs/vk_lightmap.cpp +++ b/src/common/rendering/vulkan/accelstructs/vk_lightmap.cpp @@ -132,7 +132,7 @@ void VkLightmap::SelectSurfaces(const TArray& surfaces) { LevelMeshSurface* surface = surfaces[i]; - if (!surface->needsUpdate) + if (!surface->NeedsUpdate) continue; // Only grab surfaces until our bake texture is full @@ -148,7 +148,7 @@ void VkLightmap::SelectSurfaces(const TArray& surfaces) bakeImage.maxX = std::max(bakeImage.maxX, uint16_t(selected.X + surface->AtlasTile.Width + spacing)); bakeImage.maxY = std::max(bakeImage.maxY, uint16_t(selected.Y + surface->AtlasTile.Height + spacing)); - surface->needsUpdate = false; + surface->NeedsUpdate = false; } } } @@ -272,7 +272,7 @@ void VkLightmap::Render() { while (i < count) { - selectedSurfaces[i].Surface->needsUpdate = true; + selectedSurfaces[i].Surface->NeedsUpdate = true; i++; } break; diff --git a/src/gamedata/r_defs.h b/src/gamedata/r_defs.h index e6f40dd0d..cb22f67bd 100644 --- a/src/gamedata/r_defs.h +++ b/src/gamedata/r_defs.h @@ -511,6 +511,7 @@ enum SECF_EXIT1 = 4096, SECF_EXIT2 = 8192, SECF_KILLMONSTERS = 16384, + SECF_LM_DYNAMIC = 32768, // Lightmap needs to be dynamically updated in this sector SECF_WASSECRET = 1 << 30, // a secret that was discovered SECF_SECRET = 1 << 31, // a secret sector diff --git a/src/maploader/maploader.cpp b/src/maploader/maploader.cpp index 7b2bb172f..bcce52da4 100644 --- a/src/maploader/maploader.cpp +++ b/src/maploader/maploader.cpp @@ -3118,7 +3118,7 @@ bool MapLoader::LoadLightmap(MapData* map) for (auto& surface : submesh->Surfaces) { - surface.needsUpdate = false; // let's consider everything valid until we make a mistake trying to change this surface + surface.NeedsUpdate = false; // let's consider everything valid until we make a mistake trying to change this surface if (surface.Type > ST_UNKNOWN && surface.Type <= ST_FLOOR) { @@ -3309,7 +3309,7 @@ bool MapLoader::LoadLightmap(MapData* map) { Printf("Can't map lightmap surface %d pixels[%u] -> ((x:%d, y:%d), (x2:%d, y2:%d), page:%d)\n", index, srcPixelOffset, dstX, dstY, dstX + surface.width, dstY + surface.height, dstPage); } - realSurface.needsUpdate = true; + realSurface.NeedsUpdate = true; continue; } @@ -3320,7 +3320,7 @@ bool MapLoader::LoadLightmap(MapData* map) { Printf("Surface size mismatch: Attempting to remap %dx%d to %dx%d pixel area.\n", surface.width, surface.height, realSurface.AtlasTile.Width, realSurface.AtlasTile.Height); } - realSurface.needsUpdate = true; + realSurface.NeedsUpdate = true; continue; } @@ -3392,7 +3392,7 @@ bool MapLoader::LoadLightmap(MapData* map) int loadedSurfaces = 0; for (auto& surface : submesh->Surfaces) { - if (!surface.needsUpdate) + if (!surface.NeedsUpdate) { loadedSurfaces++; } diff --git a/src/maploader/udmf.cpp b/src/maploader/udmf.cpp index 5c8d9417e..1a3226a67 100644 --- a/src/maploader/udmf.cpp +++ b/src/maploader/udmf.cpp @@ -2061,6 +2061,10 @@ public: sec->planes[sector_t::ceiling].LightmapSampleDistance = CheckInt(key); break; + case NAME_lm_dynamic: + Flag(sec->Flags, SECF_LM_DYNAMIC, key); + continue; + default: if (strnicmp("user_", key.GetChars(), 5)) DPrintf(DMSG_WARNING, "Unknown UDMF sector key %s\n", key.GetChars()); diff --git a/src/namedef_custom.h b/src/namedef_custom.h index 78d9c1a2a..2cac59f5d 100644 --- a/src/namedef_custom.h +++ b/src/namedef_custom.h @@ -856,5 +856,6 @@ xx(lm_sampledist_bot) xx(lm_sampledist_floor) xx(lm_sampledist_ceiling) xx(lm_suncolor) +xx(lm_dynamic) xx(Corona) diff --git a/src/rendering/hwrenderer/doom_levelmesh.cpp b/src/rendering/hwrenderer/doom_levelmesh.cpp index 45fad74a7..a73ff68cb 100644 --- a/src/rendering/hwrenderer/doom_levelmesh.cpp +++ b/src/rendering/hwrenderer/doom_levelmesh.cpp @@ -72,9 +72,9 @@ CCMD(invalidatelightmap) int count = 0; for (auto& surface : static_cast(level.levelMesh->StaticMesh.get())->Surfaces) { - if (!surface.needsUpdate) + if (!surface.NeedsUpdate) ++count; - surface.needsUpdate = true; + surface.NeedsUpdate = true; } Printf("Marked %d out of %d surfaces for update.\n", count, level.levelMesh->StaticMesh->GetSurfaceCount()); } @@ -89,7 +89,8 @@ void PrintSurfaceInfo(const DoomLevelMeshSurface* surface) Printf(" Atlas page: %d, x:%d, y:%d\n", surface->AtlasTile.ArrayIndex, surface->AtlasTile.X, surface->AtlasTile.Y); Printf(" Pixels: %dx%d (area: %d)\n", surface->AtlasTile.Width, surface->AtlasTile.Height, surface->Area()); Printf(" Sample dimension: %d\n", surface->sampleDimension); - Printf(" Needs update?: %d\n", surface->needsUpdate); + Printf(" Needs update?: %d\n", surface->NeedsUpdate); + Printf(" Always update?: %d\n", surface->AlwaysUpdate); Printf(" Sector group: %d\n", surface->sectorGroup); Printf(" Texture: '%s' (id=%d)\n", gameTexture ? gameTexture->GetName().GetChars() : "", surface->texture.GetIndex()); Printf(" Alpha: %f\n", surface->alpha); @@ -673,6 +674,7 @@ void DoomLevelSubmesh::CreateLinePortalSurface(FLevelLocals& doomMap, side_t* si surf.plane = ToPlane(verts[0], verts[1], verts[2], verts[3]); surf.sectorGroup = sectorGroup[front->Index()]; + surf.AlwaysUpdate = !!(front->Flags & SECF_LM_DYNAMIC); SetSideTextureUVs(surf, side, side_t::top, v1Top, v1Bottom, v2Top, v2Bottom); @@ -768,6 +770,7 @@ void DoomLevelSubmesh::CreateLineHorizonSurface(FLevelLocals& doomMap, side_t* s surf.plane = ToPlane(verts[0], verts[1], verts[2], verts[3]); surf.sectorGroup = sectorGroup[front->Index()]; + surf.AlwaysUpdate = !!(front->Flags & SECF_LM_DYNAMIC); SetSideTextureUVs(surf, side, side_t::top, v1Top, v1Bottom, v2Top, v2Bottom); @@ -821,6 +824,7 @@ void DoomLevelSubmesh::CreateFrontWallSurface(FLevelLocals& doomMap, side_t* sid surf.ControlSector = nullptr; surf.sectorGroup = sectorGroup[front->Index()]; surf.texture = side->textures[side_t::mid].texture; + surf.AlwaysUpdate = !!(front->Flags & SECF_LM_DYNAMIC); SetSideTextureUVs(surf, side, side_t::top, v1Top, v1Bottom, v2Top, v2Bottom); @@ -911,6 +915,7 @@ void DoomLevelSubmesh::CreateMidWallSurface(FLevelLocals& doomMap, side_t* side) surf.sectorGroup = sectorGroup[front->Index()]; surf.texture = texture; surf.alpha = float(side->linedef->alpha); + surf.AlwaysUpdate = !!(front->Flags & SECF_LM_DYNAMIC); SetSideTextureUVs(surf, side, side_t::top, verts[2].Z, verts[0].Z, verts[3].Z, verts[1].Z); @@ -980,6 +985,7 @@ void DoomLevelSubmesh::Create3DFloorWallSurfaces(FLevelLocals& doomMap, side_t* surf.plane = ToPlane(verts[0], verts[1], verts[2], verts[3]); surf.sectorGroup = sectorGroup[front->Index()]; surf.texture = side->textures[side_t::mid].texture; + surf.AlwaysUpdate = !!(front->Flags & SECF_LM_DYNAMIC); SetSideTextureUVs(surf, side, side_t::top, tlZ, blZ, trZ, brZ); @@ -1031,6 +1037,7 @@ void DoomLevelSubmesh::CreateTopWallSurface(FLevelLocals& doomMap, side_t* side) surf.ControlSector = nullptr; surf.sectorGroup = sectorGroup[front->Index()]; surf.texture = side->textures[side_t::top].texture; + surf.AlwaysUpdate = !!(front->Flags & SECF_LM_DYNAMIC); SetSideTextureUVs(surf, side, side_t::top, v1Top, v1TopBack, v2Top, v2TopBack); @@ -1080,6 +1087,7 @@ void DoomLevelSubmesh::CreateBottomWallSurface(FLevelLocals& doomMap, side_t* si surf.ControlSector = nullptr; surf.sectorGroup = sectorGroup[front->Index()]; surf.texture = side->textures[side_t::bottom].texture; + surf.AlwaysUpdate = !!(front->Flags & SECF_LM_DYNAMIC); SetSideTextureUVs(surf, side, side_t::bottom, v1BottomBack, v1Bottom, v2BottomBack, v2Bottom); @@ -1175,6 +1183,7 @@ void DoomLevelSubmesh::CreateFloorSurface(FLevelLocals &doomMap, subsector_t *su surf.ControlSector = controlSector; surf.plane = FVector4((float)plane.Normal().X, (float)plane.Normal().Y, (float)plane.Normal().Z, -(float)plane.D); surf.sectorGroup = sectorGroup[sector->Index()]; + surf.AlwaysUpdate = !!(sector->Flags & SECF_LM_DYNAMIC); Surfaces.Push(surf); } @@ -1230,6 +1239,7 @@ void DoomLevelSubmesh::CreateCeilingSurface(FLevelLocals& doomMap, subsector_t* surf.ControlSector = controlSector; surf.plane = FVector4((float)plane.Normal().X, (float)plane.Normal().Y, (float)plane.Normal().Z, -(float)plane.D); surf.sectorGroup = sectorGroup[sector->Index()]; + surf.AlwaysUpdate = !!(sector->Flags & SECF_LM_DYNAMIC); Surfaces.Push(surf); } diff --git a/src/rendering/hwrenderer/scene/hw_drawinfo.cpp b/src/rendering/hwrenderer/scene/hw_drawinfo.cpp index dfcf5d2c2..40e6232ba 100644 --- a/src/rendering/hwrenderer/scene/hw_drawinfo.cpp +++ b/src/rendering/hwrenderer/scene/hw_drawinfo.cpp @@ -421,7 +421,7 @@ void HWDrawInfo::UpdateLightmaps() { for (auto& e : static_cast(level.levelMesh->StaticMesh.get())->Surfaces) { - if (e.needsUpdate && !e.bSky && !e.portalIndex) + if (e.NeedsUpdate && !e.bSky && !e.portalIndex) { VisibleSurfaces.Push(&e); diff --git a/src/rendering/hwrenderer/scene/hw_drawinfo.h b/src/rendering/hwrenderer/scene/hw_drawinfo.h index 1aed24532..b89bfad61 100644 --- a/src/rendering/hwrenderer/scene/hw_drawinfo.h +++ b/src/rendering/hwrenderer/scene/hw_drawinfo.h @@ -210,16 +210,16 @@ struct HWDrawInfo return; } - if (lm_always_update) + if (lm_always_update || surface->AlwaysUpdate) { - surface->needsUpdate = true; + surface->NeedsUpdate = true; } else if (VisibleSurfaces.Size() >= unsigned(lm_max_updates)) { return; } - if (surface->needsUpdate && !surface->portalIndex && !surface->bSky) + if (surface->NeedsUpdate && !surface->portalIndex && !surface->bSky) { VisibleSurfaces.Push(surface); }