fix(render): Phase A8 — render IndoorPass entities (cottage shell walls)

User report after Step 5 disable + ColorMask cleanup + cull-cache fix +
terrain-skip fix: "Still chaos, GPU 100%. House missing lots of walls."

Root cause finally found: Pre-A8 indoor walls came from IsBuildingShell
entities (landblock-baked GfxObj slabs that represent cottage exterior
walls — NOT part of any cell's CellStruct). They were drawn via
Dispatcher.Draw(set: IndoorPass) in the pre-A8 outdoor path.

WB's algorithm assumes its StaticObjectManager.Render in Step 4 handles
these (its partition lumps shells with outdoor statics). Our EntitySet
partition (RR2) puts IsBuildingShell into IndoorPass (alongside cell
stabs), NOT OutdoorScenery — because logically shells ARE indoor walls.

A8's RenderInsideOutAcdream Step 4 calls Draw(set: OutdoorScenery)
which EXCLUDES IsBuildingShell. So cottage exterior wall slabs never
render in A8. EnvCellRenderer provides the floor + interior CellStruct
walls, but the shell slabs (exterior walls visible from inside) are
gone. Symptom: "missing walls" because half the cottage walls are
landblock-baked shells, not cell mesh.

FIX: insert a Draw(set: IndoorPass) call between Step 3 (cells) and
Step 4 (stencil-gated outdoor) when cameraInsideBuilding. Uses
currentEnvCellIds as the cell filter — narrows cell stabs to camera-
building cells; building shells (no ParentCellId) pass through and
all render. Depth-tested (DepthFunc.Less) so cottage-A's near walls
occlude cottage-B's far walls; no stencil so shells render
unconditionally inside the camera building.

Build green.

This was the root cause behind the 4 days of RR7 failures. The
handoff doc even noted "Building shells render (they ARE GfxObj
entities with proper mesh refs after hydration)" — but the new
RenderInsideOutAcdream code DIDN'T call IndoorPass, only
OutdoorScenery. Hence shells never rendered.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Erik 2026-05-27 16:22:16 +02:00
parent f143ece317
commit 2bf5013c2f

View file

@ -10710,6 +10710,34 @@ public sealed class GameWindow : IDisposable
gl.DepthMask(true);
}
// FIX 2026-05-28 (post-third-visual-gate): render IndoorPass entities.
// EnvCellRenderer covers cell GEOMETRY (floor, walls baked into the
// cell's CellStruct). But cottages ALSO have IsBuildingShell entities
// — landblock-baked GfxObjs representing exterior wall slabs that
// aren't part of any cell's CellStruct. Pre-A8 rendered these via
// Dispatcher.Draw(set: IndoorPass); WB's algorithm assumes its
// StaticObjectManager.Render handles them in Step 4. Our EntitySet
// partition puts IsBuildingShell into IndoorPass (not OutdoorScenery),
// so Step 4's `Draw(set: OutdoorScenery)` misses them entirely.
// Result with the missing call: user reports "house missing lots of
// walls" — the cottage's exterior wall slabs aren't drawn.
//
// Render IndoorPass between Step 3 and Step 4, with the
// currentEnvCellIds filter narrowing cell stabs but NOT the building
// shells (they have no ParentCellId and pass through). Depth-test
// with DepthFunc.Less so cottage-A's near walls occlude cottage-B's
// far walls. NO stencil — we want them rendered unconditionally
// inside the camera-building.
if (camBuildings.Count > 0)
{
_meshShader!.Use();
_wbDrawDispatcher!.Draw(camera, _worldState.LandblockEntries, frustum,
neverCullLandblockId: playerLb,
visibleCellIds: currentEnvCellIds,
animatedEntityIds: animatedIds,
set: AcDream.App.Rendering.Wb.WbDrawDispatcher.EntitySet.IndoorPass);
}
EmitEnvCellProbe(camBuildings.Count, otherBuildings.Count, currentEnvCellIds.Count);
// Step 4: stencil-gated outdoor (terrain + scenery + static objects).