feat(lighting): A7 visible-cell light scoping + [indoor-light] probe (NOT the #176/#177 fix)

Port retail's per-frame light collection: the point-light pool is built from ONLY the
currently-visible cells' lights, matching CObjCell::add_*_to_global_lights
(0x0052b350/0x0052b390) walked over CEnvCell::visible_cell_table (0x0052d410) — not a
flat world-space set capped at 128-nearest-camera.

- LightSource.CellId (retail insert_light arg6 -> RenderLight +0x6c); tagged at both
  registration sites from entity.ParentCellId (live weenie fixtures + dat EnvCell statics).
- LightManager.BuildPointLightSnapshot(camPos, visibleCells): a light joins the pool iff
  CellId==0 (viewer/global) or its cell is in the flood. 128 cap kept as a now-non-biting
  backstop (retail's is 40 static + 7 dynamic, 0x0081ec94/8).
- Threaded via RetailPViewDrawContext.RebuildScopedLights, invoked in DrawInside after the
  flood resolves prepareCells and before the draws (renderers select from the same
  in-place-rebuilt PointSnapshot; EnvCellRenderer clears its per-cell cache each pass).
- [indoor-light] probe (ACDREAM_PROBE_INDOOR_LIGHT=1) dumps the scoped-pool SET COMPOSITION.
  Un-skips LightManagerTests.PointSnapshot_HubScaleLightCount_ObjectSelectionIsCameraInvariant.

CORRECTION: the handoff called the camera-cap the "confirmed" #176/#177 mechanism. The probe
PROVES scoping works (291 Hub fixtures -> pool of 1-9, ~285 through-floor lights dropped/frame,
CellIds match the flood), but the user's VISUAL GATE showed BOTH symptoms unchanged. So pool
composition is NOT the cause. #176 real cause = an over-bright purple point light
(intensity=100, color 0.784,0,0.784 -- from [light-detail]); #177 = a portal-visibility miss
(stairs not drawn looking back). Both stay OPEN. This change is retail-faithful and retires the
camera-eviction latent bug; kept as such, not as the symptom fix. Register AP-85 corrected;
ISSUES #176/#177 re-diagnosed; render digest banner updated.

Decomp: insert_light 0x0054d1b0, minimize_object_lighting 0x0054d480, calc_point_light
0x0059c8b0; pseudocode docs/research/2026-07-06-a7-per-cell-lighting-pseudocode.md.
Suites green: Core 2595 + 2 skip, App 719 + 2 skip.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-07-06 00:35:01 +02:00
parent e1746ca10d
commit c500912bf8
10 changed files with 516 additions and 35 deletions

View file

@ -94,6 +94,13 @@ 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)
**⚠️ UPDATE 2026-07-06 (visual gate) — this is NOT lighting.** The A7 visible-cell
light-scoping fix shipped + was probe-validated, but the user's gate showed the stairs
STILL not visible looking back from the corridor (zoom-out changes the last-step case).
Eye-position/flood behavior ⇒ a portal-VISIBILITY miss at the stair cells
(0178/0182/0183), NOT the "its LIGHTS went dark" attribution recorded below. Re-diagnose
as visibility. See the render digest banner.
**Status:** OPEN
**Severity:** MEDIUM (visible geometry churn in the M1.5 dungeon)
**Filed:** 2026-07-06
@ -142,6 +149,14 @@ 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.
**Status:** OPEN
**Severity:** MEDIUM (visible artifact along every corridor seam in the M1.5 dungeon)
**Filed:** 2026-07-06