Through the Wormhole: Rendering a Morris–Thorne Spacetime Bridge
After rendering Gargantua, the natural sequel is the other relativistic centerpiece of Interstellar: the sphere sitting quietly near Saturn. In decades of science fiction, wormholes were drawn as flat 2D puddles or swirling whirlpools in space. Kip Thorne and the Double Negative team showed what general relativity actually predicts: a three-dimensional crystal sphere whose surface is rimmed by nested Einstein rings of two different universes at once.
Mathematically, a traversable wormhole is even cleaner to ray-trace than a black hole—and much stranger when you fly inside it. Where a Schwarzschild black hole has a one-way event horizon that terminates rays, a Morris–Thorne wormhole has a smooth minimum-radius throat at proper radial coordinate $l = 0$ connecting two asymptotically flat universes: $l \to +\infty$ (Universe A) and $l \to -\infty$ (Universe B). This post builds the full real-time WebGL ray tracer from first principles and renders a 4K 120 fps seamless fly-through loop diving straight through the throat and back.
0. Why a Wormhole Looks Like a Crystal Sphere
Suppose you take a pair of 3D Euclidean spaces, cut a ball of radius $b_0$ out of each, and glue the two spherical boundaries together smoothly. Because the boundary you glued is a 2-sphere ($S^2$), an observer approaching from Universe A does not see a flat circular doorway; from every angle, the throat projects onto a disk of apparent radius $b_0$ on the sky.
- Metric
- Zero-tidal-force Morris–Thorne / Ellis–Bronnikov wormhole with finite cylindrical throat length $2a$ and throat radius $b_0$.
- Coordinate $l \in (-\infty, +\infty)$
- Proper radial distance measured through the throat: $l > 0$ is Universe A (Saturn sector), $l = 0$ is the throat equator, and $l < 0$ is Universe B (Gargantua sector).
- Interior ($b < b_0$)
- Rays aimed inside the critical circle have impact parameter $b < b_0$; they pass through $l = 0$ into Universe B, acting like a wide-angle fisheye lens onto the far universe.
- Exterior ($b > b_0$)
- Rays aimed outside the throat hit a centrifugal barrier at $r(l_{\text{turn}}) = b$, bounce back into Universe A, and show a lensed reflection of our own sky (notice the secondary lensed image of Saturn hugging the lower-right rim).
- Boundary ($b = b_0$)
- The throat itself is an unstable photon sphere: rays with $b \approx b_0$ wind around the throat multiple times before escaping to either $+l$ or $-l$, creating an infinite stack of alternating Einstein rings.
1. The Ellis–Bronnikov / Dneg Metric
To make a wormhole human-traversable without crushing the traveller via tidal forces, Morris and Thorne (1988) set the gravitational redshift function $\Phi(l) = 0$ everywhere. Time ticks at the exact same rate inside the throat as at infinity—there is no gravitational time dilation and no horizon. The entire spacetime curvature lives in the spatial circumferential radius $r(l)$:
Here $dl$ measures true proper radial distance along a ruler poked through the throat, while $2\pi r(l)$ is the circumference of a sphere centered on the wormhole at coordinate $l$.
In the classic textbook Ellis–Bronnikov wormhole, $r(l) = \sqrt{b_0^2 + l^2}$. For Interstellar (James et al., 2015), Kip Thorne added a second dial: a cylindrical throat of half-length $a$ so the team could tune how long the Endurance spent inside the tunnel and how tightly the Einstein rings packed around the rim. Using a soft-plus transition of width $\sigma \ll a$ across $|l| = a$, the profile integrated by our shader is:
Here $\sigma$ sets the collar smoothing width across $|l| = a$. For $|l| \gg a$, $r(l) \to |l|$ and both universes become flat Euclidean space; inside the throat ($|l| < a$), $r(l) \approx b_0$ and $dr/dl \approx 0$ (for $\sigma \ll a$). Setting the Throat Length slider $2a = 0$ with $\sigma \to 0$ recovers the pure Ellis wormhole.
Because the metric is spherically symmetric on both sheets, every light ray stays in a single 2D plane spanned by the observer's radial unit vector $\hat n_0$ and the ray's initial tangent vector $\hat t_0$ on $S^2$. Parameterizing the null geodesic by proper spatial arc length $s$ (so $(dl/ds)^2 + r^2(l)(d\varphi/ds)^2 = 1$), Euler–Lagrange conservation of angular momentum gives a conserved impact parameter $b$:
Compare this to Schwarzschild: there is no singularity at $r = 0$ because $r(l) \ge b_0 > 0$ everywhere! Even better, the second-order equation for $l(s)$ has no coordinate turning-point singularity when a ray bounces off the centrifugal barrier.
💻 GLSL: Velocity-Verlet Wormhole Geodesic IntegratorGLSL
// Decompose pixel ray rd into radial (e_l = uCamDir, outward radial unit vector) and tangential components on S^2
vec3 e_l = uCamDir;
float dl_ds = dot(rd, e_l); // initial radial velocity cos(psi)
vec3 tang = rd - dl_ds * e_l;
float sinPsi = length(tang);
vec3 n0 = uCamDir;
vec3 t0 = (sinPsi > 1e-6) ? (tang / sinPsi) : normalize(cross(n0, vec3(0.0, 1.0, 0.001)));
float r0, dr0;
wormholeMetric(uCamL, r0, dr0);
float b = r0 * sinPsi * uLensing; // conserved impact parameter
float l = uCamL;
float vl = dl_ds;
float phi = 0.0;
for (int i = 0; i < MAX_STEPS; i++){
float r, drdl;
wormholeMetric(l, r, drdl);
if (abs(l) > escapeL && l * vl > 0.0) break; // escaped to Universe A (+l) or B (-l)
float ds = clamp(0.045 * r + 0.035 * abs(l), 0.025, 0.95);
// Second-order midpoint / Velocity-Verlet step on (l, vl) and phi
float acc1 = (b * b) / (r * r * r) * drdl;
float vl_mid = vl + 0.5 * acc1 * ds;
float l_mid = l + 0.5 * vl * ds;
float r_mid, dr_mid;
wormholeMetric(l_mid, r_mid, dr_mid);
float acc_mid = (b * b) / (r_mid * r_mid * r_mid) * dr_mid;
l += vl_mid * ds;
vl += acc_mid * ds;
phi += (b / (r_mid * r_mid)) * ds;
}
// Reconstruct asymptotic 3D look direction on the target celestial sphere
vec3 nFinal = cos(phi) * n0 + sin(phi) * t0;
vec3 tFinal = -sin(phi) * n0 + cos(phi) * t0;
float rEnd, drEnd;
wormholeMetric(l, rEnd, drEnd);
float vTang = clamp(b / rEnd, 0.0, 1.0);
float vRad = sign(vl) * sqrt(max(0.0, 1.0 - vTang*vTang));
vec3 skyDir = normalize(vRad * nFinal + vTang * tFinal);
vec3 col = (l >= 0.0) ? skyUniverseA(skyDir) : skyUniverseB(skyDir);
2. The Throat as a Photon Sphere: Bifurcating Einstein Rings
Look closely at the boundary of the wormhole sphere in the simulation above. Where a black hole has a photon sphere at $r = 1.5\,r_s$ bordering a pitch-black shadow, the wormhole's photon sphere sits right at the throat $l = 0$ ($r = b_0$) bordering a second universe.
Why does that matter? Because rays with impact parameter $b$ just slightly larger than $b_0$ ($b = b_0 + \epsilon$) dive toward the throat, wind around the equator $N$ times as $dr/dl \to 0$, and eventually bounce back into Universe A. Rays with $b$ just slightly smaller than $b_0$ ($b = b_0 - \epsilon$) wind around the exact same throat $N$ times and then slip across $l = 0$ into Universe B:
The flared mouths ($|l| > a$) contribute a logarithmic divergence on both sides of $b_0$, while interior rays ($b < b_0$) that enter the cylindrical throat ($r(l) \approx b_0$ on $|l| \le a$, regularized by $\sigma$) pick up an additional spiral traversal angle proportional to the throat length $2a$.
This creates a striking visual signature you can test interactively right now:
- Outside the critical circle ($b > b_0$): Saturn and the blue-cyan Milky Way of Universe A are compressed into thin concentric arcs hugging the outer rim—including an inverted secondary image of Saturn on the opposite side of the sphere.
- Inside the critical circle ($b < b_0$): The crimson-gold nebula and two-arm spiral galaxy of Universe B fill the crystal ball, with their own compressed Einstein rings stacked just inside the critical curve.
- Inside the throat ($l = 0$): Click the Throat (l=0) preset button in Controls. When the camera sits at $l = 0$, the wormhole no longer looks like a sphere in front of you—it wraps around the entire $360^\circ$ sky as an equatorial band! The forward hemisphere shows Universe B, the backward hemisphere shows Universe A, and the perpendicular equator ($\psi_0 = 90^\circ$) is trapped on the photon sphere.
3. Dual-Universe Render Pipeline
Because both celestial spheres are evaluated procedurally in GLSL, the entire two-universe spacetime requires zero external texture fetches:
4. Designing a Seamless Two-Universe Fly-Through Loop
For the offline 4K 120 fps render, a static orbit in Universe A would miss the entire point of a traversable wormhole. Instead, the camera executes a closed $C^1$-continuous harmonic plunge across the throat: starting at $l = +8.8\,b_0$ in Universe A, diving straight through the Einstein ring at $l = 0$, emerging at $l = -5.6\,b_0$ inside the crimson-gold nebula of Universe B, and smoothly gliding back through the throat to its exact starting pose at $t = L = 8.0\text{ s}$:
With $l_{\text{mid}} = 1.6\,b_0$ and $A_l = 7.2\,b_0$, the camera crosses $l = 0$ twice per loop while its radial velocity $\dot l(t) \propto -\sin(2\pi t/L)$ vanishes smoothly at both turnaround points ($t = 0$ and $t = L/2$).
To keep Universe B's rotating spiral galaxy seamless across the loop boundary without a crossfade, the shader exploits the galaxy's two-fold rotational symmetry ($\cos(2\alpha - 3.6\ln r)$): advancing the galactic azimuth $\alpha$ by exactly $\pi$ radians over the 8-second period maps Arm 1 onto Arm 2 at $t = L$, making the background evolution analytically periodic.
5. The 4K 120 fps Fly-Through Video
Rendered offline via the same stateless slice architecture as Gargantua—960 frames at 3840×2160, 120 fps—here is the complete traversal from the Saturn sector, through the wormhole throat, into the Gargantua sector, and back:
Toggle the Sky grid pill in the live simulation at the top of the page and drag the Radial pos · l slider slowly through zero—watching a coordinate grid invert across two universes in real time is the closest intuition you can get for curved 3-manifolds without leaving your browser.