Look at the sky on a clear day.
Clouds rarely have sharp edges.
They slowly grow, merge together, drift across the horizon, and disappear.
If you look closely, you'll notice large cloud formations filled with smaller details.
This layered appearance makes clouds a perfect use case for procedural noise.
Most cloud shaders use four simple ideas.
Layered noise.
Soft edges.
Slow animation.
A smooth color gradient.
We've already learned every one of these techniques.
Now we'll combine them into a complete material.
Begin with the screen coordinates.
vec2 uv = vUv;
These coordinates represent our sky.
Clouds drift slowly with the wind.
Move the coordinates horizontally.
uv.x +=
uTime * 0.03;
The movement is intentionally subtle.
Fast movement makes clouds look unnatural.
Generate layered FBM.
float cloud =
fbm(
uv * 3.0
);
The large soft blobs already resemble distant clouds.
Clouds contain both large and small features.
Increase the number of layers inside the FBM function or increase its frequency.
float detail =
fbm(
uv * 6.0
);
Mix the detail into the base pattern.
cloud +=
detail * 0.3;
The clouds become richer without becoming noisy.
Real clouds fade gradually.
Use smoothstep().
cloud =
smoothstep(
0.4,
0.7,
cloud
);
The harsh edges disappear.
The result becomes soft and fluffy.
Choose two shades of blue.
vec3 sky = mix(
vec3(0.25,0.45,0.85),
vec3(0.75,0.90,1.0),
vUv.y
);
The horizon becomes darker while the upper sky appears brighter.
Blend white into the sky.
vec3 color =
mix(
sky,
vec3(1.0),
cloud
);
The clouds now appear naturally against the background.
#ifdef GL_ES
precision mediump float;
#endif
uniform float uTime;
varying vec2 vUv;
void main(){
vec2 uv = vUv;
uv.x += uTime * 0.03;
float cloud = fbm(uv * 3.0);
cloud += fbm(uv * 6.0) * 0.3;
cloud = smoothstep(0.4,0.7,cloud);
vec3 sky = mix(
vec3(0.25,0.45,0.85),
vec3(0.75,0.90,1.0),
vUv.y
);
vec3 color = mix(
sky,
vec3(1.0),
cloud
);
gl_FragColor = vec4(color,1.0);
}
Even with relatively little code, the shader already resembles a bright daytime sky.
Reduce the sky brightness.
vec3(0.15,0.20,0.35)
Replace the white clouds with gray.
vec3(0.75)
The atmosphere immediately feels heavier.
Replace the cloud color.
vec3(
1.0,
0.75,
0.55
);
The clouds now appear warm as though illuminated by the setting sun.
Increase the animation speed.
uTime * 0.08
For peaceful skies, smaller values usually look more convincing.
Cloud shaders appear in countless projects.
Open world games.
Animated skies.
Weather systems.
Flight simulators.
Motion graphics.
Fantasy environments.
Space scenes.
Background animations.
User interfaces.
Digital artwork.
Most of them begin with layered FBM.
Create a clear sky.
Create storm clouds.
Create sunset clouds.
Increase the cloud detail.
Slow the animation.
Speed it up.
Add a second cloud layer moving in another direction.
Observe how these small changes create completely different weather conditions.
Can you create these skies?
A bright summer afternoon.
Heavy rain clouds.
A colorful sunset.
A magical fantasy sky.
Thin wispy clouds.
All of them begin with the same procedural building blocks.
Today we created our first procedural cloud shader.
By combining layered FBM, smooth transitions, slow animation, and a sky gradient, we generated a convincing sky entirely from mathematics.
This is one of the most practical procedural effects you'll encounter in shader programming.