Five smoothstep edges reversed, and SwiftShader folds them to a constant: where the rain went
The same rain-city prompt, run by Fable 5.1 inside Claude Code: 82 turns, $6.43, six render rounds. The part worth reading is rounds three and four — five smoothstep calls had their edge arguments swapped, this SwiftShader build evaluates that as a constant, and a million rain particles rendered nothing at all.
The on-screen labels are in Chinese: this is the model's verbatim output from an experiment run in Chinese, and editing it would make the artifact something other than what was measured.
How it was made
- Model
- Claude Fable 5.1 + Claude Code
- us.anthropic.claude-fable-5-1
- How
- agent loop
- Claude Code 2.1.266
- Reasoning effort
- high
- Turns
- 82
- Tool calls
- 81
- Output tokens
- 81.0k
- Wall time
- 22m 9s
- Cost
- $6.43
- Artifact
- 850 lines, one file
- Error feedback
- none
This is the best debugging record in the section, because the bug it hit only shows up on one particular implementation.
Six render rounds, each checking ready, demoError, page and console errors,
__DEMO_INFO, pixel statistics, det=1 determinism, palette switching via key=2 and
key=3, and a free-running render with no t:
- A TDZ bug: a
letdeclared afterinit()ran. Fixed by hoisting. - Washed out at mean luminance 0.59. Rain alpha, bloom strength and threshold, window brightness and exposure all reduced.
- – 4. Found where the rain went. Five
smoothstepcalls had their two edge arguments reversed, and this SwiftShader build evaluates an edge-reversedsmoothstepas a constant. It confirmed the symptom with a debug copy that forced point size and alpha, then rewrote every instance as1.0 - smoothstep(lo, hi, x). - – 6. Raised ambient and fog so no frame is dominated by black pixels, spread the searchlights along the flight path, and confirmed a full beam at t=66.
Final: mean luminance 0.13–0.21, over 93% of pixels non-black, two identical hashes at
t=7.5, about 3 FPS under software rendering.
The bug in rounds 3 and 4 is the strongest argument in this set: it is neither a syntax error nor a logic error, and on a conforming implementation it might work fine. No static check reports it, and no amount of the model “thinking it through” avoids it — the only route is to render the frame, notice the rain is gone, and write a debug copy to isolate it.
The scene itself is heavier than the Astra run: 5,422
buildings from a single InstancedMesh with a fixed-seed layout, streets every fifth
cell, a 60 m flight corridor carved along the camera path and a taller downtown core;
windows, random flicker, neon sign bands, edge strips and rooftop beacons all drawn in the
fragment shader with distance LOD; wet ground sampling a half-resolution reflection render
target with flowing distortion, two layers of expanding rain rings, a puddle mask and
Fresnel. Higher numbers — but framed from above and dark overall, so the composition reads
less like a city than Astra’s does.
Controls: mouse movement for parallax, scroll to zoom the view, space to pause,
1/2/3 for palettes (Neon Noir and others), and dragging gives a temporary free look
that returns to the flight path on release.
Same prompt, other runs
three.js r170 is served from this site, so running a demo makes no third-party request. Published by the author as an individual; testing was self-funded and nothing here represents an employer's position.