Skip to content

How WebGL fluid simulation works

A WebGL fluid simulation updates velocity and dye on the GPU every frame. You push the field with the pointer, the solver reacts, and the motion keeps flowing in real time.

Below is the frame loop itself: GPU textures, advection, swirl, pressure, and the display pass that turns the field into pixels. For the wider definition, see what is fluid simulation.

The frame loop

Each frame the GPU reads a set of textures that store velocity and dye instead of color photos. Shader programs read those textures, run the math, and write updated textures back out. The display pass then draws the dye, optional bloom and sunrays, and shading for a finished look.

Your mouse drag or finger swipe adds a splat, a small burst of force and color, directly into those textures. The next frame picks up that splat and carries it forward, which is why a fast flick feels different from a slow drag.

Why the simulation lives in GPU textures

A texture is normally a picture. This solver repurposes textures as number storage, with red, green, and blue channels holding velocity in the x and y direction, dye color, and pressure instead of pixel color. WebGL can render into a texture through a framebuffer, so a shader can treat one texture as input and another as output for the same step.

The solver flips between two copies of each texture every step, a trick usually called ping pong buffering. That lets every pixel update at once on the GPU instead of one at a time on the CPU, which is the main reason this kind of fluid can run live in a browser tab.

Core steps inside one frame

A handful of passes run back to back to turn last frame's field into this frame's field. Each one has a specific job.

Turn on Explain field on the live WebGL fluid simulation to emphasize structure in the field while you paint, which makes these steps easier to see.

  • Advection carries velocity and dye along the current flow, so motion keeps its direction frame to frame
  • External force adds your pointer input as a splat of velocity and color
  • Vorticity confinement, labeled swirl in the dock, re-adds curling motion that advection tends to smooth away
  • A pressure solve, run as several Jacobi iterations, pushes velocity toward a divergence free, roughly incompressible field so the fluid does not just explode outward
  • Dissipation slowly fades dye and velocity over time, which is why fade speed and flow fade exist as controls
  • Dye rides along with velocity through every step. That dye is what you see on screen

The method behind it: stable fluids

This kind of real-time solver traces back to stable fluids, published by Jos Stam in 1999. The key idea is semi-Lagrangian advection: tracing each point backward through the velocity field to sample where its value came from. That stays numerically stable even with a large time step, which a 60 frame per second loop needs.

Open source browser implementations, including the one this site builds on, carried that method onto WebGL shaders so the entire loop runs on the GPU.

From dye field to pixels

Once the dye texture is updated, a final display shader turns it into what you actually see. Bloom adds a soft glow around bright areas. Sunrays add light shafts for a more dramatic look. Shading adds simple lighting across the dye surface so it reads with more depth. Colorful mode cycles hue automatically so strokes change color as you paint.

None of these display effects change the underlying physics. They change how the same velocity and dye field gets rendered, which is why you can turn them off and still see the same motion underneath.

Performance choices behind the scenes

A frame budget on a 60Hz screen is about 16 milliseconds for everything, including every shader pass described above. To stay inside that budget the solver runs the velocity field at a smaller resolution than the dye field, and the pressure solve uses a fixed, limited number of iterations instead of running until perfectly converged.

Quality sets the dye texture resolution in the dock. Auto quality watches your frame rate and steps that resolution down if your device struggles, so painting stays responsive on slower phones. The slider map is in fluid simulation controls.

Honest limits

Real-time WebGL methods use coarse grids and small iteration counts that fit inside a frame budget. They aim for convincing, responsive motion, not certified engineering numbers. See CFD vs browser fluid simulation.

Questions

It runs on the GPU through WebGL shaders. Velocity and dye live in GPU textures so every pixel can update in parallel each frame.

It re-adds small scale curling motion that gets smoothed away by the advection step, which keeps swirls looking lively instead of mushy. The Swirl control sets its strength.

Dissipation settings fade dye and velocity gradually rather than instantly, so motion settles over time instead of cutting off. Pause freezes the loop completely if you want a still frame.

It uses the same family of real-time techniques, built on Jos Stam's stable fluids method, that many game and demo engines use for interactive smoke and liquid effects.