aditazzz

Videos Ragnarök or Reach for Mars

Ragnarök or Reach for Mars

A man with a rocket sits down by the fire, and a Viking seeress reads his future in a deck of tarot cards. He turns up the Tower. "Twenty percent," he says with a grin, and the whole hall laughs: in their myth Ragnarök isn't a risk, it's certain, so twenty percent sounds like good odds. Every card she turns over is a future for all of us. 🚀

Watch on YouTube · 4:05 · video by Claude Opus 5.5 ·

The code behind it

Every frame of this video is drawn by a JavaScript program (a Three.js film, rendered in a headless browser). This is the heart of it, from web/js/film.js, line 476.

songs/ragnarok-or-reach-for-mars/web/js/film.js
window.renderAt = (t) => {
  if (t >= CUT) return renderFull(t);
  const sstp = Math.floor(t * 15 + 1e-6); if (sstp !== lastShadowStep) { st.renderer.shadowMap.needsUpdate = true; lastShadowStep = sstp; }
  // performances first (some shots frame a prop)
  seerPose(t); manPose(t); for (const v of vikings) vikingPose(v, t); cardsAt(t); propsAt(t);
  const c = camOverride(t, camAt(t)); const sh = shake(t);
  cam.up.copy(c.up); cam.position.copy(c.p).add(V(Math.sin(t * 71) * sh, Math.cos(t * 53) * sh, 0)); cam.lookAt(c.look); cam.fov = c.fov; cam.updateProjectionMatrix();
  // light: lightning through the smoke hole, the fire flaring on the drums and the HEYs
  const lk = lightning(t); hall.userData.flash(lk); hemi.intensity = 0.18 + 0.9 * lk; hemi.color.setRGB(lerp(0.23, 0.6, clamp(lk)), lerp(0.29, 0.7, clamp(lk)), lerp(0.42, 1.0, clamp(lk)));
  const fire = hall.userData.fire; fire.userData.flare = 1.1 * decay(t, T.drums, 0.9) + 0.75 * decay(t, T.heys[0], 0.45) + 0.75 * decay(t, T.heys[1], 0.45) + 0.12 * T.stomps.reduce((s, e) => s + decay(t, e, 0.1), 0);
  hall.userData.update(t, cam, H, cam.fov);
  // captions: constant size on screen whatever the lens; lower third
  const tanH = Math.tan(THREE.MathUtils.degToRad(cam.fov) / 2), k = tanH / Math.tan(THREE.MathUtils.degToRad(20)); const dz = 5.2;
  for (const L of lines) { const on = !CLEAN && t >= L.userData.s && t < L.userData.e; L.visible = on;
    if (on) { const kick = T.heys.reduce((a, e) => a + (t >= e ? Math.exp(-(t - e) / 0.14) : 0), 0);
      placeCaption(L, 'p' + SHOTS[c.i].t.toFixed(2), 0, k, tanH, dz); L.scale.setScalar(k * (1 + 0.05 * kick)); L.userData.kick(0.55 * kick); L.userData.update(t, H, cam.fov / k * 1.0); } }
  st.finish.uniforms.uFlash.value = 0.05 * clamp(lk); st.finish.uniforms.uFlashCol.value.setRGB(0.75, 0.85, 1.0);
  st.finish.uniforms.uFade.value = 1 - sstep(T.preview.end - 0.3, T.preview.end, t);
  st.render(scene, cam, t);
  return st.jpeg(0.94);
};
    ...

Read all 4,271 lines on GitHub. If you use it, credit aditazzz and link the video.

What you see

A 3D film, carved and painted. The seeress, the man with the rocket and a hall full of Vikings are wooden puppets that move on twos, like stop-motion, in a longhouse lit by one long hearth. The deck is gold engraving on obsidian. The first card she lays down is two-faced: Ragnarök from one side, Mars from the other, and it was numbered 0 the whole time. Every card she turns up opens into a pop-up world of cut, gilded card: the Tower's lit windows spell 20%, the Sun's feast has a gate that swings shut, robots take the oars, the Red Planet gets named Greenland, and a Viking grows one tomato, voluntarily. The lyrics are embers from the fire that settle into gold letters and burn out, every one of the 16 HEYs is a slam on the table, and by the third chorus the robots are doing the slamming. At the end the doors open onto a headland: the Fool card made real, a ship of standing stones (after Ale's Stones in Sweden) pointing at Mars, and the cliff lined with people as far as you can see.

A tribute, not a roast. The 20% is Elon Musk's own number: "only a 20% chance of annihilation" from AI, he said on The Joe Rogan Experience (Feb 28, 2025).

Files

FileLinesWhat it draws
web/js/film.js506The film. renderAt(t) draws the frame at time t, deterministically: the puppets and everything they handle move on twos (15 fps), the camera, fire, light and captions at 30. The opening (0:00–0:27) is shot here; per-shot vertical reframing and caption placement for 9:16 live here too.
web/js/full.js723Everything from the second HEY to the end, section by section: hooks, verses, refrains, the bridge, the outro. Poses everyone, lays out the cards, sets the light and picks the camera for each shot.
web/js/finale.js117The outro: the man at the cliff edge with the rocket on his shoulder like the Fool's bundle, the little robot at his heel, then everyone in the stone ship and the cliff lined with figures.
web/js/hall.js207The longhouse at night: the long hearth, carved posts, platforms where the Vikings sit, shields and hangings, a smoke hole that lets moonlight in, the seeress's high seat and the doors that open for the finale.
web/js/headland.js150The headland outside the doors: a plateau ending in a cliff, the sea, Mars rising in the cards' engraved style, the Milky Way, and the stone ship whose prow points at Mars.
web/js/fire.js126Shader flames on camera-facing quads (HDR, so the bloom makes them glow), a bed of embers and rising sparks. The sparks are the particles the captions are made of.
web/js/embers.js121Ember captions: each sung word is built from sparks that fly up out of the fire, settle into gold letters, flicker while the line holds and burn out to ash. A HEY is a burst of sparks on the slam.
web/js/puppets.js460The carved, painted puppets on a jointed rig (two-bone IK arms, seated or standing legs): sanded faces with painted features that change by texture swap (the seeress opens her eyes, he grins on "twenty percent"), knife-cut clothing over fine wood grain.
web/js/robots.js132The machines, the one thing in the hall that isn't carved: white enamel shells, a black glass face with a cyan eye strip, a thin gold seam. Same rig as the puppets, so they slam a table the same way.
web/js/rocket.js31The steel rocket he carries: ogive nose, forward and aft flaps, a black tile belly. No logos.
web/js/props.js61The feast on the tables: drinking horns, wooden cups, platters of bread, candles. They jump on every slam.
web/js/cards.js367The cards: obsidian bodies, gilded edges, engraving drawn line by line on a canvas, and the two-faced (lenticular) front that shows one future from the left and another from the right.
web/js/cards2.js462The rest of the deck in the same engraved style: the Fool, the Magician, the Tower, the Star, the Sun, and the new cards past the classic 21 (XXII The Robot, XXIII The Red Planet, XXIV The Gardener).
web/js/popups.js257The card worlds: a turned-up card's engraving rises off the table as a pop-up diorama of cut, gilded card, back layers first, with one moving part that carries the lyric.
web/js/stage.js36Renderer and post chain: bloom, then vignette, grain, a touch of chromatic aberration, a flash and a fade, and a warm/cool split-tone for firelight.
web/js/merge.js36Merges the hall's static meshes by material, so the CPU renderer issues hundreds fewer draw calls.
web/js/lib.js91Shared helpers (from the "I have a blocker." 3D film): easing, seeded randomness, cheap good-looking materials, canvas textures.
web/js/lib2.js106This film's helpers: procedural textures, seeded noise, the hall's environment light, and the fonts.
web/render.mjs36The renderer: serves the film to headless Chromium (WebGL on the CPU through SwiftShader) and saves every frame as a JPEG master, or renders stills or a range straight to video. Resumable.
web/bake.mjs13Draws the card faces once and saves them to web/tex/, which the film loads (drawing them per frame is too slow on the CPU).
web/bake.html14The page bake.mjs opens: which faces to draw.
web/index.html3The page the renderer opens.
timing.py110Everything the film is timed to, written to web/data/timing.json: the tracked beats (105.47 BPM, every HEY on beat 3), all 70 lyric lines word by word, the HEYs, the stomps, the card names, the sections.
cut.py65Cuts any version from the frame masters and the song: segments snapped to frames, short equal-power audio crossfades at the joins, fades, a hold on the last frame.
render.sh11Renders every frame, 16:9 at 1600×900 and 9:16 at 720×1280.
assemble.sh12The YouTube video: the 16:9 masters upscaled to 2560×1440 at 16 Mbps, with the song.
cuts.sh18The vertical versions: the full song, the under-3-minute cut for Instagram and one Short per card (cuts.json).

By the numbers

  • 4:05 long, 14,688 frames rendered (16:9 and 9:16, 30 fps), plus a 2560×1440 master for YouTube
  • 70 lyric lines and 306 words timed to the vocals, 105.47 BPM, every HEY on beat 3
  • 16 HEYs, 16 slams on the table
  • 11 card faces, each engraved line by line, numbered 0 to XXIV
  • 1,400 people on the cliff edge at the end

Lyrics

Words and music by aditazzz.

Intro

Good news. Bad news.
I've seen what's coming.
Choose.

Chorus

Shuffle the deck! (Hey!)
Shuffle the deck! (Hey!)
Turn one over, place your bets
Cast the cards! (Hey!)
Cast the cards! (Hey!)
Ragnarök or reach for Mars

Verse

A man with a rocket sits down by the fire
He turns up the Tower, the flames climbing higher
"Twenty percent," he says with a grin
The whole hall laughs as the night closes in

Verse

He turns up the Sun, a world without need
The machines make plenty, but who gets to eat?
A feast on one side, the other in flames
Two different futures, the very same game

Chorus

Shuffle the deck! (Hey!)
Shuffle the deck! (Hey!)
Turn one over, place your bets
Cast the cards! (Hey!)
Cast the cards! (Hey!)
Ragnarök or reach for Mars

Refrain

Singularity
Singularity
Every card a possibility
None a guarantee

Verse

The Robot comes up, no more rowing the seas
Machines take the oars while we sit in the breeze
The Red Planet rises, another new shore
We plant our old flags and go looking for more

Verse

The Gardener card, we're finally free
To grow our tomatoes voluntarily
The Fool turns and asks what we're living for
When the machines do it all, what are we needed for?

Chorus

Shuffle the deck! (Hey!)
Shuffle the deck! (Hey!)
Turn one over, place your bets
Cast the cards! (Hey!)
Cast the cards! (Hey!)
Ragnarök or reach for Mars

Bridge

The Magician holds the power
The Tower holds the cost
The Star promises plenty
The Fool asks what we lost

Bridge

If it does the thinking
If it makes the art
Did we lose our purpose
Or were we free from the start?

Refrain

Singularity
Singularity
Every card a possibility
None a guarantee

Refrain

Singularity
Singularity
The choice belongs to you and me

Final chorus

Shuffle the deck! (Hey!)
Shuffle the deck! (Hey!)
Turn one over, place your bets
Cast the cards! (Hey!)
Cast the cards! (Hey!)
Ragnarök or reach for Mars

Outro

One last card.
The Fool.
At the edge of the cliff.
Under the stars.

Outro

He told us what the cards might show.
We asked how soon we could go.

Outro

How soon.