WOAH
A 3D tiled swimming pool with a floating pale-blue sphere and bright shifting light caustics on the pool floor

Play

The raytraced pool from 2011 that its maker built before Figma

WebGL Water renders a pool with real-time caustics, refraction and soft shadows in a browser. Evan Wallace built it in 2011, then went on to co-found Figma.

Draw on the water and rings spread out. Drag the background and the whole pool tilts so you can watch the light bend under the surface. A pale sphere bobs in the middle, throwing a wobbling net of caustics across the tiles.

This is WebGL Water, and the date on it is the sighting. Evan Wallace built it in 2011, back when getting 3D to run in a browser at all was a stunt, and it still runs today. Wallace went on to co-found Figma and was its CTO, so you are looking at an early sketch by someone who then rebuilt an entire industry's design tools in the browser.

A pool in two 256 by 256 textures

Here is what your GPU is doing while the sphere bobs. The water is a heightfield: one 256 by 256 floating-point texture holds the surface, a second identical texture receives the next frame, and a small shader ping-pongs between the two, stepping a wave equation on every pass. Poking the water is just painting a bump into that texture and letting the equation carry it away as ripples.

The rendering is per-pixel raytracing. Each ray from the camera refracts and reflects through the water surface, blended by the Fresnel effect, and lands on the tiled walls. Add soft shadows and analytic ambient occlusion and the illusion closes. There is no engine under any of this, either: the demo runs on lightgl.js, Wallace's own lightweight WebGL library, and asks the browser for exactly two extensions, floating-point textures and shader derivatives.

The caustics are the flex, and years later Wallace wrote up precisely how they work. He builds a mesh of light, one vertex per ray leaving the sun, and raytraces it in the vertex shader: refract at the surface, land on the pool floor. Where neighboring rays squeeze together, the floor brightens, and the measure of that squeezing is the ratio of a triangle's area before and after the bend. GLSL hands over that ratio almost for free through its screen-space derivative functions, which exist because fragment shaders always run in two-by-two packs. The result is drawn into a texture once per frame, then draped across the scene.

The reason it holds up fifteen years later is that none of it is faked with prebaked textures. The reflections are computed, the caustics are computed, the shadows are computed, which is why you can move the light with the L key and watch every one of them move correctly.

The whole demo is four short files of code plus the library, which makes it one of the best graphics repos to read end to end. And if it leaves you wanting to write a first shader of your own, WebGL Fundamentals starts from an empty canvas and builds up to lighting and textures with no magic skipped.

More GPU math you can smear around with a cursor: a fluid simulation solving Navier-Stokes in a fragment shader.

Next up

Watch current move through a circuit that re-solves itself constantly