Johto Autumn is a 20-second fan trailer that renders in real time in a single HTML file. It was made in about 2 hours of conversation with Claude Code (Opus 5.5). This file summarizes the session so you can reproduce the approach.
johto-trailer-20s-small.mp4
Discussion and the original post: on X
Fan-made, non-commercial. Pokémon © Nintendo / Creatures / GAME FREAK. Ho-Oh model by nguyenlouis32 (Sketchfab, CC-BY-4.0). Gyarados, Marill and Pichu models come via Pokemon-3D-api/assets. The music is original and synthesized in code.
johto.html(about 1.2 MB, fully self-contained): open it, click, and it plays at 60 fps with sound.- The shot list (a 20 s cut on taiko hits):
- Route 37 : a backlit maple leaf hanging from its twig.
- Ecruteak City : a lantern street at dusk, with the Burned Tower and Tin Tower in the mist.
- Ilex Forest : a stream, a torii, two Marill and a Pichu.
- Lake of Rage : the red Gyarados erupts from the water.
- Tin Tower : a nine-tier pagoda over a sea of maples at sunset.
- The Clear Bell : it pulses, flares and whites out.
- Ho-Oh : it circles the tower while the camera orbits.
- Title : JOHTO · AUTUMN over golden sparkles.
- Location cards : a Pokémon-style banner with a rolling Poké Ball on each place.
| Layer | What |
|---|---|
| Agent | Claude Code with Opus 5.5. GPT-6 Astra (via codex exec ) wrote the character design briefs and early SDF drafts |
| Rendering | Raw WebGL2 (no engine, no three.js). The worlds areGLSL raymarched signed-distance fields |
| Characters | Rigged glTF models. They're decoded offline (Draco → JSON) and skinned in a custom WebGL2 pass that is depth-merged with the raymarcher |
| Post | Golden-spiral bokeh DOF, a bloom pyramid, ACES tonemapping, grading, grain, and an SDF title and location cards |
| Audio | Web Audio API , rendered in anOfflineAudioContext : Karplus-Strong koto, shakuhachi, taiko, temple bells, formant choir, and risers into each cut |
| Review | puppeteer-core + headless Chrome (GPU) for stills and frame-exact capture,ffmpeg for contact sheets, luma-diff scans and encoding |
src/
gl.js WebGL2 helpers (programs, float targets, cube maps)
timeline.js the sequencer: every shot is a pure function of time t
main.js pass graph, dynamic resolution, audio-clock sync, debug HUD
scene_*.glsl one raymarched world per place (route, ecruteak, ilex, lake, tower)
leaf.glsl the maple leaf shape, hero leaf, falling-leaf layers
mesh.js skinned glTF pass + depth merge
models.js decoded models (generated)
score.js the 20 s score
label.js vector font for the location cards
final.glsl tonemap, grade, title, Poké Ball banner
build.mjs inlines everything into johto.html
tools/ still.mjs, capture.mjs, audio.mjs, perf.mjs, convert-models.mjs, sheet.sh
- Reuse an engine. An earlier procedural short (IRIS) provided the renderer, timeline and audio pipeline, so the session started from spikes, not a blank page.
- Spike the riskiest things first : creatures as SDFs, then Tin Tower, then each location as its own "spike" scene you can open with
?spike=tower. - Give the agent reference. A video of the HGSS Bell Tower rooftop scene changed the palette (cobalt roofs, gold orbs) and the ending.
- Places first, Pokémon as cameos. It's a deliberate constraint that keeps the scope sane.
- Use real models where procedural falls short. The SDF Ho-Oh and Gyarados, including two rounds of revisions by GPT-6 Astra from its own renders, read as toys. The agent searched GitHub, found rigged glTFs and built a skinned-mesh pass to use them.
- Cut down. A 2-minute rough cut became a 20 s trailer that cuts on taiko hits, with every shot polished.
- Review frame by frame, repeatedly. A pass looked like this:
- render stills at the start, middle and end of every shot;
- write every flaw into a checklist (
REVIEW-20s.md); - fix it;
- capture the whole film and run an ffmpeg per-frame luma-difference scan, so the only jumps left are deliberate cuts.
- Audio from scratch, in one pass. A single continuous render with crossfaded chords, a sustained drone, risers into each cut and envelopes that always reach zero means no seams. It was checked by measurement (RMS steps, clicks, loudness per section), since the agent can't listen.
These are paraphrased from the session:
-
"Let's do a Pokémon short: a trailer of Johto in autumn." → plan, shot list, engine port.
-
"Use GPT-6 Astra for the Pokémon designs, and focus more on the places, like the tower, than the Pokémon."
-
(shared an HGSS Bell Tower video) "FYI, this is a reference."
-
"Make it a 20 s trailer and polish it more."
-
"There are so many imperfect details. Please look frame by frame."
-
"Generate Ho-Oh and Gyarados with GPT-6 Astra, find existing renders online, and redo the audio from scratch: there are hard cuts."
-
"Aren't there real renders of the two Pokémon we can use? Search on GitHub."
-
"Add an overlay for each location… more at the bottom, Pokémon style, with a Poké Ball."
-
"Ho-Oh's landing is weird. Instead, have it circle the tower with the tower's perspective changing too."
-
Tell the agent to look at its own output. Most quality came from render → inspect → fix loops, not from the first write.
-
Real models beat hand-written creature SDFs. Procedural works for architecture, water, light and foliage.
-
Build tooling early: still rendering at any timestamp, contact sheets, a luma-scan for pops, and a per-pass performance profiler.
-
Keep everything a pure function of time. Then seeking, debugging and frame-exact capture come for free.
The source and the full Claude Code session aren't public yet. If there's interest, I'll open-source them.