Jonás Javier Encarnación’s browser visualization, Gargantua, creates its black hole by tracing a light ray for each pixel—not by placing a painted disk and ring in front of a star field. The ray’s path determines whether that pixel shows darkness, a lensed view of the background, or light from the accretion disk. That choice makes the lensing effects emerge from the rendering, but it also makes the shader computationally demanding.
Why trace rays instead of drawing a ring?
Encarnación’s early version assembled the image from separate elements: a disk, a halo, and an Einstein ring on a plane. Their boundaries exposed a seam. In the current approach, the shader traces rays backward from the camera, bending them around the black hole. Depending on each ray’s path, it falls in, escapes toward the star field, or crosses the disk.
As an Amazon Associate I earn from qualifying purchases.
This trades a hand-arranged image for more involved per-pixel computation. The benefit is that the photon ring, the far side of the disk seen through gravitational lensing, a secondary image, and distortion of background stars follow from the ray paths rather than being painted as separate overlays.
| Approach | What it does | Trade-off |
|---|---|---|
| Earlier layered plane | Combines a disk, halo, and pre-baked ring. | Simpler composition, but the elements can reveal seams and do not produce the same emergent views from traced light paths. |
| Current ray-traced shader | Traces a ray for each pixel and renders its outcome. | Produces lensing effects from the paths, at the cost of more shader work and implementation complexity. |
How a pixel’s ray becomes part of the image
The shader integrates the ray’s trajectory around the black hole. Encarnación describes the photon-orbit equation as d²u/dφ² = −u + 1.5·rs·u², where u is the inverse radial coordinate and rs is the Schwarzschild radius. He reformulates the orbit as a Cartesian central-force acceleration and advances it with a Verlet-style integration step.
#1 Best Overall
At the end of the traced path, the shader chooses what the pixel sees:
- Captured ray: the ray falls into the black hole, so the pixel is black.
- Escaping ray: the outgoing direction samples the background star field, which appears distorted by lensing.
- Disk crossing: the ray intersects the accretion disk and contributes its light. A ray can reveal a lensed view of the far side rather than just the nearest visible portion.
What the model represents—and what it does not
The ray paths use non-rotating Schwarzschild spacetime. The disk rotates, but that does not make this a Kerr black-hole simulation: the author says per-pixel Kerr ray tracing was too expensive for a browser in this project. It is therefore best understood as a rendering built around Schwarzschild lensing, with a rotating luminous disk—not as a complete simulation of a rotating black hole.
How the disk gets its texture and color
Texture that follows the disk
The disk extends from 1.58 to 17 times the horizon radius. Its fractal noise is evaluated where a ray crosses the disk plane, using log-radius coordinates. This ties the texture to the disk intersection rather than to a flat screen-space overlay.
Recommended Free Tools
Rank #2
Encarnación describes the disk material as rotating at differential Keplerian rates: its inner edge moves about 35 times faster than its outer edge. Continuous rotation would wind the texture into rings too fine to resolve. To avoid that subpixel pattern, the renderer uses two texture copies offset by half a cycle and fades between them every 20 seconds.
Doppler beaming and gravitational redshift
The shader also models Doppler beaming and gravitational redshift. With the parameters used in this rendering, the approaching side ends up a little more than twice as bright as the receding side; its color shifts toward cream, while the receding side shifts toward copper. Those are reported properties of this implementation, not universal brightness or color values for accretion disks.
Keeping bloom out of the black-hole shadow
Bloom initially spilled disk light into the shadow, weakening the dark centre. Encarnación says he saved the image before bloom, then selectively restored those pre-bloom pixels in dark parts of the shadow. In his implementation, that reduced the centre brightness from 106.8 to 18.2. He reports a truly black area of 118 × 73 pixels inside a 142-pixel shadow. These are measurements of this rendered image, not physical dimensions of a black hole.
Making per-pixel ray tracing work in a browser
Rendering tiers and accumulation
The normal tier traces 190 ray steps per pixel. The deep tier uses 340 steps and a higher output resolution; the author reserves it for desktops that meet his capability signals. The renderer accumulates the image over eight frames, shifting the sample slightly between frames to smooth edges. In the Observatory, drawing stops when the view is idle.
More steps and resolution can improve the rendered result, but increase the work the browser must do. Separate tiers let the project use a larger budget where the device can support it rather than treating every visitor’s hardware alike.
Compiling without blocking the page
Encarnación reports that the original shader compilation blocked the page for 2.4–2.7 seconds in his setup. He switched to compileAsync with KHR_parallel_shader_compile; he says this removed that blocking task. In his mobile Lighthouse measurements, total blocking time fell from 7.95 seconds to about 2 seconds. These are project-reported figures, not independently replicated benchmarks, and the available account does not establish a full benchmark protocol.
Rank #4
Adapting to phones and offering a fallback
On phones, the renderer starts at one pixel per point. It can step up to 1.25 and then 1.5 while performance holds, and step down if the phone stutters. This lets the experience respond to changing performance instead of assuming a fixed device capability.
When conditions are unsuitable—including unavailable WebGL2, software rendering, a slow network, or limited memory—the site can serve a flat 2D version. The text and routes remain available, so a visitor can still use the site without rendering the full 3D scene. The companion engineering account describes capability detection and loading choices as implementation decisions for this project, not as universal browser requirements.
Do these 3 things before closing this tab:
1Fix the driver behind crashes, sound loss and screen glitches2Clear out junk files and repair common Windows errors3Scan for outdated or missing drivers - takes under a minuteExploring the Observatory
The companion explainer describes four views: Cinematic, Lens, Disk, and Shadow. Controls for Doppler effects, secondary images, and lensing let visitors inspect how parts of the result are made. As Encarnación frames the controls, they help distinguish which parts of the image come from physics in the model and which come from rendering choices such as texture and bloom.
Best Value
For a browser-based visualization, the important design decision is not to imitate a black hole with a convincing ring, but to make the displayed light depend on where rays travel. The project’s Schwarzschild model and its rendering choices set the limits of that result; its performance tiers and 2D fallback make those choices usable across more devices.
Read Jonás Javier Encarnación’s original WebGL implementation account, along with the Observatory explainer and companion engineering article.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




