Creative Coding

Shader toys are debugging tools too

5 min read

Shader toys are easy to dismiss because they look playful.

A little fragment shader. A gradient. A field of particles. A signed-distance function. A noise pattern that moves when the mouse moves. None of that looks like serious engineering if you judge it by business output.

I think that misses the useful part.

Small visual programs are debugging tools because they make invisible state visible. They turn math into something you can inspect with your eyes.

pixels are cheap instrumentation

When a value becomes color, a lot of bugs get less abstract.

You can see discontinuities. You can see wrapping errors. You can see coordinate systems flipped. You can see a normalization bug because the whole screen clips to white. You can see a smoothing function because the edge changes shape. You can see time because the pattern drifts.

That feedback is fast.

A shader toy is often a tiny lab:

vec2 uv = fragCoord.xy / iResolution.xy;
float d = length(uv - 0.5);
vec3 color = vec3(smoothstep(0.3, 0.31, d));
fragColor = vec4(color, 1.0);

Change the threshold. Change the coordinate space. Add time. The result moves immediately.

That immediacy is why it works as debugging. The loop is shorter than logging ten intermediate values and trying to imagine the shape.

coordinate bugs become obvious

Graphics programming is full of coordinate mistakes.

Pixel space versus normalized space. Center origin versus top-left origin. Aspect ratio correction. Clip space. Texture coordinates. Device pixel ratio. Matrix order. The math may be correct in one coordinate system and nonsense in another.

A visual program exposes that quickly.

If a circle becomes an ellipse, aspect ratio is wrong. If motion goes the wrong way, an axis is flipped. If a texture swims, coordinates are not stable. If a pattern changes with resolution, normalization is wrong.

That kind of bug is easier to see than to reason about from code alone.

state fields are easier to trust when drawn

This is not limited to pretty graphics.

Any system with a field can benefit from visualization:

  • heat maps
  • distance fields
  • vector fields
  • masks
  • confidence maps
  • simulation grids
  • attention-like weights
  • collision volumes
  • signed distance functions
  • particle velocities

In AI and data systems, I keep coming back to this. Embeddings, attention, classifications, saliency, cluster membership, uncertainty, and time-series drift are all easier to debug when some slice becomes visual.

A shader toy is a low-cost way to practice that habit. What does the state look like? Where does it change? Where is it discontinuous? Where does it saturate?

toys lower the cost of experiments

The word “toy” is useful when it means the stakes are low.

A toy shader can be wrong without wasting a sprint. It can test one idea: noise, interpolation, easing, ray marching, field composition, palette mapping, temporal feedback. If the idea works, bring the intuition back to the real system. If it fails, throw it away.

That is how I like using small visual programs. They are not mini-products. They are sketches.

The sketch can answer questions:

  • what does this easing function feel like?
  • how does this noise combine across octaves?
  • what happens when the field wraps?
  • where does this threshold become unstable?
  • how does precision loss appear visually?

Those are debugging questions with a nicer interface.

webgpu makes the habit more practical

WebGPU makes browser graphics feel closer to serious compute, but the habit does not require a giant stack.

You can learn a lot from fragment shaders, Canvas, WebGL, WebGPU, or even a small Python image script. The important part is the feedback loop: write a tiny program, expose state visually, mutate inputs, and see the bug.

WebGPU matters because it makes more of that work feel native to the browser. Compute passes, buffers, textures, and GPU-side state become things you can experiment with without leaving the page.

That is useful for teaching, debugging, and intuition building.

precision problems have a look

Shader sketches also teach the feel of precision problems.

Banding, flicker, aliasing, z-fighting, unstable edges, and sudden color jumps are all visual symptoms of numerical behavior. Sometimes the fix is more precision. Sometimes it is a different mapping. Sometimes it is smoothing, clamping, dithering, or changing the coordinate space.

Seeing the artifact helps you build a memory for it.

That memory transfers. A ranking score that saturates too early, a classifier threshold that flips near a boundary, or a time-series chart that jitters because of sampling noise all have similar debugging shape. The screen teaches you to ask where the value became unstable.

a tiny debugger can be enough

The useful shader toy does not need a polished UI.

I usually want a few controls:

  • time on or off
  • mouse position
  • one or two numeric sliders
  • a way to freeze a frame
  • a way to display intermediate values as color

That is enough to answer many questions. If a field is wrong, draw the field. If a mask is wrong, draw the mask. If a value is out of range, map it to color and make the bad range loud.

The habit is the tool.

visual debugging changes the question

Logs ask: what value happened?

Visual debugging asks: what shape did the values make?

Both are useful. The shape often reveals the bug faster.

When a system has spatial state, temporal state, probability, thresholds, interpolation, or fields, I want at least one visual handle. Shader toys are a good way to build that instinct.

They are playful, yes. That is part of the point. Play makes it cheap to notice what the math is doing.

Cheap noticing is underrated engineering practice. Make state visible first.

Jeremy London

About Jeremy London

Engineering leader and builder in Denver. I write about AI platforms, agents, security, reliability, homelab infrastructure, and the parts of engineering work that have to survive production.