acdream/docs/research/2026-06-19-lighting-a7-fixD-round2-torch-reach-CHECKPOINT.md
Erik 1e6fbff9bc docs(lighting): A7 Fix D round-2 CHECKPOINT — real cause is object torch REACH (#140)
Same-instant cdb proved acdream ambient (0.447) == retail (0.4465) and time/sun match,
so the building/character over-brightness is NOT the bake/wrap/EnvCell/clamp (D-1..D-4,
all correct but off-target) — those light the wrong surfaces. The Holtburg building
exterior is a mode-0 OBJECT (IsBuildingShell, not an EnvCell). Isolation (object point
lights gated OFF) made it match retail => cause is the torch REACH being too long
(acdream range 7.8 = Falloff 6x1.3 vs retail 5.2 = Falloff 4x1.3), flooding the small
facade. OPEN: confirm same-torch Falloff acdream-vs-retail before tightening the reach.
Diagnostic shader hack reverted (tree clean); D-1..D-4 kept. Branch not merged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 23:22:50 +02:00

6.3 KiB
Raw Blame History

A7 Fix D round 2 — REAL cause found (object sun+ambient + torch REACH), CHECKPOINT

Date: 2026-06-19 Branch: claude/thirsty-goldberg-51bb9b (NOT merged — held at the visual gate) Predecessor: docs/research/2026-06-18-lighting-a7-fixABC-shipped-fixD-handoff.md Status: checkpointed at user request after pinning the root cause. D-1..D-4 are committed + correct but did NOT fix the visible symptom — they were the wrong subsystem.

TL;DR — what the visible bug actually is (and is NOT)

The user's symptom (Holtburg meeting-hall facade too bright/warm/washed-out + character backs lit) is NOT the EnvCell bake, the per-channel clamp, the half-Lambert wrap, or the SSBO leak. Those are the D-1..D-4 path. The visible surfaces are mode-0 OBJECTS, and the cause is:

  1. Building facade over-bright = the torch REACH is too long (acdream ~7.8 m vs retail ~5.2 m), so each entrance torch floods the whole small facade instead of a tight pool. CONFIRMED by isolation: gating object (mode-0) point lights OFF made the building match retail ("looks much better", user 2026-06-19).
  2. Character backs / slight object over-bright = the sun + ambient on objects (mode 0 runs both). Ambient is NOT the culprit (it MATCHES retail exactly — see values). The residual is small for the character (it ~matches retail), so the dominant visible bug is #1 (torches).

Render-path facts (source-verified, workflow wf_c4ad8cf8)

  • Building EXTERIOR = a flat-mesh WorldEntity with IsBuildingShell=true, ParentCellId=null, built from BuildingInfo.ModelId (LandblockLoader.cs:79-90), drawn by WbDrawDispatcher which hard-sets uLightingMode=0 (WbDrawDispatcher.cs:898). It is NOT an EnvCell — so D-4 (EnvCell walls get no sun) never touched it.
  • Characters/creatures/players = ordinary WorldEntity dynamics, also drawn by WbDrawDispatcher at uLightingMode=0 (plain Lambert + sun). The mode plumbing is CORRECT (mode-0 plain Lambert already zeroes a torch behind a back-face — that part of D-3 works).
  • EnvCellRenderer (uLightingMode=1, no-sun, wrap) only ever draws interior cell shells from the dat EnvCell list — never info.Buildings, never characters.
  • Render loop: in-world frames go through RetailPViewRenderer.DrawInside; the bare WbDrawDispatcher.Draw (GameWindow.cs:8230) is the no-viewer-cell fallback. Both share the ONE _meshShader (mesh_modern) program (GameWindow.cs:1845-1857), so uLightingMode is one shared uniform; each renderer re-sets it before its draws.

Ground truth (live cdb retail + acdream probe, SAME-INSTANT)

  • Ambient MATCHES exactly: acdream (0.447,0.447,0.495) == retail (0.4465,0.4465,0.4951). → same sky keyframe → same time of day; NO time desync (the earlier "retail 0.3 / acdream purple" was sequential-capture drift + acdream's un-synced spawn frame; ignore it).
  • retail sun (world_lights.sunlight @ 0x008672a0+0x18) = (0.573, ~0, 0.445), magnitude 0.725, colour (0.98,0.84,0.59) warm. acdream sun=1 (active, derived from the same sky state via Fix C |sunVec|=DirBright). Sun is NOT zero — retail DOES sun-light objects.
  • retail torches (golden, a7-fixd-golden2): static, intensity=100, falloff 3/4/5, warm (1,0.588,0.314) orange + (0.98,0.843,0.612) cream. calc_point_light makes a BRIGHT TIGHT pool (saturates to full warm to ~4 m, gone by ~5.2 m). Faithful in acdream (LightBake.cs).
  • acdream torches ([light-detail]): range=7.8 (Falloff 6×1.3) and range=6.5 (Falloff 5). acdream Range = info.Falloff * 1.3f (LightInfoLoader.cs:90) — the 1.3 is correct, NO stray 1.5.

The OPEN question to resolve FIRST on resume (don't guess)

acdream's orange torch reads Falloff 6 (range 7.8); retail's orange torch was captured at Falloff 4 (range 5.2). 6 = 4 × 1.5 (smells like rangeAdjust) BUT they might be different torches (38 static torches, several orange). Resolve by comparing the SAME torch's Falloff in acdream vs retail, matched by world position (one focused capture): break/dump acdream's torch Falloff for a specific Holtburg torch and the retail world_lights.static_lights[i].info.falloff for the same one. Then:

  • If acdream reads a too-large Falloff for the same torch → fix the dat read / conversion (the DatReaderWriter LightInfo.Falloff path) so acdream's reach == retail's.
  • If the Falloff matches and reach is genuinely ~7.8 → the building-shell-as-one-object spill is the issue; tighten how building shells receive torches (the per-vertex range gate already localises, so this is unlikely — favour the Falloff hypothesis).

Proposed fix (after the falloff is confirmed)

Tighten acdream's torch reach to match retail (≈5 m), keep torches ON. Building facade then shows a tight warm pool by each flame + dark stone elsewhere (retail-faithful). Files: LightInfoLoader.cs (the Falloff→Range conversion), possibly the DatReaderWriter light read. Add a divergence-register row if any conversion deviates. Re-verify visually (the diagnostic that confirmed the cause: object point lights OFF == retail-match).

State of the committed work (KEEP — all correct, just off-target for the visible bug)

Commit What Verdict
180b4af D-1 clamp point sum on its own faithful; keep
39c70f0 D-2 prep — LightBake conformance test keep
cf62793 D-1 shader clamp keep
c62da82 D-2 EnvCell shell binds own light set (real leak fix) keep
b57a53e/156dc45 register AP-35/AP-16 corrections keep
0980bea D-3 objects plain-Lambert / D-4 EnvCell no-sun keep; correct but doesn't touch the building (it's an object)

tools/cdb/a7-fixd-*.cdb capture scripts are committed. Diagnostic shader hack reverted (working tree clean). Branch NOT merged — finish the torch-reach fix, visual-verify, then merge.

DO-NOT-RETRY (cost a lot this session)

  • Don't re-tune the EnvCell bake / per-channel clamp / wrap / SSBO binding for the building — the building is a mode-0 OBJECT, none of that path lights it.
  • Don't chase a time-of-day / ambient desync — ambient + time MATCH retail exactly (0.446).
  • Don't "remove the sun" globally — retail DOES sun-light objects (sun 0.725).
  • The visible building bug is the torch REACH (confirmed by isolation); start there.