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 9 of 10 · Shader patterns

Chladni

Geometric vibration. The Chladni plate.

Ernst Chladni put sand on a metal plate and made it vibrate. The sand moved to the quiet spots and formed geometric patterns. Each frequency produces a different pattern.

Two waves multiply. Interference draws itself.

The formula is two sines multiplied: sin(n * p.x) * sin(m * p.y). The numbers n and m are the vibration modes, how many nodes in each direction. When you add two terms with n and m swapped, the classic patterns appear.

n and mWhole numbers that define the pattern identity. 2, 3 = complex circuit. 5, 7 = labyrinth. 8, 8 = symmetric grid. When n and m share no common factors, complexity is maximum.
TryChange 5. and 3. to 8., 8., perfect pattern. To 2., 3., few cells. To 7., 11., maximum complexity. Hint: add + T * 0.5 to both to make it mutate slowly.

The code

void main(){
  vec2 p = (2.*gl_FragCoord.xy - R) / min(R.x, R.y);
  float n = 5., m = 3.;
  float z = sin(n*3.14*p.x)*sin(m*3.14*p.y)
         + sin(m*3.14*p.x)*sin(n*3.14*p.y);
  float zx = sin(n*3.14*(p.x+.015))*sin(m*3.14*p.y)
           + sin(m*3.14*(p.x+.015))*sin(n*3.14*p.y);
  float zy = sin(n*3.14*p.x)*sin(m*3.14*(p.y-.02))
           + sin(m*3.14*p.x)*sin(n*3.14*(p.y-.02));
  float v = abs(z);
  float emboss = ((z-zx)+(z-zy))*.5;
  float hard = step(0.3, v);
  vec3 a = vec3(0.92, 0.9, 0.85);
  vec3 b = vec3(0.06, 0.04, 0.12);
  vec3 col = mix(b, a, hard);
  col += vec3(.2,.18,.12) * clamp(emboss,0.,1.) * hard;
  col -= vec3(.15,.12,.1) * clamp(-emboss,0.,1.);
  col *= .85 + .15 * exp(-length(p)*.4);
  gl_FragColor = vec4(col, 1.);
}
close