toybox
toybox · sources Multi-layer video compositor. FOUR layers, each rendered into its own framebuffer then reduced to the output by a combine DAG (fade / lumakey / chromakey / map). A layer kind selects its source: GEN = a generative fragment-shader content entry from the bundled bank (noise-fbm domain-warped simplex FBM, worley-cells animated cellular noise; the FX hsv-plasma / cos-gradient palette shaders; the SHADERTOY synthwave-sunset port) with iTime + iResolution + its declared float params on faders — NO scene input. FRAG = a Shadertoy fragment shader that RECEIVES the composited layer below as iChannel0 (recolour / displace / feedback FX, e.g. frag-invert-scan). TOYBOX hosts a faithful SHADERTOY RUNTIME: a `void mainImage(out vec4, in vec2)` source is wrapped through a mainImage→main shim with the FULL Shadertoy uniform set (iTime, iResolution as vec3, iTimeDelta, iFrame, iFrameRate, iMouse vec4 with .z/.w press semantics, iDate, iChannel0-3 + iChannelResolution[4]); the preview canvas routes pointer events to iMouse (client→engine px, GL bottom-origin Y-flip). A GEN/FRAG layer can host a MULTI-BUFFER Shadertoy project (a Common chunk + N buffer passes + an Image pass) — each pass owns its own FBO (RGBA32F via createFloatFbo for intBitsToFloat-packed / signed-precision buffers, degrading to RGBA8), channels resolve to another buffer pass output / its own previous frame (ping-pong feedback) / a keyboard stub / the scene / none, topo-ordered producers-first with Image last; the bundled GROWING PEAK preset is an ORIGINAL multi-buffer project (a growable self-feedback heightmap buffer → a raymarched weather sky Image pass) where CLICKING the preview grows the mountain via iMouse. OBJ = a 3D mesh layer (Phase 3): a bundled CC0 OBJ (Spot the cow, Utah teapot, chess pawn — parsed by an in-house ASCII OBJ parser with auto-center/auto-scale + computed flat normals) OR a built-in procedural primitive (cube / sphere / torus / hypercube tesseract; no asset file), matcap-shaded with depth testing — the matcap is synthesized procedurally in-shader (chrome / clay / neon styles, zero asset-license surface) and the layer carries rotX/rotY/rotZ, scale, spin (auto-rotate) and an RGB tint. An OBJ layer can optionally UV-map ANOTHER layer's rendered output (material.surfaceSource = that layer index, surfaceMix the blend) onto the mesh as a SURFACE TEXTURE in place of (blended with) the matcap — a per-frame dependency-ordered render pass guarantees the source layer renders first, and a self / cyclic / out-of-range source degrades to matcap-only (no WebGL feedback loop). OBJs with no authored texture coords get a planar XY-projected UV so the surface texture isn't collapsed to a single texel. The content/model catalogs + per-shader param schema live in a static manifest (packages/web/static/toybox/manifest.json); GLSL + OBJs are fetched lazily on selection (never JS-bundled) and cached. Persistence: node.data.layers (4-length array of { kind, contentId, params, material }) + node.data.combine. One video output (out).
the faceplate
inputs
| id | cable | what it does |
|---|---|---|
inA | video | RGB video stream |
inB | video | RGB video stream |
outputs
| id | cable | what it does |
|---|---|---|
out | video | RGB video stream |
source
toybox.ts on GitHub.