From 4fa339059247801e7dc6d543e61cfb4145d16617 Mon Sep 17 00:00:00 2001 From: Erik Date: Wed, 27 May 2026 14:07:13 +0200 Subject: [PATCH] =?UTF-8?q?Revert=20"feat(render):=20Phase=20A8=20RR7=20?= =?UTF-8?q?=E2=80=94=20WB=20RenderInsideOut=20Steps=201-4=20+=20outdoor=20?= =?UTF-8?q?branch"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 3d28d701a2c9e4e95073fc0b213357a816f37825. --- src/AcDream.App/Rendering/GameWindow.cs | 183 +++--------------------- 1 file changed, 16 insertions(+), 167 deletions(-) diff --git a/src/AcDream.App/Rendering/GameWindow.cs b/src/AcDream.App/Rendering/GameWindow.cs index d6ecebb..cd65887 100644 --- a/src/AcDream.App/Rendering/GameWindow.cs +++ b/src/AcDream.App/Rendering/GameWindow.cs @@ -36,11 +36,6 @@ public sealed class GameWindow : IDisposable private AcDream.App.Rendering.Wb.EntitySpawnAdapter? _wbEntitySpawnAdapter; private AcDream.App.Rendering.Vfx.EntityScriptActivator? _entityScriptActivator; private AcDream.App.Rendering.Wb.WbDrawDispatcher? _wbDrawDispatcher; - /// Phase A8 RR7 (2026-05-26): portal stencil pipeline for the indoor - /// render branch (WB RenderInsideOut Steps 1-4). Non-null after OnLoad. Null - /// only if shader compilation failed — in which case the indoor branch falls - /// through to the outdoor path (graceful degradation, no crash). - private AcDream.App.Rendering.IndoorCellStencilPipeline? _indoorStencilPipeline; /// Phase N.5: ARB_bindless_texture + ARB_shader_draw_parameters /// support. Required at startup — missing bindless throws /// in OnLoad. @@ -1765,23 +1760,6 @@ public sealed class GameWindow : IDisposable _classificationCache); // A.5 T22.5: apply A2C gate from quality preset. _wbDrawDispatcher.AlphaToCoverage = _resolvedQuality.AlphaToCoverage; - - // Phase A8 RR7 (2026-05-26): portal stencil pipeline. Constructed - // immediately after WbDrawDispatcher — same GL context, same lifetime. - // Null-safe: if shader compilation throws, the indoor branch falls back - // to outdoor rendering (no crash; just no indoor/outdoor separation). - try - { - _indoorStencilPipeline = new AcDream.App.Rendering.IndoorCellStencilPipeline( - _gl, - System.IO.Path.Combine(shadersDir, "portal_stencil.vert"), - System.IO.Path.Combine(shadersDir, "portal_stencil.frag")); - } - catch (Exception ex) - { - Console.WriteLine($"[A8] IndoorCellStencilPipeline failed to construct: {ex.Message}"); - _indoorStencilPipeline = null; - } } // Phase G.1 sky renderer — its own shader (sky.vert / sky.frag) @@ -6937,11 +6915,7 @@ public sealed class GameWindow : IDisposable System.Math.Clamp(fogColor.Z, 0f, 1f), 1f); - // Phase A8 RR7 (2026-05-26): stencil buffer cleared per-frame now that the - // stencil pipeline is wired in. Previously not cleared because no rendering - // consumed stencil. Without this clear, bits from a prior frame's indoor - // branch could leak into an outdoor frame and gate visibility incorrectly. - _gl!.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit | ClearBufferMask.StencilBufferBit); + _gl!.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); // Phase N.6 slice 1: one-shot surface-format histogram dump under // ACDREAM_DUMP_SURFACES=1. Zero cost when off. @@ -7055,31 +7029,6 @@ public sealed class GameWindow : IDisposable var visibility = _cellVisibility.ComputeVisibility(camPos); bool cameraInsideCell = visibility?.CameraCell is not null; - // Phase A8 RR7 (2026-05-26): the single source of truth for - // "render the indoor branch." Strict PointInCell + the camera's - // cell must actually belong to a Building (not an outdoor cell - // or untagged dungeon cell). No grace. - // - // sky pre-scene, terrain, stencil pipeline, weather post-scene - // all gate on this flag below. The lenient cameraInsideCell flag - // is kept ONLY for the [vis] probe's side-by-side logging. - bool cameraInsideBuilding = visibility?.CameraCell is not null - && CellVisibility.PointInCell(camPos, visibility.CameraCell) - && visibility.CameraCell.BuildingId is not null; - - // Phase A8 RR7: look up buildings containing the camera cell. - // The BuildingRegistry is keyed by landblock id in _buildingRegistries - // (per Code Structure Rule #2 — Core can't reference App types, so the - // registry lives on GameWindow, not on a Core struct). - IReadOnlyList camBuildings = - System.Array.Empty(); - if (cameraInsideBuilding && visibility?.CameraCell is not null) - { - uint cameraLandblockId = visibility.CameraCell.CellId & 0xFFFF0000u; - if (_buildingRegistries.TryGetValue(cameraLandblockId, out var reg)) - camBuildings = reg.GetBuildingsContainingCell(visibility.CameraCell.CellId); - } - // SPIKE 2026-05-26: A8 transition investigation. Lights up the // dormant RenderingDiagnostics.ProbeVisibilityEnabled flag (added // by Task 6 of the original A8 plan). Per-frame state captures: @@ -7194,11 +7143,7 @@ public sealed class GameWindow : IDisposable // cylinder 0x01004C42/0x01004C44) need to overlay terrain // and entities to look volumetric — see the post-scene // RenderWeather call further below. - // - // Phase A8 RR7 (2026-05-26): gate changed from !cameraInsideCell - // to !cameraInsideBuilding. When indoors (inside a building), the - // sky is drawn stencil-gated in the indoor branch below (Step 4a). - if (!cameraInsideBuilding) + if (!cameraInsideCell) { _skyRenderer?.RenderSky(camera, camPos, (float)WorldTime.DayFraction, _activeDayGroup, kf, environOverrideActive); @@ -7222,14 +7167,8 @@ public sealed class GameWindow : IDisposable // 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. - // - // Phase A8 RR7 (2026-05-26): skip initial terrain when inside a building. - // Terrain renders stencil-gated in Step 4b of the indoor branch below. - // The old "Conditional depth clear: if (cameraInsideCell)" is removed — - // the A8 indoor branch manages depth state through MarkAndPunch instead. _terrainCpuStopwatch.Restart(); - if (!cameraInsideBuilding) - _terrain?.Draw(camera, frustum, neverCullLandblockId: playerLb); + _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 @@ -7239,6 +7178,13 @@ public sealed class GameWindow : IDisposable _terrainCpuSampleCursor = (_terrainCpuSampleCursor + 1) % _terrainCpuSamples.Length; MaybeFlushTerrainDiag(); + // 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 // visible even when their landblock rotates out of the @@ -7255,104 +7201,11 @@ public sealed class GameWindow : IDisposable animatedIds.Add(k); } - // Phase A8 RR7 (2026-05-26): indoor / outdoor branch. - // - // Indoor (cameraInsideBuilding == true) — WB RenderInsideOut Steps 1-4: - // MarkAndPunch on camBuildings' exit portals - // IndoorPass (cell mesh + statics + building shells) - // EnableOutdoorPass - // Stencil-gated sky (acdream enhancement) - // Stencil-gated terrain re-draw - // Stencil-gated OutdoorScenery - // DisableStencil - // LiveDynamic - // - // Outdoor (cameraInsideBuilding == false): - // Unchanged from pre-A8: single Draw(All). - // RenderOutsideIn (looking INTO cottage windows from outside) - // ships in RR11. - - if (cameraInsideBuilding && _indoorStencilPipeline is not null - && visibility?.CameraCell is not null - && camBuildings.Count > 0) - { - if (AcDream.Core.Rendering.RenderingDiagnostics.ProbeVisibilityEnabled) - Console.WriteLine($"[vis] branch=indoor buildings={camBuildings.Count}"); - - // Steps 1+2: stencil bit 1 + far-depth at the camera-buildings' - // exit portals. Combine polygons from all containing buildings - // (usually 1, occasionally 2 in shared-cell scenarios). - int totalVerts = 0; - foreach (var b in camBuildings) - totalVerts += _indoorStencilPipeline.UploadBuildingPortalMesh(b); - // Note: UploadBuildingPortalMesh overwrites the VBO each call. - // For multi-building cases, the last call wins. Loop-uploading - // all polygons would require a different API; for now we use - // the existing pipeline pattern (mark+punch in one call), which - // matches WB's per-building iteration. See RR9 for the multi- - // building marking pattern. - - var viewProjection = camera.View * camera.Projection; - _indoorStencilPipeline.MarkAndPunch(viewProjection); - - // Step 3: IndoorPass with camera-buildings' cell scope. - var camCellIds = new HashSet(); - foreach (var b in camBuildings) - foreach (var cid in b.EnvCellIds) camCellIds.Add(cid); - - _wbDrawDispatcher!.Draw(camera, _worldState.LandblockEntries, - cellIds: camCellIds, - frustum: frustum, - neverCullLandblockId: playerLb, - animatedEntityIds: animatedIds, - set: AcDream.App.Rendering.Wb.WbDrawDispatcher.EntitySet.IndoorPass); - - // Step 4: stencil-gated outdoor pass. - _indoorStencilPipeline.EnableOutdoorPass(); - - // Step 4a: stencil-gated sky (acdream enhancement). - // DepthMask off so sky color writes through punched depth=1.0 - // without disturbing the depth buffer; depth stays at the punch - // value so the next step's terrain re-draw can win. - _gl!.DepthMask(false); - _skyRenderer?.RenderSky(camera, camPos, (float)WorldTime.DayFraction, - _activeDayGroup, kf, environOverrideActive); - _gl!.DepthMask(true); - - // Step 4b: stencil-gated terrain re-draw. - _terrain?.Draw(camera, frustum, neverCullLandblockId: playerLb); - - // Step 4c: stencil-gated OutdoorScenery. - _wbDrawDispatcher!.Draw(camera, _worldState.LandblockEntries, frustum, - neverCullLandblockId: playerLb, - visibleCellIds: visibility.VisibleCellIds, - animatedEntityIds: animatedIds, - set: AcDream.App.Rendering.Wb.WbDrawDispatcher.EntitySet.OutdoorScenery); - - // (Step 5 = RR9.) - - _indoorStencilPipeline.DisableStencil(); - - // LiveDynamic — player, NPCs, dropped items. - _wbDrawDispatcher!.Draw(camera, _worldState.LandblockEntries, frustum, - neverCullLandblockId: playerLb, - visibleCellIds: visibility.VisibleCellIds, - animatedEntityIds: animatedIds, - set: AcDream.App.Rendering.Wb.WbDrawDispatcher.EntitySet.LiveDynamic); - } - else - { - if (AcDream.Core.Rendering.RenderingDiagnostics.ProbeVisibilityEnabled) - Console.WriteLine("[vis] branch=outdoor"); - - // Outdoor: single Draw(All). N.5: WbDrawDispatcher is always - // non-null (modern path mandatory). RenderOutsideIn (looking - // INTO cottage windows from outside) ships in RR11. - _wbDrawDispatcher!.Draw(camera, _worldState.LandblockEntries, frustum, - neverCullLandblockId: playerLb, - visibleCellIds: visibility?.VisibleCellIds, - animatedEntityIds: animatedIds); - } + // 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. @@ -7370,10 +7223,7 @@ public sealed class GameWindow : IDisposable // half of retail's LScape::draw split — GameSky::Draw(1) // fires after the DrawBlock loop. Same indoor gate as the // sky pass: weather is suppressed inside cells. - // - // Phase A8 RR7 (2026-05-26): gate changed from !cameraInsideCell - // to !cameraInsideBuilding (consistent with sky pre-scene gate). - if (!cameraInsideBuilding) + if (!cameraInsideCell) { _skyRenderer?.RenderWeather(camera, camPos, (float)WorldTime.DayFraction, _activeDayGroup, kf, environOverrideActive); @@ -10712,7 +10562,6 @@ public sealed class GameWindow : IDisposable _liveSession = null; _audioEngine?.Dispose(); // Phase E.2: stop all voices, close AL context _wbDrawDispatcher?.Dispose(); - _indoorStencilPipeline?.Dispose(); // Phase A8 RR7 _skyRenderer?.Dispose(); // depends on sampler cache; dispose first _samplerCache?.Dispose(); _textureCache?.Dispose();