diff --git a/src/AcDream.App/Rendering/GameWindow.cs b/src/AcDream.App/Rendering/GameWindow.cs index 464fbb0..0dbcb49 100644 --- a/src/AcDream.App/Rendering/GameWindow.cs +++ b/src/AcDream.App/Rendering/GameWindow.cs @@ -7159,18 +7159,33 @@ public sealed class GameWindow : IDisposable 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. + // Phase A8 fix (post-visual): the correct WB order is + // mark-and-punch FIRST, then indoor cells. The far-depth + // punch overwrites depth at portal silhouettes to 1.0; + // indoor geometry drawn AFTER the punch wins the depth + // test (its depth is closer than 1.0) and correctly + // occludes the subsequent stencil-gated outdoor pass. + // Drawing indoor first (the old order) had indoor depth + // destroyed by the punch, so terrain at 0.99 won every + // stencil-gated pixel: closed doors leaked outside, + // walls between rooms leaked far-side door openings, + // and characters bled to terrain at portal overlaps. + + // WB Steps 1+2: mark stencil + punch far depth in portal regions. + _indoorStencil!.MarkAndPunch(camera.View * camera.Projection); + + // WB Step 3: draw indoor entities second, stencil OFF + // (MarkAndPunch left the state stencil-disabled). Indoor + // entities ALWAYS draw inside the camera-building, regardless + // of portal coverage. Animated entities (player, NPCs) flow + // through IndoorOnly via the animatedEntityIds override so + // they're not stencil-gated by the outdoor pass. _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