Turbulence without a simulation

Smoke, heat haze, water and dissolving edges all want a flow field. A real fluid solve carries state, has to be stepped in order, and drifts with frame rate, which makes it the wrong shape for a cutscene that has to be seekable. A stack of rotated sines gets surprisingly close and is a pure function of position and time.

The same circle. No warp, one octave, then four. Watch the distance bands as well as the outline.

Rotate between octaves or it is plaid

Adding sine waves along fixed axes produces visible cross-hatching almost immediately, because every octave shares the same two directions and their peaks line up. Rotating the sample axis between octaves breaks that alignment and the result stops reading as a grid.

ang += 2.399963;   // golden angle: no two octaves ever align
f   *= 2.03;       // NOT exactly 2, or harmonics stack at the same places

The frequency multiplier matters for the same reason. Doubling exactly puts every octave's peaks on top of the previous one's, so a slightly irrational ratio buys a lot of apparent randomness for free.

It is a domain warp, so the distance lies

This is the same caveat as the deformers: warping the domain by an amount that varies with position breaks the distance property. Look at the bands in the third panel, where they crowd and stretch. The shape draws correctly because drawing only needs the sign, but glow width and outline thickness will vary with the warp unless you bound it.

The practical bound: the warp's gradient is at most amplitude times frequency summed over the octaves. Divide by one plus that, and the field is conservative again.

Where it beats noise

It is smooth analytically, so you can differentiate it if you need a flow direction. It has no texture fetch, which matters on a tight WebGL budget. And it is trivially seekable, which a ping-pong feedback buffer is not: a buffer that samples its own previous frame cannot be evaluated at an arbitrary time without replaying everything that led there.

Where it loses: it has no advection, so nothing is actually carried along by the flow. Smoke made this way swirls in place rather than traveling. For a background shimmer that is invisible; for a plume it is not.

Rules of thumb

  1. Rotate the sample axis between octaves. The golden angle is a good default.
  2. Use a frequency ratio slightly off 2.0, or the harmonics stack.
  3. Halve the amplitude as you double the frequency, roughly.
  4. Three or four octaves is usually enough. Past that you are paying for detail below a pixel.
  5. It warps the domain, so bound it if anything downstream reads distance rather than sign.

All 61 notes How to use them Credits