docs+test #176/#177: 12 mechanisms refuted, apparatus shipped, probe protocol staged
The dungeon render pair (purple seam flash + stair pop-in) resisted desk root-causing, but the investigation narrowed the space to two live theories and shipped permanent apparatus: - Issue176177DungeonSeamInspectionTests: dat truth — corridor floors ARE textured drawn PortalSide portal polys; the reciprocal is NoPos; the 'stairs' are 0x8A020182's ramp shell (vertical portals, zero statics); CellBSP partitions exactly at portal planes; DXT1 textures carry zero transparent-mode texels. - Issue176177FacilityHubFloodReplayTests: production-matched flood replays — approach/descent/gaze-sweep/walk all healthy with coherent inputs; ScenarioE pins the flood's collapse-to-root sensitivity under incoherent (root, eye) pairs. - Issue176177SeamTransitLagTests: the resolver flips cells within one tick-step of the portal plane — the 0.33-0.47m [cell-transit] 'lag' in the gate logs is speed*tick quantization, not membership error. Refuted (do NOT retry — ledger in the research doc): placeholder texture, reciprocal z-fight, seal z-fight (seals only fire for OtherCellId==0xFFFF), root/eye incoherence (production camera sweep is mm-exact at planes), flood bistability, #119-class statics, undefined DXT mips (both paths decode DXT->RGBA8; the compressed-array branch is dead code), DXT1 alpha, fog mix (ramp ~538m), lightning leak (flash==0 in production), viewer-light pops (smooth (1-d/range) ramp). Filed #178 (A8 double-sided shell stopgap still live) and #179 (lightning flash lacks an indoor gate — dormant). The purple can only be the fog clear color (undrawn pixels) or the outdoor ambient+sun tint; discrimination needs ONE probe launch (ACDREAM_PROBE_LIGHT + ACDREAM_PROBE_PVINPUT + ACDREAM_PROBE_CELL) — protocol in docs/research/2026-07-06-176-177-render-pair-investigation.md. Suites: Core 2587 / App 719 green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
544d4d3eef
commit
b8e9e204ad
5 changed files with 1176 additions and 19 deletions
|
|
@ -46,6 +46,52 @@ Copy this block when adding a new issue:
|
|||
|
||||
---
|
||||
|
||||
## #179 — Lightning flash has no indoor gate (dormant until weather strobes ship)
|
||||
|
||||
**Status:** OPEN (dormant — zero production impact today)
|
||||
**Severity:** LOW (latent)
|
||||
**Filed:** 2026-07-06
|
||||
**Component:** render — scene lighting UBO / weather
|
||||
|
||||
**Description:** `mesh_modern.frag` adds `uFogParams.z × vec3(0.6, 0.6, 0.75)`
|
||||
(the lightning-flash bump) to EVERY fragment, and `SceneLightingUbo.Build`
|
||||
copies `atmo.LightningFlash` with no indoor gating (the GameWindow fog
|
||||
override explicitly preserves `.z`). Today `WeatherState._flashLevel` is 0
|
||||
in production ("Production never TriggerFlashes" — test hook only), so
|
||||
nothing is visible. The moment storm strobes ship, sealed dungeons will
|
||||
flash blue-violet with every strike. Retail's indoor lighting path (flat
|
||||
ambient, sun killed via the seen_outside gate) carries no storm terms.
|
||||
|
||||
**Acceptance:** the flash term is zeroed for `playerInsideCell` frames (or
|
||||
gated at the UBO build), verified by a storm-in-dungeon probe when weather
|
||||
strobes land. Found during the #176/#177 investigation
|
||||
(`docs/research/2026-07-06-176-177-render-pair-investigation.md`).
|
||||
|
||||
---
|
||||
|
||||
## #178 — Retire the A8 double-sided cell-shell stopgap (CullMode.Landblock → None)
|
||||
|
||||
**Status:** OPEN
|
||||
**Severity:** LOW-MEDIUM (correctness/perf debt; 2× shell fragment load)
|
||||
**Filed:** 2026-07-06
|
||||
**Component:** render — EnvCellRenderer MDI draw
|
||||
|
||||
**Description:** `EnvCellRenderer.RenderModernMDIInternal` still carries the
|
||||
Phase A8 visual-gate stopgap: `if (cullMode == CullMode.Landblock) cullMode
|
||||
= CullMode.None;` — "render cell polys double-sided while the architectural
|
||||
cause is isolated." Every cell shell draws two-sided to this day. Retail
|
||||
draws cell polygons single-sided (the drawing BSP + winding decide facing).
|
||||
The "architectural cause" (winding convention vs the frame-global CW
|
||||
front-face) was never isolated; the stopgap outlived its gate. Retiring it
|
||||
needs the winding audit (which side do CellStruct polys wind under our
|
||||
extraction?) + a visual gate — walls/floors must not vanish.
|
||||
|
||||
**Acceptance:** cell shells draw with proper backface culling, no missing
|
||||
surfaces at the Holtburg + Facility Hub gates. Found during the #176/#177
|
||||
investigation (`docs/research/2026-07-06-176-177-render-pair-investigation.md`).
|
||||
|
||||
---
|
||||
|
||||
## #177 — Dungeon stairs pop in/out across levels (invisible until entering the room; last step vanishes running down)
|
||||
|
||||
**Status:** OPEN
|
||||
|
|
@ -60,15 +106,18 @@ corridor, and (c) pops into existence on entering the room. Classic
|
|||
portal-visibility miss: the stair geometry's cell is not reached by the
|
||||
portal flood from the viewer's cell until the viewer crosses into it.
|
||||
|
||||
**Root cause / status:** unknown; the #119 class (visibility volumes /
|
||||
portal flood), dungeon edition. Level connections here go through
|
||||
floor-portal slabs (see the #137 topology notes — corridor floors are
|
||||
portal polygons to under-rooms), which the render flood may treat
|
||||
differently from wall portals. Read
|
||||
`claude-memory/project_render_pipeline_digest.md` FIRST (Option A: one
|
||||
DrawInside(viewer_cell); DO-NOT-RETRY table applies). Log
|
||||
`launch-137-gate2.log` covers the session (cells around
|
||||
`0x8A020182 → 0x8A020183` show a −6 → −9 level transition on stairs).
|
||||
**Root cause / status:** INVESTIGATED 2026-07-06 (session 2) — the #119
|
||||
class is REFUTED for this issue: the "stairs" are a RAMP owned by shell
|
||||
cell 0x8A020182 (no statics anywhere near), connected by VERTICAL portals
|
||||
(not floor-portals), and the portal flood admits 0x0182/0x0183 correctly
|
||||
from every tested corridor eye/pitch (headless replays
|
||||
`Issue176177FacilityHubFloodReplayTests`). Membership transits are
|
||||
plane-exact; mesh/frustum/texture layers verified healthy. Twelve
|
||||
candidate mechanisms refuted — full ledger + the surviving theories +
|
||||
the ONE-launch probe protocol in
|
||||
`docs/research/2026-07-06-176-177-render-pair-investigation.md`.
|
||||
NEXT: run the probe protocol (ACDREAM_PROBE_LIGHT + ACDREAM_PROBE_PVINPUT
|
||||
+ ACDREAM_PROBE_CELL) during the pending #175 door-gate launch.
|
||||
|
||||
**Acceptance:** the staircase renders whenever its room is visible through
|
||||
the connecting opening, and stays rendered through the full descent.
|
||||
|
|
@ -89,16 +138,20 @@ render; the physics fix landed (seam shake gone, user-gated) and the flash
|
|||
REMAINS — so it is a render-side issue in its own right, correlated with
|
||||
camera angle.
|
||||
|
||||
**Root cause / status:** unknown. Suggestive topology fact from the #137
|
||||
work: the corridor floor tiles ARE portal polygons (PortalSide floor
|
||||
portals to under-rooms — e.g. 0x8A02016E polys 1/3/5 → 0x011E, spans in
|
||||
`Issue137CorridorSeamInspectionTests.CorridorCell_PortalPolygonWorldSpans`),
|
||||
so "the floor at the seams" is exactly where portal surfaces live —
|
||||
suspect the portal polygon being drawn with a placeholder/uninitialized
|
||||
surface under some flood/culling state ([[feedback_ui_resolve_zero_magenta]]:
|
||||
magenta = the 1×1 placeholder texture class). Angle-dependence points at
|
||||
the visibility/stencil state, not geometry. Read
|
||||
`claude-memory/project_render_pipeline_digest.md` FIRST.
|
||||
**Root cause / status:** INVESTIGATED 2026-07-06 (session 2) — the
|
||||
placeholder-texture theory is REFUTED (all surfaces resolve; the floor
|
||||
IS drawn: the textured PortalSide floor-portal strips are included by
|
||||
CellMesh.Build; the under-hall reciprocal is NoPos). So are eleven other
|
||||
mechanisms (seal z-fight, root/eye incoherence, flood bistability, DXT
|
||||
alpha/undefined mips, fog mix, lightning leak, viewer-light pops…) —
|
||||
full refutation ledger, the two surviving theories (T-A outdoor-ambient
|
||||
flip on playerRoot gaps: sun-on-floors explains the FLOOR selectivity;
|
||||
T-B flood misbehavior under real production inputs), and the ONE-launch
|
||||
probe protocol in
|
||||
`docs/research/2026-07-06-176-177-render-pair-investigation.md`.
|
||||
The purple itself can only be the fog-tinted clear color (undrawn
|
||||
pixels) or the outdoor ambient+sun tint — every other purple source in
|
||||
the pipeline is now excluded. NEXT: the probe launch (see #177).
|
||||
|
||||
**Acceptance:** no purple/placeholder flashes on dungeon floors from any
|
||||
camera angle at the corridor seams.
|
||||
|
|
|
|||
134
docs/research/2026-07-06-176-177-render-pair-investigation.md
Normal file
134
docs/research/2026-07-06-176-177-render-pair-investigation.md
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
# #176/#177 render pair — investigation ledger (2026-07-06, session 2)
|
||||
|
||||
**Status: mechanism NOT yet pinned — but the hypothesis space is now razor-thin.**
|
||||
Twelve candidate mechanisms refuted by direct evidence (dat dumps, headless
|
||||
replays, production-log analysis, code reads). Every layer that can be checked
|
||||
offline is verified HEALTHY at the anchor cells. The surviving discriminator
|
||||
requires ONE live probe launch (protocol at the bottom — piggyback on the
|
||||
pending #175 door gate).
|
||||
|
||||
## The issues
|
||||
|
||||
- **#176** — purple flashing on dungeon floors at cell seams, camera-angle
|
||||
dependent (Facility Hub).
|
||||
- **#177** — stairs pop in/out across levels: (a) vanish on the last step
|
||||
running down, (b) invisible looking into the stair room from the corridor,
|
||||
(c) pop into existence on entering.
|
||||
|
||||
## Anchor-cell dat truth (Issue176177DungeonSeamInspectionTests)
|
||||
|
||||
- Corridor `0x8A02016E` floor = three abutting TEXTURED drawn portal polys
|
||||
(polys 1/3/5, surface 0x08000377 → DXT1 tex 0x050026F7, `[PortalSide]`) →
|
||||
under-hall `0x011E` (z=−12). Reciprocal ceiling poly = NoPos (not drawn).
|
||||
- The "stairs" = a RAMP owned by `0x8A020182` (inclined drawn polys, z −9…−6
|
||||
floor + −6…−3 ceiling); `0x0183` = flat lower cell. Connections are
|
||||
VERTICAL wall portals (NOT floor-portals). PortalSide flag asymmetry:
|
||||
0x0182→0x0183 carries PortalSide; the back-portal does not.
|
||||
- **Zero StaticObjects in all five anchor cells** (no #119-class statics, no
|
||||
torch-bearing stabs → no registered point lights except the viewer fill).
|
||||
- CellBSP volumes partition EXACTLY at the portal planes (no overlap zone).
|
||||
- All surfaces resolve; DXT1 textures contain **zero** transparent-mode
|
||||
texels (all 3-color-mode blocks, index 3 never used).
|
||||
|
||||
## REFUTED mechanisms (each by direct evidence — do NOT retry)
|
||||
|
||||
| # | Hypothesis | Killed by |
|
||||
|---|---|---|
|
||||
| 1 | Placeholder/missing texture (magenta class) | All surfaces resolve; drawn-poly sweep 0 misses |
|
||||
| 2 | Reciprocal portal-poly z-fight | Reciprocal is NoPos (never drawn) |
|
||||
| 3 | Seal depth-stamp z-fights the drawn floor-portal | Seals fire ONLY for `OtherCellId==0xFFFF` (GameWindow:11437); a sealed dungeon draws zero seals |
|
||||
| 4 | Root/eye incoherence (viewer root lags the eye across portal planes) | Production camera sweep publishes coherent pairs; out-cell flips at x=85.001/88.335 — mm-exact at the planes (gate2 log). The flood DOES collapse to 1 cell under artificially incoherent inputs (ScenarioE pin) — but production inputs are coherent |
|
||||
| 5 | Membership transit lag (0.33–0.47 m in [cell-transit]) as the render-root lag | The resolver flips within one tick-step of the plane in the harness (Issue176177SeamTransitLagTests); the logged "lag" is speed×tick quantization of the PLAYER probe, and the camera root (probe out-cell) is plane-exact |
|
||||
| 6 | Flood bistability at the anchors | ScenarioC gaze sweep (2° steps, 4 pitches): 0 one-step drops; ScenarioA stair approach: ramp+lower admitted at all tested eyes/pitches |
|
||||
| 7 | Staircase = EnvCell static culled by viewcone (#119 class) | Zero statics in the anchor cells; the stairs are shell geometry |
|
||||
| 8 | Undefined DXT mip levels (compressed arrays skip GenerateMipmap) | Both ObjectMeshManager texture paths DECODE DXT→RGBA8 (BcDecoder) — the compressed-array branch of ManagedGLTextureArray is dead WB-heritage code; RGBA8 arrays get real mips |
|
||||
| 9 | DXT1 3-color-mode alpha=0 texels + opaque-pass `discard a<0.05` / A2C | Block histogram: 0 transparent texels in all Hub floor/wall textures |
|
||||
| 10 | Fog mix toward purple FogColor at distance | Fog ramp starts at `_nearRadius×192×0.7 ≈ 538 m` (radii stay 4/12 in dungeon mode); Hub sightlines ≤ ~100 m → fog term ≡ 0 |
|
||||
| 11 | Lightning-flash additive (`uFogParams.z × (0.6,0.6,0.75)`) leaking indoors | `WeatherState._flashLevel` is 0 in production ("Production never TriggerFlashes") — dormant test hook. (The missing indoor gate is still real debt for when storm strobes ship.) |
|
||||
| 12 | Viewer-light per-cell/per-vertex pops (hard range edge or 8-set membership flips) | The point ramp is `(1−d/range)` — smoothly ZERO at the range boundary; set-membership beyond range is a zero-contribution no-op. No torches exist in the Hub cells to churn the 8-cap |
|
||||
|
||||
## VERIFIED-HEALTHY layers (offline pins, keep as regression assets)
|
||||
|
||||
- `PortalVisibilityBuilder` at the anchors: approach/descent/gaze-sweep/walk
|
||||
scenarios (`Issue176177FacilityHubFloodReplayTests`) — admissions correct
|
||||
and stable with coherent inputs; the ScenarioE incoherent-input collapse is
|
||||
the sensitivity pin (1-cell flood when root≠eye side).
|
||||
- Membership: `ResolveWithTransition` flips cells within one tick of the
|
||||
portal plane, both directions (`Issue176177SeamTransitLagTests`).
|
||||
- Mesh path: `CellMesh.Build` (production, GameWindow:7013) draws the
|
||||
textured floor-portal strips; snapshot frustum gate (WbFrustum) is the
|
||||
standard conservative p-vertex test; per-cell AABBs are vertex-derived,
|
||||
8-corner transformed.
|
||||
- Per-instance light sets are truly per-instance (EnvCellRenderer MDI).
|
||||
|
||||
## SURVIVING theories (need the live discriminator)
|
||||
|
||||
- **T-A (ambient flip):** any frame where `playerRoot` resolves null (or
|
||||
`playerSeenOutside` defaults true) runs the OUTDOOR lighting branch —
|
||||
purple sky ambient + full sun. Sun is directional-from-above → floors
|
||||
(N·L≈1) catch it, walls (N·L≈0) barely → a FLOOR-selective purple-bright
|
||||
flash, temporally lockable to whatever gaps CurrCell/TryGetCell. Desk
|
||||
analysis found no per-frame gap trigger during plain corridor runs
|
||||
(UpdatePlayerCurrCell is stale-beats-null; the registry is stable in
|
||||
AP-36 dungeon mode) — but the branch inputs are exactly probed by
|
||||
`[light] insideCell=` lines, so one run settles it.
|
||||
- **T-B (flood with REAL production inputs):** my harness feeds synthetic
|
||||
viewProj/eye. If the real per-frame inputs at the artifact moments differ
|
||||
(collided camera pressed into walls near seams, damped-forward gaze), the
|
||||
flood could still misbehave in configurations the sweeps missed.
|
||||
`[pv-input]` prints the exact inputs + flood count per frame.
|
||||
- **T-C:** unknown-unknown (GPU state, driver, MSAA resolve…). If T-A/T-B
|
||||
both read clean at a flash moment → RenderDoc frame capture next.
|
||||
|
||||
## Also found (real, filed, not these bugs)
|
||||
|
||||
- **A8 double-sided shells stopgap still live**: `EnvCellRenderer.cs`
|
||||
RenderModernMDIInternal maps `CullMode.Landblock → CullMode.None`
|
||||
("while the architectural cause is isolated") — all cell shells draw
|
||||
two-sided. Perf + correctness debt; retire under the A7/A8 lighting arc.
|
||||
- **Lightning indoor gate missing** (dormant): when weather strobes ship,
|
||||
`SceneLightingUbo.Build` needs the `playerInsideCell` gate or dungeons
|
||||
will strobe blue-violet.
|
||||
- **Flood follows floor-portals DOWNWARD from above** (ScenarioC: under-hall
|
||||
network admitted at down-pitches). Retail's `portal_side` side test
|
||||
(0x005a59a0: portal_side≠0 → NEGATIVE side only; ==0 → POSITIVE only;
|
||||
IN_PLANE(±0.0002) → refused) *appears* to refuse this direction, but my
|
||||
plane-sign reading had unresolved contradictions (CCellPortal::UnPack
|
||||
normalizes portal_side at load, 0x0053ba1c/0x0053bc6a). OPEN QUESTION —
|
||||
harmless-looking (extra admitted cells draw below the opaque floor,
|
||||
z-buffer wins) but worth settling when the flood is next touched.
|
||||
|
||||
## The live probe protocol (piggyback on the #175 door gate launch)
|
||||
|
||||
Env (add to the standard launch block):
|
||||
|
||||
```
|
||||
ACDREAM_PROBE_LIGHT=1 # [light] insideCell/ambient/sun — rate-limited
|
||||
ACDREAM_PROBE_PVINPUT=1 # [pv-input] one line/frame: exact flood inputs + count
|
||||
ACDREAM_PROBE_CELL=1 # [cell-transit] timeline anchors
|
||||
```
|
||||
|
||||
User reproduces in Facility Hub (~2 min): run the corridor across several
|
||||
seams until the purple flash shows; approach the stair room from the
|
||||
corridor, walk in, run down. Then close. Discrimination:
|
||||
|
||||
- Flash moments + `[light]` shows `insideCell=False` blips or ambient jumps
|
||||
→ **T-A confirmed** (then root-cause the gap trigger from the same log).
|
||||
- `[pv-input]` flood count drops (e.g. 12→1) at flash/pop moments while
|
||||
`[light]` stays clean → **T-B confirmed** (the line carries the exact
|
||||
inputs to replay in `Issue176177FacilityHubFloodReplayTests`).
|
||||
- Stairs invisible while the flood contains 0x0182/0x0183 → draw-side hunt
|
||||
(RenderDoc next); absent → flood-side with the printed inputs.
|
||||
- All clean → T-C: RenderDoc frame capture of a flash frame.
|
||||
|
||||
## Apparatus shipped this session
|
||||
|
||||
- `tests/AcDream.Core.Tests/Rendering/Issue176177DungeonSeamInspectionTests.cs`
|
||||
— dat truth: portal polys/surfaces/draw verdicts, reciprocal coincidence,
|
||||
stair geometry owner, CellBSP containment, under-hall surface colors,
|
||||
DXT1 alpha histograms.
|
||||
- `tests/AcDream.App.Tests/Rendering/Issue176177FacilityHubFloodReplayTests.cs`
|
||||
— production-matched flood replays: stair approach, descent, gaze sweep,
|
||||
corridor walk, and the ScenarioE incoherent-root sensitivity pin.
|
||||
- `tests/AcDream.Core.Tests/Physics/Issue176177SeamTransitLagTests.cs`
|
||||
— resolver cell-flip position at the seam (plane-exact pin).
|
||||
Loading…
Add table
Add a link
Reference in a new issue