learn GLSL from zero
ToolsCreate with shadersShader MakerFree online shader builderToolkitShader works ready for your siteSketcher LabPaint your landing’s hero with shaders3D StudioThe Three.js editor in your browser
GamesPlay with shadersOnomatoShaderType a word, blow it upThe WatcherAn eye that follows youAetherLiquid glass with an eye insideBloomcoreA word grows a garden of lightPyrokineThrow fire at the wallVoltaicThe pyramid throws lightningSurfSurf a shader ocean

Lesson 7 of 10 · Forces in a shader

Turbulence

Three frequencies. The squares never settle.

A single force feels mechanical. Three forces at different frequencies feel fluid, because they never align. Movement never repeats exactly.

Flag on a windy day.

Three sin() stackedsin(T*0.3) + sin(T*0.17) + sin(T*0.07). Frequencies are irrational to each other. Cycle before repeating is over an hour. That is real turbulence.
TryChange .35 (main amplitude) to 0.1, subtle turbulence. To 0.8, total chaos. Change T*.3 to T*.1, slow everything, contemplative. To T*1., frenetic.

The code

void main(){
  vec2 p = (2.*gl_FragCoord.xy - R) / min(R.x, R.y);
  vec3 col = vec3(0.05, 0.02, 0.1);
  for(int i = 0; i < 5; i++){
    float fi = float(i);
    float ox = sin(T*.3+fi)*.35+sin(T*.17+fi*2.)*.18+sin(T*.07+fi*3.)*.12;
    float oy = sin(T*.23+fi)*.3+sin(T*.13+fi*2.5)*.15;
    vec2 c = vec2(-0.6+fi*.3+ox, oy);
    float rot = ox*.5;
    float ca=cos(rot),sa=sin(rot);
    vec2 rp = p-c; rp = vec2(rp.x*ca-rp.y*sa,rp.x*sa+rp.y*ca);
    float sz = 0.1+fi*.02;
    vec2 q = abs(rp)-vec2(sz);
    float d = max(q.x,q.y);
    vec2 rs = rp+vec2(.04,-.05);
    col *= smoothstep(-.02,.12,max(abs(rs.x)-sz,abs(rs.y)-sz));
    col += vec3(.92-fi*.15,.35+fi*.12,.08+fi*.15) * smoothstep(.01,-.01,d) * (.6+fi*.1);
    col += vec3(.45-fi*.07,.18+fi*.06,.04+fi*.08) * exp(-max(d,0.)*5.) * .2;
  }
  gl_FragColor = vec4(col, 1.);
}
close