Exploration
Tracing Light
Around a Black Hole
An interactive Schwarzschild geodesic explorer
What is a Geodesic?
In flat spacetime, light travels in straight lines. A laser pointer, a flashlight beam, a photon crossing the void between galaxies — they all follow the shortest possible path between two points. But near a massive object, spacetime itself curves, and "the shortest path" stops being a straight line. It becomes a geodesic — the generalization of a straight line to curved geometry.
Around a black hole, the curvature is extreme. A photon passing nearby doesn't just bend a little — it can loop, spiral, or fall in entirely. The trajectory depends on a single number: the impact parameter b, which measures how far off-center the photon's approach is. Think of it as the photon's "miss distance." Small b? Captured. Large b? Escapes with a gentle bend. But right at a critical value of b, things get really interesting.
The Photon Sphere
At exactly 1.5 times the Schwarzschild radius (the event horizon), something remarkable happens: spacetime curves so severely that a photon can orbit the black hole in a perfect circle. This is the photon sphere, and it corresponds to a critical impact parameter of bcrit = 3√3/2 ≈ 2.598 (in units where rs = 1).
The photon sphere is a knife's edge. A photon arriving with b just below that critical value spirals inward and gets captured. Just above, it loops around the black hole — sometimes several times — but ultimately escapes. Right at bcrit, the photon winds around forever in an unstable circular orbit, never quite falling in, never quite escaping. Play with the slider below and you'll see exactly where this boundary lives.
What You're Seeing
The slider controls the impact parameter b. At low values (b < 2.6), the photon spirals into the black hole — captured. Crank b up past the critical value and the photon bends dramatically around the black hole but escapes. Right at b ≈ 2.598, you'll see the photon wind around many times before the integrator gives up — that's the unstable photon orbit, the boundary between capture and escape. It's weirdly satisfying to dial it in.
The faint ring marks the photon sphere at r = 1.5rs. The black sphere is the event horizon. Everything you see is computed in real time by a fourth-order Runge–Kutta integrator solving the Schwarzschild null geodesic equations — the same physics that governs light around real black holes, just rendered in your browser.
Seeing the Curvature
The flat top-down view hides something essential: why the light bends. Flamm's paraboloid fixes that — it takes the equatorial plane and embeds it into three dimensions, stretching it into a funnel whose depth encodes the warping of space. Now the photon path is drawn on this curved surface, and what looked like a mysterious deflection becomes totally intuitive: the light is just following the surface downhill around the throat. Drag to rotate and you'll see it.
Through the Lens
The geodesic tracer shows paths, but what would you actually see standing near a black hole? Every point of light in the sky arrives via a curved geodesic, so the entire starfield behind the hole gets warped into a luminous halo — the Einstein ring. Stars that should be hidden behind the black hole become visible, smeared around its silhouette. It's beautiful and deeply unintuitive.
Below, every pixel fires a light ray backward through Schwarzschild spacetime (the same Binet equation, solved 300,000 times per frame on your GPU). Where the ray escapes, it samples a starfield. Where it crosses the equatorial plane, it hits a thin accretion disk whose inner material glows white-hot near the innermost stable circular orbit. One side of the disk is Doppler blue-shifted (brighter) and the other red-shifted (dimmer) — a real relativistic effect. Drag to orbit; slide to approach.
How It Renders
There's no 3D scene here — no meshes, no lights, no camera matrix. The entire image is painted by a single GLSL fragment shader running on a fullscreen quad. Three.js serves as a thin harness: a PlaneGeometry(2, 2), a ShaderMaterial, and an orthographic camera. Every pixel is a self-contained physics simulation. The GPU runs roughly 300,000 of them in parallel, 60 times per second.
Backward Raytracing in Curved Spacetime
Traditional raytracers fire rays from the camera and bounce them off surfaces. This one fires rays from each pixel and integrates them backward through curved spacetime until they either escape to infinity (sample the starfield), cross the equatorial plane inside the disk, or fall past the horizon (render black). The key insight is that light paths are reversible — a photon arriving at your eye followed the exact same geodesic in reverse.
The Orbital Plane Trick
This is the cleverest part of the implementation. In Schwarzschild geometry, every null geodesic lies in a plane that passes through the black hole's center. That means a 3D ray can always be reduced to a 2D problem. For each pixel, I compute two unit vectors: ê1 (the radial direction from the black hole to the camera) and ê2 (the tangential component of the ray direction in that plane). These define the geodesic's orbital plane.
The Binet equation is then integrated entirely in 2D — just (u, φ) coordinates, where u = 1/r. At each step, the 3D position is reconstructed as r · (cos φ · ê1 + sin φ · ê2). This is what makes the shader fast enough to run in real time — a 2D ODE solve instead of a 4D one, with no loss of generality.
Detecting the Accretion Disk
The disk lies in the equatorial plane (y = 0). To find crossings, I track the y-coordinate of the ray's 3D position at each integration step. When y changes sign between steps, the ray has crossed the plane. A linear interpolation finds the crossing radius, and if it falls between the ISCO (r = 3rs) and the outer edge, the shader samples the disk's color — a blackbody gradient from deep red at the cool outer edge to blue-white at the searing inner rim.
Each crossing composites a semi-transparent layer (opacity 0.55) front-to-back. A ray that spirals near the photon sphere can cross the disk three or four times, building up the ghostly higher-order images that stack right at the shadow's edge. The transparency lets earlier layers show through later ones — exactly how real light transport works.
Procedural Starfield
The background isn't a photograph — it's a 2048×1024 canvas generated at startup with a seeded PRNG. Nine thousand stars placed in two passes: a uniform scatter across the sky, then a denser cluster along a synthetic Milky Way band (a Gaussian in latitude, modulated by a sine in longitude). Bright stars get a radial gradient halo. The seeded RNG means every visitor sees the same sky — deterministic but organic-looking.
Post-Processing Pipeline
The raw shader output is linear HDR — values well above 1.0 where the disk is hot. Three.js's EffectComposer processes this through four passes: ACES filmic tone mapping compresses the dynamic range with a cinematic highlight rolloff. Unreal bloom bleeds bright pixels into neighbors, giving the photon ring and inner disk their characteristic glow. A custom cinematic pass adds lens vignetting (cos⁴ falloff), subtle chromatic aberration at the frame edges, and a touch of film grain. I even added faint scratch lines and micrometeorite pitting on the "lens" that only catch the light when bright regions pass behind them — a small detail that sells the illusion of looking through an actual optical system.
The Mathematics
So here's the thing — everything you just played with is real general relativity. Not an approximation, not a "looks about right" fudge. The actual Einstein field equations, solved on your GPU in real time. I wanted to walk through the math behind each effect, because honestly, the equations are half the fun.
The Binet Equation
All three visualizations on this page solve the same differential equation. You start with the Schwarzschild metric — Einstein's exact solution for the curved spacetime around a spherical mass — and ask: what path does light follow? For a photon, the conservation of energy and angular momentum do a lot of the heavy lifting. They collapse the full four-dimensional geodesic equations down into a single ODE. If you substitute u = 1/r (so u gets bigger as you get closer to the black hole), you get:
d²u/dφ² + u = 3⁄2 u²
That's it. That's the whole thing. The entire physics of light bending around a non-rotating black hole lives in this one equation. What I love about it is how cleanly it separates the Newtonian world from general relativity. The left side — d²u/dφ² + u — is just Newtonian gravity. It gives you hyperbolic deflection, the kind of gentle bending you see in weak gravitational fields. The right side — 3⁄2 u² — is the only relativistic correction. At large distances it's negligible. But near the black hole, that little term takes over completely, bending light into spirals, loops, and capture orbits.
To actually solve this numerically, I rewrite it as a pair of first-order equations:
du/dφ = v
dv/dφ = −u + 3⁄2 u²
and then march forward in φ using a fourth-order Runge–Kutta integrator — 200 steps per ray. Near the horizon (when u gets above 0.3), I halve the step size because that's where the curvature is most extreme and you need the precision. The raytracer fires one ray per pixel, so at 700×437 you're watching roughly 300,000 simultaneous geodesic solutions, 60 times per second. Your GPU is doing some serious physics.
Impact Parameter & the Critical Orbit
Every ray's trajectory comes down to one number: the impact parameter b. It's the ratio of angular momentum to energy, but geometrically you can think of it as "how far off-center is this photon's approach?" I derive it from the camera position and ray direction:
b = r · sin α · (1 − rs/r)−1/2
That last factor — (1 − rs/r)−1/2 — is a fun one. It's the gravitational correction: at the camera's position, local rulers are already stretched by curved geometry, so the "true" angular momentum differs from the coordinate value. It barely matters when you're far away, but slide the camera close and it changes the image significantly. That's what the local curvature toggle does — try switching it off and you'll see the lensing pattern shift.
Here's where it gets really elegant. The photon sphere falls right out of the Binet equation. Just ask: when can a photon travel in a perfect circle? That means du/dφ = 0 and d²u/dφ² = 0 (no radial change at all). Plug that in:
u = 3⁄2 u² ⇒ u = ⅔ ⇒ r = 3⁄2 rs
And there it is — the photon sphere at 1.5 times the event horizon, derived in one line. The critical impact parameter works out to bcrit = 3√3/2 rs ≈ 2.598 rs. This orbit is unstable — any tiny nudge and the photon spirals in or escapes. But near bcrit, something wild happens. The total deflection angle diverges:
Δφ ∼ −log(b/bcrit − 1)
That's a logarithmic divergence — as you approach the critical impact parameter, photons can wind around the black hole two, five, twenty times before deciding whether to escape or fall in. That's the origin of the photon ring, the razor-thin bright halo right at the shadow's edge. You can see it in the raytracer if you look closely.
Why One Side Glows Brighter
Drag the raytracer around and you'll immediately notice: one side of the disk is way brighter than the other. That asymmetry is relativistic Doppler beaming, and it's one of my favorite effects because it's so visceral. The disk material is orbiting the black hole at the Keplerian velocity:
vK = √(M/2r)
On the approaching side, photons get blue-shifted — higher frequency, more arriving per second, solid angle compressed by aberration. On the receding side, the opposite. The Doppler factor g captures all of this:
g = 1/(1 − vK sin φ)
But here's the kicker: the observed brightness scales as g³. Not g, not g² — g cubed. One power for the energy shift of each photon, one for the arrival rate (time dilation), and one for the aberration of the solid angle. That cubic scaling is why the bright side of the disk can be ten times brighter than the dim side when you're up close. I also shift the color — blue-shifted regions tint blue, red-shifted regions warm toward red — which gives the disk that asymmetric color gradient you see.
Gravitational Redshift
Even before Doppler comes into play, there's another effect dimming the inner disk. Photons climbing out of the black hole's gravitational well lose energy on the way up. A photon emitted at radius r arrives at a distant observer with its energy scaled by:
gred = √(1 − rs/r)
At the ISCO (the disk's inner edge, r = 3rs), that works out to √(2/3) ≈ 0.816 — an 18% energy loss just from climbing out of the gravity well. At the photon sphere (r = 1.5rs), it's √(1/3) ≈ 0.577 — nearly half the energy gone. This is why the innermost disk material, despite being the hottest, doesn't just blow everything else out. The redshift acts like a natural dimmer, which honestly makes the final image way more interesting than if everything were uniformly bright.
The Innermost Stable Circular Orbit
You might have noticed the disk has a sharp inner edge — it doesn't just fade smoothly into the black hole. That's not a modeling choice on my part. It's a genuine prediction of general relativity. The effective potential for orbiting particles in Schwarzschild geometry,
Veff(r) = (1 − rs/r)(1 + L²/r²)
only has a stable minimum for r ≥ 3rs. Below that, circular orbits exist mathematically, but they're unstable — any perturbation and the material spirals into the black hole. So matter in a real accretion disk can only safely orbit down to r = 3rs (that's 6GM/c² in physical units). This is the innermost stable circular orbit, or ISCO. Below it, everything is in free fall toward the horizon.
The bright rim you see at the disk's inner edge? That's the ISCO. The material there is orbiting at close to relativistic speeds, radiating intensely, right on the precipice between stable orbit and capture. It's the most dramatic spot in the whole image.
Higher-Order Photon Images
This is the part that really blew my mind when I first implemented it. Look carefully at the raytracer near the shadow's edge. The disk doesn't appear just once — it appears multiple times, each image thinner and closer to the photon ring.
Here's why: light can orbit the black hole before reaching your eye. A photon that crosses the disk plane once gives you the direct image — what you'd naively expect to see. But a photon that loops halfway around the black hole and crosses the plane again shows you the underside of the disk, reflected by the curvature of spacetime. That's the first indirect image. Each additional half-orbit adds another image, each one compressed into a thinner and thinner ring. In theory, there are infinitely many images, each exponentially demagnified, all stacking up right at the photon ring.
To make these visible, I set the disk opacity to 0.55 per crossing and composite front-to-back. Each time a ray passes through the disk plane, it picks up a semi-transparent layer of color. A ray that spirals close to the photon sphere might cross the disk three or four times — and each crossing adds another ghostly image, progressively redshifted and dimmed. This is the same trick the Interstellar VFX team used to reveal what they called the "hat brim" of light arching over and under the black hole's shadow. Pretty cool that the same math runs in a browser.