Back to presets
2D value noise built from a hash function
Polar coordinate twirl and time-based advection
Layered noise for smoke detail
Smoothstep thresholding for soft density bands

Twirl Smoke volume shader preset

Twirl Smoke shows how a shader can look volumetric without marching through a full 3D density field. It warps 2D coordinates around the center, samples layered value noise, then maps the result into a smoky color ramp.

This preset is useful when you want a visual smoke effect that stays lighter than true 3D ray marching. It still stresses fragment work through noise lookups and coordinate transforms, but it avoids per-pixel depth traversal.

Performance factors

Noise layers

Each extra octave adds repeated hash and interpolation work per pixel.

Coordinate warping

Trigonometric functions in the twirl are more expensive than simple UV transforms.

No ray loop

The preset is usually lighter than real 3D clouds because it does not march along depth.

Editable parameters

Twirl strength

Higher strength changes the visual flow but also leans on trigonometric math.

Noise scale

Higher scale creates tighter details that can alias on small screens.

Smoke threshold

Lower thresholds fill more of the screen and make the effect brighter.

Best fit

  • Fast smoke previews
  • Mobile-friendly visual experiments
  • Comparing 2D shader pressure against true volume presets

Shader preview

#version 300 es
precision highp float;
out vec4 outColor;
in vec2 v_uv;
uniform float u_time; uniform vec2 u_resolution;

float hash(vec2 p){p=fract(p*vec2(123.34,345.45));p+=dot(p,p+34.345);return fract(p.x*p.y);}
float noise(vec2 p){ vec2 i=floor(p); vec2 f=fract(p); f=f*f*(3.0-2.0*f);
  float a=hash(i), b=hash(i+vec2(1,0)), c=hash(i+vec2(0,1)), d=hash(i+vec2(1,1));
  return mix(mix(a,b,f.x), mix(c,d,f.x), f.y);
}

void main(){
  vec2 uv = v_uv;
  vec2 p = (uv*2.0-1.0);
  p.x *= u_resolution.x/u_resolution.y;
  float r = length(p);
  float ang = atan(p.y,p.x) + 0.8*sin(u_time*0.5) + 2.5*r;

Preset FAQ

Is Twirl Smoke a true volume shader?

It is a volumetric-looking fragment shader, but it does not sample a 3D field along a ray.

Why does it run faster than Cloud Layer?

It samples 2D noise a few times instead of running a 3D accumulation loop for every pixel.

External references