Starfall Back to the journey

Behind the scenes

How Starfall was made

Starfall is a narrated, planetarium style trip through the solar system. Every world in it was rendered from real spacecraft imagery in Blender, on my own PC, by Python scripts rather than by hand. It also lets you leave the story and fly over the real terrain of Earth, the Moon and Mars yourself. This page explains how it was built and what went wrong along the way.

Rubab Ibn Hasib

Nine 4K renders: the Sun, Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus and Neptune, each lit from one side against a dark starfield.
The nine final 4K renders. Each one is also a 12 second rotation loop and a 5 second fly-in.

The goal

I wanted the feeling of sitting in a planetarium: dark, slow, a calm voice telling a story. The visual reference was the kind of cinematic space imagery seen on high end brand sites, with huge planets lit from one side, real city lights on Earth's night side, and a thin glowing atmosphere. A first version used planets painted by code, and it looked like a toy. Real imagery and real lighting were the only way to get there.

The pipeline

  1. Real imageryNASA Visible Earth (Blue Marble surface, Black Marble city lights, cloud cover), NASA 3D Resources for Io, Europa and Titan, and Solar System Scope maps (CC BY 4.0) for the other worlds.
  2. Blender, driven by PythonOne script builds any world from scratch: sphere, surface material, night lights, clouds, a camera-only atmosphere glow, rings, sun angle and camera framing. No manual editing in the Blender interface.
  3. GPU renderingCycles path tracing on an AMD Radeon RX 7900 XTX through HIP. 4K stills at 256 samples, 1080p loops and flights at 64 samples with denoising.
  4. A static websitePlain HTML, CSS and JavaScript. Three.js for the live 3D solar system and the Web Audio API for music generated in the browser.
  5. A real narrator voiceEvery chapter and every explorer location is read by Kokoro, an open source text to speech model (Apache 2.0), generated on my own PC with Python. Each clip ships with sentence timings, so the captions follow the voice.
  6. A 3D explorerCesiumJS streams real terrain for Earth, the Moon and Mars, so you can fly over them like a game. Sunlight follows the real time of day, and the International Space Station flies on its live orbit.
  7. An encyclopediaIn depth pages for the most important worlds, written as data files and turned into pages by a small Python build script, so new worlds can be added without touching the design. Every fact is checked by a separate review against NASA and other agency sources, and every place mentioned links straight into the explorer.
  8. CloudflareServed as static assets from Cloudflare's network, deployed with Wrangler.

Getting Earth right

Most of the look was found by rendering small test images, studying them, and changing one thing at a time.

First test: Earth lit almost fully, North America facing the camera, a thick white haze around the edge.
1. First test. Real textures, but lit almost head on, so it read as a globe rather than a planet in space.
Second test: Africa and Europe in view, but the night side still faintly lit.
2. Turned and relit. Africa and Europe in view, sun moved behind. Yet the night side was still glowing.
Third test: a true dark night side with city lights and a thin crescent.
3. The bug found. The atmosphere layer was emitting light onto the planet. Making it visible to the camera only gave a true night side.
Final Earth: Sahara in sunlight, Europe and the Nile lit at night, thin blue rim, soft bloom.
4. Final. A sunset tint along the day and night line, a faint blue haze, and a soft camera bloom.

Problems solved

The Earth map was too big for the GPU

SymptomThe first render failed with a GPU image size error.

FixNASA's Blue Marble is 21,600 pixels wide, beyond the 16,384 pixel texture limit. Blender itself resized it to 16K once, keeping far more detail than the usual 8K maps.

Renders suddenly ten times slower

SymptomA 40 second Earth render took over 9 minutes.

FixWindows GPU memory counters showed another app's Python process holding 13 GB of the card's 24 GB and competing for compute. Closing it restored full speed.

The overnight batch kept disappearing

SymptomThe video batch stopped after about 11 minutes, with no crash in the Windows event logs.

FixThe processes were being cleaned up along with the terminal session that launched them. Starting the batch through Windows' own process service made it independent. Each video now renders to a temporary file and is only renamed when Blender exits cleanly, so a broken file can never be mistaken for a finished one.

Four times faster, with identical images

SymptomVideo frames took 5 to 8 seconds each, much slower than the stills suggested.

FixBlender was rebuilding the scene and re-uploading every texture on each frame. Persistent Data plus GPU denoising cut that to under 2 seconds. A pixel by pixel comparison of the same frame both ways showed a largest difference of 1 out of 255, which is invisible.

A pink Sun

SymptomThe Sun rendered salmon pink instead of fiery gold.

FixThe AgX colour transform shifts very bright oranges toward pink. Rendering the Sun alone with the Khronos PBR Neutral transform kept its true colour.

Real data, not decoration

In the 3D view, every planet sits where it actually is on the chosen date. Positions come from NASA JPL's published Keplerian orbital elements, solved with Kepler's equation in the browser. You can scrub from 1800 to 2050, jump to any date, and switch to true scale, where the distances become real and the planets shrink to specks. The weight and age calculator uses each world's surface gravity and orbital period.

// position of a planet, in astronomical units, for a given date
let E = M + e * Math.sin(M);                       // mean to eccentric anomaly
for (let i = 0; i < 8; i++) E -= (E - e * Math.sin(E) - M) / (1 - e * Math.cos(E));
const x = a * (Math.cos(E) - e), y = a * Math.sqrt(1 - e * e) * Math.sin(E);

Flying over real worlds

The explorer started from one question: could you drag the Moon around and fly across it like a video game? Pre-rendered video can't do that, so this part runs live in the browser on CesiumJS, which streams real elevation data and imagery as you move.

Keyboard and mouse on a computer, a joystick and up and down buttons on a phone.

Open the explorer

More problems solved

Clouds on the wrong side of the planet

SymptomThe cloud and city light layers sat exactly half a world away from the land beneath them.

FixThe sphere's texture coordinates started at a different longitude than the maps. Shifting them half a turn lined every coastline up.

Cities glowing in daylight

SymptomThe night lights showed across the sunlit side, and the ground stayed bright after sunset.

FixThe built in day and night blending didn't behave as documented, so city lights became their own layer that only shows where the real Sun has set.

A giant wedge instead of a space station

SymptomThe ISS model appeared stretched into a huge shape.

FixIts orientation was built from an unnormalised velocity. A proper frame from its direction of travel and the local up direction made it fly level, the right size.

The narrator was one place behind

SymptomThe story about Calgary was still playing when the camera reached Mount Fuji.

FixThe queue now keeps only the newest place, jumping somewhere new stops the current clip, and places passed on the way don't interrupt.

Security versus a 3D engine

SymptomThe explorer stayed black on the live site.

FixThe strict security policy blocks the code generation a 3D engine needs. The policy was split per page, so only the explorer gets that allowance and the rest of the site stays locked down.

By the numbers

13worlds rendered, 9 planets and 4 moons
~40 sper 4K still on the RX 7900 XTX
4×faster video rendering after the fix
16KEarth surface map from NASA Blue Marble
3real worlds to fly over: Earth, the Moon and Mars
51narrated places in the explorer
~77narration clips voiced by Kokoro

Tools

Credits

Imagery: NASA Visible Earth (Blue Marble, Black Marble, cloud cover), NASA 3D Resources, and Solar System Scope textures under CC BY 4.0. Orbital elements: NASA JPL Solar System Dynamics.

Explorer: CesiumJS and Cesium ion (World Terrain, Moon and Mars terrain from NASA LRO and Mars Global Surveyor data), Google Photorealistic 3D Tiles, Microsoft Bing aerial imagery, the NASA ISS 3D model, ISS orbit data from wheretheiss.at and CelesTrak. Narration voice: Kokoro (Apache 2.0).