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 10 of 10 · Domain warping

Your Pattern

Each point rules what is closest. Wars happen at the borders.

The Domain Warp finale is animated Voronoi: you split space into cells, each cell belongs to the closest seed point. Borders appear where two seeds compete.

The loop walks the 9 neighbor cells, measures the distance to each seed, which moves with sin(T*0.3), and keeps the two closest, d1 and d2. The difference d2 - d1 is the distance to the border. Where it is small, the border glows.

Before Voronoi, space passes through a domain warp with T. Cells are not square, they float, twist, feel organic.

Animated Voronoi with warp. Every technique you learned lives here.

d1, d2 and the borderd1 is the distance to the closest seed. d2 to the second closest. d2 - d1 is the distance to the border between them. exp(-(d2-d1)*15.) lights that border with a warm glow.
TryChange 5.0 in uv (zoom) to 2.0 for huge cells. To 10.0 for tiny ones. Change 15. in exp(-edge*15.) to 40. for knife-thin borders. To 5. for fat, soft borders. Change the colors above for your signature. Sign it.

The code

void main(){
  vec2 uv = gl_FragCoord.xy / R * 5.0;
  float warp = fb(uv * 0.4 + T * 0.03) * 0.8;
  vec2 p = uv + warp;
  vec2 g = floor(p);
  float d1 = 10., d2 = 10.;
  float cid = 0.;
  for(int y=-1;y<=1;y++){
    for(int x=-1;x<=1;x++){
      vec2 nb = vec2(float(x),float(y));
      vec2 cp = g + nb;
      vec2 seed = vec2(h2(cp), h2(cp+99.));
      seed = 0.5+0.4*sin(T*0.3+6.2831*seed);
      float d = length(nb+seed-fract(p));
      if(d<d1){d2=d1;d1=d;cid=h2(cp+50.);}
      else if(d<d2){d2=d;}
    }
  }
  float edge = d2-d1;
  float border = exp(-edge*15.);
  vec3 col = vec3(0.02, 0.01, 0.03);
  col += mix(vec3(0.15,0.04,0.08), vec3(0.08,0.03,0.15), cid) * smoothstep(0.4,0.0,d1);
  col += vec3(0.9,0.7,0.2) * border * 0.7;
  col += vec3(1.,0.9,0.5) * pow(border,4.) * 0.4;
  col += vec3(0.4,0.15,0.05) * exp(-d1*3.) * 0.3;
  col *= 1.0 - length(gl_FragCoord.xy/R-0.5)*0.6;
  col = hueShift(col, 0.0);
  gl_FragColor = vec4(col, 1.0);
}
close