From cace430299818ac54c729dd0fb2f32fb8543f331 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 6 Jul 2026 22:43:43 +0200 Subject: [PATCH] diag #176/#181: artifact CHARACTERIZED - static ~10x-hot magenta wash zebra-striping wall geometry; root = weenie lamps on the dynamic light curve (A7 fix #2); retail static curve Ghidra-verified (calc_point_light 0x0059c8b0) VSync-on test (30fps): stripes remain => not tearing (windowed + DWM never tears - the tear framing was structurally wrong). Clean captures at the user's spot: the scene is pixel-static except idle anim; the 'stripes/triangles' are the corridor wall's angled braces silhouetted against blown-out saturated magenta. Server-weenie stationary lamps register isDynamic:true (1/d, range x1.5); retail statics use f=(1-d/range)*intensity*wrap/d^3 beyond 1m, range=falloff*1.3, per-channel colour clamp - ~10x dimmer at 3m. Next: A7 fix #2 (static curve; isDynamic decided by motion, not origin) + conformance pin, then the combined #176/#180/#181 gate. a7 pseudocode doc SS1.6 updated with the verified curve; render digest re-bannered. Co-Authored-By: Claude Fable 5 --- docs/ISSUES.md | 19 ++++++++++-- ...6-07-06-a7-per-cell-lighting-pseudocode.md | 30 +++++++++++++------ 2 files changed, 38 insertions(+), 11 deletions(-) diff --git a/docs/ISSUES.md b/docs/ISSUES.md index 0f34e657..2d7180da 100644 --- a/docs/ISSUES.md +++ b/docs/ISSUES.md @@ -107,8 +107,23 @@ instrument: a capture session with the game window UNOBSTRUCTED (no chat overlay snip tool) while the user confirms the flicker is visibly active, + the user's description of exactly WHAT changes (wash extent? the stripe? brightness?).** -**PORT + VERIFICATION SWEEP (2026-07-06 night, after the user's "retail camera is rock -steady" axiom):** retail's viewer step subdivision ported (`3f34bca0` — radius-anchored +**🎯 ARTIFACT CHARACTERIZED (2026-07-06 late night — the VSync test + clean live +captures):** VSync ON (30 fps) and the stripes REMAIN ⇒ not tearing (and the client is +windowed — DWM never tears windowed apps; the tear theory was structurally wrong). +Clean captures at the user's spot with frame-pair diffs across 1 s: **the scene is +pixel-STATIC except the idle animation — the "stripes/triangles" are STATIC RENDERED +CONTENT**: the corridor wall's angled brace geometry silhouetted as dark triangles +against a BLOWN-OUT saturated magenta glow (zoom: scratchpad live-band.png). Retail +shows the same geometry against a dim wall; ours zebra-stripes because the pink +fixtures are ~10× too hot. **ROOT = the A7 fix-#2 item: server-weenie stationary lamps +take the DYNAMIC light path (`isDynamic: true` at the GameWindow registration, 1/d, +range×1.5) instead of retail's static curve — now Ghidra-verified at 0x0059c8b0: +`f = (1 − d/range)·intensity·wrap/d³` beyond 1 m, `range = falloff×1.3`, per-channel +clamped to the light's own colour (see the a7 pseudocode doc §1.6).** The "flicker" +in motion = the high-contrast pattern's edge crawl (+ the wall-press mm wobble), +secondary to the brightness. NEXT: implement fix #2 (static curve for stationary +lights; `isDynamic` decided by whether the light MOVES, not by weenie-vs-dat origin), +then the combined #176/#180/#181 re-gate. retail's viewer step subdivision ported (`3f34bca0` — radius-anchored steps, remainder final step, viewer-exempt small-offset abort; `calc_num_steps` 0x0050a0b0 / `find_transitional_position` 0x0050bdf0 via Ghidra, pseudocode `docs/research/2026-07-06-viewer-step-subdivision-pseudocode.md`). The wall-press diff --git a/docs/research/2026-07-06-a7-per-cell-lighting-pseudocode.md b/docs/research/2026-07-06-a7-per-cell-lighting-pseudocode.md index b081f34b..57ef4dda 100644 --- a/docs/research/2026-07-06-a7-per-cell-lighting-pseudocode.md +++ b/docs/research/2026-07-06-a7-per-cell-lighting-pseudocode.md @@ -186,15 +186,27 @@ calc_point_light(vertex, &r, &g, &b, info): b += clamp(f * info.color.b, ..) ``` -> ⚠️ **Do NOT port the exact `atten` curve from this BN pseudo-C.** Lines -> 425331–425341 are dense x87 FPU register juggling (`distsq/dist` vs -> `1.5/(distsq·dist)` branch on `distsq ≷ 1`), exactly the "x87 dropout / misread" -> class the project has been burned by twice (see `feedback_bn_decomp_field_names`, -> `feedback_retail_binary_dispatch`). When implementing fix #2, cross-reference a -> SECOND source (ACE / ACViewer static-light port, or the Ghidra decomp) and pin -> the curve with a conformance test before trusting it. The STRUCTURE above -> (range = falloff × static_light_factor, per-vertex N·L, intensity scale, colour -> clamp) is solid; the attenuation exponent is the part to verify. +> ✅ **CURVE VERIFIED via Ghidra (2026-07-06 night, the #181 arc).** The exact +> retail static point-light evaluation (0x0059c8b0, clean decompile): +> +> ``` +> L = light.origin − vertex.pos ; d² = |L|² ; d = √d² +> range = falloff · static_light_factor # ≈ 1.3 +> if d ≥ range: contribute nothing +> wrap = (1/(2·LIGHT_POINT_RANGE)) · ( dot(N, L) + (2·LIGHT_POINT_RANGE − 1)·d ) +> if wrap ≤ 0: contribute nothing # back-facing beyond the wrap term +> denom = (d² > 1) ? d³ : d # 1/d³ beyond 1 m, 1/d inside +> f = (1 − d/range) · intensity · (wrap / denom) +> r += min(f·color.r, color.r) # per-channel clamp to the light's +> g += min(f·color.g, color.g) # own colour (never exceeds it) +> b += min(f·color.b, color.b) +> ``` +> +> (`LIGHT_POINT_RANGE` is a global — read its value when porting; if 1.0 the wrap +> reduces to `0.5·(dot(N,L) + d)`, matching the earlier BN gloss.) Against the +> DYNAMIC D3D path our server-weenie fixtures currently use (1/d, range×1.5), a +> fixture at 3 m is ~an order of magnitude hotter than retail — quantifying the +> #176 magenta wash. Still pin with a conformance test on port. ---