Clouds & smoke (2D)
Billowing clouds and smoke from fBm noise, bent by a domain warp, cut with a soft threshold and drifted over time.
Cards
One live example to tweak, learn and copy.
How it works
Clouds, smoke, steam and dust share one trait: soft shapes with detail at every size, a big puff made of smaller puffs
made of wisps. That is exactly what fBmA sum of several copies of a noise, each at a higher frequency and a lower strength than the last, so the result has detail at many sizes at once, like clouds, smoke or terrain. Fractal Brownian motion (fBm) A sum of several copies of a noise, each at a higher frequency and a lower strength than the last, so the result has detail at many sizes at once, like clouds, smoke or terrain. Noise A smooth pseudo-random function of position. Random values or gradients sit on a grid and are blended in between, so nearby points get similar values and the result has no visible pattern. Octave One layer of noise in a fractal sum. Each octave usually has twice the frequency and half the amplitude of the one before, adding finer and fainter detail.fbm(p) = Σ gainᵏ · noise(lacunarityᵏ · p)fbm(p) = Σ gainᵏ · noise(lacunarityᵏ · p)
The recipe has four parts:
- Density. An fBm of the coordinate gives a smooth value around 0.5 everywhere, higher where layers happen to agree.
- Shape. A smoothstepA soft threshold. It is 0 below the first edge, 1 above the second, and follows an S-shaped curve with flat ends in between.Fundamental
Smoothstep
A soft threshold. It is 0 below the first edge, 1 above the second, and follows an S-shaped curve with flat ends in between.
t = clamp((x − e0) / (e1 − e0), 0, 1); s = t² (3 − 2t)Sourcesaround a threshold turns the density into coverage: below it is clear sky, above it is cloud, and the width of the smoothstep is how soft the edges are. Lowering the threshold adds clouds; raising it leaves a few scattered puffs.- smoothstep (opens in a new tab)Reference
- Smoothstep (opens in a new tab)Reference
- Motion. Sliding the coordinate with time makes the wind. On its own that looks like a picture being dragged
across the screen, so a domain warpOffsetting the coordinates a pattern reads by another noise, so straight features bend into swirls and folds while the result stays smooth.Fundamental · Noise
Domain warping
Offsetting the coordinates a pattern reads by another noise, so straight features bend into swirls and folds while the result stays smooth.
n = fbm(p + k · vec2(fbm(p), fbm(p + offset)))that moves at a different speed makes the shapes churn and change while they travel. - Color. mixBlends from a to b by a factor t, along a straight line. GLSL calls it mix; HLSL and most node editors call it lerp.Fundamental
Linear interpolation (mix)
Blends from a to b by a factor t, along a straight line. GLSL calls it mix; HLSL and most node editors call it lerp.
mix(a, b, t) = a (1 − t) + b tSourcesthe cloud colors over the background by the coverage, and shade by the density so thick cores look darker than thin, sunlit edges.- mix (opens in a new tab)Reference
- Linear interpolation (opens in a new tab)Reference
The same four parts make smoke in a sprite (a radial mask instead of a sky, rising instead of drifting), fog banks low on the screen, or an aurora with the coverage stretched into bands. What changes between them is the threshold, the direction of motion and the palette, not the noise.
Where it stops
This is a flat picture of clouds: there is no depth, no light passing through and no parallax as the camera moves. For a sky behind a 2D game, a skybox texture or a cheap background it is enough, and at a fraction of the cost of volumetric clouds, which march a ray through a 3D density field and light every sample.
Further reading
- Domain warping (opens in a new tab)Article
- Fractal Brownian Motion (opens in a new tab)Book
- fBM (opens in a new tab)Article
- Fractional Brownian motion (opens in a new tab)Reference
- mix (opens in a new tab)Reference
- clamp (opens in a new tab)Reference
- Linear interpolation (opens in a new tab)Reference
- Uniforms (opens in a new tab)Book
- Window: requestAnimationFrame() method (opens in a new tab)Docs
- The OpenGL ES Shading Language, version 3.00 (opens in a new tab)Docs
- Noise (opens in a new tab)Book
- Value noise (opens in a new tab)Reference
- smoothstep (opens in a new tab)Reference
- NoiseTexture2D (opens in a new tab)Docs
- FastNoiseLite (opens in a new tab)Docs
- CanvasItem shaders (opens in a new tab)Docs
- Shading language (opens in a new tab)Docs