From fef6c619a9004e6838e7646a6ad4395cc0daf858 Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 26 May 2026 09:38:37 +0200 Subject: [PATCH] =?UTF-8?q?Revert=20"feat(render):=20Phase=20A8=20?= =?UTF-8?q?=E2=80=94=20wire=20stencil=20pipeline=20into=20render=20frame"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 41c2e67cd831b2d5e5f335b37e56ce83f181456e. --- src/AcDream.App/Rendering/CellVisibility.cs | 11 -- src/AcDream.App/Rendering/GameWindow.cs | 127 ++++---------------- 2 files changed, 24 insertions(+), 114 deletions(-) diff --git a/src/AcDream.App/Rendering/CellVisibility.cs b/src/AcDream.App/Rendering/CellVisibility.cs index ffddd9a..b4debbc 100644 --- a/src/AcDream.App/Rendering/CellVisibility.cs +++ b/src/AcDream.App/Rendering/CellVisibility.cs @@ -344,17 +344,6 @@ public sealed class CellVisibility local.Z <= cell.LocalBoundsMax.Z + PointInCellEpsilon; } - /// - /// Looks up a loaded cell by full 32-bit cell id, or returns null if - /// not loaded. Used by the Phase A8 stencil pipeline to materialize - /// back into - /// instances for portal mesh extraction. - /// - public LoadedCell? TryGetCell(uint cellId) - { - return _cellLookup.TryGetValue(cellId, out var cell) ? cell : null; - } - /// /// Brute-force scan of every loaded cell to test whether /// is inside any of them. Does not touch diff --git a/src/AcDream.App/Rendering/GameWindow.cs b/src/AcDream.App/Rendering/GameWindow.cs index 464fbb0..e1e3e1b 100644 --- a/src/AcDream.App/Rendering/GameWindow.cs +++ b/src/AcDream.App/Rendering/GameWindow.cs @@ -108,10 +108,6 @@ public sealed class GameWindow : IDisposable // Step 4: portal-based interior cell visibility. private readonly CellVisibility _cellVisibility = new(); - // Phase A8: indoor-cell stencil pipeline (#78). Null until OnLoad runs - // (requires GL context). Never null after OnLoad completes normally. - private IndoorCellStencilPipeline? _indoorStencil; - // Phase A.1 hotfix / Phase A.5 T10: DatCollection is NOT thread-safe. // DatReaderWriter's DatBinReader uses a shared buffer position internally — // concurrent _dats.Get calls from the streaming worker thread (T11+) and @@ -1773,13 +1769,6 @@ public sealed class GameWindow : IDisposable // the player. _particleRenderer = new ParticleRenderer(_gl, shadersDir, _textureCache, _dats); - // Phase A8 — indoor-cell visibility culling pipeline (#78). - // Shader files are deployed alongside the existing terrain/mesh - // shaders via the same .csproj content glob. - _indoorStencil = new IndoorCellStencilPipeline(_gl, - Path.Combine(shadersDir, "portal_stencil.vert"), - Path.Combine(shadersDir, "portal_stencil.frag")); - // A.5 T22.5: apply radii from the already-resolved _resolvedQuality. // _resolvedQuality was set by the quality block immediately after // LoadAndApplyPersistedSettings() above, absorbing all env-var overrides. @@ -7108,38 +7097,26 @@ public sealed class GameWindow : IDisposable goto SkipWorldGeometry; } - // Phase A8 — indoor-cell visibility culling. - // When the camera is inside an EnvCell, build a portal-silhouette - // stencil mask and use it to gate outdoor passes (terrain + - // outdoor entities) so they only write fragments inside actual - // portal openings. WB-style stencil port (closes #78 + cellar- - // stairs artifact). Retail oracle: PView::DrawCells at - // acclient_2013_pseudo_c.txt:432709 ("outside_view.view_count > 0"). - int portalTriCount = 0; - if (cameraInsideCell && visibility is not null && _indoorStencil is not null) - { - // Resolve VisibleCellIds → LoadedCell list via - // CellVisibility.TryGetCell (added in Task 7). - var currentBuildingCells = new List(visibility.VisibleCellIds.Count); - foreach (var id in visibility.VisibleCellIds) - { - var cell = _cellVisibility.TryGetCell(id); - if (cell is not null) currentBuildingCells.Add(cell); - } - portalTriCount = _indoorStencil.UploadPortalMesh(currentBuildingCells); + // Phase N.5b: wrap Draw in CPU stopwatch for [TERRAIN-DIAG] rollup + // (gated on ACDREAM_WB_DIAG=1, same env var as [WB-DIAG]). Stopwatch + // is cheap; only the periodic Console.WriteLine is gated. + _terrainCpuStopwatch.Restart(); + _terrain?.Draw(camera, frustum, neverCullLandblockId: playerLb); + _terrainCpuStopwatch.Stop(); + // Multiply by 100 then divide by 100 in the diag print to keep + // 0.01 µs precision in the long-typed sample buffer. Terrain Draw + // is sub-microsecond on simple scenes; truncating to integer µs + // would round nearly every sample to 0. + _terrainCpuSamples[_terrainCpuSampleCursor] = (long)(_terrainCpuStopwatch.Elapsed.TotalMicroseconds * 100.0); + _terrainCpuSampleCursor = (_terrainCpuSampleCursor + 1) % _terrainCpuSamples.Length; + MaybeFlushTerrainDiag(); - if (AcDream.Core.Rendering.RenderingDiagnostics.ProbeVisibilityEnabled) - { - Console.WriteLine( - $"[vis] cameraInside=true cells={visibility.VisibleCellIds.Count} " + - $"exitPortalVisible={visibility.HasExitPortalVisible} " + - $"portalTris={portalTriCount / 3}"); - } - } - else if (AcDream.Core.Rendering.RenderingDiagnostics.ProbeVisibilityEnabled) - { - Console.WriteLine("[vis] cameraInside=false"); - } + // Conditional depth clear: when camera is inside a building, clear + // depth (not color) so interior geometry writes fresh Z values on top + // of the terrain color buffer. Exit portals show outdoor terrain color + // because we kept the color buffer. Matching ACME GameScene.cs pattern. + if (cameraInsideCell) + _gl!.Clear(ClearBufferMask.DepthBufferBit); // L-fix1 (2026-04-28): pass the set of animated-entity ids so // the renderer keeps remote players / NPCs / monsters @@ -7157,65 +7134,11 @@ public sealed class GameWindow : IDisposable animatedIds.Add(k); } - if (cameraInsideCell && portalTriCount > 0) - { - // WB Step 3: draw indoor entities first, stencil OFF. - // Indoor entities (cell mesh + cell statics) ALWAYS draw - // inside the camera-building, regardless of portal coverage. - _wbDrawDispatcher!.Draw(camera, _worldState.LandblockEntries, frustum, - neverCullLandblockId: playerLb, - visibleCellIds: visibility!.VisibleCellIds, - animatedEntityIds: animatedIds, - set: AcDream.App.Rendering.Wb.WbDrawDispatcher.EntitySet.IndoorOnly); - - // WB Steps 1+2: mark stencil + punch far depth in portal regions. - _indoorStencil!.MarkAndPunch(camera.View * camera.Projection); - - // WB Step 4a: terrain, stencil-gated to portal silhouettes. - _indoorStencil!.EnableOutdoorPass(); - // Phase N.5b: wrap Draw in CPU stopwatch for [TERRAIN-DIAG] rollup - // (gated on ACDREAM_WB_DIAG=1, same env var as [WB-DIAG]). Stopwatch - // is cheap; only the periodic Console.WriteLine is gated. - _terrainCpuStopwatch.Restart(); - _terrain?.Draw(camera, frustum, neverCullLandblockId: playerLb); - _terrainCpuStopwatch.Stop(); - _terrainCpuSamples[_terrainCpuSampleCursor] = - (long)(_terrainCpuStopwatch.Elapsed.TotalMicroseconds * 100.0); - _terrainCpuSampleCursor = (_terrainCpuSampleCursor + 1) % _terrainCpuSamples.Length; - MaybeFlushTerrainDiag(); - - // WB Step 4b: outdoor entities, still stencil-gated. - _wbDrawDispatcher!.Draw(camera, _worldState.LandblockEntries, frustum, - neverCullLandblockId: playerLb, - visibleCellIds: visibility.VisibleCellIds, - animatedEntityIds: animatedIds, - set: AcDream.App.Rendering.Wb.WbDrawDispatcher.EntitySet.OutdoorOnly); - - _indoorStencil!.DisableStencil(); - } - else - { - // Outdoor (or indoor with no exit portals): pre-A8 path. - // Phase N.5b: wrap Draw in CPU stopwatch for [TERRAIN-DIAG] rollup. - _terrainCpuStopwatch.Restart(); - _terrain?.Draw(camera, frustum, neverCullLandblockId: playerLb); - _terrainCpuStopwatch.Stop(); - // Multiply by 100 then divide by 100 in the diag print to keep - // 0.01 µs precision in the long-typed sample buffer. Terrain Draw - // is sub-microsecond on simple scenes; truncating to integer µs - // would round nearly every sample to 0. - _terrainCpuSamples[_terrainCpuSampleCursor] = - (long)(_terrainCpuStopwatch.Elapsed.TotalMicroseconds * 100.0); - _terrainCpuSampleCursor = (_terrainCpuSampleCursor + 1) % _terrainCpuSamples.Length; - MaybeFlushTerrainDiag(); - - // N.5: WbDrawDispatcher is always non-null (modern path mandatory). - _wbDrawDispatcher!.Draw(camera, _worldState.LandblockEntries, frustum, - neverCullLandblockId: playerLb, - visibleCellIds: visibility?.VisibleCellIds, - animatedEntityIds: animatedIds, - set: AcDream.App.Rendering.Wb.WbDrawDispatcher.EntitySet.All); - } + // N.5: WbDrawDispatcher is always non-null (modern path mandatory). + _wbDrawDispatcher!.Draw(camera, _worldState.LandblockEntries, frustum, + neverCullLandblockId: playerLb, + visibleCellIds: visibility?.VisibleCellIds, + animatedEntityIds: animatedIds); // Phase G.1 / E.3: draw all live particles after opaque // scene geometry so alpha blending composites correctly. @@ -10571,8 +10494,6 @@ public sealed class GameWindow : IDisposable _liveSession = null; _audioEngine?.Dispose(); // Phase E.2: stop all voices, close AL context _wbDrawDispatcher?.Dispose(); - _indoorStencil?.Dispose(); - _indoorStencil = null; _skyRenderer?.Dispose(); // depends on sampler cache; dispose first _samplerCache?.Dispose(); _textureCache?.Dispose();