Smoke behaves very differently from fire.
Fire is energetic.
Smoke drifts slowly.
It spreads outward.
It fades into the air.
Instead of sharp movements, smoke relies on soft transitions and gradual changes.
Fortunately, procedural shaders are excellent at producing exactly these kinds of effects.
Smoke is built from a few simple ideas.
Smooth noise.
Slow movement.
Soft edges.
Transparent layers.
Every one of these can be created mathematically.
As always, we'll begin with the UV coordinates.
vec2 uv = vUv;
These coordinates will be animated over time.
Smoke rises slowly.
Instead of moving quickly like fire, we'll use a gentle speed.
uv.y -=
uTime * 0.1;
The movement is much slower.
This immediately changes the feeling of the animation.
Generate a smooth FBM texture.
float smoke =
fbm(
uv * 3.0
);
The result already resembles soft cloudy shapes.
Real smoke curls as it rises.
Add a small distortion.
uv.x +=
fbm(
uv * 2.0
) * 0.15;
The smoke now drifts from side to side.
Small distortions usually look better than large ones.
Smoke is usually denser near its source.
Create a vertical gradient.
float fade =
1.0 -
vUv.y;
The bottom becomes brighter.
The top gradually fades away.
Multiply the smoke by the fade.
smoke *= fade;
Now the smoke naturally disappears into the sky.
Smoke rarely has hard boundaries.
Use smoothstep().
smoke =
smoothstep(
0.2,
0.8,
smoke
);
The edges become much softer.
The overall effect feels more realistic.
#ifdef GL_ES
precision mediump float;
#endif
uniform float uTime;
varying vec2 vUv;
void main(){
vec2 uv = vUv;
uv.y -= uTime * 0.1;
uv.x += fbm(uv * 2.0) * 0.15;
float smoke = fbm(uv * 3.0);
float fade = 1.0 - vUv.y;
smoke *= fade;
smoke = smoothstep(0.2,0.8,smoke);
gl_FragColor = vec4(vec3(smoke),1.0);
}
Even in grayscale, the result resembles drifting smoke.
Smoke doesn't have to be pure gray.
vec3 color = mix(
vec3(0.1,0.1,0.12),
vec3(0.8,0.8,0.85),
smoke
);
Dark gray creates dense smoke.
Light gray represents thinner areas.
Nothing says smoke has to be gray.
Try blue.
vec3(0.2,0.3,0.8)
Or purple.
vec3(0.6,0.3,0.8)
These work well for magical or fantasy effects.
Increase the FBM frequency.
fbm(
uv * 5.0
);
The smoke gains more detail.
Lower the frequency for large soft clouds.
Professional shaders often combine several smoke layers.
Each layer moves at a different speed.
Each has a different scale.
Together they create depth and richness.
Smoke shaders appear in many projects.
Many of these effects differ only in color and movement speed.
Slow the animation.
Speed it up.
Create darker smoke.
Create blue magical smoke.
Layer several FBM patterns.
Add domain warping.
Observe how subtle changes dramatically affect the final result.
Can you create these effects?
All of them begin with the same procedural techniques.
Today we created procedural smoke using animated FBM, coordinate distortion, gradients, and smooth transitions.
Although the shader shares many ideas with the fire shader, slowing the movement and softening the edges completely changes the final appearance.
This demonstrates how flexible procedural graphics can be.