agentvfx 0.0.0-stage → 0.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +8 -0
- package/GEMINI.md +1 -0
- package/LICENSE +172 -0
- package/README.md +236 -2
- package/package.json +35 -4
- package/skills/agentvfx/LICENSE +172 -0
- package/skills/agentvfx/NOTICE +44 -0
- package/skills/agentvfx/SKILL.md +90 -0
- package/skills/agentvfx/engine/core/constants.mjs +84 -0
- package/skills/agentvfx/engine/core/flash-constants.mjs +23 -0
- package/skills/agentvfx/engine/core/flash.mjs +240 -0
- package/skills/agentvfx/engine/core/mark.mjs +28 -0
- package/skills/agentvfx/engine/core/palettes.mjs +36 -0
- package/skills/agentvfx/engine/core/schedule.mjs +85 -0
- package/skills/agentvfx/engine/core/templates.mjs +43 -0
- package/skills/agentvfx/engine/core/util.mjs +167 -0
- package/skills/agentvfx/engine/core/validate.mjs +334 -0
- package/skills/agentvfx/engine/node/analysis.mjs +172 -0
- package/skills/agentvfx/engine/node/audio.mjs +621 -0
- package/skills/agentvfx/engine/node/board.mjs +24 -0
- package/skills/agentvfx/engine/node/chrome.mjs +349 -0
- package/skills/agentvfx/engine/node/encode.mjs +110 -0
- package/skills/agentvfx/engine/node/eye.mjs +77 -0
- package/skills/agentvfx/engine/node/footage.mjs +129 -0
- package/skills/agentvfx/engine/node/frame-worker.mjs +39 -0
- package/skills/agentvfx/engine/node/host.mjs +31 -0
- package/skills/agentvfx/engine/node/job.mjs +181 -0
- package/skills/agentvfx/engine/node/png.mjs +112 -0
- package/skills/agentvfx/engine/node/render.mjs +161 -0
- package/skills/agentvfx/engine/node/stage-capture.mjs +187 -0
- package/skills/agentvfx/engine/node/stage-serve.mjs +72 -0
- package/skills/agentvfx/engine/node/stills.mjs +100 -0
- package/skills/agentvfx/engine/node/ws-server.mjs +132 -0
- package/skills/agentvfx/engine/web/gl.mjs +319 -0
- package/skills/agentvfx/engine/web/glsl-common.mjs +78 -0
- package/skills/agentvfx/engine/web/init.js +23 -0
- package/skills/agentvfx/engine/web/prelude.mjs +150 -0
- package/skills/agentvfx/engine/web/render.html +11 -0
- package/skills/agentvfx/engine/web/render.mjs +388 -0
- package/skills/agentvfx/engine/web/scale.mjs +15 -0
- package/skills/agentvfx/engine/web/text.mjs +158 -0
- package/skills/agentvfx/plates/terminalcore/README.md +61 -0
- package/skills/agentvfx/plates/terminalcore/__pycache__/crt.cpython-313.pyc +0 -0
- package/skills/agentvfx/plates/terminalcore/__pycache__/font.cpython-313.pyc +0 -0
- package/skills/agentvfx/plates/terminalcore/__pycache__/gallery.cpython-313.pyc +0 -0
- package/skills/agentvfx/plates/terminalcore/__pycache__/gallery_mats.cpython-313.pyc +0 -0
- package/skills/agentvfx/plates/terminalcore/__pycache__/gallery_room.cpython-313.pyc +0 -0
- package/skills/agentvfx/plates/terminalcore/__pycache__/materials.cpython-313.pyc +0 -0
- package/skills/agentvfx/plates/terminalcore/__pycache__/nodekit.cpython-313.pyc +0 -0
- package/skills/agentvfx/plates/terminalcore/__pycache__/room.cpython-313.pyc +0 -0
- package/skills/agentvfx/plates/terminalcore/__pycache__/shots.cpython-313.pyc +0 -0
- package/skills/agentvfx/plates/terminalcore/__pycache__/textures.cpython-313.pyc +0 -0
- package/skills/agentvfx/plates/terminalcore/__pycache__/wall.cpython-313.pyc +0 -0
- package/skills/agentvfx/plates/terminalcore/crt.py +143 -0
- package/skills/agentvfx/plates/terminalcore/font.py +80 -0
- package/skills/agentvfx/plates/terminalcore/gallery.py +61 -0
- package/skills/agentvfx/plates/terminalcore/gallery_mats.py +144 -0
- package/skills/agentvfx/plates/terminalcore/gallery_room.py +126 -0
- package/skills/agentvfx/plates/terminalcore/materials.py +170 -0
- package/skills/agentvfx/plates/terminalcore/nodekit.py +87 -0
- package/skills/agentvfx/plates/terminalcore/room.py +82 -0
- package/skills/agentvfx/plates/terminalcore/scene.py +219 -0
- package/skills/agentvfx/plates/terminalcore/shots.py +48 -0
- package/skills/agentvfx/plates/terminalcore/textures.py +79 -0
- package/skills/agentvfx/plates/terminalcore/wall.py +103 -0
- package/skills/agentvfx/references/plates.md +22 -0
- package/skills/agentvfx/references/template-format.md +149 -0
- package/skills/agentvfx/references/web.md +63 -0
- package/skills/agentvfx/runtime/agentvfx.js +708 -0
- package/skills/agentvfx/schemas/fx-score.schema.json +98 -0
- package/skills/agentvfx/scripts/export-web.mjs +155 -0
- package/skills/agentvfx/scripts/loop.mjs +129 -0
- package/skills/agentvfx/scripts/make-beat.mjs +133 -0
- package/skills/agentvfx/scripts/plate.mjs +82 -0
- package/skills/agentvfx/scripts/vfx.mjs +173 -0
- package/skills/agentvfx/templates/_test/feedback-counter/fx.json +11 -0
- package/skills/agentvfx/templates/_test/feedback-counter/main.frag +4 -0
- package/skills/agentvfx/templates/_test/feedback-counter/pass0.frag +4 -0
- package/skills/agentvfx/templates/_test/gradient/fx.json +23 -0
- package/skills/agentvfx/templates/_test/gradient/main.frag +5 -0
- package/skills/agentvfx/templates/_test/identity/fx.json +10 -0
- package/skills/agentvfx/templates/_test/identity/main.frag +4 -0
- package/skills/agentvfx/templates/_test/strobe/fx.json +14 -0
- package/skills/agentvfx/templates/_test/strobe/main.frag +6 -0
- package/skills/agentvfx/templates/_test/text-probe/fx.json +15 -0
- package/skills/agentvfx/templates/_test/text-probe/main.frag +6 -0
- package/skills/agentvfx/templates/brutal/NOTES.md +14 -0
- package/skills/agentvfx/templates/brutal/_src/boot-log/def.mjs +57 -0
- package/skills/agentvfx/templates/brutal/_src/boot-log/main.src.frag +129 -0
- package/skills/agentvfx/templates/brutal/_src/build.mjs +33 -0
- package/skills/agentvfx/templates/brutal/_src/halftone-field/def.mjs +72 -0
- package/skills/agentvfx/templates/brutal/_src/halftone-field/main.src.frag +94 -0
- package/skills/agentvfx/templates/brutal/_src/hud-deck/deck-left.src.glsl +100 -0
- package/skills/agentvfx/templates/brutal/_src/hud-deck/deck-right.src.glsl +61 -0
- package/skills/agentvfx/templates/brutal/_src/hud-deck/deck-tiles.src.glsl +153 -0
- package/skills/agentvfx/templates/brutal/_src/hud-deck/def.mjs +82 -0
- package/skills/agentvfx/templates/brutal/_src/hud-deck/main.src.frag +110 -0
- package/skills/agentvfx/templates/brutal/_src/hud-deck/pass0.src.frag +38 -0
- package/skills/agentvfx/templates/brutal/_src/shared/defs.mjs +28 -0
- package/skills/agentvfx/templates/brutal/_src/shared/icons.glsl +72 -0
- package/skills/agentvfx/templates/brutal/_src/shared/lib.glsl +115 -0
- package/skills/agentvfx/templates/brutal/_src/shared/screen.glsl +43 -0
- package/skills/agentvfx/templates/brutal/boot-log/demo-acid.json +1 -0
- package/skills/agentvfx/templates/brutal/boot-log/demo-phosphor.json +1 -0
- package/skills/agentvfx/templates/brutal/boot-log/demo-ultramarine.json +1 -0
- package/skills/agentvfx/templates/brutal/boot-log/fx.json +257 -0
- package/skills/agentvfx/templates/brutal/boot-log/main.frag +242 -0
- package/skills/agentvfx/templates/brutal/collage/_src/00-lib.glsl +73 -0
- package/skills/agentvfx/templates/brutal/collage/_src/10-spectrum-scope.glsl +73 -0
- package/skills/agentvfx/templates/brutal/collage/_src/20-meter-readout-cross.glsl +87 -0
- package/skills/agentvfx/templates/brutal/collage/_src/30-footage-fillers.glsl +92 -0
- package/skills/agentvfx/templates/brutal/collage/_src/40-editorial.glsl +232 -0
- package/skills/agentvfx/templates/brutal/collage/_src/50-typefx.glsl +163 -0
- package/skills/agentvfx/templates/brutal/collage/_src/60-scene-lib.glsl +104 -0
- package/skills/agentvfx/templates/brutal/collage/_src/61-scene-specimen.glsl +71 -0
- package/skills/agentvfx/templates/brutal/collage/_src/62-scene-wiring.glsl +96 -0
- package/skills/agentvfx/templates/brutal/collage/_src/63-scene-fieldcut.glsl +119 -0
- package/skills/agentvfx/templates/brutal/collage/_src/64-scene-pattern.glsl +64 -0
- package/skills/agentvfx/templates/brutal/collage/_src/641-scene-anatomy.glsl +49 -0
- package/skills/agentvfx/templates/brutal/collage/_src/642-scene-deck.glsl +78 -0
- package/skills/agentvfx/templates/brutal/collage/_src/643-scene-bootlog.glsl +60 -0
- package/skills/agentvfx/templates/brutal/collage/_src/644-scene-tunnel.glsl +48 -0
- package/skills/agentvfx/templates/brutal/collage/_src/645-scene-runner.glsl +42 -0
- package/skills/agentvfx/templates/brutal/collage/_src/646-scene-ascii.glsl +66 -0
- package/skills/agentvfx/templates/brutal/collage/_src/647-scene-cubewall.glsl +80 -0
- package/skills/agentvfx/templates/brutal/collage/_src/648-scene-vortex.glsl +46 -0
- package/skills/agentvfx/templates/brutal/collage/_src/649-scene-sticker.glsl +72 -0
- package/skills/agentvfx/templates/brutal/collage/_src/65-scene-main.glsl +1 -0
- package/skills/agentvfx/templates/brutal/collage/_src/650-scene-ribbon.glsl +55 -0
- package/skills/agentvfx/templates/brutal/collage/_src/651-scene-slab.glsl +38 -0
- package/skills/agentvfx/templates/brutal/collage/_src/652-scene-framedial.glsl +79 -0
- package/skills/agentvfx/templates/brutal/collage/_src/653-scene-tilt.glsl +40 -0
- package/skills/agentvfx/templates/brutal/collage/_src/654-scene-marquee.glsl +45 -0
- package/skills/agentvfx/templates/brutal/collage/_src/655-scene-lens.glsl +57 -0
- package/skills/agentvfx/templates/brutal/collage/_src/656-scene-liquid.glsl +35 -0
- package/skills/agentvfx/templates/brutal/collage/_src/657-scene-panelgrid.glsl +75 -0
- package/skills/agentvfx/templates/brutal/collage/_src/658-scene-mirror.glsl +49 -0
- package/skills/agentvfx/templates/brutal/collage/_src/66-scene-main.glsl +27 -0
- package/skills/agentvfx/templates/brutal/collage/_src/90-main.glsl +120 -0
- package/skills/agentvfx/templates/brutal/collage/_src/build.mjs +24 -0
- package/skills/agentvfx/templates/brutal/collage/_src/sync-presets.mjs +16 -0
- package/skills/agentvfx/templates/brutal/collage/demo-bone-lime.json +1 -0
- package/skills/agentvfx/templates/brutal/collage/demo-lime-sparse.json +1 -0
- package/skills/agentvfx/templates/brutal/collage/demo-orange-dense.json +1 -0
- package/skills/agentvfx/templates/brutal/collage/demo-ultra-slow.json +1 -0
- package/skills/agentvfx/templates/brutal/collage/fx.json +4882 -0
- package/skills/agentvfx/templates/brutal/collage/layout.mjs +97 -0
- package/skills/agentvfx/templates/brutal/collage/layouts.json +366 -0
- package/skills/agentvfx/templates/brutal/collage/main.frag +2367 -0
- package/skills/agentvfx/templates/brutal/collage/pass0.frag +265 -0
- package/skills/agentvfx/templates/brutal/halftone-field/demo-acid.json +1 -0
- package/skills/agentvfx/templates/brutal/halftone-field/demo-ascii.json +1 -0
- package/skills/agentvfx/templates/brutal/halftone-field/demo-dither.json +1 -0
- package/skills/agentvfx/templates/brutal/halftone-field/demo-orange.json +1 -0
- package/skills/agentvfx/templates/brutal/halftone-field/demo-phosphor.json +1 -0
- package/skills/agentvfx/templates/brutal/halftone-field/demo-ultramarine.json +1 -0
- package/skills/agentvfx/templates/brutal/halftone-field/fx.json +474 -0
- package/skills/agentvfx/templates/brutal/halftone-field/main.frag +248 -0
- package/skills/agentvfx/templates/brutal/hud-deck/demo-acid.json +1 -0
- package/skills/agentvfx/templates/brutal/hud-deck/demo-night.json +1 -0
- package/skills/agentvfx/templates/brutal/hud-deck/demo-octagon.json +1 -0
- package/skills/agentvfx/templates/brutal/hud-deck/demo-ultramarine.json +1 -0
- package/skills/agentvfx/templates/brutal/hud-deck/fx.json +601 -0
- package/skills/agentvfx/templates/brutal/hud-deck/main.frag +645 -0
- package/skills/agentvfx/templates/brutal/hud-deck/pass0.frag +38 -0
- package/skills/agentvfx/templates/brutal/lattice/demo-cobalt-fine.json +1 -0
- package/skills/agentvfx/templates/brutal/lattice/demo-ink-yellow.json +1 -0
- package/skills/agentvfx/templates/brutal/lattice/demo-vermilion.json +1 -0
- package/skills/agentvfx/templates/brutal/lattice/demo-violet-slow.json +1 -0
- package/skills/agentvfx/templates/brutal/lattice/fx.json +130 -0
- package/skills/agentvfx/templates/brutal/lattice/main.frag +175 -0
- package/skills/agentvfx/templates/brutal/lattice/pass0.frag +29 -0
- package/skills/agentvfx/templates/glitch/block-glitch/demo-mosaic.json +1 -0
- package/skills/agentvfx/templates/glitch/block-glitch/demo-onset.json +1 -0
- package/skills/agentvfx/templates/glitch/block-glitch/demo-static.json +1 -0
- package/skills/agentvfx/templates/glitch/block-glitch/demo-tear.json +1 -0
- package/skills/agentvfx/templates/glitch/block-glitch/fx.json +54 -0
- package/skills/agentvfx/templates/glitch/block-glitch/main.frag +132 -0
- package/skills/agentvfx/templates/glitch/block-glitch/pass0.frag +12 -0
- package/skills/agentvfx/templates/glitch/pixel-sort/NOTES.md +13 -0
- package/skills/agentvfx/templates/glitch/pixel-sort/build-passes.mjs +162 -0
- package/skills/agentvfx/templates/glitch/pixel-sort/demo-chunk.json +1 -0
- package/skills/agentvfx/templates/glitch/pixel-sort/demo-hue.json +1 -0
- package/skills/agentvfx/templates/glitch/pixel-sort/demo-kick.json +1 -0
- package/skills/agentvfx/templates/glitch/pixel-sort/demo-streak.json +1 -0
- package/skills/agentvfx/templates/glitch/pixel-sort/demo-vertical.json +1 -0
- package/skills/agentvfx/templates/glitch/pixel-sort/fx.json +60 -0
- package/skills/agentvfx/templates/glitch/pixel-sort/main.frag +83 -0
- package/skills/agentvfx/templates/glitch/pixel-sort/pass0.frag +64 -0
- package/skills/agentvfx/templates/glitch/pixel-sort/pass1.frag +66 -0
- package/skills/agentvfx/templates/glitch/pixel-sort/pass2.frag +66 -0
- package/skills/agentvfx/templates/glitch/pixel-sort/pass3.frag +66 -0
- package/skills/agentvfx/templates/glitch/pixel-sort/pass4.frag +66 -0
- package/skills/agentvfx/templates/glitch/pixel-sort/pass5.frag +66 -0
- package/skills/agentvfx/templates/glitch/pixel-sort/pass6.frag +66 -0
- package/skills/agentvfx/templates/glitch/pixel-sort/pass7.frag +66 -0
- package/skills/agentvfx/templates/glitch/pixel-sort/pass8.frag +66 -0
- package/skills/agentvfx/templates/glitch/rgb-split/demo-diagonal-stutter.json +1 -0
- package/skills/agentvfx/templates/glitch/rgb-split/demo-hard.json +1 -0
- package/skills/agentvfx/templates/glitch/rgb-split/demo-kick.json +1 -0
- package/skills/agentvfx/templates/glitch/rgb-split/demo-radial.json +1 -0
- package/skills/agentvfx/templates/glitch/rgb-split/fx.json +46 -0
- package/skills/agentvfx/templates/glitch/rgb-split/main.frag +76 -0
- package/skills/agentvfx/templates/glitch/vhs/demo-clean.json +1 -0
- package/skills/agentvfx/templates/glitch/vhs/demo-crash.json +1 -0
- package/skills/agentvfx/templates/glitch/vhs/demo-tape.json +1 -0
- package/skills/agentvfx/templates/glitch/vhs/demo-worn.json +1 -0
- package/skills/agentvfx/templates/glitch/vhs/fx.json +46 -0
- package/skills/agentvfx/templates/glitch/vhs/main.frag +96 -0
- package/skills/agentvfx/templates/impact/impact-1bit/demo-onebit-bayer.json +1 -0
- package/skills/agentvfx/templates/impact/impact-1bit/fx.json +45 -0
- package/skills/agentvfx/templates/impact/impact-1bit/main.frag +64 -0
- package/skills/agentvfx/templates/impact/impact-invert/demo-invert-snap.json +1 -0
- package/skills/agentvfx/templates/impact/impact-invert/fx.json +37 -0
- package/skills/agentvfx/templates/impact/impact-invert/main.frag +44 -0
- package/skills/agentvfx/templates/impact/punch-shake/demo-punch-hard.json +1 -0
- package/skills/agentvfx/templates/impact/punch-shake/fx.json +36 -0
- package/skills/agentvfx/templates/impact/punch-shake/main.frag +62 -0
- package/skills/agentvfx/templates/impact/rgb-hit/demo-rgb-slam.json +1 -0
- package/skills/agentvfx/templates/impact/rgb-hit/fx.json +39 -0
- package/skills/agentvfx/templates/impact/rgb-hit/main.frag +62 -0
- package/skills/agentvfx/templates/impact/signal-cut/demo-lime-hold.json +1 -0
- package/skills/agentvfx/templates/impact/signal-cut/demo-lime.json +1 -0
- package/skills/agentvfx/templates/impact/signal-cut/demo-orange.json +1 -0
- package/skills/agentvfx/templates/impact/signal-cut/demo-ultramarine.json +1 -0
- package/skills/agentvfx/templates/impact/signal-cut/fx.json +83 -0
- package/skills/agentvfx/templates/impact/signal-cut/main.frag +101 -0
- package/skills/agentvfx/templates/impact/signal-cut/pass0.frag +68 -0
- package/skills/agentvfx/templates/impact/speedline-burst/demo-speed-white.json +1 -0
- package/skills/agentvfx/templates/impact/speedline-burst/fx.json +44 -0
- package/skills/agentvfx/templates/impact/speedline-burst/main.frag +68 -0
- package/skills/agentvfx/templates/impact/strobe-burst/demo-strobe-white-16.json +1 -0
- package/skills/agentvfx/templates/impact/strobe-burst/fx.json +42 -0
- package/skills/agentvfx/templates/impact/strobe-burst/main.frag +43 -0
- package/skills/agentvfx/templates/light/anamorphic-streak/demo-anamorphic-cinema.json +10 -0
- package/skills/agentvfx/templates/light/anamorphic-streak/demo-data.json +10 -0
- package/skills/agentvfx/templates/light/anamorphic-streak/fx.json +47 -0
- package/skills/agentvfx/templates/light/anamorphic-streak/main.frag +45 -0
- package/skills/agentvfx/templates/light/anamorphic-streak/pass0.frag +22 -0
- package/skills/agentvfx/templates/light/anamorphic-streak/pass1.frag +16 -0
- package/skills/agentvfx/templates/light/anamorphic-streak/pass2.frag +16 -0
- package/skills/agentvfx/templates/light/anamorphic-streak/pass3.frag +16 -0
- package/skills/agentvfx/templates/light/bloom-glow/demo-clip01-low.json +11 -0
- package/skills/agentvfx/templates/light/bloom-glow/demo-neon-night.json +10 -0
- package/skills/agentvfx/templates/light/bloom-glow/demo-phosphor.json +11 -0
- package/skills/agentvfx/templates/light/bloom-glow/fx.json +53 -0
- package/skills/agentvfx/templates/light/bloom-glow/main.frag +85 -0
- package/skills/agentvfx/templates/light/bloom-glow/pass0.frag +21 -0
- package/skills/agentvfx/templates/light/bloom-glow/pass1.frag +50 -0
- package/skills/agentvfx/templates/light/bloom-glow/pass2.frag +44 -0
- package/skills/agentvfx/templates/light/bloom-glow/pass3.frag +32 -0
- package/skills/agentvfx/templates/light/bloom-glow/pass4.frag +48 -0
- package/skills/agentvfx/templates/light/bloom-glow/pass5.frag +46 -0
- package/skills/agentvfx/templates/light/god-rays/demo-golden-hour.json +10 -0
- package/skills/agentvfx/templates/light/god-rays/demo-point-lamp.json +10 -0
- package/skills/agentvfx/templates/light/god-rays/fx.json +39 -0
- package/skills/agentvfx/templates/light/god-rays/main.frag +54 -0
- package/skills/agentvfx/templates/light/lens-flare/demo-clip01-bar.json +11 -0
- package/skills/agentvfx/templates/light/lens-flare/demo-eye-bar.json +10 -0
- package/skills/agentvfx/templates/light/lens-flare/demo-sun-ghosts.json +10 -0
- package/skills/agentvfx/templates/light/lens-flare/fx.json +49 -0
- package/skills/agentvfx/templates/light/lens-flare/main.frag +86 -0
- package/skills/agentvfx/templates/light/lens-flare/pass0.frag +24 -0
- package/skills/agentvfx/templates/light/light-leak/demo-slit.json +10 -0
- package/skills/agentvfx/templates/light/light-leak/demo-vintage-burn.json +10 -0
- package/skills/agentvfx/templates/light/light-leak/fx.json +40 -0
- package/skills/agentvfx/templates/light/light-leak/main.frag +46 -0
- package/skills/agentvfx/templates/light/light-stage/fx.json +29 -0
- package/skills/agentvfx/templates/light/light-stage/main.frag +56 -0
- package/skills/agentvfx/templates/light/light-sweep/demo-hard-bar.json +12 -0
- package/skills/agentvfx/templates/light/light-sweep/demo-logo-sweep.json +10 -0
- package/skills/agentvfx/templates/light/light-sweep/demo-onset.json +11 -0
- package/skills/agentvfx/templates/light/light-sweep/fx.json +45 -0
- package/skills/agentvfx/templates/light/light-sweep/main.frag +29 -0
- package/skills/agentvfx/templates/light/light-sweep/pass0.frag +17 -0
- package/skills/agentvfx/templates/light/light-sweep/pass1.frag +15 -0
- package/skills/agentvfx/templates/light/neon-saber/demo-hairline.json +10 -0
- package/skills/agentvfx/templates/light/neon-saber/demo-saber-laser.json +10 -0
- package/skills/agentvfx/templates/light/neon-saber/fx.json +48 -0
- package/skills/agentvfx/templates/light/neon-saber/main.frag +27 -0
- package/skills/agentvfx/templates/light/neon-saber/pass0.frag +46 -0
- package/skills/agentvfx/templates/light/neon-saber/pass1.frag +15 -0
- package/skills/agentvfx/templates/psychedelic/echo-flow/demo-trail.json +1 -0
- package/skills/agentvfx/templates/psychedelic/echo-flow/fx.json +38 -0
- package/skills/agentvfx/templates/psychedelic/echo-flow/main.frag +19 -0
- package/skills/agentvfx/templates/psychedelic/echo-flow/pass0.frag +16 -0
- package/skills/agentvfx/templates/psychedelic/echo-flow/pass1.frag +20 -0
- package/skills/agentvfx/templates/psychedelic/echo-flow/pass2.frag +11 -0
- package/skills/agentvfx/templates/psychedelic/echo-flow/pass3.frag +4 -0
- package/skills/agentvfx/templates/psychedelic/hologram-scan/demo-cyan.json +1 -0
- package/skills/agentvfx/templates/psychedelic/hologram-scan/fx.json +36 -0
- package/skills/agentvfx/templates/psychedelic/hologram-scan/main.frag +30 -0
- package/skills/agentvfx/templates/psychedelic/kaleido-fold/demo-six.json +1 -0
- package/skills/agentvfx/templates/psychedelic/kaleido-fold/fx.json +37 -0
- package/skills/agentvfx/templates/psychedelic/kaleido-fold/main.frag +10 -0
- package/skills/agentvfx/templates/psychedelic/kaleido-fold/pass0.frag +34 -0
- package/skills/agentvfx/templates/psychedelic/mosh-melt/demo-classic.json +1 -0
- package/skills/agentvfx/templates/psychedelic/mosh-melt/fx.json +38 -0
- package/skills/agentvfx/templates/psychedelic/mosh-melt/main.frag +20 -0
- package/skills/agentvfx/templates/psychedelic/mosh-melt/pass0.frag +22 -0
- package/skills/agentvfx/templates/psychedelic/sacred/NOTES.md +13 -0
- package/skills/agentvfx/templates/psychedelic/sacred/demo-classic.json +1 -0
- package/skills/agentvfx/templates/psychedelic/sacred/demo-halo.json +1 -0
- package/skills/agentvfx/templates/psychedelic/sacred/demo-slow-tide.json +1 -0
- package/skills/agentvfx/templates/psychedelic/sacred/demo-thermal.json +1 -0
- package/skills/agentvfx/templates/psychedelic/sacred/fx.json +263 -0
- package/skills/agentvfx/templates/psychedelic/sacred/main.frag +109 -0
- package/skills/agentvfx/templates/psychedelic/sacred/pass0.frag +25 -0
- package/skills/agentvfx/templates/psychedelic/sacred/pass1.frag +23 -0
- package/skills/agentvfx/templates/psychedelic/tidal-bands/demo-classic.json +1 -0
- package/skills/agentvfx/templates/psychedelic/tidal-bands/fx.json +37 -0
- package/skills/agentvfx/templates/psychedelic/tidal-bands/main.frag +54 -0
- package/skills/agentvfx/templates/scope/_chrome.glsl +242 -0
- package/skills/agentvfx/templates/scope/goniometer/demo-boot-green.json +1 -0
- package/skills/agentvfx/templates/scope/goniometer/demo-field-lime.json +1 -0
- package/skills/agentvfx/templates/scope/goniometer/demo-field-ultramarine.json +1 -0
- package/skills/agentvfx/templates/scope/goniometer/demo-glow-phosphor.json +1 -0
- package/skills/agentvfx/templates/scope/goniometer/demo-hud-black.json +1 -0
- package/skills/agentvfx/templates/scope/goniometer/fx.json +635 -0
- package/skills/agentvfx/templates/scope/goniometer/main.frag +33 -0
- package/skills/agentvfx/templates/scope/goniometer/pass0.frag +58 -0
- package/skills/agentvfx/templates/scope/goniometer/pass1.frag +43 -0
- package/skills/agentvfx/templates/scope/goniometer/pass2.frag +12 -0
- package/skills/agentvfx/templates/scope/goniometer/pass3.frag +12 -0
- package/skills/agentvfx/templates/scope/goniometer/pass4.frag +12 -0
- package/skills/agentvfx/templates/scope/goniometer/pass5.frag +12 -0
- package/skills/agentvfx/templates/scope/goniometer/pass6.frag +251 -0
- package/skills/agentvfx/templates/scope/scope-polar/demo-boot-green.json +1 -0
- package/skills/agentvfx/templates/scope/scope-polar/demo-field-lime.json +1 -0
- package/skills/agentvfx/templates/scope/scope-polar/demo-field-ultramarine.json +1 -0
- package/skills/agentvfx/templates/scope/scope-polar/demo-glow-phosphor.json +1 -0
- package/skills/agentvfx/templates/scope/scope-polar/demo-hud-black.json +1 -0
- package/skills/agentvfx/templates/scope/scope-polar/fx.json +686 -0
- package/skills/agentvfx/templates/scope/scope-polar/main.frag +39 -0
- package/skills/agentvfx/templates/scope/scope-polar/pass0.frag +84 -0
- package/skills/agentvfx/templates/scope/scope-polar/pass1.frag +49 -0
- package/skills/agentvfx/templates/scope/scope-polar/pass2.frag +12 -0
- package/skills/agentvfx/templates/scope/scope-polar/pass3.frag +12 -0
- package/skills/agentvfx/templates/scope/scope-polar/pass4.frag +12 -0
- package/skills/agentvfx/templates/scope/scope-polar/pass5.frag +12 -0
- package/skills/agentvfx/templates/scope/scope-polar/pass6.frag +251 -0
- package/skills/agentvfx/templates/scope/scope-triggered/demo-boot-green.json +1 -0
- package/skills/agentvfx/templates/scope/scope-triggered/demo-field-lime.json +1 -0
- package/skills/agentvfx/templates/scope/scope-triggered/demo-field-ultramarine.json +1 -0
- package/skills/agentvfx/templates/scope/scope-triggered/demo-glow-phosphor.json +1 -0
- package/skills/agentvfx/templates/scope/scope-triggered/demo-hud-black.json +1 -0
- package/skills/agentvfx/templates/scope/scope-triggered/fx.json +712 -0
- package/skills/agentvfx/templates/scope/scope-triggered/main.frag +36 -0
- package/skills/agentvfx/templates/scope/scope-triggered/pass0.frag +78 -0
- package/skills/agentvfx/templates/scope/scope-triggered/pass1.frag +50 -0
- package/skills/agentvfx/templates/scope/scope-triggered/pass2.frag +12 -0
- package/skills/agentvfx/templates/scope/scope-triggered/pass3.frag +12 -0
- package/skills/agentvfx/templates/scope/scope-triggered/pass4.frag +12 -0
- package/skills/agentvfx/templates/scope/scope-triggered/pass5.frag +12 -0
- package/skills/agentvfx/templates/scope/scope-triggered/pass6.frag +251 -0
- package/skills/agentvfx/templates/scope/spectrogram-scroll/demo-boot-green.json +1 -0
- package/skills/agentvfx/templates/scope/spectrogram-scroll/demo-field-lime.json +1 -0
- package/skills/agentvfx/templates/scope/spectrogram-scroll/demo-field-ultramarine.json +1 -0
- package/skills/agentvfx/templates/scope/spectrogram-scroll/demo-glow-phosphor.json +1 -0
- package/skills/agentvfx/templates/scope/spectrogram-scroll/demo-hud-black.json +1 -0
- package/skills/agentvfx/templates/scope/spectrogram-scroll/fx.json +595 -0
- package/skills/agentvfx/templates/scope/spectrogram-scroll/main.frag +83 -0
- package/skills/agentvfx/templates/scope/spectrogram-scroll/pass0.frag +52 -0
- package/skills/agentvfx/templates/scope/spectrogram-scroll/pass1.frag +251 -0
- package/skills/agentvfx/templates/scope/xy-phosphor/demo-boot-green.json +1 -0
- package/skills/agentvfx/templates/scope/xy-phosphor/demo-field-lime.json +1 -0
- package/skills/agentvfx/templates/scope/xy-phosphor/demo-field-ultramarine.json +1 -0
- package/skills/agentvfx/templates/scope/xy-phosphor/demo-glow-phosphor.json +1 -0
- package/skills/agentvfx/templates/scope/xy-phosphor/demo-hud-black.json +1 -0
- package/skills/agentvfx/templates/scope/xy-phosphor/fx.json +642 -0
- package/skills/agentvfx/templates/scope/xy-phosphor/main.frag +33 -0
- package/skills/agentvfx/templates/scope/xy-phosphor/pass0.frag +56 -0
- package/skills/agentvfx/templates/scope/xy-phosphor/pass1.frag +44 -0
- package/skills/agentvfx/templates/scope/xy-phosphor/pass2.frag +12 -0
- package/skills/agentvfx/templates/scope/xy-phosphor/pass3.frag +12 -0
- package/skills/agentvfx/templates/scope/xy-phosphor/pass4.frag +12 -0
- package/skills/agentvfx/templates/scope/xy-phosphor/pass5.frag +12 -0
- package/skills/agentvfx/templates/scope/xy-phosphor/pass6.frag +251 -0
- package/skills/agentvfx/templates/spectrum/_src/bars-linear/fx.src.json +61 -0
- package/skills/agentvfx/templates/spectrum/_src/bars-linear/main.src.frag +112 -0
- package/skills/agentvfx/templates/spectrum/_src/bars-linear/pass0.src.frag +2 -0
- package/skills/agentvfx/templates/spectrum/_src/bars-mirror/fx.src.json +51 -0
- package/skills/agentvfx/templates/spectrum/_src/bars-mirror/main.src.frag +72 -0
- package/skills/agentvfx/templates/spectrum/_src/bars-mirror/pass0.src.frag +2 -0
- package/skills/agentvfx/templates/spectrum/_src/bass-circle/fx.src.json +56 -0
- package/skills/agentvfx/templates/spectrum/_src/bass-circle/main.src.frag +136 -0
- package/skills/agentvfx/templates/spectrum/_src/bass-circle/pass0.src.frag +2 -0
- package/skills/agentvfx/templates/spectrum/_src/build.mjs +68 -0
- package/skills/agentvfx/templates/spectrum/_src/label-bars/fx.src.json +54 -0
- package/skills/agentvfx/templates/spectrum/_src/label-bars/main.src.frag +102 -0
- package/skills/agentvfx/templates/spectrum/_src/label-bars/pass0.src.frag +2 -0
- package/skills/agentvfx/templates/spectrum/_src/shared/bars-fn.glsl +64 -0
- package/skills/agentvfx/templates/spectrum/_src/shared/bars-pass.glsl +22 -0
- package/skills/agentvfx/templates/spectrum/_src/shared/clock.glsl +7 -0
- package/skills/agentvfx/templates/spectrum/_src/shared/hud.glsl +50 -0
- package/skills/agentvfx/templates/spectrum/_src/shared/stage.glsl +74 -0
- package/skills/agentvfx/templates/spectrum/_src/spectrum-particles/fx.src.json +58 -0
- package/skills/agentvfx/templates/spectrum/_src/spectrum-particles/main.src.frag +119 -0
- package/skills/agentvfx/templates/spectrum/_src/spectrum-particles/pass0.src.frag +33 -0
- package/skills/agentvfx/templates/spectrum/_src/spectrum-radial/fx.src.json +56 -0
- package/skills/agentvfx/templates/spectrum/_src/spectrum-radial/main.src.frag +95 -0
- package/skills/agentvfx/templates/spectrum/_src/spectrum-radial/pass0.src.frag +2 -0
- package/skills/agentvfx/templates/spectrum/_src/waveform-line/fx.src.json +60 -0
- package/skills/agentvfx/templates/spectrum/_src/waveform-line/main.src.frag +98 -0
- package/skills/agentvfx/templates/spectrum/_src/waveform-line/pass0.src.frag +43 -0
- package/skills/agentvfx/templates/spectrum/bars-linear/demo-graph-acid.json +1 -0
- package/skills/agentvfx/templates/spectrum/bars-linear/demo-graph-black.json +1 -0
- package/skills/agentvfx/templates/spectrum/bars-linear/fx.json +632 -0
- package/skills/agentvfx/templates/spectrum/bars-linear/main.frag +233 -0
- package/skills/agentvfx/templates/spectrum/bars-linear/pass0.frag +91 -0
- package/skills/agentvfx/templates/spectrum/bars-mirror/demo-field-acid.json +1 -0
- package/skills/agentvfx/templates/spectrum/bars-mirror/demo-field-ultramarine.json +1 -0
- package/skills/agentvfx/templates/spectrum/bars-mirror/fx.json +539 -0
- package/skills/agentvfx/templates/spectrum/bars-mirror/main.frag +193 -0
- package/skills/agentvfx/templates/spectrum/bars-mirror/pass0.frag +91 -0
- package/skills/agentvfx/templates/spectrum/bass-circle/demo-bracket-black.json +1 -0
- package/skills/agentvfx/templates/spectrum/bass-circle/demo-bracket-ultramarine.json +1 -0
- package/skills/agentvfx/templates/spectrum/bass-circle/fx.json +552 -0
- package/skills/agentvfx/templates/spectrum/bass-circle/main.frag +258 -0
- package/skills/agentvfx/templates/spectrum/bass-circle/pass0.frag +91 -0
- package/skills/agentvfx/templates/spectrum/label-bars/demo-deck-black.json +1 -0
- package/skills/agentvfx/templates/spectrum/label-bars/demo-deck-ultramarine.json +1 -0
- package/skills/agentvfx/templates/spectrum/label-bars/fx.json +552 -0
- package/skills/agentvfx/templates/spectrum/label-bars/main.frag +223 -0
- package/skills/agentvfx/templates/spectrum/label-bars/pass0.frag +91 -0
- package/skills/agentvfx/templates/spectrum/spectrum-particles/demo-cloud-black.json +1 -0
- package/skills/agentvfx/templates/spectrum/spectrum-particles/demo-cloud-ultramarine.json +1 -0
- package/skills/agentvfx/templates/spectrum/spectrum-particles/fx.json +584 -0
- package/skills/agentvfx/templates/spectrum/spectrum-particles/main.frag +240 -0
- package/skills/agentvfx/templates/spectrum/spectrum-particles/pass0.frag +101 -0
- package/skills/agentvfx/templates/spectrum/spectrum-radial/demo-starburst-black.json +1 -0
- package/skills/agentvfx/templates/spectrum/spectrum-radial/demo-starburst-ultramarine.json +1 -0
- package/skills/agentvfx/templates/spectrum/spectrum-radial/fx.json +566 -0
- package/skills/agentvfx/templates/spectrum/spectrum-radial/main.frag +217 -0
- package/skills/agentvfx/templates/spectrum/spectrum-radial/pass0.frag +91 -0
- package/skills/agentvfx/templates/spectrum/waveform-line/demo-strip-acid.json +1 -0
- package/skills/agentvfx/templates/spectrum/waveform-line/demo-strip-black.json +1 -0
- package/skills/agentvfx/templates/spectrum/waveform-line/fx.json +481 -0
- package/skills/agentvfx/templates/spectrum/waveform-line/main.frag +219 -0
- package/skills/agentvfx/templates/spectrum/waveform-line/pass0.frag +48 -0
- package/skills/agentvfx/templates/spectrum/waveform-line/pass1.frag +86 -0
- package/skills/agentvfx/test/_render_light.mjs +38 -0
- package/skills/agentvfx/test/audio-stereo.test.mjs +45 -0
- package/skills/agentvfx/test/audio.test.mjs +257 -0
- package/skills/agentvfx/test/brutal.test.mjs +190 -0
- package/skills/agentvfx/test/concept-collage-layout.test.mjs +236 -0
- package/skills/agentvfx/test/concept-collage-scenes.test.mjs +305 -0
- package/skills/agentvfx/test/concept-collage-typefx.test.mjs +153 -0
- package/skills/agentvfx/test/concept-collage.test.mjs +84 -0
- package/skills/agentvfx/test/concept-lattice.test.mjs +133 -0
- package/skills/agentvfx/test/concept-signal-cut.test.mjs +172 -0
- package/skills/agentvfx/test/credit-overlay.test.mjs +58 -0
- package/skills/agentvfx/test/credit.test.mjs +42 -0
- package/skills/agentvfx/test/doctor.test.mjs +31 -0
- package/skills/agentvfx/test/encode.test.mjs +22 -0
- package/skills/agentvfx/test/fixtures/r7-collage-LAYOUTS.json +5780 -0
- package/skills/agentvfx/test/fixtures/score-bad-duration.json +7 -0
- package/skills/agentvfx/test/fixtures/score-bad-safety.json +8 -0
- package/skills/agentvfx/test/fixtures/score-identity-footage.json +8 -0
- package/skills/agentvfx/test/fixtures/score-missing-template.json +7 -0
- package/skills/agentvfx/test/fixtures/score-ok.json +8 -0
- package/skills/agentvfx/test/fixtures/score-strobe-12hz.json +8 -0
- package/skills/agentvfx/test/fixtures/score-text-probe.json +1 -0
- package/skills/agentvfx/test/flash-audit.test.mjs +150 -0
- package/skills/agentvfx/test/flash.test.mjs +83 -0
- package/skills/agentvfx/test/footage.test.mjs +88 -0
- package/skills/agentvfx/test/glitch.test.mjs +272 -0
- package/skills/agentvfx/test/impact.test.mjs +231 -0
- package/skills/agentvfx/test/imports.test.mjs +39 -0
- package/skills/agentvfx/test/light.test.mjs +200 -0
- package/skills/agentvfx/test/loop.test.mjs +80 -0
- package/skills/agentvfx/test/psychedelic.test.mjs +99 -0
- package/skills/agentvfx/test/render.test.mjs +73 -0
- package/skills/agentvfx/test/sacred.test.mjs +175 -0
- package/skills/agentvfx/test/schema.test.mjs +103 -0
- package/skills/agentvfx/test/scope.test.mjs +306 -0
- package/skills/agentvfx/test/spectrum.test.mjs +165 -0
- package/skills/agentvfx/test/text.test.mjs +142 -0
- package/skills/agentvfx/test/web.test.mjs +397 -0
- package/skills/agentvfx/test-media/SOURCES.md +39 -0
- package/skills/agentvfx/test-media/beat-132.mp3 +0 -0
- package/skills/agentvfx/test-media/clip-01.mp4 +0 -0
- package/skills/agentvfx/test-media/clip-02.mp4 +0 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"""Procedural terminal-screen images (bitmap font drawn by font.py, text composed here). No external assets."""
|
|
2
|
+
import random
|
|
3
|
+
|
|
4
|
+
import bpy
|
|
5
|
+
import numpy as np
|
|
6
|
+
|
|
7
|
+
from font import glyph
|
|
8
|
+
|
|
9
|
+
W, H = 768, 1152
|
|
10
|
+
CW, CH, PX = 12, 18, 2
|
|
11
|
+
COLS, ROWS = W // CW, H // CH
|
|
12
|
+
|
|
13
|
+
_WORDS = ["SYNC", "NODE", "LINK", "RELAY", "CARRIER", "BUFFER", "PHASE", "VECTOR", "SIGNAL", "KERNEL", "UPLINK",
|
|
14
|
+
"TRACE", "DAEMON", "CACHE", "SECTOR", "ARRAY", "RASTER", "BEACON", "LATCH", "OSC", "MUX", "DECK"]
|
|
15
|
+
_STATE = ["OK", "OK", "OK", "LOCKED", "NOMINAL", "DRIFT", "WARN", "STANDBY", "ARMED", "OK"]
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def _hex(rng, n):
|
|
19
|
+
return "".join(rng.choice("0123456789ABCDEF") for _ in range(n))
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _line(rng, kind):
|
|
23
|
+
if kind == 0:
|
|
24
|
+
return f"[{rng.randint(0, 9999):04d}.{rng.randint(0, 99):02d}] {rng.choice(_WORDS)}_{rng.randint(0, 31):02d} {rng.choice(_STATE)} 0x{_hex(rng, 6)}"
|
|
25
|
+
if kind == 1:
|
|
26
|
+
return f"0x{_hex(rng, 4)}: " + " ".join(_hex(rng, 2) for _ in range(rng.randint(8, 14)))
|
|
27
|
+
if kind == 2:
|
|
28
|
+
n = rng.randint(0, 20)
|
|
29
|
+
return f"> {rng.choice(_WORDS)} --{rng.choice(_WORDS).lower()} [{'#' * n}{'.' * (20 - n)}] {n * 5:3d}%"
|
|
30
|
+
if kind == 3:
|
|
31
|
+
return f"{rng.choice(_WORDS)}.{rng.choice(_WORDS)} = {rng.random() * 100:7.3f} // {rng.choice(_STATE)}"
|
|
32
|
+
return ""
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _draw_char(buf, ch, col, row):
|
|
36
|
+
g = glyph(ch)
|
|
37
|
+
y0, x0 = row * CH + 2, col * CW
|
|
38
|
+
for gy, r in enumerate(g):
|
|
39
|
+
for gx, v in enumerate(r):
|
|
40
|
+
if v:
|
|
41
|
+
buf[y0 + gy * PX:y0 + gy * PX + PX, x0 + gx * PX:x0 + gx * PX + PX] = 1.0
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _blur(a):
|
|
45
|
+
a = a + 0.5 * (np.roll(a, 1, 0) + np.roll(a, -1, 0))
|
|
46
|
+
a = a + 0.5 * (np.roll(a, 1, 1) + np.roll(a, -1, 1))
|
|
47
|
+
return a / 4.0
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def terminal_pixels(seed, density=0.75):
|
|
51
|
+
"""Float luminance image HxW (top row first) holding a wrapping scroll of fake terminal output."""
|
|
52
|
+
rng = random.Random(seed)
|
|
53
|
+
buf = np.zeros((H, W), dtype=np.float32)
|
|
54
|
+
for row in range(ROWS):
|
|
55
|
+
if rng.random() > density:
|
|
56
|
+
continue
|
|
57
|
+
kind = rng.choice([0, 0, 1, 1, 2, 3])
|
|
58
|
+
indent = 3 + rng.choice([0, 0, 0, 2, 4])
|
|
59
|
+
text = (" " * indent + _line(rng, kind))[:COLS - 5]
|
|
60
|
+
bright = 1.0 if rng.random() > 0.2 else 0.55
|
|
61
|
+
row_buf = np.zeros_like(buf)
|
|
62
|
+
for col, ch in enumerate(text):
|
|
63
|
+
if ch != " ":
|
|
64
|
+
_draw_char(row_buf, ch, col, row)
|
|
65
|
+
buf = np.maximum(buf, row_buf * bright)
|
|
66
|
+
_draw_char(buf, "BLOCK", rng.randint(4, 30), 20)
|
|
67
|
+
return np.clip(_blur(buf) * 1.35, 0.0, 1.0)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def make_image(name, seed, density=0.75):
|
|
71
|
+
pix = terminal_pixels(seed, density)
|
|
72
|
+
rgba = np.repeat(np.flipud(pix)[:, :, None], 4, axis=2)
|
|
73
|
+
rgba[:, :, 3] = 1.0
|
|
74
|
+
img = bpy.data.images.new(name, W, H, alpha=False, float_buffer=False)
|
|
75
|
+
img.colorspace_settings.name = "Non-Color"
|
|
76
|
+
img.pixels.foreach_set(rgba.ravel())
|
|
77
|
+
img.update()
|
|
78
|
+
img.pack()
|
|
79
|
+
return img
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"""The CRT bank: rack frame, instanced monitors with per-object screen variants, status LEDs, cable tray + cables."""
|
|
2
|
+
import math
|
|
3
|
+
import random
|
|
4
|
+
|
|
5
|
+
import bpy
|
|
6
|
+
|
|
7
|
+
import crt
|
|
8
|
+
from crt import SLOT_PLASTIC, SLOT_GLASS, SLOT_VENT, SLOT_STEEL, SLOT_LED
|
|
9
|
+
from room import add_box
|
|
10
|
+
|
|
11
|
+
COLS, ROWS = 9, 5
|
|
12
|
+
BAY, PITCH, BASE_Z = 0.56, 0.5, 0.24
|
|
13
|
+
FRONT_Y = -0.05
|
|
14
|
+
HERO = (2, 4) # row, column of the monitor the close-up shot holds on
|
|
15
|
+
|
|
16
|
+
# (image seed, tint, strength, rows per second) ; None image = unpowered glass
|
|
17
|
+
VARIANTS = {
|
|
18
|
+
"green_a": (11, (0.20, 1.00, 0.34), 6.0, 5.0),
|
|
19
|
+
"green_b": (23, (0.28, 1.00, 0.40), 5.5, 2.5),
|
|
20
|
+
"amber": (37, (1.00, 0.52, 0.07), 6.5, 3.5),
|
|
21
|
+
"cold": (51, (0.62, 0.85, 1.00), 5.0, 6.0),
|
|
22
|
+
}
|
|
23
|
+
WEIGHTS = ["green_a"] * 5 + ["green_b"] * 4 + ["amber"] * 4 + ["cold"] * 2 + [None] * 3
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def monitor_position(r, c):
|
|
27
|
+
x0 = -(COLS - 1) / 2 * BAY
|
|
28
|
+
return x0 + c * BAY, FRONT_Y, BASE_Z + r * PITCH + PITCH / 2
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def build_rack(coll, mats):
|
|
32
|
+
x0 = -(COLS - 1) / 2 * BAY - BAY / 2
|
|
33
|
+
height = ROWS * PITCH
|
|
34
|
+
for k in range(COLS + 1):
|
|
35
|
+
add_box(coll, f"post_{k}", (x0 + k * BAY, 0.22, BASE_Z + height / 2), (0.04, 0.54, height), mats["steel"], 0.004)
|
|
36
|
+
for r in range(ROWS + 1):
|
|
37
|
+
add_box(coll, f"shelf_{r}", (0, 0.22, BASE_Z + r * PITCH), (COLS * BAY, 0.54, 0.018), mats["steel"], 0.003)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def build_monitors(coll, mats, screens, rng):
|
|
41
|
+
mesh, _ = crt.build_crt_mesh()
|
|
42
|
+
for m in (mats["plastic"], mats["glass_base"], mats["vent"], mats["steel"], mats["led"]):
|
|
43
|
+
mesh.materials.append(m)
|
|
44
|
+
objs = {}
|
|
45
|
+
for r in range(ROWS):
|
|
46
|
+
for c in range(COLS):
|
|
47
|
+
ob = bpy.data.objects.new(f"crt_{r}_{c}", mesh)
|
|
48
|
+
x, y, _ = monitor_position(r, c)
|
|
49
|
+
s = rng.uniform(0.9, 1.06)
|
|
50
|
+
ob.location = (x + rng.uniform(-0.012, 0.012), y + (0.0 if rng.random() > 0.2 else rng.uniform(0.0, 0.06)), BASE_Z + r * PITCH + 0.22 * s)
|
|
51
|
+
ob.rotation_euler = (0, 0, math.radians(rng.uniform(-2.2, 2.2)))
|
|
52
|
+
ob.scale = (s, s, s)
|
|
53
|
+
coll.objects.link(ob)
|
|
54
|
+
key = "green_a" if (r, c) == HERO else rng.choice(WEIGHTS)
|
|
55
|
+
slot = ob.material_slots[SLOT_GLASS]
|
|
56
|
+
slot.link = "OBJECT"
|
|
57
|
+
slot.material = screens[key] if key else mats["glass_off"]
|
|
58
|
+
objs[(r, c)] = ob
|
|
59
|
+
return objs
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def build_tray_and_cables(coll, mats, rng):
|
|
63
|
+
steel, rub = mats["steel"], mats["rubber"]
|
|
64
|
+
tray_z, tray_y = 3.02, -0.55
|
|
65
|
+
for side in (-0.2, 0.2):
|
|
66
|
+
add_box(coll, "tray_rail", (0, tray_y + side, tray_z), (5.6, 0.03, 0.09), steel, 0.004)
|
|
67
|
+
for i in range(46):
|
|
68
|
+
add_box(coll, "tray_rung", (-2.7 + i * 0.118, tray_y, tray_z - 0.04), (0.025, 0.44, 0.012), steel, 0.002)
|
|
69
|
+
for i in range(6):
|
|
70
|
+
pts = [(-2.8 + j * 1.12, tray_y + rng.uniform(-0.12, 0.12), tray_z + 0.02 + rng.uniform(0, 0.05)) for j in range(6)]
|
|
71
|
+
crt.add_cable(f"bundle_{i}", pts, rng.uniform(0.016, 0.026), rub, coll, seed=i, sag=0.03)
|
|
72
|
+
x0 = -(COLS - 1) / 2 * BAY - BAY / 2
|
|
73
|
+
for k in (1, 3, 4, 6, 8):
|
|
74
|
+
x = x0 + k * BAY
|
|
75
|
+
bottom = BASE_Z + rng.choice([1, 2, 3]) * PITCH
|
|
76
|
+
pts = [(x - 0.02, tray_y, tray_z), (x - 0.02, -0.25, tray_z - 0.25), (x + 0.015, FRONT_Y - 0.06, tray_z - 0.7),
|
|
77
|
+
(x + 0.02, FRONT_Y - 0.06, (tray_z + bottom) / 2), (x, FRONT_Y - 0.05, bottom + 0.1), (x, 0.25, bottom - 0.02)]
|
|
78
|
+
crt.add_cable(f"drop_{k}", pts, rng.uniform(0.014, 0.022), rub, coll, seed=k, sag=0.0)
|
|
79
|
+
for i in range(4):
|
|
80
|
+
x = rng.uniform(-1.6, 1.6)
|
|
81
|
+
pts = [(x, -1.15, 0.3), (x + rng.uniform(-0.3, 0.3), -1.4, 0.03), (x + rng.uniform(-1, 1), -2.2, 0.02),
|
|
82
|
+
(x + rng.uniform(-1.6, 1.6), -3.2, 0.02), (x + rng.uniform(-2, 2), -4.4, 0.02), (x + rng.uniform(-2, 2), -6.0, 0.02)]
|
|
83
|
+
crt.add_cable(f"floor_{i}", pts, rng.uniform(0.02, 0.034), rub, coll, seed=40 + i, sag=0.0)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def build_status_array(coll, mats, rng):
|
|
87
|
+
"""Rows of tiny status LEDs set into the lintel face."""
|
|
88
|
+
me = bpy.data.meshes.new("led_chip")
|
|
89
|
+
import bmesh
|
|
90
|
+
bm = bmesh.new()
|
|
91
|
+
bmesh.ops.create_cube(bm, size=1.0)
|
|
92
|
+
bm.to_mesh(me)
|
|
93
|
+
bm.free()
|
|
94
|
+
me.materials.append(mats["led"])
|
|
95
|
+
y_face = -0.35 - 0.975
|
|
96
|
+
for row in range(3):
|
|
97
|
+
for i in range(48):
|
|
98
|
+
if rng.random() < 0.3:
|
|
99
|
+
continue
|
|
100
|
+
ob = bpy.data.objects.new("led", me)
|
|
101
|
+
ob.scale = (0.014, 0.004, 0.009)
|
|
102
|
+
ob.location = (-2.6 + i * 0.11 + (0.5 if i % 12 > 5 else 0) * 0.0, y_face - 0.002, 3.28 + row * 0.1)
|
|
103
|
+
coll.objects.link(ob)
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Plates: Blender-rendered background footage
|
|
2
|
+
|
|
3
|
+
A plate is a short procedural Blender render used as `input.video` footage under an agentvfx template.
|
|
4
|
+
Scenes live in `plates/<scene>/scene.py`; `scripts/plate.mjs` runs Blender headless (Cycles, Metal GPU, OIDN denoise),
|
|
5
|
+
then encodes the frames to H.264 `film.mp4` with ffmpeg.
|
|
6
|
+
|
|
7
|
+
node scripts/plate.mjs --scene terminalcore --shot wall|closeup|gallery --out <dir> \
|
|
8
|
+
--width 640 --height 360 --seconds 4 --fps 30 --samples 40
|
|
9
|
+
|
|
10
|
+
- Output: `<dir>/film.mp4`, `still_first|mid|last.png`, `plate.json` (measured s/frame), `blender.log`.
|
|
11
|
+
- `--frame N` renders a single still for look-dev; `--quality preview|final`, `--exposure`, `--bloom`, `--key`, `--haze` tune the grade.
|
|
12
|
+
- Requirements: Blender 5.x (`BLENDER_PATH` or the macOS app bundle) and ffmpeg (`FFMPEG_PATH` or `PATH`).
|
|
13
|
+
- Everything is generated in code (geometry, shaders, bitmap font, terminal text); no downloaded assets.
|
|
14
|
+
- Preview defaults are small and fast (`--quality preview`). For finals add `--quality final` and raise `--width/--height`:
|
|
15
|
+
256 samples, accurate denoise, camera motion blur (camera keyframed per frame), crf 14. Gallery at 1920x1080 final measured
|
|
16
|
+
about 109 s/frame (one test frame). Time scales with pixels x samples; schedule full finals deliberately.
|
|
17
|
+
|
|
18
|
+
Available scenes: `terminalcore` (see `plates/terminalcore/README.md`), shots `wall` and `closeup` (dark brutalist, handheld)
|
|
19
|
+
and `gallery` (clean hyper-real concrete exhibition room, CRT wall as an installation, steady dolly, lighter grain; own
|
|
20
|
+
exposure/haze/bloom defaults). Example: `--shot gallery --out gallery/plates/terminalcore-gallery` (measured 2.0 s/frame at 640x360, 56 samples, Metal GPU: 240 s for 120 frames).
|
|
21
|
+
Adding a scene: create `plates/<name>/scene.py` that accepts the same `--shot --out --width --height --seconds --fps --samples --frame` args
|
|
22
|
+
and writes numbered PNGs to `<out>/frames/f_####.png` (or `<out>/still_NNN.png` with `--frame`).
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# Template format
|
|
2
|
+
|
|
3
|
+
A template is a folder `templates/<family>/<id>/` with:
|
|
4
|
+
|
|
5
|
+
- `fx.json`: ISF 2.0-compatible JSON plus one namespaced key `X_AGENTVFX`
|
|
6
|
+
- `main.frag`: the last (or only) pass
|
|
7
|
+
- optional `pass0.frag`, `pass1.frag`, ...: earlier passes, in `PASSES` order
|
|
8
|
+
- optional `demo-<preset>.json`: FX scores that render the gallery clips
|
|
9
|
+
|
|
10
|
+
`vfx.mjs validate` checks every template; `vfx.mjs list` shows them.
|
|
11
|
+
|
|
12
|
+
## fx.json
|
|
13
|
+
|
|
14
|
+
```json
|
|
15
|
+
{
|
|
16
|
+
"DESCRIPTION": "one line: what it looks like",
|
|
17
|
+
"CREDIT": "agentvfx",
|
|
18
|
+
"ISFVSN": "2",
|
|
19
|
+
"CATEGORIES": ["psychedelic"],
|
|
20
|
+
"INPUTS": [
|
|
21
|
+
{ "NAME": "tideSpeed", "TYPE": "float", "MIN": 0, "MAX": 3, "DEFAULT": 0.6 },
|
|
22
|
+
{ "NAME": "tideWaves", "TYPE": "long", "MIN": 1, "MAX": 3, "DEFAULT": 2 },
|
|
23
|
+
{ "NAME": "halo", "TYPE": "bool", "DEFAULT": false },
|
|
24
|
+
{ "NAME": "tint", "TYPE": "color", "DEFAULT": [1, 0, 0.5, 1] },
|
|
25
|
+
{ "NAME": "center", "TYPE": "point2D", "DEFAULT": [0.5, 0.5] }
|
|
26
|
+
],
|
|
27
|
+
"PASSES": [
|
|
28
|
+
{ "TARGET": "smoothLuma", "FLOAT": true },
|
|
29
|
+
{ "TARGET": "trail", "PERSISTENT": true, "FLOAT": true },
|
|
30
|
+
{}
|
|
31
|
+
],
|
|
32
|
+
"X_AGENTVFX": {
|
|
33
|
+
"id": "sacred",
|
|
34
|
+
"family": "psychedelic",
|
|
35
|
+
"input": "footage",
|
|
36
|
+
"spdx": "LicenseRef-agentvfx",
|
|
37
|
+
"flash": "none",
|
|
38
|
+
"fps": 30,
|
|
39
|
+
"palette": true,
|
|
40
|
+
"presets": { "a": { "tideSpeed": 0.4 }, "b": {}, "c": {} },
|
|
41
|
+
"audioBind": { "tideSpeed": "bass" },
|
|
42
|
+
"safeSubstitute": { "params": { "flashAmount": 0 } },
|
|
43
|
+
"credits": ["iq cosine palette, https://iquilezles.org/articles/palettes/"]
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
- INPUT types: `float`, `long` (int; optional `VALUES` / `LABELS`), `bool`, `color` (`[r,g,b,a]` 0..1, sRGB),
|
|
49
|
+
`point2D`, `image`, `audio`, `audioFFT`.
|
|
50
|
+
- `X_AGENTVFX.input`: `generative` (no clip), `footage` (needs `input.video`), `either`.
|
|
51
|
+
- `spdx`: LicenseRef-agentvfx (the agentvfx licence, the library's own), MIT, BSD-2-Clause, BSD-3-Clause, Apache-2.0 or CC0-1.0 only. Shaders are written fresh;
|
|
52
|
+
algorithms are credited by name and URL in `credits` and in comments. No Shadertoy ports, no Lygia, no
|
|
53
|
+
hydra-synth, no MilkDrop presets.
|
|
54
|
+
- `flash`: `none`, `possible` (can flash at some settings) or `strobe` (flashes by design).
|
|
55
|
+
- At least 3 presets. Preset values are range-checked against `INPUTS`.
|
|
56
|
+
|
|
57
|
+
## Passes
|
|
58
|
+
|
|
59
|
+
With no `PASSES`, `main.frag` is the only pass. With `PASSES`, pass *i* is `pass<i>.frag`, except the
|
|
60
|
+
last, which is `main.frag`. A pass with `TARGET` renders into a named buffer that every later pass
|
|
61
|
+
(and, if `PERSISTENT`, every pass of the next frame) can sample as `uniform sampler2D <TARGET>`.
|
|
62
|
+
Buffers are RGBA16F (`FLOAT` is accepted for ISF compatibility; all buffers are float). A persistent
|
|
63
|
+
buffer holds the previous frame's value when it is read before it is written in the current frame.
|
|
64
|
+
Frames are rendered strictly in order, so persistent buffers are deterministic.
|
|
65
|
+
|
|
66
|
+
## The prelude (prepended to every pass by the engine; do not redeclare)
|
|
67
|
+
|
|
68
|
+
```glsl
|
|
69
|
+
#version 300 es
|
|
70
|
+
precision highp float; precision highp int; precision highp sampler2D;
|
|
71
|
+
in vec2 vUv; // 0..1, origin bottom-left
|
|
72
|
+
out vec4 fragColor; // LINEAR-light RGB, alpha 1
|
|
73
|
+
uniform float TIME; // seconds = FRAMEINDEX / fps
|
|
74
|
+
uniform float TIMEDELTA; // 1 / fps
|
|
75
|
+
uniform int FRAMEINDEX;
|
|
76
|
+
uniform int PASSINDEX;
|
|
77
|
+
uniform vec2 RENDERSIZE; // pixels of the current pass target
|
|
78
|
+
uniform float SEED; // 0..1 from the score seed
|
|
79
|
+
uniform sampler2D inputImage; // footage frame or the layer below; linear light; black when absent
|
|
80
|
+
uniform bool HAS_INPUT;
|
|
81
|
+
uniform vec3 PALETTE[8]; // linear light, from the score palette (or the template default)
|
|
82
|
+
uniform int PALETTE_COUNT;
|
|
83
|
+
// audio (zero when no audio): per frame, normalised as in references/audio.md
|
|
84
|
+
uniform float AUDIO_RMS, AUDIO_PEAK, AUDIO_BASS, AUDIO_MID, AUDIO_TREB, AUDIO_BASS_ATT, AUDIO_MID_ATT,
|
|
85
|
+
AUDIO_TREB_ATT, AUDIO_FLUX, AUDIO_ONSET, AUDIO_BEAT, AUDIO_BEATPHASE, AUDIO_BPM;
|
|
86
|
+
uniform sampler2D audio; // 512x2: row 0 = wave L/mono, row 1 = wave R, values 0..1 (0.5 = silence)
|
|
87
|
+
uniform sampler2D audioFFT; // 512x1 spectrum 0..1, low to high
|
|
88
|
+
uniform float AUDIO_BANDS[32];
|
|
89
|
+
#define isf_FragNormCoord vUv
|
|
90
|
+
#define IMG_NORM_PIXEL(img, uv) texture(img, uv)
|
|
91
|
+
#define IMG_THIS_NORM_PIXEL(img) texture(img, vUv)
|
|
92
|
+
#define IMG_PIXEL(img, px) texture(img, (px) / vec2(textureSize(img, 0)))
|
|
93
|
+
#define IMG_THIS_PIXEL(img) texture(img, vUv)
|
|
94
|
+
#define IMG_SIZE(img) vec2(textureSize(img, 0))
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Each declared INPUT becomes a uniform of the same name: float → `float`, long → `int`, bool → `bool`,
|
|
98
|
+
color → `vec4` (converted to linear), point2D → `vec2`, image/audio/audioFFT → `sampler2D`.
|
|
99
|
+
|
|
100
|
+
## Common helpers (also in the prelude)
|
|
101
|
+
|
|
102
|
+
```glsl
|
|
103
|
+
float hash12(vec2 p); // seeded by SEED, 0..1
|
|
104
|
+
vec2 hash22(vec2 p);
|
|
105
|
+
float vnoise(vec2 p); // value noise 0..1
|
|
106
|
+
float fbm(vec2 p, int octaves); // 0..1
|
|
107
|
+
float luma(vec3 linRgb); // Rec.709 luminance of linear RGB
|
|
108
|
+
vec3 rgb2hsv(vec3 c); vec3 hsv2rgb(vec3 c); // on linear values; fine for effects
|
|
109
|
+
vec3 cosPalette(float t, vec3 a, vec3 b, vec3 c, vec3 d); // iq: a + b*cos(6.28318*(c*t + d))
|
|
110
|
+
vec3 paletteRamp(float t); // PALETTE as a clamped ramp, t 0..1
|
|
111
|
+
vec3 paletteCycle(float t); // PALETTE as a cyclic ramp, t wraps
|
|
112
|
+
vec3 srgbToLinear(vec3 c); vec3 linearToSrgb(vec3 c);
|
|
113
|
+
mat2 rot(float a);
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
The engine converts the last pass's linear output to sRGB with blue-noise dither before readback.
|
|
117
|
+
No `#version` line, no `precision` line and no `out` declaration in template files.
|
|
118
|
+
|
|
119
|
+
## Text layer (engine-drawn type)
|
|
120
|
+
|
|
121
|
+
A template may declare `X_AGENTVFX.text`: a list of text items the engine draws every frame with Canvas 2D and
|
|
122
|
+
system fonts into `uniform sampler2D TEXTMASK` (R = glyph and line ink, G = solid box/bar fill; `HAS_TEXT` is
|
|
123
|
+
true). The template colours the mask (e.g. `mix(bg, ink, m.r)`). Scores override strings with
|
|
124
|
+
`"labels": { "<key>": "..." }`.
|
|
125
|
+
|
|
126
|
+
```json
|
|
127
|
+
"text": [
|
|
128
|
+
{ "key": "artist", "default": "ARTIST NAME", "x": 0.03, "y": 0.06, "size": 0.07, "font": "display", "style": "outline", "box": "tab" },
|
|
129
|
+
{ "key": "title", "default": "TRACK TITLE", "x": 0.97, "y": 0.05, "size": 0.09, "font": "tall", "align": "right" },
|
|
130
|
+
{ "key": "log", "default": "BOOT 0x7G75\nCACHE OK", "x": 0.1, "y": 0.2, "size": 0.025, "font": "mono", "reveal": "type", "revealStart": 0, "revealDur": 2 },
|
|
131
|
+
{ "key": "tag", "default": "HEADLINE", "x": 0.5, "y": 0.45, "size": 0.12, "font": "grotesk", "align": "center", "box": "bar" }
|
|
132
|
+
]
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
- `x`, `y`: top-left of the block as fractions of the frame (align moves the anchor); `size`: cap size as a fraction of frame height.
|
|
136
|
+
- `font`: `display` (condensed, DIN-like), `tall` (ultra-tall thin condensed), `grotesk` (heavy Helvetica-like), `mono` (Menlo-like), `serif`.
|
|
137
|
+
- `style`: `fill` or `outline`; `box`: `none`, `frame` (rounded outline), `tab` (outline with a folder tab), `bar` (solid fill in G).
|
|
138
|
+
- `reveal`: `none`, `type` (typewriter with a block cursor), `decode` (seeded random glyphs settle left to right) over `revealStart` .. `revealStart + revealDur` seconds. Deterministic per frame and seed.
|
|
139
|
+
- `\n` makes new lines; `lineHeight` (default 1.15), `tracking` (em).
|
|
140
|
+
- `family`: an installed font family named directly, e.g. `"family": "Pretendard", "weight": 900` (also accepted in `textStyle`). The CSS stack becomes `"<family>", <the generic stack of `font`>`, so on a machine without that family the item silently falls back to the generic `font` (`display`, `tall`, `grotesk`, `mono`, `serif`); `font` still decides the vertical stretch (`tall`) and the fallback. Names are limited to letters, digits, spaces, `.`, `_`, `-` (up to 64 characters). The engine waits for the face to resolve (`document.fonts.load`) before the first frame. Only the font name is referenced: no font file is read, copied or bundled by the skill, and nothing here grants a licence for any font. Installed on the author's Mac and used by the collage experimental presets: `Monument Extended` (weights 400 / 800; commercial font, licensed to the user, never redistribute it with this skill), `Pretendard` (100..900, Hangul and Latin; SIL OFL 1.1) and `MesloLGS NF` (monospace, Apache-2.0). Glyph widths differ per font, so a layout tuned for one face moves a little when the fallback is used.
|
|
141
|
+
- `channel`: `r` (default), `g` or `b`. The glyph ink goes into that mask channel, so a template can keep up to three independent sheets of type that overlap on the page and read each one with `TEXTMASK.r / .g / .b`. (`box: "bar"` fill always goes to G, so keep box items off the `g` sheet.)
|
|
142
|
+
- `set`: integer 0..9 (default 0). A template that declares any item with a `set` draws only the items whose `set` equals its `textSet` input (an INPUT of type long, default 0), so presets can each own a whole text sheet without sharing page space. Templates without `set` items are unaffected.
|
|
143
|
+
- A score may restyle any declared item without editing the template: `"textStyle": { "<key>": { "font": "mono", "size": 0.12, "x": 0.05, "y": 0.6, "tracking": 0.1, "align": "left", "weight": 700 } }` (every field optional; merged over the template's item; unknown keys, fonts and out-of-range values are validation errors). `labels` changes the string, `textStyle` the look.
|
|
144
|
+
- System fonts only; nothing is bundled. Text never quotes third-party marks or slogans.
|
|
145
|
+
|
|
146
|
+
## House style
|
|
147
|
+
|
|
148
|
+
Defaults are aggressive and stage-grade (spec Amendment A1): saturated colour, hard contrast, strobe,
|
|
149
|
+
glitch and noise at full strength. Never tame a default. A gentler look is a preset, not the default.
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# agentvfx on a page
|
|
2
|
+
|
|
3
|
+
`node scripts/export-web.mjs <templateId...> --out <dir>` writes three files and nothing else:
|
|
4
|
+
|
|
5
|
+
- `agentvfx.js` — the WebGL2 runtime, with the engine prelude inlined
|
|
6
|
+
- `templates.js` — `export default { <id>: { fx, passes } }` for the ids you named
|
|
7
|
+
- `demo.html` — a hero canvas, a hit button, an audio file input, and a text headline
|
|
8
|
+
|
|
9
|
+
The folder loads from disk. It does not fetch fonts, scripts, or media. Copy it into the site and import it as a module.
|
|
10
|
+
|
|
11
|
+
```js
|
|
12
|
+
import { AgentVfx } from "./agentvfx.js";
|
|
13
|
+
import templates from "./templates.js";
|
|
14
|
+
|
|
15
|
+
const fx = await AgentVfx.mount(canvas, {
|
|
16
|
+
templates,
|
|
17
|
+
template: "sacred",
|
|
18
|
+
preset: "sacred-classic",
|
|
19
|
+
params: { tideSpeed: 0.4 },
|
|
20
|
+
palette: "rainbow",
|
|
21
|
+
source: image,
|
|
22
|
+
dpr: 1,
|
|
23
|
+
});
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
`source` may be omitted (generative), an `<img>`, a `<video>`, or another canvas. `AgentVfx.textSource({ text, font, color, background, width, height })` returns a canvas you can pass as `source`.
|
|
27
|
+
|
|
28
|
+
`fx.set(params)` replaces input values. `fx.trigger(id, { preset, params, durationMs })` draws that template over the current frame for `durationMs` (default 400). `fx.audio(elementOrStream)` connects an AnalyserNode and fills `AUDIO_*`, the 512×2 `audio` wave texture, the 512×1 `audioFFT` texture, and `AUDIO_BANDS[32]`. `fx.pause()`, `fx.resume()`, and `fx.destroy()` stop, continue, and release the context. `fx.renderAt(t)` paints one frame at time `t` in seconds and holds it, for tests and stills.
|
|
29
|
+
|
|
30
|
+
The canvas backing store follows its CSS size times `devicePixelRatio`, capped at `dpr` (default 1.5). A `ResizeObserver` rebuilds the targets. An `IntersectionObserver` pauses the loop when the canvas is fully off screen. A lost WebGL context is restored on `webglcontextrestored`.
|
|
31
|
+
|
|
32
|
+
`prefers-reduced-motion: reduce` paints one still frame and ignores `trigger()`, unless `motion: "always"` is set. A template whose `X_AGENTVFX.flash` is `"strobe"` logs one `console.warn` that names WCAG 2.3.1. The effect still runs when motion is allowed.
|
|
33
|
+
|
|
34
|
+
Live flash guard. Every shown frame is read back on the render audit's grid and checked with the audit's own detector. A frame that would make a seventh luminance transition, or a second saturated-red transition, within one second is replaced by the previous frame before the browser shows it; motion then stops, the runtime logs a `console.warn`, and calls `onFlashGuard({ template, reason, shownTransitions, shownRedTransitions })` if you passed one to `mount`. `fx.resume()` starts again with a fresh guard. A good handler resets the parameters the visitor changed and resumes once, and falls back to a still or an audited video loop if it trips again. Sliders, pointer mappings and hits can all push a template past the limit even with its `safeSubstitute` values, so keep the guard on; `flashGuard: false` turns it off for a page that does its own checking. The guard costs one small readback per shown frame. If a pass fails to compile, the runtime logs `console.error` with the template id and the pass, clears the canvas, and does not throw into the page.
|
|
35
|
+
|
|
36
|
+
## Recipes
|
|
37
|
+
|
|
38
|
+
Hero background. Fix the canvas to the viewport, `pointer-events: none`, and mount a generative or footage template behind the copy. Cap `dpr` at 1 on a full-bleed 4K wall if the GPU falls behind; the default cap is 1.5.
|
|
39
|
+
|
|
40
|
+
```html
|
|
41
|
+
<canvas id="hero" style="position:fixed;inset:0;width:100%;height:100%;pointer-events:none"></canvas>
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Section transition. On the way into a section, `trigger` a short hit (a few hundred milliseconds) and `set` the base template's mix or speed. Remove the hit by letting `durationMs` end. Do not leave a second canvas running for a transition that is already over; call `destroy()` if the section unmounts.
|
|
45
|
+
|
|
46
|
+
Hover glitch on a button. Keep the button as a real `<button>` above the canvas. On `pointerenter` and `click`, call `trigger` with a short `durationMs`. The canvas itself stays `pointer-events: none` so the button still receives the click. Under reduced motion the hit does not fire.
|
|
47
|
+
|
|
48
|
+
Glitch or decode headline. Draw the words with `textSource` and pass that canvas as `source` on a small canvas sitting over the heading box. The DOM heading stays in the document for selection and screen readers; the canvas is decorative.
|
|
49
|
+
|
|
50
|
+
```js
|
|
51
|
+
const plate = AgentVfx.textSource({ text: "AGENTVFX", font: "700 64px sans-serif", color: "#fff", background: "#000", width: 960, height: 180 });
|
|
52
|
+
await AgentVfx.mount(headCanvas, { templates, template: "sacred", source: plate });
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Audio-reactive player. Point `<audio>` at a file the visitor picked, or at a same-origin file, then `fx.audio(audio)`. The element must be allowed to play (a click or the file input). The runtime reconnects the element through the AnalyserNode so the sound still comes out of the speakers.
|
|
56
|
+
|
|
57
|
+
Image hover Sacred. Mount Sacred with the `<img>` as `source` on a canvas that covers the image. On `pointerenter`, `set` a faster `tideSpeed` or `trigger` a short hit; on `pointerleave`, `set` the quiet preset back. The `<img>` can stay in the page underneath, with the canvas `pointer-events: none` except when the canvas is the control.
|
|
58
|
+
|
|
59
|
+
Performance budget. One live canvas per view, not one per card, unless the extras are paused. The loop stops off screen. Prefer `dpr: 1` for a full-viewport hero and the default 1.5 cap for a small headline. Persistent buffers are RGBA16F at the canvas size, so a 4K canvas is expensive; scale the CSS box down rather than uploading a 4K source and displaying it small. `pause()` when a tab or modal hides the effect. `destroy()` on teardown.
|
|
60
|
+
|
|
61
|
+
## with frontend-ui-ux
|
|
62
|
+
|
|
63
|
+
Put the canvas on its own layer: `position: absolute` or `fixed`, inset to the frame it decorates. `pointer-events: none` unless that canvas is the control the person is meant to use. DOM text, buttons, and links sit above it and stay readable; do not run a full-frame strobe under body copy without a still fallback. The effect never blocks input. Size the canvas to the section, not the document, and let the off-screen pause drop the work when the section scrolls away. Reduced motion is the default. `motion: "always"` is an explicit author choice, not the layout default.
|