Smoke Fluid SimulatorBeta

Drag to stir colorful smoke in a real-time stable-fluids simulation

This tool is a beta version still being stabilized. Please let us know if a result looks off.

Loading the fluid engine (WebAssembly)…

Drag across the canvas to push the fluid in that direction while spraying colored smoke. Every frame, Jos Stam's Stable Fluids method diffuses (viscosity) and advects the velocity field, then solves for pressure and projects it to be divergence-free, so swirls form naturally. The smoke you spray is hot, so buoyancy lifts it and it slows as it cools. Swirl boost (vorticity confinement) puts back the small eddies the grid smears out, so the edges of the smoke curl. Raise viscosity for a honey-like feel; set the fade rate to 0 and the smoke never disappears.

About Smoke Fluid Simulator

This tool follows the Stable Fluids method Jos Stam presented at SIGGRAPH 1999. A square grid (64², 128² or 192²) stores a velocity field and three dye concentrations, red, green and blue. Every frame the velocity goes through diffuse (viscosity), project, advect, project; the dye goes through diffuse, advect and fade. Dragging adds a Gaussian blob of velocity and dye under the pointer.

To make it behave like smoke, the tool now carries a temperature and a buoyancy force. The smoke you spray is hot, so it is pushed upward; the heat is carried along with the flow and cools by roughly 45% a second, so the lift fades (the approach of Fedkiw et al., 2001). The coloured dye itself is only a tracer and never pushes on the flow. Set the buoyancy slider to 0 and the smoke no longer billows upward; only the motion you put in spreads and dies away. All four edges are closed walls.

What “stable” refers to

Earlier explicit schemes blew up as soon as the fluid moved more than about one cell in a frame. Stam removed that limit in two ways. Advection is done semi-Lagrangian style: for each cell, trace backwards along the velocity to find where its contents were one step ago, and interpolate the value there. An interpolated value always lies between its neighbours, so no new extremes can appear. Viscous diffusion is solved implicitly, so even a large coefficient cannot make it diverge.

The price is accuracy. Every interpolation smears small swirls a little, which acts like extra viscosity. That is why eddies fade even with the viscosity slider at zero. Drop the grid to 64² and they die faster; raise it to 192² and fine filaments survive longer. In 2001 Fedkiw, Stam and Jensen added a vorticity confinement term to put that lost spin back. This tool includes it as the Swirl boost slider: raise it and the edges of the smoke curl into fine eddies; push it too far and the flow turns jittery.

Projection, or why vortices appear by themselves

Water and slow air are nearly incompressible: what flows into a cell must flow out (zero divergence). The projection step treats any divergence in the velocity field as a pressure and subtracts its gradient. That means solving a Poisson equation, done here with over-relaxed (SOR, ω = 1.8) Gauss–Seidel sweeps. Bigger grids converge more slowly, so the sweep count grows with resolution (20 at 64² and 128², 30 at 192²).

Draw one short, straight stroke and you can see the effect. Fluid pushed forward has nowhere to go and steps aside; the space left behind is filled from the sides. The result is a pair of counter-rotating vortices at the end of the stroke. Nobody drew them: the single rule of conserving volume produces them. The sweep count is fixed, so the divergence is not driven exactly to zero, but the leftover at 192² dropped from about 17% of the velocity gradient with the old 20 plain Gauss–Seidel sweeps to about 2%.

What the sliders actually set

  • Viscosity: slider × 10⁻⁴ becomes the kinematic viscosity, with the domain width as 1. At the maximum of 10 that is 10⁻³. On a 128² grid at 1/60 s per frame, the diffusion coefficient a = dt·ν·N² ≈ 0.27, enough to smear a stroke within seconds, like honey.
  • Smoke spread: diffuses only the dye (slider × 10⁻⁵). The motion is unchanged; colour edges just blur.
  • Fade rate k: each frame multiplies the dye by e^(−k·dt). The default 0.3 gives a half-life of ln2 / 0.3 ≈ 2.3 s; at 3 it is 0.23 s. At 0 the dye only changes through numerical error.

Why games and films adopted it

Stable Fluids is not the most accurate way to solve the equations; it is the way that never blows up, whatever the time step. For real-time graphics, where a frame must finish on schedule, that property matters more than accuracy. Stam published a compact C version at the 2003 Game Developers Conference (Real-Time Fluid Dynamics for Games), and it became the starting point for countless web demos and game effects. Engineering CFD codes make the opposite trade: small time steps and higher-order advection to keep errors down.

Worked examples

How long the smoke lasts

Input
Fade rate 0.3 per second, initial concentration 1
Output
0.5 after 2.3 s, about 0.05 after 10 s

e^(−0.3×10) = e^(−3) ≈ 0.050. The display uses a 1 − e^(−x) tone curve, so halving the concentration dims the pixel by less than half.

Viscosity at maximum

Input
ν = 10⁻³, 128² grid, dt = 1/60 s
Output
Per-frame diffusion coefficient a ≈ 0.27

a = (1/60) × 10⁻³ × 128² = 0.273. A swirl 10 cells wide (about 8% of the box) spreads out on a time scale L²/ν ≈ 0.078² / 10⁻³ ≈ 6 s.

Resolution comparison

Input
The same stroke on 64² and on 192²
Output
On 64² the vortices vanish after a turn or two; on 192² thin bands wind up several times

Numerical viscosity from semi-Lagrangian interpolation scales with cell size. Three times as many cells means cells a third the size.

How to use it

  1. Make one quick, short stroke and watch the vortex pair form at its end.
  2. Change viscosity and resolution and compare how long the same stroke survives.
  3. Set the fade rate to 0, mix several colours and watch the boundaries roll up.

Frequently asked questions

Why does the smoke rise?

The sprayed smoke is given a temperature, and an upward force proportional to it (buoyancy) is added to the velocity. As the smoke cools it lifts less, so it rises for a while and then spreads. With the buoyancy slider at 0 the dye is just a coloured tracer and does not rise.

Why do swirls stop even with zero viscosity?

Semi-Lagrangian advection averages neighbouring values every time it interpolates, which wears away small structures like a viscosity would. A finer grid reduces it.

Can I use this for real engineering?

The qualitative behaviour is right (projection creating vortex pairs, the effect of viscosity), but numerical dissipation and the limited number of pressure iterations make it unsuitable for quantitative prediction. Stam proposed the method for animation.

How is this different from lattice Boltzmann?

Stable Fluids solves the Navier–Stokes equations for velocity and pressure directly. Lattice Boltzmann, used in this site's Kármán vortex and 3D wind tunnels, simulates collisions and streaming of particle distributions whose averages behave like a fluid.

Related guides

Sources

Last reviewed:

Privacy and how data is handled