shader-templates/registry.ts
PURPOSE
Central registry of every baked-VFX shader template available to the workbench. Imports each .frag.ts GLSL module, tags it with a family + uniform schema, and exports the flat TEMPLATES record for O(1) lookup by string id plus a templatesInFamily() helper for UI grouping.
OWNS
TEMPLATES: Record<TemplateId, TemplateSpec>— single source of truth for what templates exist.TemplateFamilyunion — nine category tags.TemplateIdunion — full enumerated list of every template string id.UniformType/UniformEntry/TemplateSpecinterfaces — the shape every template entry must conform to.TEMPLATE_FAMILIES— stable display order for the library pane.- Local
U()/U2()helpers — terse builders for float and vec2 uniform entries.
READS FROM
./baked/*.frag— 17 legacy baked-shader GLSL modules../shape/*.frag— 7 SDF primitives../fill/*.frag— 13 fill generators../mask/*.frag— 4 mask generators../stroke/*.frag— 3 outline shaders../glow/*.frag— 1 halo shader../energy/*.frag— 6 energy-effect shaders../impact/*.frag— 3 impact shaders../post/*.frag— 10 post-process shaders (sampleu_src).
PUSHES TO
Nothing — pure data export. Consumers (workbench UI, baked-atlas compositor) import TEMPLATES / templatesInFamily / TEMPLATE_FAMILIES and drive rendering, library tree population, and uniform-handle editors off of these structures.
DOES NOT
- Does not compile or compose GLSL — only references frag strings imported from sibling files.
- Does not instantiate GL programs, bind uniforms, or render anything.
- Does not validate uniform values at runtime —
rangeis advisory metadata for the editor. - Does not version templates or migrate uniform schemas.
- Does not own the shared uniform contract itself (
u_time/u_resolution/u_palette[4]/u_intensity); it just references it in the add-a-template comment.
Signals
| Signal | Source | Shape |
|---|---|---|
TEMPLATES[id] | exported const | TemplateSpec — { id, family, fragGlsl, uniformSchema } |
templatesInFamily(family) | helper fn | TemplateSpec[] filtered by family |
TEMPLATE_FAMILIES | exported const | ordered list of 9 family strings |
UniformEntry | type | { name, type, default, range?, handle?, handleColor?, doc? } |
Entry points
- Library pane tree calls
templatesInFamily(family)once per family inTEMPLATE_FAMILIESorder. - Workbench renderer does
TEMPLATES[id].fragGlslto fetch GLSL by string id. - Uniform editor reads
TEMPLATES[id].uniformSchemato build sliders / vec2 drag handles, usingrangefor slider bounds andhandle/handleColorfor canvas-overlay gizmos.
Pattern notes
- Flat record, grouped comments. The registry is grouped visually by family in source order with
── family (N) ──separators, but exported as one flatRecord<TemplateId, TemplateSpec>so id-lookup is O(1) and no nested traversal is needed. - Family count distribution (66 templates total):
baked— 17 (arc, beam, bolt, chevron, crescent, cross, diamond, disc, fire_flame, plasma_ball, ring, smoke_puff, sparkle, spiral, star, streak, teardrop)shape— 7 (SDF capsule / cone / pie / polygon_n / rose / heart / ellipse)fill— 13 (solid, two gradients, fbm + warped fbm, worley, voronoi_cracks, fire_rising, smoke_rising, plasma_hue_wobble, nebula_2stop, hex_grid, mandala_n_fold)mask— 4 (sdf_primitive, noise_threshold, scrolling_flow, kaleidoscope)stroke— 3 (sdf_outline, pulse_outline, fuzzy_outline)glow— 1 (inverse_distance_halo)energy— 6 (fresnel_rim, electric_arc, shield_hex, portal_swirl, reactor_core, hologram_stack)impact— 3 (shockwave_ring, explosion_fireball, muzzle_starburst)post— 10 (bloom, chromatic_aberration, five warp variants, grain, vignette, barrel)
- Uniform types are minimal.
UniformType = 'float' | 'vec2' | 'vec3' | 'vec3[4]'.vec3[4]is reserved for palette uniforms; onlyfloatandvec2are actually built via theU()/U2()helpers in this file. - Handle metadata is editor-only.
handle: 'point' | 'radius' | 'angle'plus optionalhandleColortell the workbench UI to draw a draggable gizmo on the preview canvas — they have no GLSL effect. - Post family contract. Templates in
family: 'post'are documented as samplingu_srcand writing a modified output — they are the only family that reads from a prior framebuffer rather than synthesizing from scratch. - Add-a-template recipe (from header comment): create
<family>/<name>.frag.tsexporting default GLSL matching the shared uniform contract, import here, add aTEMPLATESentry withuniformSchema, and widenTemplateId. - No magic ids. Every template’s string id matches the property key, the
idfield, and theTemplateIdunion member — three locations, kept in sync manually.
EXTRACT-CANDIDATE
- Schema drift risk.
TemplateIdis hand-maintained alongsideTEMPLATESkeys — could be inferred viakeyof typeof TEMPLATESonce the file stops needing the union as a forward reference, eliminating one place to update when adding a template. - Family counts are scattered. The
── family (N) ──comments hard-code counts that must be updated by hand when templates are added; a one-liner derived fromtemplatesInFamily(f).lengthin the workbench UI would prevent drift between comment and reality. vec3andvec3[4]uniform types are declared but unused by every current entry (palette is presumed injected outsideuniformSchema). Either prune them fromUniformTypeor add theU3()/UPalette()helpers to make the contract complete.fire_flameimport is namedfireFlame(noFragsuffix) while every other baked import uses the*Fragconvention — minor inconsistency worth normalizing on the next touch.