Advanced shaders · lesson 6 of 19 · Advanced · about 5 min
Clouds 2: marching through the volume
You will build: Fly the camera forward through a cloud layer. Walk each ray in 44 steps, track how much light is blocked, and blend white cloud over the sky.
To see a volume we cannot look for one surface. A ray has to walk through it and add up how much cloud it meets along the way.
Light follows the Beer-Lambert law: after passing through some cloud with density d over a short step, the fraction of light that still gets through is exp(-d * k). Keep a running number T (the transmittance): start at 1 (nothing blocks the view) and multiply it by that factor at every step. When T is near 0 the view is blocked: you are looking at the cloud.
We make density a function of position, dens(p), from the noise, restricted to a horizontal layer so clouds do not fill the whole world (band fades the density in and out between two heights).
Put the camera inside the layer and move it forward with time: you fly through the cloud!
float T = 1.0; // how much of the view is still clear
float t = 0.1;
for (int i = 0; i < 44; i++)
{
float d = dens(ro + rd * t);
float a = 1.0 - exp(-d * 0.4); // how much this step blocks
T *= 1.0 - a;
t += 0.32;
}
float3 col = lerp(white, sky, T);
This version is a flat white cloud, with no light and shadow yet. That is the next lesson.
The numbers you need
Everything the picture depends on is given, so the challenge is the code, not guessing.
- Density
dens(p) = saturate((fbm3(p * 0.5) - 0.42) * 3.5) * band, band = smoothstep(-2.0, -1.0, p.y) * (1.0 - smoothstep(1.0, 2.0, p.y))- Camera
ro = float3(0.0, 0.0, time * 1.1), rd = normalize(float3(p.x, p.y + 0.15, 1.4)), p = (uv - 0.5) * float2(aspect, 1.0) * 2.0- Sky
lerp(float3(0.62, 0.78, 0.95), float3(0.25, 0.48, 0.85), saturate(rd.y * 1.5 + 0.2))- March
T = 1.0; t = 0.1; 44 steps: d = dens(ro + rd * t); a = 1.0 - exp(-d * 0.4); T *= 1.0 - a; t += 0.32- Color
lerp(float3(1.0, 1.0, 1.0), sky, T)
Try it in your own language
The lesson is written once and shown in every language. Pick yours: Unity (Built-in), Unity (URP), Unreal, Shadertoy / WebGL, OpenGL (LWJGL, raylib), three.js, GameMaker, LÖVE (Lua), Godot, Apple (iOS, macOS), WebGPU / Bevy.
Start codingGo deeper
Part of the learning path: Realistic water and sky.