Overview
What shadertown is, and the three ways to get a shader into your app.
shadertown is a catalogue of 77 fullscreen WebGPU shaders and a small runtime that draws them. Every shader is a single WGSL fragment stage compiled by vgpu; nothing on this site is a video or a canvas recording.
The three surfaces
There is no single right way to adopt a shader, so there are three, and they share one vocabulary.
| Surface | You get | Use it when |
|---|---|---|
| SDK | shadertown on npm: ShaderCanvas, createShaderRenderer | You want the catalogue to keep improving under you |
| Config | A typed defineShader({ … }) preset | You tuned something and want it pinned and reviewable |
| Registry | npx shadertown add <slug> vendors the WGSL into your repo | You want to own and edit the shader source |
The SDK and the config are meant to be used together: the package ships the runtime, and your repo holds the parameters you chose.
One uniform block, the whole catalogue
Every shader in the catalogue reads the same uniform struct. Six controls mean
the same thing everywhere (speed, scale, intensity, vibrancy, grain,
vignette), plus warp, which most shaders point at their strongest effect,
four generic slots that each shader names for itself, and three colours.
That is why setParams never recompiles anything, why the runtime can swap a
shader without touching a binding, and why a preset written for one shader
degrades sensibly rather than throwing when pointed at another.
See Parameters for the full ABI.
Four kinds of shader
Forty-four of them invent their picture out of nothing but that uniform block. Three simulate one: Particles, Fluid and Cloth carry state in GPU buffers and step it with compute passes before every draw, so they answer the pointer the way a physical thing would. Sixteen render one in passes: a whole render graph in one module, encoded into the frame ahead of the draw — the particle fields as a displacement field, an instanced particle draw and a bloom chain, Blueprint as a layer measured, distance-fielded and drawn up as a plate, and Filament, Spectra, Shafts, Billow and Gossamer as one scene of light, bloomed, Alloy as metal ribbons and glass in a studio, and Basalt as a floor of slabs drawn box by box. The other fourteen read a layer (your image, a video frame, a line of text, an SVG, or another shadertown shader) and refract, recolour or resample it.
<ShaderCanvas shader="glass" source="/hero.jpg" />
<ShaderCanvas shader="duotone" source={videoElement} />
<ShaderCanvas shader="lens" source={{ shader: "neon-grid" }} />A source shader adds a texture, a sampler and a small Source uniform at
bindings 1 to 3. Those are additive, so the Params block at binding 0 is
byte-identical either way: a shader you vendored before source shaders existed
is on exactly the same ABI as one you vendor today.
Leave source out and it falls back to the shader named in its registry entry,
so it draws something rather than nothing. Ask a shader which kind it is with
shaderKind(name).
See Source shaders for the bindings and the accepted inputs.
Browser support
shadertown needs WebGPU. That means Chrome and Edge 113+, Safari 26+, and
Firefox behind a flag. ShaderCanvas reports an unsupported status and can
render a fallback instead, so a missing device is a design decision rather
than a blank rectangle.