Install
openclaw skills install @vargai/code-path-traced-filmMake a short animated film in which everything is code the agent writes, including the renderer: a path tracer in one WebGL2 shader (no Blender, no three.js, no meshes, no textures), characters and props as signed distance fields, a meadow of analytic curved grass blades, moon, firefly and window lights with soft shadows, depth of field and motion blur, a variance-guided denoiser, a score synthesized in numpy from the same timeline, captions and an encode. Includes the complete tested film "The Smallest Star" (70 s, 11 shots, two characters) as a starter, a live page that runs the same renderer in the browser, and the speed-ups and traps found while making it. Use when someone asks for a film, short or music piece "made entirely in code", "write your own renderer / ray tracer / path tracer and make a film with it", a storybook or clay-diorama 3D short without Blender, a "no assets, no video model" showcase of what a coding model can do, or a remake of The Smallest Star with another story. Not for a Blender film (blender-code-film), a three.js explainer (code-3d-explainer), recording a browser game (code-game-trailer), 2D motion graphics (kinetic-type-art, hyperframes) or AI-generated footage (varg-ai).
openclaw skills install @vargai/code-path-traced-filmCoding models make video by writing programs. Most of those programs drive someone else's renderer (Blender, three.js). This skill goes one step down: the agent writes the path tracer itself, then tells a story with it. The claim a viewer can check is simple and strong: no 3D software, no models, no textures, no video model, no music model. The starter is a finished film made this way in one session.
scripts/smallest-star/ renders "The Smallest Star", a 70 s fable about a firefly and a lost mouse
(watch it). All
1,560 frames at 1280x720 took 1 h 46 min on a MacBook Pro M4 Pro; the whole session, from a one-line
prompt to the encoded film, took under three hours (2026-11-10).scripts/smallest-star/live/ bundles the same renderer into one HTML file. Viewers drag the
camera and watch the picture converge on their own GPU (28 ms a sample at 960x540 on the same laptop).
Post the link with the film: it is the proof.Put these to the person before building. Each one changes hours of work.
timeline.json. Picture, score and assembly all read this file.audio/score.py is pure numpy: music box, pad, bass, crickets,
wing buzz, footfalls, a hand-written reverb and a BS.1770 loudness meter. It reads timeline.json, so it
follows every later change. Hand it to a second agent with the brief in references/score-brief.md.src/world.js): where the path runs, pond, house, props. The same file
emits GLSL constants and JS helpers, so the shader and the animation never disagree.--dev dev_mouse:0.2), not in the dark scene.src/shots.js): camera, both characters, lights, exposure.
Motion blur is free: the renderer asks for the state at a different time for every sample.references/look.md.render.ts skips frames that exist). Do not edit src/ while it runs: a retry would pick up the
new code mid-film.--modes 2,1 writes normals and albedo from one render;
one sample per pixel with no denoise shows the raw light. post/compose.py scales, adds captions and
pipes frames to ffmpeg with the score.live/build.py) and test that its canvas really draws before publishing.These three changes took a 720p frame from 13-23 s to about 4 s at 16 samples, and stopped the GPU from dropping the WebGL context.
height / (slope bound - ray slope) with
a local slope bound. A grazing ray over flat ground takes 5 steps instead of 120.| You see | Cause | Fix |
|---|---|---|
| A black wedge across the sky with a dead-straight edge | pow(x, 2.0) with negative x is NaN on Metal | Multiply instead of pow wherever the base can be negative |
| "webgl context lost" after a few heavy frames | One draw call ran too long | Draw in bands, one sample per call, sync between them |
| Everything looks like fog at dusk, not night | Visible sky uses the same gain as the sky that lights the scene | Separate skyVis (dark) from sky (ambient), cut fog colour and glow by 5-10x |
| Stars look like snow | Too many, all the same brightness | Three layers, sixth-power brightness, 10-25% cell fill |
| A blurred blade covers the hero | Camera stands in the grass | Clear a corridor by blade hash (two zones: empty sight line, thinned sides); never by moving the camera |
| The pond shows no reflection | The mirror point lies on the shore | Solve the camera height: reflection point = camera + (h_cam / (h_cam + h_subject)) x distance must land on water |
| Bokeh discs of stars sparkle from frame to frame | Each disc is a few lucky rays | More samples for that shot only, then a light temporal filter in the encode |
| Hops land off the beat | The cue marks the landing, the animation starts at take-off | Advance the hop phase by the air fraction |
| Text on dark frames bands after upload | 8-bit gradients | Add grain after the temporal filter, never before |
A narrator makes the film work with sound on, and it is the one part that cannot be code. Generate one
clip per caption (the starter used ElevenLabs v4 through varg, 11 lines, $0.11), put the clips in
audio/vo/ and their start times in timeline.json under narration, then run audio/mix_vo.py: it
levels every line, ducks the music 9.5 dB under speech and brings the mix to -16 LUFS. Build with
post/compose.py --narrated, which also adds a credit line for the voice. Keep the captions on screen:
feeds start muted. Deliver both cuts and let the person choose.
Say only what is true of the files. For the starter: story, characters, world, light transport, denoiser, animation, score and sound effects are code written in the session; nothing was modelled, painted, sampled or generated by an image, video or music model. The letterforms in captions are a system font, so do not say "every pixel". If you add a narrator, say that the voice is an AI voice. Publish the source next to the film.
scripts/smallest-star/src/shader.js: the path tracer and post passes (GLSL in template strings)scripts/smallest-star/src/engine.js: accumulate, denoise, bloom, tone mapscripts/smallest-star/src/world.js, shots.js, vec.js: layout, animation, helpersscripts/smallest-star/render.ts: Bun driver for headless Chrome; stills, ranges, modes, resumescripts/smallest-star/audio/score.py: the score and sound from timeline.jsonscripts/smallest-star/audio/mix_vo.py: optional narration over the scorescripts/smallest-star/post/compose.py: captions, making-of wipe, end card, encodescripts/smallest-star/live/: the one-file interactive pagereferences/look.md, references/score-brief.md, references/commands.md