Physics WebGL GLSL

When Two Shadows Collide: Ray-Tracing a Binary Black Hole Merger


Live Binary Black Hole Ray Tracer. Every pixel above integrates a light ray through a two-center Majumdar–Papapetrou spacetime ($M_{\text{tot}} = M_1 + M_2 = 1$). Drag to orbit, open ⚙ Controls to sweep the binary separation $d/M \in [0, 5.5]$ from a wide pair down to a single merged remnant, adjust the mass ratio $q = M_2/M_1$, or click Eyebrow Bridge (d=2.4M) and Eclipsing Ring to inspect the figure-eight photon bridge and secondary eyebrow shadows.

In Part 1 (Schwarzschild), Part 2 (Morris–Thorne Wormhole), and Part 3 (Boyer–Lindquist Kerr), every spacetime we ray-traced shared a hidden luxury: integrability. A single black hole—even a spinning one—has enough continuous symmetries (energy $E$, axial angular momentum $L_z$, and Carter's constant $Q$) to reduce every photon trajectory to decoupled 1D equations.

What happens when two black holes orbit each other on the verge of merging? All continuous spatial symmetries vanish. Light rays can skim the photon sphere of Black Hole 1, cross the gravitational saddle point between the pair, wind around Black Hole 2 in a figure-eight ($\infty$), and either escape to the camera or plunge into the companion horizon. As the Simulating eXtreme Spacetimes (SXS) collaboration and the Interstellar team showed (Bohn et al., 2015), a binary black hole does not just cast two circular shadows: each primary shadow is flanked by a fractal hierarchy of thin, crescent-shaped "eyebrow" shadows bridged by a glowing saddle caustic.

This post builds a real-time WebGL ray tracer for an orbiting binary black hole system using the exact Majumdar–Papapetrou two-hole metric, Fermat's optical refractive index formulation, and a three-zone accretion model (two tidally truncated mini-disks inside a circumbinary cavity).


0. Anatomy of a Binary Black Hole Image

Measuring lengths and masses in units of the total system mass $M_{\text{tot}} = M_1 + M_2 = 1$ ($G = c = 1$), the binary geometry is governed by the separation $d = |\vec x_1 - \vec x_2|$ and mass ratio $q = M_2 / M_1 \in (0, 1]$:

Metric
Two-center Majumdar–Papapetrou spacetime in isotropic coordinates $(t, \vec x)$, where the harmonic potential $U(\vec x) = 1 + M_1/r_1 + M_2/r_2$ satisfies $\nabla^2 U = 0$ exactly.
Punctured Horizons ($\vec x_i$)
In isotropic coordinates, each point $\vec x_i$ ($r_i = |\vec x - \vec x_i| \to 0$) is not a point singularity but a regular event horizon of finite surface area $A_i = 4\pi M_i^2$ (Hartle & Hawking, 1972).
Primary Shadows
Rays captured directly by the local photon shell ($r_{\text{ph},i} \approx M_i$) of either black hole cast two facing teardrop-flattened shadows.
Eyebrow Shadows
Rays aimed just outside Primary Shadow 1 are deflected across the inter-hole saddle point and captured by Black Hole 2, carving thin crescent "eyebrows" outside the main shadows.
Three-Zone Disks
Gravitational torques clear a central cavity inside the outer circumbinary disk ($r > r_{\text{cb,in}}$) while feeding two co-moving mini-disks around $\vec x_1(t)$ and $\vec x_2(t)$.

1. The Majumdar–Papapetrou Metric and Fermat's Refractive Index

In general relativity, Einstein's field equations are nonlinear: you cannot normally superpose two black hole solutions by adding their potentials. Remarkably, Majumdar (1947) and Papapetrou (1945) discovered that for extremal black holes in Einstein–Maxwell theory, the nonlinear gravitational cross-terms cancel the Maxwell stress tensor identically, reducing the entire Einstein system to the linear 3D Laplace equation $\nabla^2 U = 0$:

Exact Two-Center Majumdar–Papapetrou Metric ($G = c = 1$)
$$ds^2 = -\frac{dt^2}{U^2(\vec x)} + U^2(\vec x)\,\big(dx^2 + dy^2 + dz^2\big), \qquad U(\vec x) = 1 + \frac{M_1}{|\vec x - \vec x_1|} + \frac{M_2}{|\vec x - \vec x_2|}$$

Because $\lim_{r_i \to 0} U(\vec x)\,r_i = M_i$, a coordinate sphere of infinitesimal Euclidean radius $r_i = \epsilon$ around $\vec x_i$ has proper circumferential area $\lim_{\epsilon \to 0} 4\pi (U\epsilon)^2 = 4\pi M_i^2$—an event horizon of areal radius $R_{H,i} = M_i$.

For a real-time GPU ray tracer, the isotropic form of the Majumdar–Papapetrou metric offers an extraordinary simplification. Along any null geodesic ($ds^2 = 0$), the coordinate travel time $dt$ and Euclidean arc length $ds = \sqrt{dx^2 + dy^2 + dz^2}$ obey:

Fermat's Principle and Exact Optical Refractive Index $n(\vec x)$
$$ds^2 = 0 \quad\Longrightarrow\quad dt = U^2(\vec x)\,ds = n(\vec x)\,ds, \qquad n(\vec x) \equiv U^2(\vec x) = \left(1 + \frac{M_1}{r_1} + \frac{M_2}{r_2}\right)^2$$

Null geodesics of the 4D Majumdar–Papapetrou spacetime are exact Fermat rays ($\delta\int n(\vec x)\,ds = 0$) propagating through flat 3D Euclidean space with refractive index $n(\vec x) = U^2(\vec x)$.

Applying the Euler–Lagrange equation $\frac{d}{ds}(n\hat v) = \nabla n$ to the unit tangent vector $\hat v = d\vec x/ds$ ($|\hat v| = 1$) gives the exact spatial curvature equation integrated per pixel:

Exact Unit-Tangent Ray Equation Integrated Per Pixel
$$\frac{d\vec x}{ds} = \hat v, \qquad \frac{d\hat v}{ds} = \nabla_\perp \ln n(\vec x) = \vec g(\vec x) - \big(\hat v \cdot \vec g(\vec x)\big)\,\hat v$$ $$\vec g(\vec x) \equiv \frac{2\,\nabla U(\vec x)}{U(\vec x)} = -\frac{2}{U(\vec x)}\left(\frac{M_1(\vec x - \vec x_1)}{|\vec x - \vec x_1|^3} + \frac{M_2(\vec x - \vec x_2)}{|\vec x - \vec x_2|^3}\right)$$

Notice that $\hat v \cdot \frac{d\hat v}{ds} = \hat v \cdot \vec g - (\hat v \cdot \vec g)(\hat v \cdot \hat v) = 0$ identically: projecting $\vec g(\vec x)$ perpendicular to $\hat v$ preserves unit speed $|\hat v| = 1$ analytically at every point in the 3D volume.

💻 GLSL: Majumdar–Papapetrou Optical Field & Midpoint Fermat IntegratorGLSL
// Exact Majumdar-Papapetrou potential U(x) and log-index gradient g(x) = 2 * grad(U) / U
void mpField(vec3 p, out float U, out vec3 gVec, out float r1, out float r2) {
  vec3 d1 = p - uPos1;
  vec3 d2 = p - uPos2;
  r1 = length(d1);
  r2 = length(d2);
  float r1Safe = max(r1, 0.02);
  float r2Safe = max(r2, 0.02);
  U = 1.0 + uM1 / r1Safe + uM2 / r2Safe;
  vec3 gradU = -uM1 * d1 / (r1Safe * r1Safe * r1Safe) - uM2 * d2 / (r2Safe * r2Safe * r2Safe);
  gVec = (2.0 / U) * gradU;
}

// Inside per-pixel ray loop (pos = x(s), vel = dx/ds with |vel| = 1):
float U; vec3 gVec;
mpField(pos, U, gVec, r1, r2);
if (r1 < cap1 || (r2 < cap2 && uM2 > 0.001)) { captured = true; break; }

float dMin = min(r1 - cap1, r2 - cap2);
float ds   = clamp(0.11 * max(dMin, 0.04) * (1.0 + 0.06 * rBary), 0.016, 0.75);

// Second-order midpoint step on (pos, vel) preserving |vel| = 1
vec3 acc1   = gVec - dot(vel, gVec) * vel;
vec3 posMid = pos + 0.5 * vel * ds;
vec3 velMid = normalize(vel + 0.5 * acc1 * ds);

float UMid; vec3 gMid; float r1m, r2m;
mpField(posMid, UMid, gMid, r1m, r2m);
vec3 accMid = gMid - dot(velMid, gMid) * velMid;

pos += velMid * ds;
vel  = normalize(vel + accMid * ds);

2. Figure-Eight Photon Orbits and "Eyebrow" Shadows

Click the Eyebrow Bridge (d=2.4M) preset in the simulation above and toggle Accretion Disks off for a moment so you can see the pure silhouette against the starfield. Alongside the two large black shadows, you will see thin dark arcs curving around their outer rims, linked across the center by a bright gold-cyan caustic bridge.

Where do those extra shadows come from? For a single isolated Majumdar–Papapetrou black hole ($M_2 = 0$), setting the inward optical curvature $|\vec g(r)| = \frac{2M_1}{r^2(1 + M_1/r)}$ equal to the circular orbit curvature $1/r$ gives a single photon sphere at isotropic radius $r_{\text{ph}} = M_1$, casting a single circular shadow of apparent radius $b_c = U^2(M_1)\,M_1 = 4M_1$.

When two black holes sit at $\vec x_1$ and $\vec x_2$, the potential $U(\vec x)$ develops an unstable gravitational saddle point ($\nabla U(\vec x_{\text{saddle}}) = \vec 0$) on the axis connecting them:

Single-hole photon sphere vs. binary inter-hole saddle point ($\nabla U = \vec 0$)
$$r_{\text{ph}, i} = M_i \;\;\Longrightarrow\;\; b_{c, i} = 4M_i, \qquad \vec x_{\text{saddle}} = \frac{\sqrt{M_2}\,\vec x_1 + \sqrt{M_1}\,\vec x_2}{\sqrt{M_1} + \sqrt{M_2}}$$

For an equal-mass binary ($M_1 = M_2 = \tfrac{1}{2}$), $\vec x_{\text{saddle}}$ sits at the origin $\vec 0$. Photons passing through this saddle can switch allegiance from Hole 1 to Hole 2 mid-flight.

Because photons can cross the saddle and trade holes, the binary shadow decomposes into a self-similar hierarchy indexed by how many times a ray switches partners before plunging through a horizon:

  • 0-switch rays (Primary Shadows): Rays aimed directly inside the local photon shell of Hole 1 or Hole 2 plunge straight into that hole, forming the two main shadows (flattened into facing teardrops by the companion's tidal pull).
  • 1-switch rays (Primary "Eyebrows"): A narrow fan of rays aimed just outside Hole 1's shadow is bent by $\sim 180^\circ$ around Hole 1, flung across $\vec x_{\text{saddle}}$, and swallowed by Hole 2—carving a dark crescent eyebrow shadow belonging to Hole 2 right outside Hole 1's rim (and vice versa).
  • $N$-switch rays (Figure-Eight Caustic Bridge): At the boundary between escaping and captured 1-switch rays sit unstable periodic figure-eight ($\infty$) photon orbits that weave back and forth around both horizons forever. The gold-cyan Photon Bridge pill highlights rays that skim within $2.4\,M_i$ of both black holes (`minR1 < 2.4 && minR2 < 2.4`), illuminating this chaotic separatrix in real time.
Try the Eclipsing Ring preset: when the binary orbits nearly edge-on ($\theta_0 \approx 85^\circ$), the foreground black hole acts as a gravitational microscope for the background black hole. At conjunction, the far shadow is stretched into a complete binary Einstein ring wrapping all the way around the near shadow!

3. Circumbinary Cavities, Mini-Disks, and Binary Doppler Beaming

General-relativistic magnetohydrodynamic (GRMHD) simulations of supermassive black hole binaries show that gas does not form a single smooth disk all the way to the horizons. Instead, gravitational torques from the orbiting pair clear out a central cavity ($r_{\text{cb,in}} = 0.80\,d + 1.50\,M_{\text{tot}}$ in the shader, smoothly approaching the single-hole inner edge as $d \to 0$) surrounded by an outer circumbinary disk with $m=2$ spiral density waves, while streams of gas feed two tidally truncated mini-disks ($r_{\text{out},i} = 0.42\,d$) around $\vec x_1(t)$ and $\vec x_2(t)$.

When a ray crosses the equatorial plane ($y = 0$), the shader evaluates this three-zone geometry and computes the total velocity $\vec\beta(\vec x)$ of the emitting plasma by superposing the binary orbital velocity $\vec v_i = \vec\Omega_{\text{orb}} \times \vec x_i$ with the local circular orbital speed around Hole $i$. In a single-center Majumdar–Papapetrou metric ($U = 1 + M_i/r_i$), the physical circular-orbit speed measured by a local static observer is $\beta_{\text{circ}}(r_i) = \sqrt{-r_i U' / (U + r_i U')} = \sqrt{M_i / r_i}$ exactly (reaching $c$ at the photon sphere $r_{\text{ph},i} = M_i$). Combining the static lapse redshift $\sqrt{-g_{tt}} = U^{-1}(\vec x)$ with the special-relativistic boost gives:

Combined Majumdar–Papapetrou Lapse & Binary-Plus-Disk Doppler Factor
$$\vec\beta(\vec x) = \vec v_i + \sqrt{\frac{M_i}{r_i}}\,\hat e_{\varphi,i}, \qquad g(\vec x, \vec\beta) = \underbrace{\frac{1}{U(\vec x)}}_{\text{MP lapse }\sqrt{-g_{tt}}} \cdot \underbrace{\frac{\sqrt{1 - \beta^2}}{1 - \vec\beta \cdot \hat d_{\text{obs}}}}_{\text{orbital + disk Doppler}}, \qquad I_{\text{obs}} \propto g^{\,3.2}\,I_{\text{emit}}$$

Because $\vec v_1$ and $\vec v_2$ point in opposite directions on opposite sides of the barycenter, the entire mini-disk of the approaching black hole receives a coherent relativistic boost on top of its internal rotation—making the two mini-disks alternate in brightness twice per binary orbit.

💻 GLSL: Three-Zone Binary Disk & Relativistic Doppler ShiftGLSL
// Mini-disk 1 around BH 1 (tidally truncated at rOut1 = 0.42 * d)
if (uSep > 0.9 && d1 > rIn1 && d1 < rOut1) {
  float x = d1 / rIn1;
  env = smoothstep(rIn1, rIn1 * 1.12, d1) * (1.0 - smoothstep(rOut1 * 0.68, rOut1, d1));
  emitFlux = 2.8 * pow(1.0 / x, 2.1) * env;
  baseTemp = 9200.0 * pow(x, -0.55);
  vec3 tang1 = normalize(vec3(-rel1.z, 0.0, rel1.x));
  vGas = uVel1 + clamp(sqrt(uM1 / max(d1, 0.25)), 0.0, 0.65) * tang1;
}
// ... (Mini-disk 2 around BH 2 and outer Circumbinary Disk with m=2 spiral arm) ...

// Exact MP lapse redshift (1 / U) * special-relativistic Doppler boost
float Uhit     = 1.0 + uM1 / max(d1, 0.15) + uM2 / max(d2, 0.15);
float grav     = 1.0 / Uhit;
float beta2    = clamp(dot(vGas, vGas), 0.0, 0.78);
float betaCosT = dot(vGas, -vel); // beta * cos(theta), since |vel| = 1 and |vGas| = beta
float dop      = sqrt(1.0 - beta2) / max(1.0 - betaCosT, 0.16);
float g        = clamp(grav * mix(1.0, dop, uDoppler), 0.18, 3.0);

vec3 bb = blackbody(baseTemp * g);
accumCol += T * bb * emitFlux * pow(g, 3.2) * (0.35 + 1.25 * turb) * 3.8;

4. The Binary Ray-Tracing Pipeline

Each frame updates the Keplerian barycentric positions $(\vec x_1(t), \vec x_2(t))$ on the CPU, hands them as uniforms to the fullscreen fragment shader, and integrates the Fermat optical curvature across the two-center potential:

Binary state x₁(t), x₂(t), M₁, M₂ Fermat MP integrator v' = g − (v·g)v, n = U² Saddle & eyebrows minR₁, minR₂ caustics 3-Zone disks 2 mini + circumbinary ACES + Bloom
Figure 1: Fermat's optical metric $n(\vec x) = U^2(\vec x)$ turns 3D multi-black-hole ray tracing into a unit-tangent ODE with zero coordinate chart switches.

5. Across the Series: Single vs. Spinning vs. Binary Black Holes

Looking back across all three black hole ray tracers shows how symmetry—and its breaking—shapes the optical appearance of curved spacetime:

Property Schwarzschild ($a=0$) Boyer–Lindquist Kerr ($a\to 1$) Majumdar–Papapetrou Binary
Spatial symmetry Spherical ($SO(3)$) Axisymmetric ($SO(2)$ + Killing tensor) None in 3D (2-center $U(\vec x)$)
Integrability Planar 1D Binet orbit ($h^2$) Integrable via Carter's constant ($Q$) Non-integrable; chaotic figure-8 orbits
Shadow topology Single circle ($b_c = 3\sqrt{3}M$) Single shifted D-shadow 2 primary shadows + fractal "eyebrows"
Accretion structure Single disk ($r_{\text{in}} = 6M$) Single disk ($r_{\text{in}} \to 1M$ or $9M$) 2 mini-disks + cleared cavity + circumbinary ring
Quasi-static approximation Exact static vacuum Exact stationary vacuum Exact static MP snapshot per orbital phase ("fast-light")

Drag the Binary Separation · $d/M$ slider in the live demo slowly from $4.0M$ down to $0.0M$: watching the two mini-disks merge into the circumbinary ring while the twin shadows and their outer eyebrows coalesce into a single horizon is a front-row view of the final seconds of a binary black hole inspiral.