The rolling smoke in a film, the fireball of an explosion, the churn of a river surface — a huge share of the fluid you see in modern computer graphics traces back to one remarkably short SIGGRAPH paper: Jos Stam's "Stable Fluids" (1999). Before it, fluid solvers in animation were fragile: push the timestep a little too hard and the simulation would explode into a screenful of NaNs. Stam's trick made the solver unconditionally stable — you could take big, movie-sized timesteps and it would never blow up. That single property is why grid-based fluids became practical for production, and the method still sits at the heart of tools like FumeFX, Phoenix and Houdini's smoke solver.
This page builds the solver from its idea outward: the Eulerian way of storing a
fluid, the equations that govern it, and Stam's four-step recipe — add forces, advect, diffuse,
project — with the two clever pieces (semi-Lagrangian advection and pressure projection) that
make it work. It assumes you have met
There are two fundamentally different vantage points for describing a moving fluid, and choosing one is the first design decision in any solver.
Stable Fluids is thoroughly Eulerian. Picture a fixed checkerboard laid over your smoke: every square remembers two things, a little velocity arrow (which way and how fast the air is moving there) and a greyness (how much smoke is in that square). Every timestep the solver rewrites those two fields. The great advantage of a grid is that spatial derivatives — the gradients and Laplacians all over Navier–Stokes — become simple differences between neighbouring cells, and pressure can be solved globally across the whole grid at once. The cost is that fine detail can only be as sharp as the grid is fine, a limitation we will meet head-on later.
A moving fluid of constant density obeys the incompressible Navier–Stokes equations.
The first says how the velocity field
Read the top equation term by term — each term is one thing the fluid does, and Stam's solver handles each with its own dedicated step:
The constraint
Trying to satisfy that whole coupled system in one shot is hard. Stam's move — operator
splitting — is to march through the terms one after another, each a small,
well-understood sub-problem, feeding the output of one into the next. Over a single timestep
After the four stations the velocity field is ready for the next frame, and the smoke density is
advected along that same clean velocity so the smoke rides the flow. Splitting is an approximation —
the terms genuinely interact — but with small enough
Advection is "move the field along the flow", and the naïve way to do it — step each quantity forward along its velocity — is exactly what used to blow up: a big timestep sends stuff flying past several cells and the scheme goes unstable. Stam's inspired reversal is to work backward.
To find the new value at grid cell
Why is this unconditionally stable? Because the new value is an interpolation of
values that already existed in the old field. An average of existing numbers can never be larger
than the largest of them, so no matter how big
After forces, advection and diffusion, the velocity field is generally not divergence-free — those steps don't respect the incompressibility constraint. The projection step fixes that, and its justification is a clean theorem from vector calculus.
The scalar
On the grid this is a big sparse linear system (each cell's pressure couples to its neighbours), solved
iteratively — Gauss–Seidel, Jacobi or a multigrid/conjugate-gradient method. Once
Take a small
Add forces. Warm smoke is buoyant, so apply an upward force
Advect. Move the smoke density along
Project. That upward push has made the velocity field diverge: fluid is streaming out
of the top of the puff cell with nothing filling in from below, so
Grid-based fluids in computational physics predate Stam by decades — but physicists cared about accuracy and were willing to take tiny, carefully-bounded timesteps (the Courant–Friedrichs–Lewy condition: a parcel must not cross more than one cell per step). Animation has the opposite priorities — it wants big timesteps, it wants to never crash mid-render, and it can trade a little physical accuracy for a lot of robustness because the goal is a plausible-looking fluid, not a certified-correct one. Stam's genius was recognising that the graphics community's different value function made the unconditionally-stable semi-Lagrangian scheme — too diffusive for a physicist — exactly the right tool. It is a lovely case of a field's constraints, not just its techniques, driving the breakthrough.
The very interpolation that makes advection stable is also its curse: every backtrace averages
nearby cells, and averaging is smoothing. Step after step, that repeated blurring is
numerical dissipation — it bleeds energy out of the fine-scale motion and rounds off
exactly the small vortices and crisp filaments that make smoke look alive. A raw Stable-Fluids sim
tends to look too smooth, too viscous, as if the air were syrup, even when you set
the viscosity
The fix is to put the lost detail back. Two standard remedies: vorticity confinement (measure where curl is being lost and inject a small force that pushes it back up, re-energising the swirls), and higher-order advection — BFECC and MacCormack schemes, which run the semi-Lagrangian step forward and backward to estimate its own error and cancel most of it, giving far sharper smoke at a modest extra cost while keeping the stability. If your smoke looks like fog, reach for one of these before you reach for a finer grid.