feat(overhaul): port S5 particle cell visibility

Publish the exact completed walk landscape set as the typed retained particle-view product. Apply retail CLandCell membership versus constant-true non-null CEnvCell eligibility while preserving the x87 distance and AP-116 behavior.

Delete the null-root terrain visibility reconstruction and the dead drawable-cell point-light feedback chain. Retire AP-117, correct AP-85 and AD-21, and keep directional shadows, building degrade, AP-232, probes, RHI, shaders, and DAT outside this chunk.

Automated return: Release 0 warnings/0 errors; Core VFX 111/111; App particle/frame/renderer/terrain 146/146; warmed production allocation 1/1 at 0 B. First official hermetic artifact s5-c1-hermetic-20260904 is preserved at 16759/16760 with only the stale 162-row assertion; after the bounded 161 correction, exact pin 1/1 and fresh s5-c1-hermetic-corrected-20260904 16760/16760. InstalledDat 385 pass, 10 documented failures, 1 documented skip, no new identity.

Mutation 1: making EnvCell eligibility set-dependent first failed ParticleSystemTests.cs:553 Assert.True, expected true actual false. Mutation 2: making outdoor eligibility constant true first failed ParticleSystemTests.cs:559 Assert.False, expected false actual true.

Mutation 3: feeding the diagnostic union first failed WorldSceneRendererTests.cs:279 HashSet equality, expected [16842755], actual [16843008, 16842755]. Mutation 4: restoring CollectVisibleCells first failed TerrainParticleCellVisibilityTests.cs:37 and named TerrainModernRenderer.cs.

Mutation 5: restoring ObserveDrawableCells first failed TerrainParticleCellVisibilityTests.cs:37 and named WorldRenderFrameBuilder.cs. Mutation 6: changing the inclusive boundary from <= to < first failed ParticleSystemTests.cs:519 Assert.True, expected true actual false.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-09-04 16:27:46 +02:00
parent efb0756190
commit 94a6b5ef39
18 changed files with 352 additions and 269 deletions

View file

@ -194,9 +194,7 @@ public sealed class WorldSceneRendererTests
"flat:clip",
"flat:sky",
"flat:terrain",
"visibility:mark",
"flat:entities",
"frame:clear-cells",
"passes:disable-clip",
"particles:global",
"flat:weather",
@ -220,7 +218,7 @@ public sealed class WorldSceneRendererTests
}
[Fact]
public void PViewWorld_PublishesTheWalkVisibleCellsOnce()
public void PViewWorld_PublishesTheWalkLandscapeCellsOnce()
{
var root = new LoadedCell
{
@ -240,7 +238,6 @@ public sealed class WorldSceneRendererTests
"passes:begin",
"pview:draw",
"visibility:mark",
"frame:observe-cells",
"diagnostics:pview",
"passes:disable-clip",
"particles:none",
@ -265,7 +262,7 @@ public sealed class WorldSceneRendererTests
}
[Fact]
public void PViewWorld_PublishesLookInCellsToParticleAndLightVisibility()
public void PViewWorld_PublishesOnlyLandscapeCellsToParticleVisibility()
{
var root = new LoadedCell
{
@ -276,15 +273,11 @@ public sealed class WorldSceneRendererTests
rig.Renderer.Render(default);
// Retail gates effects on cell->IsInView() (ShouldDrawParticles
// @0x0050FE60), and a cell entered through a building portal
// (DrawBuilding @0x0059F2A0 -> PView::ConstructView @0x005A57B0) is
// drawn by the same traversal as a flooded cell. The particle gate and
// light-candidate scope must therefore receive the walk's one visited
// set, including look-ins.
Assert.Contains(0x01010003u, rig.Visibility.MarkedCells);
Assert.NotNull(rig.Frames.ObservedCells);
Assert.Contains(0x01010003u, rig.Frames.ObservedCells!);
// The borrowed result deliberately has three distinct products:
// DrawableCells contains the EnvCell, VisibleCells is their diagnostic
// union, and VisibleLandscapeCells contains only this outdoor id.
Assert.Equal([0x0101_0003u], rig.Visibility.MarkedCells);
Assert.DoesNotContain(0x0101_0100u, rig.Visibility.MarkedCells);
}
[Fact]
@ -925,15 +918,6 @@ public sealed class WorldSceneRendererTests
return frame;
}
public IReadOnlySet<uint>? ObservedCells { get; private set; }
public void ObserveDrawableCells(IReadOnlySet<uint> drawableCells)
{
calls.Add("frame:observe-cells");
ObservedCells = new HashSet<uint>(drawableCells);
}
public void ClearDrawableCells() => calls.Add("frame:clear-cells");
}
private sealed class EntitySource : IWorldSceneEntitySource
@ -995,7 +979,7 @@ public sealed class WorldSceneRendererTests
{
public HashSet<uint> MarkedCells { get; } = [];
public void MarkVisibleCells(HashSet<uint> cellIds)
public void MarkVisibleLandscapeCells(HashSet<uint> cellIds)
{
calls.Add("visibility:mark");
MarkedCells.UnionWith(cellIds);
@ -1015,13 +999,14 @@ public sealed class WorldSceneRendererTests
public PViewRenderer(List<string> calls)
{
_calls = calls;
// Distinct flood-only vs in-view sets: 0x01010003 is a look-in
// cell that is drawn but never part of the main flood.
// Distinct typed products: EnvCell shell preparation, diagnostic
// union, and the outdoor landscape IsInView answer.
_interiorResult = new RetailPViewFrameResult().Reset(
ClipFrameAssembler.BeginWalkFrame(
ClipFrame.NoClip(), outdoorRoot: false),
[0x01010001u],
[0x01010001u, 0x01010003u],
[0x0101_0100u],
[0x0101_0100u, 0x0101_0003u],
[0x0101_0003u],
default,
default,
diagnosticPartition: null);
@ -1030,6 +1015,7 @@ public sealed class WorldSceneRendererTests
ClipFrame.NoClip(), outdoorRoot: true),
[],
[],
[],
default,
default,
diagnosticPartition: null);
@ -1062,8 +1048,6 @@ public sealed class WorldSceneRendererTests
public bool ThrowOnAbort { get; set; }
public HashSet<uint>? TerrainVisibleCellIds { get; } = [0x01010001u];
public RenderFrameFoundation? SkyFoundation { get; private set; }
public RenderFrameFoundation? WeatherFoundation { get; private set; }