Repository navigation
The thin feature's lock: lamps finer than a pixel keep their light, held still and in motion - #60
Merged
Merged
Conversation
…eld still and in motion (ROADMAP § 1a) Two faults of the upscaler, measured against offline renders, both older than the flicker tolerance: - Held still, a field of lamps a third of a pixel wide kept a third of its light. `judge` takes a surface for gone from in front when what was nearest among the nine samples a frame ago is nearer than what is nearest now and the history's colour is not in this frame: a lamp the jitter hit last frame and missed this one. Its history was dropped every frame it was missed. - In motion the history is clamped into the frame's nine samples, and a lamp none of them hit is outside them: Tokyo Tower in a turn lost its legs and a quarter of its light. `Lock` (FSR 2's pixel locks; UE's TSR loosens its clamp the same way for thin geometry): a half word per traced pixel, made where the sample's emission is a thin feature, a jitter sequence long, carried with the surface, none on animated shading. A locked pixel's history is not clamped in motion, a locked sample's distance from the history's range is no finding, and nothing is gone where one of the nine samples is locked. The lamps field: 0.035 to 0.106 still, 0.027 to 0.112 moving (offline 0.103). The tower in a turn against offline: dE 2.81 to 2.23, SSIM 0.867 to 0.928, luminance 0.77 to 1.05. Cost: where a view translates past emitters the locked ones trail a little (Kabukichō's signs 6.42 to 6.67 in a strafe, Bistro 2.49 to 2.63 a tenth of a second after one, the slice's explosion 5.28 to 5.41); bench-ghosting passes on both scenes. Tests: upscale/lamps-still-live, upscale/lamps-in-motion-live. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
…75 a frame): no second copy of a lamp The first form spared a locked pixel's history from the motion clamp entirely. In a quick orbit of the play window (a degree a frame about a point 50 m ahead) a lamp the samples missed reprojected with what is behind it, and the spared history became a second copy: Tokyo Tower's beacon doubled, its lamps drawn out sideways. TSR caps how far it loosens its clamp for thin geometry; here 0.75 of the unclamped history is spared a frame and what no sample supports fades by a quarter a frame. Tokyo Tower against offline, dE / luminance: the quick orbit 4.86 / 1.20 to 4.15 / 0.86 (main 5.06 / 0.71); the slow turn 2.23 / 1.05 to 2.17 / 0.80 (main 2.81 / 0.77). Kabukichō's signs a tenth of a second after a strafe 5.55 to 5.39 (main 5.27), Bistro 2.63 to 2.54 (main 2.49). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Nov 13, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What was wrong
Dragging the view over Tokyo at night, the tower broke up: its legs and most of its lamps gone while the camera turned, back half a second after it stopped. Measured against offline renders, these are two faults of the upscaler, both older than #59.
judgetakes a surface for gone from in front when what was nearest among the nine samples a frame ago is nearer than what is nearest now, and the history's colour is not in this frame. A lamp the jitter hit last frame and missed this one is exactly that, so its history was dropped every frame it was missed.The change
The remedy is the one FSR 2 (pixel locks) and UE's TSR (thin geometry detection) have: where the picture is a thin feature, the rules that hold the history to this frame's samples stand back.
Lockinlive.wgslis a half word per traced pixel, in space the fast mean's buffer had free:composemakes it where the sample's emission is thin: no 2 × 2 block of the nine like it (FSR 2's rule), and above or below both of some pair of opposite neighbours.The test runs on emission (what the camera ray saw directly) because that part of a traced sample has no noise. FSR 2's test on the composed sample called most of a night street "thin".
Measured
cargo test --release --locked114 + 2,npm test159, typecheck clean.upscale/lamps-still-liveandupscale/lamps-in-motion-live: main fails both (0.021 and 0.027 of 0.1).compose+judge+upscale: 1.73 → 1.80 ms at 1440p output.What it costs
Where a view translates past emitters, the locked ones trail a little. bench-ghosting still passes on both scenes.
Left
What was tried and left out is in
docs/ROADMAP.md§ 1a.🤖 Generated with Claude Code
Note
Medium Risk
Changes core temporal upscaler behavior (
compose,judge,upscale) with intentional ghosting tradeoffs on fast translation; validated by new tests but affects all live upscaled output.Overview
Adds a thin-feature lock (
Lockinlive.wgsl) so sub-pixel emitters (lamps, lit windows) are not discarded by temporal upscaling when jitter misses them or motion clamps history into the nine-sample neighborhood.composedetects thin emission (FSR2-like local similarity + opposite-neighbor contrast), persists lock state in spareae_inf16 bits for a jitter sequence, and skips animated shading.judgeno longer treats locked samples as disoccluded “gone” or penalizes history-range distance;upscalerelaxes in-motion history clamping byLOCK_RELAX(0.75) when any contributing sample is locked;rejectpropagates max lock across the nine neighbors.docs/ROADMAP.mddocuments the problem, tuning tradeoffs, and benchmark deltas (e.g. lamp field radiance0.035→0.106 still, Tokyo Tower metrics improved). New render testsupscale/lamps-still-liveandupscale/lamps-in-motion-liveguard mean radiance (~0.1) for procedural sub-pixel lamp fields.Reviewed by Cursor Bugbot for commit fa89a24. Bugbot is set up for automated code reviews on this repo. Configure here.