Skip to content
devcode90Public

About

Rotating supermassive black hole ray traced through Kerr spacetime in real time, in a single self-contained HTML file

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Gargantua

A rotating supermassive black hole, ray traced through curved spacetime in real time, in a single self contained HTML file. No build step, no dependencies, no asset downloads. Open the file and it runs.

Live demo →

A rotating black hole seen near edge on, the accretion disk warped into a halo around the shadow with nested photon rings

Nothing here is painted in. The halo above the shadow, the band beneath it, the thin bright rings hugging the darkness and the lopsided brightness of the disk are all consequences of tracing light backwards through the metric. Give the renderer a different spin or a different camera and it produces whatever those parameters imply.

Run it

Download gargantua.html and open it in a desktop browser. That is the whole procedure. It needs WebGL2 and a reasonably current Chrome, Edge, Firefox or Safari.

Input Action
Drag Orbit the camera
Scroll Move between 3.9 M and 360 M
Leave it alone Slow automatic drift resumes after a few seconds

Gallery

The same simulation, same parameters, different viewpoints.

Nearly edge on view, the disk split into a halo above and a band below the shadow Close dramatic view with the near side of the disk sweeping across the frame
Near edge on, where lensing is most violent. The disk's far side is bent up over the shadow and its underside appears below, so a flat disk reads as a halo wrapped around a sphere. Closer in. The approaching side runs blue white and the receding side sinks to deep red, which is Doppler beaming rather than a colour ramp.
Moderately inclined view showing the warped disk and a lensed background galaxy High inclination view looking down onto the disk, turbulent spiral structure visible
A moderate tilt. The disk's outer edge is cool and clumpy, the inner edge is hot enough to run white. Looking down the throat. The turbulence is sheared into spirals by differential rotation, and the temperature climbs steeply inward.

Wide view with the black hole small in frame, encircled by a ring of lensed background starlight

Pulled far back, the lensing of the background sky becomes the subject: light from stars behind the hole is bent around it into a ring.

The physics

Geometric units, M = 1, spin a/M = 0.9. Kerr geometry in Kerr-Schild Cartesian coordinates, which stay regular across the horizon instead of blowing up at it. That puts the horizon at r = 1.44 M and the innermost stable circular orbit at r = 2.32 M; the disk spans from there out to 30 M.

Light transport. Each pixel fires a ray and integrates the null geodesic equations backwards in time to find where that light came from. The integrator switches order by where it is: fourth order Runge-Kutta close in where curvature is strong and the path bends hard, second order further out where it is nearly straight and the extra evaluations would be wasted. Rays are terminated on the horizon or at an escape radius.

The disk. An optically thick, geometrically thin flow with a Novikov-Thorne emissivity profile, so temperature falls off with radius the way a real accreting disk does, and colour comes from a blackbody lookup rather than an artistic gradient. At each sample the local circular orbit four velocity is constructed and the full frequency shift is computed from it, combining gravitational redshift with special relativistic Doppler shift. Beaming goes as g³·²⁵, which is what makes one side of the disk far brighter than the other. Emission and extinction are integrated with an analytic constant source slab per step, which removes the step size bias that otherwise brightens or darkens the optically thick regions depending on how finely you march.

Structure. The turbulence is a stack of log-polar noise octaves, domain warped by the coarsest layer, combined into a ridged filamentary web and a granular emission field, with logarithmic spiral density waves and a few orbiting hot knots layered on. The disk's midplane is warped and precessing, so it is not a perfect plane.

Surroundings. A procedural starfield with physically motivated colour temperatures and a scattering of distant galaxies, all lensed by the same geodesics as everything else, which is why the background visibly streams and arcs near the shadow. A hot, optically thin inner flow hugs the ISCO; because near critical photons wind around the hole several times before escaping, this is what builds the thin nested rings pressed against the shadow's edge.

How it is rendered

geodesic + volume trace   →  temporal accumulation  →  sharpen  →  bloom + grade
(at a fraction of                (reprojected,          (at trace     (AgX, auto
 display resolution)            neighbourhood clamped)   resolution)   exposure)

Tracing is the expensive part, so it runs below display resolution and the result is reconstructed. Frames are jittered on a Halton sequence and accumulated into a history buffer that is reprojected through the camera's rotation each frame, with a neighbourhood clamp to throw away history the current frame contradicts. Detail recovery happens at trace resolution, where it is cheap, rather than at display resolution, where a wide reconstruction filter measured about 45 ms per frame on integrated graphics and was not worth it.

Grading is a photographic chain: a downsampled average drives exposure adaptation toward a target luminance, bloom is built with a Karis average downsample and tent upsample to keep fireflies out, then AgX tonemapping and a mild vignette.

Performance

There is no fixed quality setting. A controller watches frame pacing and walks through eight tiers of internal resolution, geodesic step count and volume step count, remembering any tier that failed as a ceiling so it settles quickly instead of oscillating. It also drops two tiers while you are dragging, so the camera stays responsive, and restores shortly after you let go. GPU timer queries are deliberately not used; several integrated drivers report them inaccurately.

The practical consequence: on integrated graphics it settles at a low tier and the image is softer, on a discrete GPU it climbs and sharpens. Shrinking the window is the fastest way to trade area for detail.

perf.js drives headless Chrome and reports frame pacing, the settled tier and the internal resolution, capturing two frames seconds apart to confirm the disk is actually rotating:

node perf.js gargantua.html 1920 1080 14

shots.js renders the gallery above. It pins the top tier and lets the accumulation converge, because frame rate is irrelevant for a still:

node shots.js gargantua.html screenshots

Two problems worth describing

Time is a time lapse, and that is a choice. A hole of this mass has orbital periods measured in days. Any visible motion is already an enormous speed up, so the rate is a presentation decision, not a physical one. It is set so the pattern sweeps around in roughly 37 seconds while the innermost flow takes about 7.

Differential rotation destroys turbulence if you let it. The inner disk orbits far faster than the outer disk, so any pattern advected with the flow is sheared, and the shear grows without bound. Left alone the turbulence winds up into smooth concentric rings, like grooves on a record, and the flow stops looking like a flow. This is invisible for the first few minutes and then unmistakable.

The fix splits rotation in two. A rigid component carries the whole pattern around and has no radial gradient, so it never winds up. The radius dependent remainder, the part that actually shears, is rebuilt in overlapping generations on roughly an orbital timescale, with a short crossfade between them, which is also how real turbulence behaves: it is continuously regenerated rather than sheared forever. Only the layers that genuinely shear are regenerated, so the second noise lookup is confined to the crossfade window. The flow now stays turbulent indefinitely, and the time rate can be raised freely because it no longer trades against the disk degenerating.

Deploying

dist/ is generated and untracked, so recreate it before publishing:

mkdir dist
cp gargantua.html dist/index.html
netlify deploy --dir=dist --prod

Publishing only dist/ keeps the rest of the working directory off the public site.

About

Rotating supermassive black hole ray traced through Kerr spacetime in real time, in a single self-contained HTML file

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages