Repository navigation
Live: local lights guided by light tiles - #87
Conversation
scenes/lamp-rooms.ts (4 x 3 rooms, 96 spot and point lamps with ranges, no sky) and lamp-rooms-wide.ts (12 x 8, 768), and their bench-window shots still-rooms / still-rooms-wide: the case the other shots lack, where a light sampler has to find the lamps a point can see. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
Each camera pixel reports the local light its resampled shadow ray found; a pass makes each 8 x 8 tile's reports a list; the next frame's paths take 4 candidates from their tile's list (2 past the camera hit) beside the uniform ones, which then stand for the lights the list lacks. Unbiased whatever a list holds. Off in scenes whose local lights are summed exactly. still-rooms dE / flicker 0.67 / 0.138 -> 0.63 / 0.068; still-rooms-wide (768 lamps) 1.01 / 0.126 -> 0.58 / 0.081; Bistro and Kabukicho unchanged. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
The lists' kernel code is compiled only for scenes with more than 8 local lights (FEAT bit F_LISTS): others get main's kernel (Bistro trace 8.50 / 8.50 ms). Each list carries a 64-bit mask of its lights' low index bits, so most uniform candidates skip the search. 2 list candidates by default. light/many-shadowed(-live): 24 shadowed point lights, 10 hidden, analytic. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
Lists are fed by the camera hit's resampling, which covers shadow-casting lights only: a scene without more than 8 of them (Kabukicho: none) keeps main's kernel. The mask saved nothing in the trace and cost the pass 0.11 ms. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
- The resampling's weight is one expression with or without a list (a list's candidate weighed relative to a uniform one's). - RIS_EXACT is a constant in gpu.rs, held to the shader's by a test. - THREERT_LT_LIST is gone (LIST_CANDIDATES). - The lists' place in the direct buffer comes from layout::light_lists. - light/many-shadowed at 1024 spp (64 left ~2 % of noise in its patch). Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Reviewed by Cursor Bugbot for commit b6831e2. Configure here.
| let list = L.lt.z + (wg.y * L.lt.w + wg.x) * 64u; | ||
| let at = less.x + less.y + less.z + less.w; | ||
| if (first && at < 63u) { light_rw[list + at] = vec4<f32>(bitcast<f32>(key), bitcast<f32>(same.x + same.y + same.z + same.w), 0.0, 0.0); } | ||
| if (li == 0u) { light_rw[list + 63u] = vec4<f32>(bitcast<f32>(min(all.x + all.y + all.z + all.w, 63u)), 0.0, 0.0, 0.0); } |
There was a problem hiding this comment.
Light indices stored as denormal floats
Medium Severity
Light-tile keys and unique counts are packed with bitcast into the vec4<f32> direct buffer. Integer values 1..63 are IEEE-754 denormal bit patterns, and WGSL allows implementations to flush denormals to zero. On a flush-to-zero device the stored count reads back as 0, so lt_list_n stays empty and guiding silently falls back to uniform resampling. Apple silicon (where this was measured) typically preserves f32 denormals; Vulkan/NVIDIA and some mobile GPUs often do not.
Additional Locations (2)
Reviewed by Cursor Bugbot for commit b6831e2. Configure here.
A small integer's bits are a denormal float, which a driver may flush to zero (the lists would read empty and the guiding stop, silently). Found in review. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>


The live kernel chose among shadow-casting local lights uniformly. With many of them, most behind walls, few candidates found a light that reaches the point.
Now each camera pixel reports the light its shadow ray found, a pass (
light_tiles) makes each 8 x 8 tile's reports a list, and the next frame's paths take candidates from their tile's list beside the uniform ones, which then stand for the lights the list lacks. Unbiased whatever a list holds. The scheme is the one MegaLights and RTXPT guide their draws by; written from their published descriptions, no code taken.Compiled in only for scenes with more than 8 shadow-casting local lights (
F_LISTS). Other scenes get main's kernel.Measured (M5 Pro, dE / flicker of the held frame, lower is better)
still-rooms(new: 96 lamps, 12 rooms)still-rooms-wide(new: 768 lamps)The wide shot's reference was rendered with a light tree on another branch (kept in the local cache): main's offline chooses among the 768 lamps uniformly and is noisy at 4096 samples. Against main's own reference: dE 0.90 -> 0.71.
Cost: Bistro's trace 8.5 ms on both; Kabukichō's perf smoke passes; lamp-rooms' frame 9.05 -> 9.90 ms (trace +0.63, the pass 0.22).
Checks
cargo test --release: 143 passed.test-render: 192 / 192 (two new:light/many-shadowed,-live), with the loop guard.render-identityagainst main: 170 outputs byte-identical, 21 within their run-to-run spread, 1 changed (the new live test, the only one with lists).Not done
🤖 Generated with Claude Code
Note
Medium Risk
Touches core live tracing and light sampling with temporal feedback; biased if weighting is wrong, but designed unbiased and gated behind
F_LISTSwith scenes ≤8 lights unchanged.Overview
Live path tracing now biases shadowed local-light resampling using per-tile history, similar in spirit to MegaLights/RTXPT, when a scene has more than eight shadow-casting local lights (
F_LISTS).Camera-hit shadow rays record the chosen light in the direct buffer’s fourth component. A new first live pass
light_tilesaggregates those reports into sorted, deduplicated 8×8 tile lists (grid offset jitters each frame). On the next frame,pathtrace.wgsladds list-driven RIS candidates alongside uniform picks, with weights so the estimator stays unbiased even if lists are stale or incomplete.Host changes wire
ltileparams, enlarge the direct buffer for list storage, skip the pass whenF_LISTSis off, and reset guidance after viewport resets. Benchmark scenes (lamp-rooms,lamp-rooms-wide) and render tests (light/many-shadowed, live variant) plus bench-windowstill-roomsshots document the noise/flicker wins on many-lamp interiors without affecting Bistro/Kabukichō-style scenes.Reviewed by Cursor Bugbot for commit d418e3c. Bugbot is set up for automated code reviews on this repo. Configure here.