WOAH
Bright ribbons of magenta, cyan and yellow ink swirling across a dark screen next to a simulation control panel

Play

Drag your cursor and the GPU solves real fluid dynamics

WebGL Fluid Simulation runs the Navier-Stokes equations on your graphics card, twenty pressure iterations a frame, in about fifty kilobytes of JavaScript.

You move the mouse and a rope of magenta uncoils behind it, curls back on itself, drags a streak of cyan into the fold. Let go and the whole screen keeps churning like weather.

WebGL Fluid Simulation, by Pavel Dobryakov, is not painting those swirls with canned animation. It is solving the incompressible Navier-Stokes equations, the same math that describes real smoke and water, on your graphics card, once for every frame. The ink is just a dye field being carried along by the velocity it computes.

The receipt is the size. The whole simulation is one JavaScript file, 51 kilobytes by my download, MIT-licensed and sitting on more than sixteen thousand GitHub stars. The moment it loads it fires between five and twenty-four random ink splats, a range the source rolls with Math.random() * 20 + 5, so the screen is already alive before you touch it.

What the GPU does every frame

The fluid's entire state lives in a few floating-point textures, one for velocity and one for dye, and each frame a short stack of fragment-shader passes rewrites them in place.

Advection runs first: every pixel traces backward along the flow to see what is drifting into it, carrying velocity and ink downstream in one cheap step. Vorticity confinement follows, putting back the small curls that numerical error keeps smoothing away.

Then the physics gets enforced. A Jacobi pressure solve runs twenty passes per frame, PRESSURE_ITERATIONS: 20 in the config, forcing the field incompressible before a final pass subtracts the pressure gradient. It is Jos Stam's stable-fluids method as Mark Harris laid it out in NVIDIA's GPU Gems chapter 38, ported pass for pass into WebGL. The GPU runs the same tiny program on every pixel at once. That is the whole speed trick.

The prettiness has a separate trick. Velocity is simulated on a grid only 128 cells across, while the dye rides its own texture at 1024, so the physics stays cheap and the ink stays crisp. On phones the script drops the dye to 512 and switches the sunrays pass off; it asks for WebGL2 with EXT_color_buffer_float, falls back to WebGL1 with half-float texture extensions, and that fallback ladder is why a mid-range Android holds full frame rate.

Turn on Bloom in the dat.GUI panel and eight stacked blur passes set the bright cores of the vortices glowing. The same panel exposes the honest knobs, sim resolution from 32 up to 256 cells, dye quality in four steps. The glow is not part of the physics. That is just showing off, and it earned it.

Where to start if you want one

Harris's GPU Gems chapter is free online and remains the clearest map of that pass stack. When you want to build one rather than read one, Jamie Wong's WebGL fluid simulation walkthrough derives the advection and pressure steps from the math, with live demos running in the page. Between those two and Dobryakov's MIT-licensed source, the whole trail is marked.

Same idea, different flavor: one line of code driving two hundred and fifty-six dots.

Next up

Summer is a website and it has a tracklist