feat(lighting): SelectForCell (all dynamic lights per EnvCell) + #176 handoff — residual is a runtime z-fight

cdb trace of LIVE retail (tools/cdb/issue176-floor-light.cdb, binary<->PDB MATCH) PROVED retail
applies ALL its dynamic lights — 4 intensity-100 magenta portal lights (d3dIdx 3-6, falloff 6) +
the viewer fill (d3dIdx 1, 2.25) — as D3D hardware lights to EVERY Facility Hub cell, every frame,
stable. So the faceted purple wedges on the floor are retail-FAITHFUL. acdream did a per-cell
SelectForObject sphere-overlap 8-cap for cells, so the portal set could differ/flip per cell.

- LightManager.SelectForCell (retail minimize_envcell_lighting 0x0054c170): ALL dynamic lights
  applied unconditionally (shader range cutoff zeroes non-reaching = D3D hardware range), then
  nearest static torches fill remaining slots. Wired into EnvCellRenderer.GetCellLightSet.
  Objects keep SelectForObject (minimize_object_lighting). Pins:
  SelectForCell_AppliesAllDynamicLights_EvenOutOfReach + _SameDynamicSet_ForCellsFarApart_NoFlap.
- Apparatus: [light-detail] gains owner/cell/dyn (pinned the culprit = 2 portal weenies
  0x000F4247/48 in 0x8A020118/19, intensity=100 magenta); CellVertexNormals_SmoothOrFaceted_Dump
  (corridor floor uses SMOOTH per-vertex dat normals, not flat); tools/cdb/issue176-floor-light.cdb.

#176 RESIDUAL is NOT this fix. It's a RUNTIME draw z-fight in the seam floor. Eliminated (evidence):
NOT lighting (per-light cap + this both no-change), NOT membership (render cell 0x8A020164 stable
100% of 188k frames / 526 angles, res=None), NOT dat geometry (coplanar sweep empty at z=-6 floor
incl. cell 0164). NEXT = RenderDoc pixel-history. Full handoff + DO-NOT-RETRY:
docs/research/2026-07-06-176-seam-floor-zfight-handoff.md. Suites green: Core 2599 + 2 skip.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-07-06 13:55:16 +02:00
parent 92bb27c03b
commit 8cb3176daa
8 changed files with 366 additions and 11 deletions

View file

@ -149,13 +149,19 @@ the connecting opening, and stays rendered through the full descent.
## #176 — Purple flashing on dungeon floors at cell seams, camera-angle dependent
**⚠️ UPDATE 2026-07-06 (visual gate) — the light-set/camera-cap theory is REFUTED.** The
A7 scoping fix shipped + was probe-validated (~285 through-floor lights dropped/frame),
yet the purple flash was UNCHANGED. `[light-detail]` names the real cause: a single
over-bright purple POINT light — `kind=Point range=9 intensity=100 color=(0.784,0,0.784)`
(200/255,0,200/255) — washing the floor. NEXT: identify its owning entity/Setup; decide
whether `intensity=100` is a dat mis-parse or a portal/effect light we render wrong. Not
set-composition, not through-floor. See the render digest banner.
**⚠️ UPDATE 2026-07-06 (final — cdb-confirmed, RenderDoc handoff) — it's a RUNTIME draw
z-fight, NOT lighting.** Full elimination table + plan:
`docs/research/2026-07-06-176-seam-floor-zfight-handoff.md`. The purple WEDGE SHAPE is
retail-FAITHFUL — cdb (`tools/cdb/issue176-floor-light.cdb`) proved retail applies the same
4 intensity-100 magenta portal lights + the viewer fill to EVERY Hub cell via D3D hardware,
so the faceted per-vertex purple is exactly what retail shows. The only defect is the
FLICKER, eliminated as: NOT lighting (per-light cap + all-dynamic-per-cell both no-change),
NOT membership (render cell `0x8A020164` stable on 100% of 188k frames / 526 angles), NOT dat
geometry (coplanar sweep empty at the z=6 corridor floor, incl. cell `0164`). → a RUNTIME
double-draw of the seam floor. Suspects: the `+0.02 m` shell lift (AP-32/#130), the #178
double-sided cell-shell stopgap, a portal depth-mask. **NEXT: RenderDoc pixel-history** on a
flickering floor pixel to name the two fighting draws. Shipped this arc (retail-faithful, NOT
the fix): scoping `c500912b` + `SelectForCell` (all-dynamic-lights-per-cell).
**Status:** OPEN
**Severity:** MEDIUM (visible artifact along every corridor seam in the M1.5 dungeon)