An emitter, a pool, and a lot of dead particles
Every particle system starts from the same skeleton. An emitter spawns new particles at some rate from a source shape — a point, a cone, a disc. Each particle gets a position, a velocity, a lifetime and a random seed, and is pushed into a fixed-size pool. Every frame the whole pool is updated: age each particle, integrate its motion, and if its age exceeds its lifetime, mark it dead and let the emitter recycle the slot. Nothing here is unique to VFX — it is exactly the fixed-array update loop used by any particle simulation on this site — the difference between a boring grey dust cloud and a believable fire is entirely in the per-particle rules layered on top.
Lifetime curves: the secret of a convincing flame
A real flame is bright yellow-white at its base, thins to orange, and dissipates as translucent smoke. A particle fakes this with curves over normalised lifetime — functions of t = age / lifetime, from 0 (birth) to 1 (death) — driving colour, size and opacity independently:
t = age / lifetime // 0 at birth, 1 at death color = gradient(t) // white -> yellow -> orange -> dark red -> smoke grey size = lerp(startSize, endSize, t) * (1 + wobble(t)) alpha = fadeInOut(t) // ramps up fast, fades out slowly near t=1
Sparks use the same machinery with a much shorter lifetime and a colour curve that stays near white-hot until it snaps almost instantly to black, because incandescent metal cools and stops emitting visible light quickly. Fire uses a longer lifetime, more randomised initial upward velocity, and size that grows over its life to suggest expanding hot gas, whereas sparks shrink and disappear.
Additive blending: why fire looks like it is glowing
Normal transparency mixes a particle's colour with what is behind it. Additive blending instead sums the colour values directly onto the frame buffer: result = background + particleColor * alpha, with no subtraction. Where many bright particles overlap, their colours keep stacking until the pixel clips to pure white, which is exactly how overlapping incandescent light sources behave in reality. It is the reason a cluster of overlapping embers reads as one bright glow instead of a stack of visible translucent discs — and why using it for smoke looks wrong, since smoke absorbs light rather than emitting it and needs ordinary alpha blending instead.
Curl noise: turbulence without solving fluid dynamics
Real fire and smoke are governed by the Navier-Stokes equations, which are too expensive to solve per-particle at 60 frames per second for a game or a real-time preview. The standard shortcut is curl noise: take a 3D Perlin noise field and compute its curl (∇ × field) to get a new vector field that is divergence-free by construction — meaning it has no sources or sinks, so particles advected through it swirl and eddy without ever bunching into an unnatural clump or thinning into a hole. Each particle simply samples the curl field at its position each frame and adds a scaled version to its velocity, producing turbulent, swirling motion that looks convincingly fluid-like for a fraction of the cost of an actual fluid solver.
velocity += gravity * dt velocity += curlNoise(position, time) * turbulenceStrength * dt velocity *= (1 - drag * dt) position += velocity * dt
Sorting, depth and the GPU shortcut
Transparent particles must be drawn back-to-front to composite correctly, which means sorting the whole pool by camera distance every frame — an O(n log n) cost that becomes real for tens of thousands of particles. Additively blended effects like fire and sparks get a free pass here: because addition is commutative, draw order does not change the final colour, so games skip sorting entirely for additive emitters and only pay the cost for alpha-blended smoke and dust. Modern engines push the whole simulation loop onto the GPU as a compute shader, updating hundreds of thousands of particles in parallel — the CPU only issues the draw call and never touches individual particle data.
Frequently asked questions
Are game and film particles simulated with real physics?
Rarely fully. Most particle VFX use simplified kinematics — gravity, drag, a curl-noise turbulence field — rather than solving the Navier-Stokes equations that govern real fire and smoke. Full computational fluid dynamics is reserved for hero shots in film where render time is not constrained; games almost always use the cheap approximation because it has to run at 60 frames per second alongside everything else on screen.
Why does additive blending make fire and sparks look bright and glowing?
Additive blending adds each particle's colour directly to the pixel already on screen instead of mixing between them, so overlapping particles keep stacking brightness until they clip to pure white. That mimics how real incandescent light behaves — many overlapping photon sources really do add up — which is why it looks convincing for fire, sparks and energy effects but wrong for smoke or dust, which absorb light and need standard alpha blending instead.
What is curl noise and why is it used for turbulence instead of ordinary noise?
Curl noise takes the curl of a Perlin noise field to produce a vector field that is divergence-free by construction, meaning it has no sources or sinks — particles swirl and never bunch up or spread out unnaturally. Advecting particles along raw Perlin noise gradients instead can make them pile into clumps or thin patches, which looks obviously wrong for smoke and fire that should conserve volume as they curl and drift.
Try it live
Everything above runs in your browser — open Particle VFX and change the parameters while it is running. Nothing is installed, nothing is uploaded, the whole model lives in one tab.
▶ Open Particle VFX simulation