GLSL debugging and live recovery: gotchas, error reading, and the panic shader
Learning objectives
- learner can port a Shadertoy shader to glslViewer by replacing all incompatible uniform names and the entry-point signature
- learner can identify and fix GLSL type-system and syntax errors — int/float mixing, integer division truncation, wrong vector constructor arity, undeclared uniforms, uniform-bounded loops on ES 1.00, mismatched #version syntax, and missing main()/gl_FragColor — from the compiler's error line before a set
- learner can diagnose a black, blown-out, or visually-degraded frame by tracing the likely cause (NaN from undefined math, clamped channel, unbounded/mediump time precision loss, feedback gain ≥ 1, an unfilled feedback buffer, or step-edge aliasing) and apply the targeted fix (smoothstep+fwidth, highp/bounded time, #ifdef guard, or gain < 1)
- learner can recover from any GLSL compile or runtime failure mid-set using the error-line/bisect procedure and the canonical panic shader
Capstone — one whole task that evidences the objectives
Port and repair a deliberately broken glslViewer shader, then recover from it live. The shader ships with every fault class seeded at once: Shadertoy uniforms and entry-point (iTime/iResolution/iMouse/mainImage) that must be replaced with rig names and a u_mouse pixel-to-0..1 normalization; a missing precision block plus mediump banding in large u_time / fine gradients; the full strict-typing set — an int/float mixed expression, an integer-division truncation, a wrong-arity vector constructor, an undeclared uniform, a for-loop bounded by a uniform on ES 1.00, mixed #version syntax, and an absent void main()/gl_FragColor; a hard step() edge that aliases; and the runtime failures — a NaN-producing pow()/normalize call that renders black, a feedback pass whose render code lacks its #ifdef guard so the buffer never fills, and a feedback gain ≥ 1 that blows to white. Diagnose and fix each fault reading only the compiler error line (bisecting to a known-good body when the message is ambiguous) and the visual frame — relying on the fact that glslViewer keeps the last good frame while you work — replacing the step edge with smoothstep+fwidth and bounding u_time so precision holds over a long set. Confirm the rig has no audio bridge, so all motion is driven by u_time, then swap in the canonical cosine-palette panic shader from memory in under thirty seconds: it must compile cleanly, define main()/gl_FragColor, output a clamped colour, and loop correctly over unbounded u_time.
Prerequisite modules
Live visual coding with glslViewer in this rig means one thing above all else: you are one bad save away from a compile error, and the audience sees the last good frame while you race to fix it. That safety net is the first thing to internalise — glslViewer never swaps in a broken shader — and the second thing is the repair workflow: read the line number, fix the named token, and bisect if the message is unclear. This module builds the reflex for both halves: the preventive knowledge that keeps you from landing in trouble, and the recovery procedures that get you out when you do.
The preventive layer covers two clusters of failure. The first is the rig-incompatibility cluster: Shadertoy shaders look runnable but every uniform name is wrong (iTime → u_time, iResolution → u_resolution, iMouse → u_mouse, mainImage → main() writing gl_FragColor), the mouse uniform is in pixels rather than 0..1, and the rig has no audio bridge — a.fft simply does not exist, so any reactivity must come from u_time. The second is the GLSL type-system cluster: the compiler is strict in ways JavaScript is not — every float literal needs a decimal point, integers cannot appear in float expressions without a cast, integer division silently truncates, vector constructors require the exact right number of components, uniforms must be declared before use, every shader must assign gl_FragColor from a void main(), and #version syntax must be internally consistent.
The runtime failure layer is about pixels that compile but look wrong: NaN from pow(negative, x), 1.0/0.0, or normalize(vec3(0)) spreads black clusters; feedback buffers without their #ifdef guard never fill; gain ≥ 1 in a double-buffer loop saturates to white within frames; unbounded u_time in float32 loses precision over minutes, creating jitter in periodic animations; and hard step() edges alias while smoothstep with fwidth is the per-pixel-correct alternative.
The arc runs from gotcha inventory to drill to live repair. Work through each failure category on a scaffold shader: first introduce and fix the Shadertoy porting errors on a known-good template, then mutate the type system one error at a time and read the compiler messages, then exercise the runtime failures (feedback, NaN, precision) and read the frame. The L5 atoms arrive in the second half: practice the error-line/bisect procedure on an ambiguous message, then memorise and type the panic shader from scratch — not copy-paste, from memory — until it takes under thirty seconds. The capstone is a gauntlet that presents all five fault classes at once: you diagnose from error messages and visual evidence alone, fix each in situ, then execute the panic-shader swap as if the set were live.
Supporting atoms for grounding: glsl-standard-uniforms is the authoritative list of what glslViewer provides without declaration; glsl-float-decimal-requirement and glsl-coordinate-normalization are from the prerequisite module but recur constantly in debugging sessions — having them here as supporting gives you fast look-up context without re-gating the capstone on material already drilled.
Atoms in this module
Required — these gate the capstone
Supporting — enrichment, not gating
Part of curricula
- Generative & AI AV Artist — real-time machine-driven performance — Orient the machine collaborator & ship a first ML AV artefact recommended
- Live Visualist — zero to performing live-coded & generative visuals — Perform the set — live-coded, generative, audio-reactive visuals for an audience required
- Shader Artist — real-time GPU craft to a demoscene-grade visual — The demoscene-grade piece: pipeline, reactivity, and release recommended