Fluid Simulation
Fluid dynamics is, famously, unsolved. The Navier-Stokes existence and smoothness problem is one of the seven Millennium Prize Problems — we can write the equations that describe fluid motion, but we can't prove that solutions to them always behave well. Luckily, visual effects don't need proofs. They need water that looks like water, at a resolution that fits in memory, computed before the deadline. The history of fluid simulation in graphics is a history of principled cheating: taking the real physics and stripping it down to whatever produces a convincing image for the least compute.
The Equations, Simplified
The Navier-Stokes equations describe how fluids move under forces. The output isn't a position but a velocity field — at every point in space, a vector telling the fluid which way to go and how fast. This is the key conceptual shift that confuses people coming from rigid body simulation, where you track positions directly. In fluid sim, you track velocities, and positions follow from advection — particles move through the velocity field over time.1
For visual effects, you can strip the equations down aggressively. Assume the fluid is incompressible (water doesn't compress in any visually meaningful way, even though sound travels through it). Ignore viscosity (it barely matters for water-scale effects). What's left is surprisingly simple: acceleration equals body forces minus the pressure gradient divided by density. Since density is constant for an incompressible fluid, this just says that fluid accelerates toward low-pressure regions and decelerates as it enters high-pressure regions, with gravity pulling it down. The pressure field exists to enforce incompressibility — it's whatever it needs to be to prevent the fluid from gaining or losing volume.1
The hard part isn't the equations themselves. It's the boundary conditions. As Robert Bridson put it in his textbook: "most of the fun in numerically simulating fluids is in getting the boundary conditions correct." Solid walls, free surfaces (the water-air interface), and especially multi-fluid interactions (oil and water) all require special handling. A simulation that conserves mass perfectly but lets water clip through walls isn't useful to anyone.
The Method Wars
Three fundamental approaches have competed for dominance in graphics, and the history of their development reads like an intellectual genealogy of the VFX industry.
Lagrangian (particle) methods track individual fluid particles. Smoothed Particle Hydrodynamics (SPH) solves the Navier-Stokes equations by treating each particle as a kernel that contributes to the fluid properties of its neighbors. SPH is intuitive — you can watch particles pour and splash — and it handles free surfaces naturally because the surface is wherever the particles are. But it struggles with large bodies of water because you need an impractical number of particles, and it can develop artificial clumping artifacts.1
Eulerian (grid) methods fix a regular grid in space and track fluid properties at each grid point. Jos Stam's 1999 "Stable Fluids" paper was foundational here — he showed how to make an unconditionally stable solver using a semi-Lagrangian advection scheme, which traces backward through the velocity field to find where each grid cell's fluid came from. Grid methods handle large-scale fluid beautifully (oceans, flooding) but struggle with fine detail at small scales. Things look "blobby" when you zoom in because the grid can't resolve features smaller than a cell. Grid methods also suffer from numerical diffusion — the advection step smooths out detail, and water can quietly lose mass over time through rounding errors.1
Hybrid methods — the FLIP family — combine both. This is where the most important work happened, and the genealogy is worth knowing. James Harlow's group at Los Alamos invented the Particle-In-Cell (PIC) method in the 1960s for nuclear weapons research. Robert Bridson, a PhD student of Ron Fedkiw at Stanford (who had invented the Particle Level Set method to fix mass loss in grid simulations), went back to Harlow's original work and made FLIP (Fluid Implicit Particles) work for incompressible flows in graphics.1
FLIP works by using particles to carry velocity information but solving the pressure equation on a grid. Each timestep: transfer particle velocities to the grid, solve the pressure projection on the grid, compute the velocity correction, transfer corrections back to particles, and advect the particles through the corrected field. The particles handle transport without diffusion (solving the grid method's mass loss problem), while the grid handles pressure (solving the particle method's incompressibility problem). It's the best of both worlds, and it's what virtually all high-end VFX fluid solvers use today.
Marcus Nordenstam and Robert Bridson commercialized this as Naiad (later acquired by Autodesk), and it was used on Avatar, Pirates of the Caribbean, X-Men: First Class, and dozens of other films. The FLIP solver in Naiad specifically solved a problem that had plagued earlier methods: in Pirates of the Caribbean: On Stranger Tides, a mermaid trapped in a glass box was losing water volume over time in early tests due to numerical mass loss. FLIP's particle-based transport eliminated this almost entirely.1
Real-Time Approximations
Production VFX sims can run for hours or days per frame. Real-time applications — games, interactive visualizations — need different approaches entirely. The GPU chapters on fluid dynamics show two main strategies.1
The simpler one is to solve a 2D or simplified 3D version of the Navier-Stokes equations on a grid using the GPU's parallel architecture. Each grid cell maps to a thread, and the pressure solve (which is the expensive part) uses iterative methods like Jacobi relaxation that parallelize naturally. This gives you swirling, fluid-like behavior that responds to interaction in real time, at the cost of being unable to represent free surfaces or splashing.
The more exotic approach is the lattice Boltzmann method (LBM), which simulates fluids not by solving Navier-Stokes directly but by tracking particle distribution functions on a grid — essentially modeling the statistical mechanics of imaginary gas molecules. Streaming and collision steps at each tick produce fluid-like behavior that emerges from simple local rules, much like how cellular automata produce complex behavior from simple update rules. Eben Packwood implemented a complete LBM simulation in under 1,024 bytes of JavaScript for JS1K — a real, publishable simulation technique compressed into demoscene constraints.2
Despite both being called "particle-based," SPH and LBM are fundamentally different. SPH tracks real particles moving through continuous space — each one carries physical properties (mass, velocity, density) and interacts with neighbors through smoothing kernels. LBM tracks distribution functions of fictitious particles on a fixed grid — the particles don't move freely but stream between grid nodes in discrete velocity directions. SPH solves Navier-Stokes by interpolating properties over moving particles; LBM recovers Navier-Stokes as an emergent macroscopic behavior from microscopic streaming and collision rules.3 The practical consequence: SPH handles free surfaces and spray naturally (particles are where the fluid is) but struggles with incompressibility; LBM parallelizes beautifully on GPUs (all operations are local to grid nodes) but needs special boundary handling for moving surfaces. For real-time applications, this tradeoff often decides the method — LBM for smoke and fire (no free surface needed), SPH for splashing water.
What's Hard and What's Not
I think the interesting thing about fluid simulation in graphics is how it reveals the difference between physical accuracy and visual plausibility. Nobody in VFX is solving Navier-Stokes faithfully. They're ignoring viscosity, assuming incompressibility, using operator-split solvers that introduce artificial dissipation, and running at resolutions that would make a CFD engineer cry. But the results look right because the human visual system is exquisitely tuned to notice certain fluid phenomena (the curl of a breaking wave, the splash pattern of a droplet) and almost completely blind to others (exact velocity field divergence, pressure solver residuals).
The hardest visual problems in fluid simulation aren't the ones that are hardest physically. Thin sheets of water, foam, spray, and the transition between bulk fluid and individual droplets are all phenomenologically simple but representationally hard — they exist at scales below the simulation grid, so they need separate models bolted onto the main solver. A pouring shot that generates a thin sheet of water which breaks into droplets that create ripples on a surface involves at least three different simulation regimes stitched together. Getting the transitions right is the art.
The boundary between fluid simulation and emergence is also blurry in interesting ways. Some of the most visually striking fluid phenomena — Kelvin-Helmholtz instabilities at the interface between fluids moving at different speeds, Rayleigh-Taylor instabilities where dense fluid sits on top of light fluid — are emergent behaviors that the simulation produces naturally if the resolution is high enough. You don't program turbulence; you just simulate at a fine enough scale and turbulence appears. This is why increasing resolution in a fluid sim doesn't just make the image sharper — it qualitatively changes what phenomena are visible, revealing structure that was smoothed away at coarser scales.
GPU Fluid Solvers: From Textbook to Trick Shot
The GPU Gems chapters on fluid simulation are a matched pair that, read together, trace the evolution from textbook implementation to production technique. Mark Harris's 2D solver starts from first principles: store velocity and pressure in textures, discretize the Navier-Stokes equations as finite differences, solve each term — advection, diffusion, pressure, external forces — as a separate full-screen shader pass. The pressure solve uses Jacobi iteration (sample six neighbors, compute the average, repeat), which is slow to converge but parallelizes trivially. The key insight is the Helmholtz-Hodge decomposition: any velocity field can be split into a divergence-free part and a pressure gradient. Subtract the gradient of the solved pressure field from the intermediate velocity and you enforce incompressibility in one shot.4
Keenan Crane and colleagues at NVIDIA extended this to 3D for real-time smoke, water, and fire in the GeForce 8 demo "Smoke in a Box." Their solver uses 3D textures instead of 2D, renders slice by slice via the geometry shader's SV_RenderTargetArrayIndex semantic, and addresses the numerical diffusion problem with a MacCormack advection scheme — two semi-Lagrangian steps (one forward, one backward in time) combined with a limiter that clamps the result to the range of contributing source values. The limiter is critical: MacCormack without clamping is unstable, but with it the scheme preserves far more detail than basic semi-Lagrangian advection at minimal extra cost. Their observation that higher-order advection is usually cheaper than increasing grid resolution — because math is cheap relative to bandwidth — is a principle that generalizes well beyond fluid simulation.5
Code Golf as Physics
There's a genre of fluid simulation that treats the Navier-Stokes equations not as a system to solve but as a creative constraint to compress. David Roberts's one-tweet fluid simulator (270 bytes of GLSL) implements a complete 2D fluid with surface tension, splashing, and conservation of momentum. The method is a simplified variant of reintegration tracking: each cell stores mass and velocity, moves its particle according to velocity, then splatters the result across neighbors weighted by a Gaussian kernel. Forces come from smoothed-particle hydrodynamics — wherever density exceeds a reference value, particles push outward; where it falls below, they pull inward. The entire update loop is a single nested for-loop over a 14x14 neighborhood.6
The business card version wraps this in self-contained WebGL2 boilerplate, fitting the entire application — HTML, JavaScript, shader code — into a data URL you can paste into a browser address bar. The tricks are instructive: method hashing abbreviates verbose WebGL API names by splitting camelCase into words and keeping two characters each (texImage2D becomes teIm2D), the vertex shader generates a screen-covering triangle without a vertex buffer, and ping-ponging between two framebuffers provides the temporal state. It's the demoscene ethos applied to computational physics — prove that a complex phenomenon fits in a space everyone assumed was too small.7
Roberts's earth simulation pushes the same sensibility to planetary scale: procedural craters, tectonic plates, hydraulic erosion, global climate, and biome evolution, all running in GLSL fragment shaders at 60fps. The tectonic model moves plates at discrete pixel-scale intervals with randomized timing to maintain average velocities. Collisions cause subduction (local elevation increase), which thermal erosion then spreads. Hydraulic erosion follows Barnes's single-pixel-wide river model — each cell routes water to its steepest downhill neighbor, with erosion following a stream power law. The climate simulation derives wind from MSLP (mean sea-level pressure) gradients with Coriolis correction, advects moisture from ocean to land, and produces precipitation patterns that, remarkably, reproduce phenomena like the Indian monsoon reversal.8
Footnotes
-
The science of fluid sims by fxguide — source ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7
-
Computational Fluid Dynamics in Under 1K by Eben Packwood — source ↩
-
Chapter 38: Fast Fluid Dynamics Simulation on the GPU by Mark J. Harris — source ↩
-
Chapter 30: Real-Time Simulation and Rendering of 3D Fluids by Keenan Crane, Ignacio Llamas, Sarah Tariq — source ↩
Linked from
- Analog Computing
So does a lot of fluid simulation and computational biology.
- Graphics And Rendering Overview
Fluid Simulation connects through lattice Boltzmann methods compressed to 1KB of JavaScript.
- Volumetric Rendering
The Fluid Simulation article covers the dynamics side — how to generate the density fields themselves.