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 1 of 10 · Shader animation

Breathe

The circle breathes. The shadow grows with it.

You already know how to move things with T. Now you will control how they move. Motion is not animating, it is choreographing. Giving intention to time.

0.618, irrational frequency. The loop that never closes.

The first trick: sin(T * 0.618). That 0.618 is the inverse golden ratio, an irrational number. It never aligns with any integer cycle. The result: the animation breathes, but never repeats exactly. Organic, not mechanical.

Irrational frequencyWhen you multiply T by an irrational number (0.618, 0.7071, PI/4), the cycle never closes perfectly. Each loop is slightly different. That is what makes something feel alive.
TryChange 0.618 to 1.0, it feels mechanical. Switch back to 0.618 and notice the difference. Change 0.18 (breath amplitude) to 0.3 for deeper breathing.

The code

void main(){
  vec2 p = (2.*gl_FragCoord.xy - R) / min(R.x, R.y);
  float breath = 0.38 + 0.18 * sin(T * 0.618);
  float d = length(p) - breath;
  float shape = smoothstep(0.02, -0.02, d);
  float shadow = smoothstep(0.0, 0.35, length(p + vec2(.06, -.1)) - breath);
  float glow = exp(-max(d, 0.) * 4.) * 0.5;
  float inner = exp(-length(p) * 2.) * shape;
  vec3 col = vec3(0.03, 0.02, 0.05) * shadow;
  col += vec3(0.95, 0.5, 0.15) * shape;
  col += vec3(1.0, 0.85, 0.5) * inner * 0.3;
  col += vec3(0.9, 0.35, 0.1) * glow;
  col += vec3(.5,.2,.05) * exp(-max(d,0.)*1.5) * .2;
  gl_FragColor = vec4(col, 1.);
}
close