// VOLCANIC SIMULATION
NAVIER-STOKES ON GPU
The fluid above is not a texture trick or a particle system faking it. It solves the actual Navier-Stokes equations — the same partial differential equations that describe smoke, ocean currents, and atmospheric weather. Every frame runs 9 shader passes across 6 framebuffer objects.
THE INCOMPRESSIBLE NAVIER-STOKES
Two equations govern incompressible fluid flow. The momentum equation: velocity changes due to self-advection, pressure gradients, and external forces. The continuity equation: divergence of velocity is zero, meaning mass is conserved — fluid doesn't compress or expand, it just moves.
The simulation uses Chorin's projection method from 1968. First, advect the velocity field through itself — each texel traces backward through the flow to find where its velocity came from. This is semi-Lagrangian advection: unconditionally stable at any timestep, which is why the simulation never explodes no matter how fast you drag.
After advection, the velocity field has divergence — it's no longer physically valid.
The pressure solve fixes this. Compute the divergence scalar field, then iteratively
solve the Poisson equation laplacian(p) = div(v) using 25 Jacobi iterations per frame.
Subtract the pressure gradient from velocity. Now divergence is zero and the fluid
is incompressible again.
Vorticity confinement is the secret weapon. Numerical dissipation kills small-scale rotation — the beautiful curls and eddies that make fluid look alive. The confinement step computes the curl of velocity, finds its gradient, and injects a force that re-energizes the vortices. Strength parameter: 35. Without it, the simulation goes laminar in seconds.
// 9-PASS SIMULATION PIPELINE
SPLAT INJECTION
Mouse input creates Gaussian splats that inject velocity and dye into the field. Click for radial eruption bursts. Drag for elongated fault-line splats that follow the cursor direction. Scroll wheel controls magma pressure — force multiplier.
CURL COMPUTATION
Finite differences on the velocity field compute the scalar curl (z-component of the 3D curl in 2D). This measures local rotation — how much the fluid spins at each point.
VORTICITY CONFINEMENT
Gradient of |curl| gives the direction toward vortex centers. Cross product with the curl gives a force vector that pushes fluid toward existing vortices, counteracting numerical damping. This is what makes smoke billow instead of smear.
ADVECTION
Semi-Lagrangian backtracking: for each texel, trace backward through the velocity
field by dt * vel, sample the source quantity there. Applied to velocity
(self-advection) and dye (transport). Dissipation factors control decay.
DIVERGENCE
Central differences compute how much velocity is diverging at each cell. Positive divergence = expansion (source), negative = compression (sink). Physical fluids have zero divergence — the pressure solve enforces this.
PRESSURE JACOBI
25 iterations of the Jacobi relaxation method solve laplacian(p) = div(v).
Each iteration averages neighbor pressures minus the divergence term. More
iterations = more accurate pressure field = cleaner incompressibility.
GRADIENT SUBTRACTION
Final projection step: v = v - grad(p). Subtracting the pressure gradient
removes all divergent components from the velocity field. The result is
divergence-free — physically valid incompressible flow.
TEMPERATURE ADVECT
A separate temperature field advects with the velocity and dissipates over time. Hot regions emit blackbody radiation colors. Cooling regions form dark crusty textures with crack glow. The thermal field drives the volcanic aesthetic.
GPU ARCHITECTURE
WebGL2 with half-float render targets (RG16F, R16F, RGBA16F). The simulation runs at 256x resolution — independent of screen size. The dye field renders at 1024x for visual fidelity. This decoupling means the physics stays fast even on 4K displays.
Six double-buffered framebuffer objects store the simulation state: velocity (2-channel), pressure (1-channel), divergence (1-channel), curl (1-channel), dye (4-channel), and temperature (1-channel). Each step reads from one buffer and writes to the other, then swaps. No CPU-side data ever touches the simulation — it lives entirely on the GPU.
The display shader combines three textures: dye for color, velocity for motion glow, temperature for blackbody emission. Blackbody approximation maps temperature 0-1 through dark red, orange, yellow, white — the same progression as heating metal. Cooling regions with residual dye get a dark crust overlay with stochastic crack glow.
The particle overlay is a separate Canvas2D layer — ejecta rocks and sparks launched from eruption points. This follows the composition principle: the GPU handles the fluid, the CPU handles the ballistic particles. Each system does what it's best at. Reinhard tonemapping and gamma correction in the final output.
VOLCANIC CO-AUTHORSHIP
Three interaction modes, each physically distinct. Click triggers a radial eruption — 8 to 16 splats explode outward from the click point, scaled by pressure. This is the volcanic vent: pure thermal energy injected into the field.
Drag creates fault lines — elongated splats that follow your cursor direction, depositing velocity and dye along a tectonic fracture. Scroll wheel adjusts magma pressure from 0.3x to 4.0x, controlling the force multiplier on all injections. At critical pressure, the system produces explosive chain reactions from ambient eruptions.