The Phase W indoor seal did NOT land. The 2026-06-02 visual gate proved the interior render is fundamentally broken (#78: transparent walls, outdoor terrain + scenery entities bleeding in, grey floors, no outside-looking-in). Stage 4 (sky-through-door clip) was real but a top layer on a base that never sealed. DECISIVE EVIDENCE (committed in the handoff): the PVS computes correctly AND the cell shells render correctly (opaque, textured, complete — the [shell] probe shows zero NOSNAP / zero missing-texture). The failure is the SEAL + three inconsistent gates — concretely the WbDrawDispatcher.cs:1756 ParentCellId==null -> return true bypass draws outdoor scenery indoors, and the indoor path draws the outdoor world then gates it instead of running ONLY DrawInside. Retail, when inside, runs ONE PView flood: visibility IS the cull; the landscape enters only through clipped exit portals + a conditional depth-only clear. Dossier (per the user's mandate: NO shortcuts/bandaids, port from retail, redesign the whole pipeline if needed, brainstorm first): - Master handoff (root cause + retail target + reusable-vs-redesign + apparatus + do-not-repeat + copy-paste pickup prompt). - Huge staged redesign plan R0(brainstorm)->R1(one visibility authority, kill the bleed)->R2(indoor=DrawInside-only)->R3(the seal, DrawCells port)->R4(per-cell object/particle clip)->R5(outside-looking-in)->R6(dungeons)->R7(polish/conformance). Each ends at a user visual gate. - 3 research docs: full retail render pipeline reference (705 lines, decomp-verified), acdream pipeline inventory + failure map, reference cross-check (WB two-pipe is the wrong model). #78 promoted to the redesign. The 5 remaining Core test failures are pre-existing physics/collision bugs, none render-related. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
431 lines
28 KiB
Markdown
431 lines
28 KiB
Markdown
# Render Pipeline Redesign — Master Handoff (2026-06-02)
|
||
|
||
> **Canonical pickup for the full render-pipeline redesign.** Phase W's interior "seal"
|
||
> did **not** land. The single final visual verification (user, 2026-06-02) proved the
|
||
> indoor render is fundamentally broken (issue **#78** — outdoor geometry visible inside
|
||
> EnvCells — plus transparent walls, missing-floor appearance, entity/scenery bleed, and
|
||
> no outside-looking-in). This document consolidates ALL research + the decisive live
|
||
> diagnostic evidence + the retail-faithful target + the mandate.
|
||
>
|
||
> **Read order for the next session:** this doc → the 3 research docs (§5–§7 links) →
|
||
> then **BRAINSTORM** (`superpowers:brainstorming`) the architecture **before writing any
|
||
> code**. The plan in §10 is the spine; the brainstorm refines it with the user.
|
||
|
||
---
|
||
|
||
## 0. The mandate (user, 2026-06-02 — NON-NEGOTIABLE)
|
||
|
||
Quoting the user's intent directly:
|
||
|
||
- **FULLY WORKING** outdoor, indoor, and dungeon rendering. **No flaps, no missing
|
||
textures, no transparent walls, no ground/terrain texture leaking into the cellar, no
|
||
bleed-through.** Outside, inside, portal transitions, dungeons, particle clipping —
|
||
**EVERYTHING.**
|
||
- **No shortcuts. No bandaids. No quick fixes.** "If you have choices of doing something
|
||
fast when it might not be the best way or the most architecturally correct way, never
|
||
take that way." If the correct way is slower, take it anyway.
|
||
- **If you have to refactor and redesign the whole pipeline, DO THAT.**
|
||
- **Port from retail** decomp where needed — it is the oracle (`docs/research/named-retail/`).
|
||
- **If you need more research mid-session, do it** — never guess.
|
||
- **Start with a brainstorm** before implementing.
|
||
|
||
This supersedes the incremental "wire 3 gaps" framing of the Phase W render plan. The
|
||
render half of Phase W is **reopened as a ground-up, retail-faithful redesign.**
|
||
|
||
---
|
||
|
||
## 1. Current broken state — the visual gate (2026-06-02, Holtburg cottage)
|
||
|
||
The user walked the cottage and reported five distinct failures:
|
||
|
||
1. **Outdoor → looking through an open door/window:** interior walls are **transparent**
|
||
(you see into/through the house). *(= outside-looking-in not implemented; deferred U.5.)*
|
||
2. **Just inside:** you see **only the outdoor world background + NPCs/particles/doors** —
|
||
no interior shell sealing you in.
|
||
3. **Inside → looking out:** sky is visible, but you see **houses and trees through the
|
||
ground**.
|
||
4. **On the cellar stairs:** the cellar walls show, but the **floor is grey**, and NPCs /
|
||
particles / doors show **through the walls above**.
|
||
5. **In the cellar:** you see the **grey world instead of the floor**.
|
||
|
||
Net: **the interior is not a sealed space.** This is issue **#78** ("outdoor geometry
|
||
visible inside EnvCells") in full, plus entity/scenery bleed and the missing
|
||
outside-looking-in path.
|
||
|
||
---
|
||
|
||
## 2. Decisive live evidence — the root cause is PROVEN (not theorized)
|
||
|
||
Captured this session via the in-tree probes (`ACDREAM_PROBE_CELL` / `_VIS` / `_SHELL`),
|
||
read from the UTF-16 `Tee-Object` logs. **These three facts together pinpoint the cause:**
|
||
|
||
### 2.1 The visibility math is CORRECT
|
||
- `[cell-transit]` shows the player moving cleanly through the cottage cells:
|
||
`0xA9B40031`(outdoor) → `0170`(vestibule) → `0171`(room) → `0175`(stairs) → `0174`(cellar).
|
||
Membership works (the Stage-1/2 fix `59f3a13` holds; some doorway flips are the player
|
||
genuinely crossing the threshold, not a strobe).
|
||
- `[vis]` shows the right visible set + portal openings, e.g.:
|
||
- `root=0xA9B40171 cells=2 ids=[0171,0170] outside(polys=1,planes=4)` — from the room,
|
||
the exit portal to outdoors IS detected (terrain/sky can draw through it).
|
||
- `root=0xA9B40174 cells=1 ids=[0174] outside(polys=0,planes=0)` — the cellar is
|
||
correctly **sealed** (no exit portal in view → terrain Skip).
|
||
- Per-cell clip-plane counts are populated. **`max filter=3`** cells in any single frame.
|
||
|
||
**⇒ The PVS (`PortalVisibilityBuilder`) is not the bug. It computes the correct answer.**
|
||
|
||
### 2.2 The cell shells RENDER CORRECTLY — opaque, textured, complete
|
||
The `[shell]` probe (added for #78) emits, per opaque pass, the actual geometry drawn.
|
||
Distinct patterns observed (frequency × line):
|
||
|
||
```
|
||
205977x filter=1 ... tris=2 [0xA9B40174:gfx=1 tf=1 batch=3 idx=42 tr=0 zh=0] (cellar: 14 tris)
|
||
1476x filter=3 ... tris=48 [0xA9B40171:...idx=270 tr=0 zh=0] [0173:idx=24] [0172:idx=144] (room+subcells: 90+8+48 tris)
|
||
130x filter=1 ... tris=38 [0xA9B40171:...idx=270 tr=0 zh=0] (room: 90 tris)
|
||
125x filter=2 ... [0xA9B40174:idx=42] [0xA9B40175:idx=24] (cellar+stairs)
|
||
75x filter=1 ... [0xA9B40175:idx=24] (stairs)
|
||
```
|
||
- **Zero `NOSNAP`** (no "geometry not prepared" cases). **Zero `zh>0`** (no missing-texture
|
||
cases). **Zero `tr`** (all opaque). Every visible cell draws its full, textured mesh.
|
||
- Per the probe's own diagnosis tree: `idx>0 + zh=0 + tr=0` ⇒ **"opaque geometry IS drawn,
|
||
with valid textures — the fault is DEPTH/OCCLUSION, or the geometry isn't the wall."**
|
||
|
||
**⇒ The shells are not the bug either. They draw fine. This was NEVER a shader/texture/
|
||
missing-mesh problem** (which is what naive guesses would chase).
|
||
|
||
### 2.3 So the failure is the SEAL + the GATES
|
||
Putting 2.1 + 2.2 together with the symptoms: the visible cells draw correctly, but
|
||
- only **≤3 cells'** shells draw, and **they do not form a closed opaque occluder** over
|
||
the rest of the world, so the outdoor scene shows through wherever indoor geometry isn't;
|
||
- the **outdoor terrain + outdoor scenery entities** (the "houses and trees through the
|
||
ground" = `ParentCellId == null` stabs/scenery) are **not culled or depth-occluded** when
|
||
you're indoors — they draw and win;
|
||
- **outside-looking-in** draws no interior at all (no exterior→interior portal path; U.5).
|
||
|
||
This is the **three-inconsistent-gates** failure (see §3), the exact problem the project's
|
||
own memory (`render — one gate (PView)`) flags as the core unsolved indoor-render issue —
|
||
"the week of 2026-05-25→31 made no indoor-render progress because the pipeline had 3
|
||
inconsistent gates (terrain/shell/entity)."
|
||
|
||
---
|
||
|
||
## 3. Root-cause analysis — three inconsistent gates, no closed-occluder seal
|
||
|
||
acdream's render loop gates four classes of geometry, from **inconsistent sources**:
|
||
|
||
| Geometry | Gate in code | Source of truth | Problem |
|
||
|---|---|---|---|
|
||
| **Terrain** | `terrainClipMode` (Skip/Scissor/Planes) | `ClipFrameAssembler` ← `PortalVisibilityBuilder` OutsideView | OK-ish, but only one of several gates |
|
||
| **Cell shells** | `envCellShellFilter = clipAssembly.CellIdToSlot.Keys` | `PortalVisibilityBuilder` | Draws ≤3 cells; never forms a *closed occluder* |
|
||
| **Entities** (incl. outdoor scenery, doors, NPCs) | `visibility?.VisibleCellIds` | **`CellVisibility.ComputeVisibilityFromRoot`** — a *different* traversal | Disagrees with the shell/terrain gate; **outdoor scenery (`ParentCellId=null`) not culled indoors** |
|
||
| **Particles** | *(none)* | — | Issue #104 — no cell clip at all |
|
||
| **Sky/weather** | `drawSkyThisFrame` (Stage 4) | `ClipFrameAssembler` | The only consistent one — but a top layer |
|
||
|
||
**Two distinct architecture defects:**
|
||
|
||
1. **Two visibility computations, not one.** `PortalVisibilityBuilder.Build` (the faithful
|
||
PView BFS) feeds the shell + terrain + sky gates. But the **entity** gate reads
|
||
`CellVisibility.ComputeVisibilityFromRoot` — an *older, separate* visibility path. They
|
||
are not guaranteed to agree, and the entity one does not properly cull outdoor scenery
|
||
when indoors. **Retail has ONE traversal (`PView`) that produces one `cell_draw_list`,
|
||
and every cell's objects are drawn (and only those) — there is no second gate.**
|
||
|
||
2. **No "closed interior occluder" model.** Retail's interior render is *sealed by
|
||
construction*: it draws the visible cells (whose `drawing_bsp` are closed boxes — floor,
|
||
walls, ceiling), draws `LScape` only through exit-portal clip regions, does a conditional
|
||
**Z-only** clear at the doorway, and draws each cell's objects clipped to that cell. The
|
||
outdoor world is *never drawn behind a wall* because the traversal simply never visits it
|
||
and the closed cells occlude it. acdream instead draws the outdoor world (terrain +
|
||
scenery) and *then* a few cell shells on top, relying on depth/gates that don't hold —
|
||
so the world bleeds through.
|
||
|
||
**The fix is not another gate or another clip. It is to make the render obey ONE
|
||
visibility answer for ALL geometry, with the interior sealed by drawing closed cells +
|
||
clipping LScape through portals — i.e., port retail's `PView::DrawCells` faithfully.**
|
||
|
||
---
|
||
|
||
## 4. Reusable vs Redesign (from the live evidence; research doc B §5 deepens this)
|
||
|
||
**KEEP (proven correct, build on these):**
|
||
- **Cell membership** — the transition-owned `find_cell_list` fix (`59f3a13`). `[cell-transit]`
|
||
confirms correct cell tracking. Do not reopen.
|
||
- **`PortalVisibilityBuilder`** (the PView BFS) — produces the correct visible set +
|
||
OutsideView + `OrderedVisibleCells`, with `seen`-HashSet termination (#102 closed). This
|
||
is the single visibility authority the redesign should route EVERYTHING through.
|
||
- **The sky/weather NDC-clip insight** (Stage 4, `ce2edad`/`b595cfb`): OutsideView clip
|
||
planes are screen-space half-spaces → projection-independent, so `sky.vert` clips the
|
||
dome exactly. Reusable once the base seals; keep the commits.
|
||
- **`ClipFrame` / `ClipPlaneSet` / `ClipFrameAssembler` / `PortalView`** — the clip-plane
|
||
machinery + the per-cell NDC regions. Reusable.
|
||
- **Cell shell rendering** (`EnvCellRenderer`) — draws correct opaque textured geometry.
|
||
Keep; the bug is *what gets drawn around it*, not the shells.
|
||
- **The diagnostic apparatus** — `ACDREAM_PROBE_CELL/VIS/SHELL` + the `[shell]` diagnosis
|
||
tree. Indispensable; see §8.
|
||
|
||
**REDESIGN (the broken parts):**
|
||
- **The gating.** Collapse the two visibility computations into ONE (`PortalVisibilityBuilder`'s
|
||
visible set), and route terrain + shells + **entities** + particles through it. Delete the
|
||
`CellVisibility.ComputeVisibilityFromRoot` entity path (or make it the same answer).
|
||
- **The interior seal** — adopt retail's closed-cell + LScape-through-portal + Z-clear model
|
||
so the outdoor world is never drawn behind a wall (occlusion by construction, not by gate).
|
||
- **Outdoor-scenery gating** — `ParentCellId=null` entities (houses, trees, stabs) must be
|
||
culled / occluded when indoors and not visible through a portal.
|
||
- **Particle cell-clip** (#104) — particles need a cell and must clip to the visible set.
|
||
- **Outside-looking-in (U.5)** — the exterior→interior portal path (look into a building
|
||
from outside and see its sealed interior, not transparent walls).
|
||
- **Dungeons** (#95) — validate BFS convergence + the no-landscape path on a real dungeon.
|
||
|
||
---
|
||
|
||
## 5. The retail-faithful target architecture
|
||
**→ Full reference: `docs/research/2026-06-02-retail-render-pipeline-full-reference.md`** (research doc A —
|
||
verified against the named-retail pseudo-C + `acclient.h` this session).
|
||
|
||
### 5.1 The ten load-bearing retail facts (THE architecture to port)
|
||
1. **One cell graph, one membership answer, render obeys it.** Physics tracks `curr_cell`
|
||
through the sweep; the camera tracks `viewer_cell`; both resolve via the same
|
||
`CObjCell::GetVisible`.
|
||
2. **The top-level decision is BINARY** (`RenderNormalMode @ 0x453aa0`): viewer in an
|
||
outdoor landcell → `LScape::draw` (full landscape). Viewer in an EnvCell → **`DrawInside`
|
||
only.** It is **NOT** "draw outdoors then draw cells on top." **When inside, the full
|
||
outdoor scene is never drawn.** ← *This single fact is the inversion of acdream's bug.*
|
||
3. **`DrawInside` = one PView portal flood** (`ConstructView → DrawCells`) producing the
|
||
`cell_draw_list` + per-cell clip regions + **one** `outside_view`.
|
||
4. **Exit portals (`other_cell_id == 0xffffffff`) pull the landscape INTO the indoor
|
||
traversal** — `ClipPortals` (pc:433662) copies the doorway clip region into `outside_view`.
|
||
The outdoors is seen *only* through that clipped region.
|
||
5. **The seal sequence in `DrawCells`** (when `outside_view.view_count > 0`):
|
||
`LScape::draw` **clipped to the doorway** → conditional **Z-ONLY** `Clear(4,…)` (NOT
|
||
color) → exit-portal stencil → `DrawEnvCell` (closed geometry) → per-cell objects.
|
||
6. **No blue clear-color hole by construction** — the only clear is depth-only + conditional;
|
||
the doorway shows real terrain because LScape drew there first.
|
||
7. **Ceilings/walls sealed by dat geometry** — `drawing_bsp` is a closed box; portal holes
|
||
are stencil-masked, never filled; there is no "cap the ceiling" step.
|
||
8. **VISIBILITY *IS* THE CULL.** Only `cell_draw_list` cells render, and only **their**
|
||
`object_list` objects (drawn with `PortalList` set). There is **no second "draw all
|
||
entities then gate them" pass.** → no wall/object/particle bleed, by construction.
|
||
9. **Outside-looking-in is the mirror image** — `DrawPortal @ 0x5a5ab0` runs
|
||
`ConstructView(CBldPortal)` + `DrawCells` to render the interior through the door's clip,
|
||
the **same** machinery.
|
||
10. **Dungeons are emergent** — all-EnvCell, `seen_outside == 0`, no exit portals →
|
||
`outside_view` stays 0 → `LScape::draw` is never called → no terrain/sky, automatically.
|
||
|
||
Plus: BFS convergence is **watermark-bounded** by per-cell `portal_view_type.update_count`
|
||
(the retail replacement for a fixed reprocess cap — fixes #102 *and* the dungeon PVS blowup
|
||
#95); `find_visible_child_cell @ 0x52dc50` resolves child cells via the portal/stab graph +
|
||
BSP `point_in_cell` (never AABB); each cell carries **three** BSPs (`drawing_bsp` render /
|
||
`physics_bsp` collision / `cell_bsp` containment).
|
||
|
||
### 5.2 The porting checklist (doc A §7 — the spine of the plan)
|
||
- **CL-A Membership foundation** (physics owns the cell): swept-cell return, exit-portal
|
||
crossing, interior-wins + prune, commit-on-difference. *(Largely DONE — `59f3a13`.)*
|
||
- **CL-B Render-root unification:** single decision, root at physics `CurrCell`, child-cell
|
||
via graph, landscape keep/release on `seen_outside`, `grab_visible_cells`, pre-position terrain.
|
||
- **CL-C PView traversal:** BFS, InitCell, ClipPortals (both branches), AddViewToPortals/AddToCell,
|
||
`update_count` watermark, GetClip. *(`PortalVisibilityBuilder` already covers much of this.)*
|
||
- **CL-D Seal mechanics in DrawCells:** LScape-through-door FIRST, conditional Z-only clear,
|
||
exit-portal stencil, closed-geometry draw, **per-cell clipped objects**, self-contained GL state.
|
||
- **CL-E Outside-looking-in:** DrawPortal, ConstructView(CBldPortal) recursion, separate outdoor pview.
|
||
- **CL-F Entity/particle cell clipping:** graph placement, draw only visible cells, portal-clip straddlers.
|
||
- **CL-G Conformance/acceptance:** cottage sealed + sky-through-door, dungeon sealed + no terrain,
|
||
outside-looking-in, headless asserts.
|
||
|
||
**The redesign verdict:** acdream must stop drawing the outdoor world and then gating it.
|
||
When the viewer is in an EnvCell, it must run **one `DrawInside` flood** that draws only the
|
||
visible cells + their objects, pulling LScape in only through clipped exit portals. The cull
|
||
*is* the visibility. Everything in §3 ("three inconsistent gates") collapses into this.
|
||
|
||
---
|
||
|
||
## 6. Reference cross-check
|
||
**→ Full cross-check: `docs/research/2026-06-02-render-reference-crosscheck.md`** (research doc C).
|
||
|
||
**WorldBuilder is the wrong model and must NOT be re-adopted for the seal** (10-point verdict):
|
||
WB has a hard `isInside` branch switching two completely different render paths (retail has
|
||
one); WB's "seal" is a per-**building** GPU stencil from portal-polygon rasters (flat,
|
||
building-granularity) whereas retail's is a CPU-derived `OutsideView` clip polygon from the
|
||
recursive per-**portal** BFS; **WB's flap is inherent** — the `isInside` branch flips at the
|
||
doorway and the two stencil setups tear on that frame; WB clips one stencil per building
|
||
(per-portal precision is impossible); WB works for a static dat-viewer but is
|
||
**architecturally wrong for a live client that crosses thresholds**; grafting onto WB's
|
||
two-pipe is **not recoverable** — the retail PView port is the correct fix.
|
||
|
||
- **ADOPT:** retail PView BFS (already in acdream as `PortalVisibilityBuilder`), the
|
||
`SeenOutside` terrain gate, the `OtherCellId==0xFFFF` exit-portal sentinel, the WB **mesh
|
||
pipeline** (keep — it's just GL plumbing), `EnvCellRenderer.PrepareRenderBatches(filter)`,
|
||
entity outdoor-slot routing via `WbDrawDispatcher.ResolveEntitySlot`.
|
||
- **AVOID (do not reintroduce):** WB `RenderInsideOut`/`RenderOutsideIn` stencil two-pipe,
|
||
`BuildingPortalGPU`/`RenderBuildingStencilMask`, any `isInside` / `cameraInsideBuilding`
|
||
gate, ACViewer brute-force all-cells draw, any AABB grace-frame fallback for the visibility root.
|
||
|
||
---
|
||
|
||
## 7. Current pipeline inventory + failure map
|
||
**→ Full inventory: `docs/research/2026-06-02-acdream-render-pipeline-inventory-and-failures.md`** (research doc B).
|
||
|
||
### 7.1 The concrete bugs (file:line — these are the *mechanisms* behind §1's symptoms)
|
||
- **🔴 THE outdoor-scenery bleed ("houses/trees through the ground"):**
|
||
`WbDrawDispatcher.EntityPassesVisibleCellGate` hits an **unconditional `return true` at
|
||
`WbDrawDispatcher.cs:1756`** for entities with `ParentCellId == null` (outdoor scenery:
|
||
houses, trees, landblock stabs). The `IsShellScopedSet` anchor-cull branch that *should*
|
||
gate them is **dead code** (always false since U.1 deleted shell sets). ⇒ **outdoor stabs
|
||
always draw, even inside a sealed cellar.** This is the #1 visible bleed.
|
||
- **🔴 Two visibility computations:** the entity gate is fed by `CellVisibility.VisibleCellIds`
|
||
(a *parallel, separate* BFS), while shells + terrain are fed by `PortalVisibilityBuilder`.
|
||
They are not the same answer. Retail has ONE (§5.1 fact 8).
|
||
- **🟠 Terrain `Skip` over-aggression:** `TerrainClipMode.Skip` fires whenever the exit portal
|
||
is not in the current view — correct for a true dungeon, but it removes the terrain floor for
|
||
a `seen_outside=true` cottage when the player faces away from the door. (In the retail model
|
||
this is moot: terrain is only ever drawn *through* an exit-portal clip, never as a floor under
|
||
the interior.)
|
||
- **🟠 Particles:** no cell gate at all (#104).
|
||
- **🟠 `CullMode.Landblock → None` double-sided stopgap** (`EnvCellRenderer.cs:~1210`) — cells
|
||
draw double-sided to dodge a winding issue; a redesign should resolve the actual winding.
|
||
- **🟠 Outside-looking-in (U.5):** no outdoor-root shell pass → transparent walls through a door.
|
||
|
||
### 7.2 The gate table (the inconsistency, from B)
|
||
| Geometry | Gate | Fed by | Verdict |
|
||
|---|---|---|---|
|
||
| Terrain | `TerrainClipMode` | `PortalVisibilityBuilder` | over-aggressive Skip; wrong *model* (floor vs portal-clip) |
|
||
| Cell shells | `envCellShellFilter` | `PortalVisibilityBuilder` | correct geometry, but never a closed occluder |
|
||
| **Entities** | `CellVisibility.VisibleCellIds` | **parallel BFS** | wrong source + `null`-ParentCell bypass = bleed |
|
||
| Particles | *(none)* | — | #104 |
|
||
| Sky/weather | `drawSkyThisFrame` | `PortalVisibilityBuilder` | the only consistent one (Stage 4) |
|
||
|
||
### 7.3 KEEP (from B): `PortalVisibilityBuilder`, `ClipFrame`/`ClipFrameAssembler`/`ClipPlaneSet`,
|
||
Stage-4 sky/weather clip + doorway Z-clear, `EnvCellRenderer` geometry/MDI path,
|
||
`TerrainModernRenderer`, `ResolveEntitySlot` (correct for indoor statics), all probes.
|
||
### 7.4 REDESIGN/FIX (from B): (a) delete the `ParentCellId==null → return true` bypass + gate
|
||
outdoor stabs; (b) feed entity dispatch from `pvFrame.OrderedVisibleCells`, not the parallel
|
||
`CellVisibility` BFS; (c) fix terrain `Skip`/model; (d) particle cell-gate (#104); (e) resolve
|
||
the double-sided stopgap; (f) implement U.5 outside-looking-in.
|
||
|
||
---
|
||
|
||
## 8. Diagnostic apparatus (use it — evidence-first, always)
|
||
|
||
- **Launch** (per CLAUDE.md "Running the client"): set `ACDREAM_LIVE=1`, host/port/user/pass,
|
||
`ACDREAM_DAT_DIR`, then `dotnet run --project src\AcDream.App\AcDream.App.csproj --no-build
|
||
-c Debug 2>&1 | Tee-Object -FilePath launch.log`, in the background. The character `+Acdream`
|
||
spawns at the Holtburg cottage (`0xA9B40031`, outdoor); walk in to reach `0170→0171→0175→0174`.
|
||
- **Probes** (env vars; the log is **UTF-16** — read with PowerShell `Select-String` or the
|
||
ripgrep Grep tool, **NOT** GNU grep):
|
||
- `ACDREAM_PROBE_CELL=1` → `[cell-transit]` (membership; low volume, decisive).
|
||
- `ACDREAM_PROBE_VIS=1` → `[vis]` (the PVS frame: root cell, visible cells, OutsideView
|
||
poly/plane counts, per-cell plane counts).
|
||
- `ACDREAM_PROBE_SHELL=1` → `[shell]` (per opaque pass: `filter`, `drawCalls`, `inst`,
|
||
`tris`, and per-cell `gfx tf batch idx tr zh`). **Diagnosis tree:** `NOSNAP`/`gfx=0` ⇒
|
||
no geometry prepared; `idx>0 + zh>0` ⇒ prepared but missing texture (invisible);
|
||
`idx>0 + zh=0 + tr=0` ⇒ opaque drawn, fault is depth/occlusion or wrong geometry.
|
||
⚠ Unthrottled — fires every frame (183K lines in a short walk). Filter in PowerShell.
|
||
- **Screenshots:** Windows blocks foreground-steal from a background process; capturing the
|
||
AcDream window reliably needs the user to foreground it (or a `PrintWindow` approach that
|
||
is unreliable for GL surfaces). Prefer the probes + the user's description for render bugs.
|
||
- **`tools/A8CellAudit`** + the committed doorway fixture remain for offline membership checks.
|
||
|
||
---
|
||
|
||
## 9. Do-NOT-repeat / settled facts
|
||
|
||
- **Do not chase shaders/textures/missing-meshes for #78.** The `[shell]` evidence proves
|
||
shells draw opaque + textured + complete. The bug is the seal + the gating, not the shells.
|
||
- **Do not add another gate, scissor, or clip layer on top.** That is the failed incremental
|
||
approach. The redesign collapses to ONE visibility answer + a closed-occluder seal.
|
||
- **Do not reintroduce WorldBuilder's `RenderInsideOut` stencil two-pipe** (abandoned
|
||
2026-05-30; reference-divergent from retail). Port retail's recursive PView.
|
||
- **Do not reopen the membership fix** (`59f3a13`) — `[cell-transit]` confirms it works.
|
||
- **My mistake this session (learn from it):** I trusted the prior handoff's "render infra
|
||
already exists, just wire 3 gaps" framing and built the Stage-4 sky-through-door clip on
|
||
top **without verifying the base seal end-to-end** (I can't see the screen; I leaned on the
|
||
test suite + a smoke-launch). The visual gate correctly caught that the premise was wrong.
|
||
**Lesson:** for a render seal, get the user's eyes (or the `[shell]`/`[vis]` evidence) on
|
||
the ACTUAL sealed result EARLY, before building layers on top. A green test suite proves
|
||
nothing about whether the interior looks sealed.
|
||
- **Stage-4 commits are kept** (`ce2edad`, `a8b831c`, `872dd34`, `21609a7`, `4bc99fc`,
|
||
`b595cfb`) — the sky NDC-clip + the green-tests triage are real and reusable; they are a
|
||
top layer that becomes correct once the base seals. The 5 remaining Core test failures are
|
||
pre-existing physics/collision bugs (2 step-up gaps incl. a regression from A6.P4's door
|
||
fix; 3 door-collision apparatus / A6.P5), none Phase-W's, flagged not fixed.
|
||
|
||
---
|
||
|
||
## 10. The redesign plan
|
||
**→ `docs/superpowers/plans/2026-06-02-render-pipeline-redesign-plan.md`** (the huge staged plan).
|
||
Stages: **R0** brainstorm/lock → **R1** one-visibility-authority (kill the outdoor-scenery bleed)
|
||
→ **R2** indoor = `DrawInside`-only (stop drawing the outdoor world indoors) → **R3** the seal
|
||
(`DrawCells` faithful port: LScape-through-door → Z-only clear → closed cells) → **R4** per-cell
|
||
object + particle clip → **R5** outside-looking-in (U.5 / `DrawPortal`) → **R6** dungeons → **R7**
|
||
polish + conformance. Each ends at a **user visual gate**. The core inversion: **when inside, run
|
||
ONLY the PView flood — visibility IS the cull; the outdoor world enters only through clipped exit
|
||
portals.**
|
||
|
||
---
|
||
|
||
## 11. Pickup prompt (copy-paste for the next session)
|
||
|
||
```
|
||
RENDER PIPELINE REDESIGN — full retail-faithful rewrite of the world render (outdoor + indoor +
|
||
dungeon + portals + particles). Continue on branch claude/thirsty-goldberg-51bb9b (do NOT
|
||
branch/worktree; do NOT push without asking; NEVER git stash/gc — a shared stash is under
|
||
investigation). Use PowerShell on Windows; the launch logs are UTF-16 (read with Select-String /
|
||
the ripgrep Grep tool, NOT GNU grep).
|
||
|
||
MANDATE (user, non-negotiable): FULLY WORKING outdoor + indoor + dungeon rendering — no flaps, no
|
||
missing textures, no transparent walls, no terrain leaking into cellars, no entity/particle
|
||
bleed-through, outside-looking-in works. NO shortcuts, NO bandaids, NO quick fixes; take the
|
||
architecturally-correct path even if slower; redesign the whole pipeline if needed; PORT FROM
|
||
RETAIL; do more research mid-session rather than guess; START WITH A BRAINSTORM.
|
||
|
||
READ FIRST (in order):
|
||
1. docs/research/2026-06-02-render-pipeline-redesign-handoff.md (THIS handoff: §2 proven evidence,
|
||
§3 root cause = three inconsistent gates + no closed-occluder seal, §5 retail target + porting
|
||
checklist CL-A..G, §9 do-not-repeat).
|
||
2. docs/research/2026-06-02-retail-render-pipeline-full-reference.md (the retail PView pipeline to
|
||
port — the seal mechanics in DrawCells).
|
||
3. docs/research/2026-06-02-acdream-render-pipeline-inventory-and-failures.md (the concrete bugs:
|
||
the WbDrawDispatcher.cs:1756 ParentCellId==null bypass = the outdoor bleed; the parallel
|
||
visibility BFS; terrain Skip model).
|
||
4. docs/research/2026-06-02-render-reference-crosscheck.md (why WB's two-pipe stencil is the wrong
|
||
model — do NOT reintroduce it).
|
||
5. THE PLAN: docs/superpowers/plans/2026-06-02-render-pipeline-redesign-plan.md (stages R0..R7).
|
||
|
||
PROVEN ROOT CAUSE (don't re-investigate): the PVS computes correctly and the cell shells render
|
||
correctly (opaque, textured, complete — [shell] probe). The failure is the SEAL + the GATING:
|
||
acdream draws the outdoor world (terrain + scenery ENTITIES that aren't culled) and then a few cell
|
||
shells on top, relying on three inconsistent gates. Retail, when inside, runs ONLY DrawInside (one
|
||
PView flood) — visibility IS the cull, and the landscape enters only through clipped exit portals.
|
||
That inversion is the redesign.
|
||
|
||
DO NEXT:
|
||
1. Phase R0 — BRAINSTORM the §1 architecture (handoff §5 / plan §1) with the user; resolve the open
|
||
questions (plan §3); write the per-phase design spec. NO code until the design is locked.
|
||
2. Then execute R1→R7 (plan §2), each retail-anchored, each ending at a user visual gate. R1 (one
|
||
visibility authority + kill the WbDrawDispatcher.cs:1756 bypass) kills the headline bleed first.
|
||
|
||
EVIDENCE-FIRST: launch per CLAUDE.md "Running the client" with ACDREAM_PROBE_CELL/VIS/SHELL=1; walk
|
||
the Holtburg cottage (spawn 0xA9B40031 outdoor → 0170 vestibule → 0171 room → 0175 stairs → 0174
|
||
cellar). The [shell] diagnosis tree + [vis] OutsideView counts are decisive. GET THE USER'S EYES on
|
||
the actual sealed result at every visual gate — never declare a seal off the test suite (that was
|
||
the mistake that produced this handoff).
|
||
|
||
KEEP (don't rewrite): PortalVisibilityBuilder (the PVS), ClipFrame/ClipFrameAssembler/ClipPlaneSet,
|
||
EnvCellRenderer mesh path, TerrainModernRenderer, the WB mesh pipeline, the membership fix (59f3a13),
|
||
the Stage-4 sky NDC-clip + doorway Z-clear (ce2edad/b595cfb). The work is RESTRUCTURING THE
|
||
ORCHESTRATION + the entity/particle draw to be per-cell, not a from-scratch rewrite.
|
||
|
||
TEST STATE: full suite green except 5 pre-existing Core failures (2 step-up gaps incl. an A6.P4 door
|
||
regression; 3 door-collision apparatus / A6.P5) — none render-related, flagged in the handoff, do not
|
||
chase as part of this work.
|
||
```
|
||
|
||
---
|
||
|
||
## 12. Session ledger (2026-06-02, render half)
|
||
- Stage 4 (sky/weather portal clip + Z-clear + green-tests triage) shipped: `ce2edad`, `a8b831c`,
|
||
`872dd34`, `21609a7`, `4bc99fc`, `b595cfb`. Real + reusable, but a top layer — the base seal was
|
||
never working (#78). Visual gate FAILED → this redesign handoff.
|
||
- Research this session: retail pipeline reference (doc A), acdream inventory+failures (doc B),
|
||
reference cross-check (doc C), this master handoff, the redesign plan.
|
||
- Issues to file/track: #78 (the core seal — now the redesign target), #95 (dungeon BFS), #104
|
||
(particle cell-clip), the `WbDrawDispatcher.cs:1756` outdoor-scenery bypass, the
|
||
`CullMode.Landblock→None` double-sided stopgap, U.5 outside-looking-in.
|