All writing
2 min read

Why I still write GLSL by hand

A note on shaders, three.js, and the joy of building the thing on the screen you're looking at right now.

WebGLthree.jsCraft

The hero of this very site is a fragment shader — a few dozen lines of GLSL running on your GPU, painting a flowing gradient that reacts to your cursor.

I could have dropped in a stock library. I wrote it by hand instead. Here's why.

You understand what you build

A shader is just a function that runs once per pixel, in parallel, every frame. Once that clicks, the whole field opens up.

void main() {
  vec2 uv = vUv;
  float n = fbm(uv * 2.2 + uTime * 0.06);
  vec3 color = mix(ink, gold, smoothstep(0.0, 1.0, n));
  gl_FragColor = vec4(color, 1.0);
}

That's the entire idea: sample some noise, map it to color, animate it with time. Everything else is taste.

Noise is the secret ingredient

Organic motion comes from layered simplex noise — fbm, fractional Brownian motion. Stack a few octaves at different frequencies and flat math starts to look like smoke, marble, or aurora.

Performance is a design constraint

A shader hero that drops frames isn't luxurious — it's broken. So I cap the device pixel ratio, keep the noise octaves modest, and respect prefers-reduced-motion. Beauty that costs the user a hot phone isn't beauty.

Writing it by hand means I know exactly where every millisecond goes. That's the whole point.