agentvfx 0.0.0-stage → 0.3.5

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.
Files changed (483) hide show
  1. package/AGENTS.md +8 -0
  2. package/GEMINI.md +1 -0
  3. package/LICENSE +202 -0
  4. package/README.md +228 -2
  5. package/package.json +35 -4
  6. package/skills/agentvfx/LICENSE +202 -0
  7. package/skills/agentvfx/NOTICE +50 -0
  8. package/skills/agentvfx/SKILL.md +90 -0
  9. package/skills/agentvfx/engine/core/constants.mjs +84 -0
  10. package/skills/agentvfx/engine/core/flash-constants.mjs +23 -0
  11. package/skills/agentvfx/engine/core/flash.mjs +240 -0
  12. package/skills/agentvfx/engine/core/mark.mjs +25 -0
  13. package/skills/agentvfx/engine/core/palettes.mjs +36 -0
  14. package/skills/agentvfx/engine/core/schedule.mjs +85 -0
  15. package/skills/agentvfx/engine/core/templates.mjs +43 -0
  16. package/skills/agentvfx/engine/core/util.mjs +167 -0
  17. package/skills/agentvfx/engine/core/validate.mjs +334 -0
  18. package/skills/agentvfx/engine/node/analysis.mjs +172 -0
  19. package/skills/agentvfx/engine/node/audio.mjs +621 -0
  20. package/skills/agentvfx/engine/node/board.mjs +24 -0
  21. package/skills/agentvfx/engine/node/chrome.mjs +349 -0
  22. package/skills/agentvfx/engine/node/encode.mjs +110 -0
  23. package/skills/agentvfx/engine/node/eye.mjs +77 -0
  24. package/skills/agentvfx/engine/node/footage.mjs +129 -0
  25. package/skills/agentvfx/engine/node/frame-worker.mjs +39 -0
  26. package/skills/agentvfx/engine/node/host.mjs +31 -0
  27. package/skills/agentvfx/engine/node/job.mjs +181 -0
  28. package/skills/agentvfx/engine/node/png.mjs +112 -0
  29. package/skills/agentvfx/engine/node/render.mjs +161 -0
  30. package/skills/agentvfx/engine/node/stage-capture.mjs +187 -0
  31. package/skills/agentvfx/engine/node/stage-serve.mjs +72 -0
  32. package/skills/agentvfx/engine/node/stills.mjs +100 -0
  33. package/skills/agentvfx/engine/node/ws-server.mjs +132 -0
  34. package/skills/agentvfx/engine/web/gl.mjs +319 -0
  35. package/skills/agentvfx/engine/web/glsl-common.mjs +78 -0
  36. package/skills/agentvfx/engine/web/init.js +23 -0
  37. package/skills/agentvfx/engine/web/prelude.mjs +150 -0
  38. package/skills/agentvfx/engine/web/render.html +11 -0
  39. package/skills/agentvfx/engine/web/render.mjs +388 -0
  40. package/skills/agentvfx/engine/web/scale.mjs +15 -0
  41. package/skills/agentvfx/engine/web/text.mjs +158 -0
  42. package/skills/agentvfx/plates/terminalcore/README.md +61 -0
  43. package/skills/agentvfx/plates/terminalcore/__pycache__/crt.cpython-313.pyc +0 -0
  44. package/skills/agentvfx/plates/terminalcore/__pycache__/font.cpython-313.pyc +0 -0
  45. package/skills/agentvfx/plates/terminalcore/__pycache__/gallery.cpython-313.pyc +0 -0
  46. package/skills/agentvfx/plates/terminalcore/__pycache__/gallery_mats.cpython-313.pyc +0 -0
  47. package/skills/agentvfx/plates/terminalcore/__pycache__/gallery_room.cpython-313.pyc +0 -0
  48. package/skills/agentvfx/plates/terminalcore/__pycache__/materials.cpython-313.pyc +0 -0
  49. package/skills/agentvfx/plates/terminalcore/__pycache__/nodekit.cpython-313.pyc +0 -0
  50. package/skills/agentvfx/plates/terminalcore/__pycache__/room.cpython-313.pyc +0 -0
  51. package/skills/agentvfx/plates/terminalcore/__pycache__/shots.cpython-313.pyc +0 -0
  52. package/skills/agentvfx/plates/terminalcore/__pycache__/textures.cpython-313.pyc +0 -0
  53. package/skills/agentvfx/plates/terminalcore/__pycache__/wall.cpython-313.pyc +0 -0
  54. package/skills/agentvfx/plates/terminalcore/crt.py +143 -0
  55. package/skills/agentvfx/plates/terminalcore/font.py +80 -0
  56. package/skills/agentvfx/plates/terminalcore/gallery.py +61 -0
  57. package/skills/agentvfx/plates/terminalcore/gallery_mats.py +144 -0
  58. package/skills/agentvfx/plates/terminalcore/gallery_room.py +126 -0
  59. package/skills/agentvfx/plates/terminalcore/materials.py +170 -0
  60. package/skills/agentvfx/plates/terminalcore/nodekit.py +87 -0
  61. package/skills/agentvfx/plates/terminalcore/room.py +82 -0
  62. package/skills/agentvfx/plates/terminalcore/scene.py +219 -0
  63. package/skills/agentvfx/plates/terminalcore/shots.py +48 -0
  64. package/skills/agentvfx/plates/terminalcore/textures.py +79 -0
  65. package/skills/agentvfx/plates/terminalcore/wall.py +103 -0
  66. package/skills/agentvfx/references/plates.md +22 -0
  67. package/skills/agentvfx/references/template-format.md +149 -0
  68. package/skills/agentvfx/references/web.md +63 -0
  69. package/skills/agentvfx/runtime/agentvfx.js +708 -0
  70. package/skills/agentvfx/schemas/fx-score.schema.json +98 -0
  71. package/skills/agentvfx/scripts/export-web.mjs +157 -0
  72. package/skills/agentvfx/scripts/loop.mjs +129 -0
  73. package/skills/agentvfx/scripts/make-beat.mjs +133 -0
  74. package/skills/agentvfx/scripts/plate.mjs +82 -0
  75. package/skills/agentvfx/scripts/vfx.mjs +173 -0
  76. package/skills/agentvfx/templates/_test/feedback-counter/fx.json +11 -0
  77. package/skills/agentvfx/templates/_test/feedback-counter/main.frag +4 -0
  78. package/skills/agentvfx/templates/_test/feedback-counter/pass0.frag +4 -0
  79. package/skills/agentvfx/templates/_test/gradient/fx.json +23 -0
  80. package/skills/agentvfx/templates/_test/gradient/main.frag +5 -0
  81. package/skills/agentvfx/templates/_test/identity/fx.json +10 -0
  82. package/skills/agentvfx/templates/_test/identity/main.frag +4 -0
  83. package/skills/agentvfx/templates/_test/strobe/fx.json +14 -0
  84. package/skills/agentvfx/templates/_test/strobe/main.frag +6 -0
  85. package/skills/agentvfx/templates/_test/text-probe/fx.json +15 -0
  86. package/skills/agentvfx/templates/_test/text-probe/main.frag +6 -0
  87. package/skills/agentvfx/templates/brutal/NOTES.md +14 -0
  88. package/skills/agentvfx/templates/brutal/_src/boot-log/def.mjs +57 -0
  89. package/skills/agentvfx/templates/brutal/_src/boot-log/main.src.frag +129 -0
  90. package/skills/agentvfx/templates/brutal/_src/build.mjs +33 -0
  91. package/skills/agentvfx/templates/brutal/_src/halftone-field/def.mjs +72 -0
  92. package/skills/agentvfx/templates/brutal/_src/halftone-field/main.src.frag +94 -0
  93. package/skills/agentvfx/templates/brutal/_src/hud-deck/deck-left.src.glsl +100 -0
  94. package/skills/agentvfx/templates/brutal/_src/hud-deck/deck-right.src.glsl +61 -0
  95. package/skills/agentvfx/templates/brutal/_src/hud-deck/deck-tiles.src.glsl +153 -0
  96. package/skills/agentvfx/templates/brutal/_src/hud-deck/def.mjs +82 -0
  97. package/skills/agentvfx/templates/brutal/_src/hud-deck/main.src.frag +110 -0
  98. package/skills/agentvfx/templates/brutal/_src/hud-deck/pass0.src.frag +38 -0
  99. package/skills/agentvfx/templates/brutal/_src/shared/defs.mjs +28 -0
  100. package/skills/agentvfx/templates/brutal/_src/shared/icons.glsl +72 -0
  101. package/skills/agentvfx/templates/brutal/_src/shared/lib.glsl +115 -0
  102. package/skills/agentvfx/templates/brutal/_src/shared/screen.glsl +43 -0
  103. package/skills/agentvfx/templates/brutal/boot-log/demo-acid.json +1 -0
  104. package/skills/agentvfx/templates/brutal/boot-log/demo-phosphor.json +1 -0
  105. package/skills/agentvfx/templates/brutal/boot-log/demo-ultramarine.json +1 -0
  106. package/skills/agentvfx/templates/brutal/boot-log/fx.json +257 -0
  107. package/skills/agentvfx/templates/brutal/boot-log/main.frag +242 -0
  108. package/skills/agentvfx/templates/brutal/collage/_src/00-lib.glsl +73 -0
  109. package/skills/agentvfx/templates/brutal/collage/_src/10-spectrum-scope.glsl +73 -0
  110. package/skills/agentvfx/templates/brutal/collage/_src/20-meter-readout-cross.glsl +87 -0
  111. package/skills/agentvfx/templates/brutal/collage/_src/30-footage-fillers.glsl +92 -0
  112. package/skills/agentvfx/templates/brutal/collage/_src/40-editorial.glsl +232 -0
  113. package/skills/agentvfx/templates/brutal/collage/_src/50-typefx.glsl +163 -0
  114. package/skills/agentvfx/templates/brutal/collage/_src/60-scene-lib.glsl +104 -0
  115. package/skills/agentvfx/templates/brutal/collage/_src/61-scene-specimen.glsl +71 -0
  116. package/skills/agentvfx/templates/brutal/collage/_src/62-scene-wiring.glsl +96 -0
  117. package/skills/agentvfx/templates/brutal/collage/_src/63-scene-fieldcut.glsl +119 -0
  118. package/skills/agentvfx/templates/brutal/collage/_src/64-scene-pattern.glsl +64 -0
  119. package/skills/agentvfx/templates/brutal/collage/_src/641-scene-anatomy.glsl +49 -0
  120. package/skills/agentvfx/templates/brutal/collage/_src/642-scene-deck.glsl +78 -0
  121. package/skills/agentvfx/templates/brutal/collage/_src/643-scene-bootlog.glsl +60 -0
  122. package/skills/agentvfx/templates/brutal/collage/_src/644-scene-tunnel.glsl +48 -0
  123. package/skills/agentvfx/templates/brutal/collage/_src/645-scene-runner.glsl +42 -0
  124. package/skills/agentvfx/templates/brutal/collage/_src/646-scene-ascii.glsl +66 -0
  125. package/skills/agentvfx/templates/brutal/collage/_src/647-scene-cubewall.glsl +80 -0
  126. package/skills/agentvfx/templates/brutal/collage/_src/648-scene-vortex.glsl +46 -0
  127. package/skills/agentvfx/templates/brutal/collage/_src/649-scene-sticker.glsl +72 -0
  128. package/skills/agentvfx/templates/brutal/collage/_src/65-scene-main.glsl +1 -0
  129. package/skills/agentvfx/templates/brutal/collage/_src/650-scene-ribbon.glsl +55 -0
  130. package/skills/agentvfx/templates/brutal/collage/_src/651-scene-slab.glsl +38 -0
  131. package/skills/agentvfx/templates/brutal/collage/_src/652-scene-framedial.glsl +79 -0
  132. package/skills/agentvfx/templates/brutal/collage/_src/653-scene-tilt.glsl +40 -0
  133. package/skills/agentvfx/templates/brutal/collage/_src/654-scene-marquee.glsl +45 -0
  134. package/skills/agentvfx/templates/brutal/collage/_src/655-scene-lens.glsl +57 -0
  135. package/skills/agentvfx/templates/brutal/collage/_src/656-scene-liquid.glsl +35 -0
  136. package/skills/agentvfx/templates/brutal/collage/_src/657-scene-panelgrid.glsl +75 -0
  137. package/skills/agentvfx/templates/brutal/collage/_src/658-scene-mirror.glsl +49 -0
  138. package/skills/agentvfx/templates/brutal/collage/_src/66-scene-main.glsl +27 -0
  139. package/skills/agentvfx/templates/brutal/collage/_src/90-main.glsl +120 -0
  140. package/skills/agentvfx/templates/brutal/collage/_src/build.mjs +24 -0
  141. package/skills/agentvfx/templates/brutal/collage/_src/sync-presets.mjs +16 -0
  142. package/skills/agentvfx/templates/brutal/collage/demo-bone-lime.json +1 -0
  143. package/skills/agentvfx/templates/brutal/collage/demo-lime-sparse.json +1 -0
  144. package/skills/agentvfx/templates/brutal/collage/demo-orange-dense.json +1 -0
  145. package/skills/agentvfx/templates/brutal/collage/demo-ultra-slow.json +1 -0
  146. package/skills/agentvfx/templates/brutal/collage/fx.json +4882 -0
  147. package/skills/agentvfx/templates/brutal/collage/layout.mjs +97 -0
  148. package/skills/agentvfx/templates/brutal/collage/layouts.json +366 -0
  149. package/skills/agentvfx/templates/brutal/collage/main.frag +2367 -0
  150. package/skills/agentvfx/templates/brutal/collage/pass0.frag +265 -0
  151. package/skills/agentvfx/templates/brutal/halftone-field/demo-acid.json +1 -0
  152. package/skills/agentvfx/templates/brutal/halftone-field/demo-ascii.json +1 -0
  153. package/skills/agentvfx/templates/brutal/halftone-field/demo-dither.json +1 -0
  154. package/skills/agentvfx/templates/brutal/halftone-field/demo-orange.json +1 -0
  155. package/skills/agentvfx/templates/brutal/halftone-field/demo-phosphor.json +1 -0
  156. package/skills/agentvfx/templates/brutal/halftone-field/demo-ultramarine.json +1 -0
  157. package/skills/agentvfx/templates/brutal/halftone-field/fx.json +474 -0
  158. package/skills/agentvfx/templates/brutal/halftone-field/main.frag +248 -0
  159. package/skills/agentvfx/templates/brutal/hud-deck/demo-acid.json +1 -0
  160. package/skills/agentvfx/templates/brutal/hud-deck/demo-night.json +1 -0
  161. package/skills/agentvfx/templates/brutal/hud-deck/demo-octagon.json +1 -0
  162. package/skills/agentvfx/templates/brutal/hud-deck/demo-ultramarine.json +1 -0
  163. package/skills/agentvfx/templates/brutal/hud-deck/fx.json +601 -0
  164. package/skills/agentvfx/templates/brutal/hud-deck/main.frag +645 -0
  165. package/skills/agentvfx/templates/brutal/hud-deck/pass0.frag +38 -0
  166. package/skills/agentvfx/templates/brutal/lattice/demo-cobalt-fine.json +1 -0
  167. package/skills/agentvfx/templates/brutal/lattice/demo-ink-yellow.json +1 -0
  168. package/skills/agentvfx/templates/brutal/lattice/demo-vermilion.json +1 -0
  169. package/skills/agentvfx/templates/brutal/lattice/demo-violet-slow.json +1 -0
  170. package/skills/agentvfx/templates/brutal/lattice/fx.json +130 -0
  171. package/skills/agentvfx/templates/brutal/lattice/main.frag +175 -0
  172. package/skills/agentvfx/templates/brutal/lattice/pass0.frag +29 -0
  173. package/skills/agentvfx/templates/glitch/block-glitch/demo-mosaic.json +1 -0
  174. package/skills/agentvfx/templates/glitch/block-glitch/demo-onset.json +1 -0
  175. package/skills/agentvfx/templates/glitch/block-glitch/demo-static.json +1 -0
  176. package/skills/agentvfx/templates/glitch/block-glitch/demo-tear.json +1 -0
  177. package/skills/agentvfx/templates/glitch/block-glitch/fx.json +54 -0
  178. package/skills/agentvfx/templates/glitch/block-glitch/main.frag +132 -0
  179. package/skills/agentvfx/templates/glitch/block-glitch/pass0.frag +12 -0
  180. package/skills/agentvfx/templates/glitch/pixel-sort/NOTES.md +13 -0
  181. package/skills/agentvfx/templates/glitch/pixel-sort/build-passes.mjs +162 -0
  182. package/skills/agentvfx/templates/glitch/pixel-sort/demo-chunk.json +1 -0
  183. package/skills/agentvfx/templates/glitch/pixel-sort/demo-hue.json +1 -0
  184. package/skills/agentvfx/templates/glitch/pixel-sort/demo-kick.json +1 -0
  185. package/skills/agentvfx/templates/glitch/pixel-sort/demo-streak.json +1 -0
  186. package/skills/agentvfx/templates/glitch/pixel-sort/demo-vertical.json +1 -0
  187. package/skills/agentvfx/templates/glitch/pixel-sort/fx.json +60 -0
  188. package/skills/agentvfx/templates/glitch/pixel-sort/main.frag +83 -0
  189. package/skills/agentvfx/templates/glitch/pixel-sort/pass0.frag +64 -0
  190. package/skills/agentvfx/templates/glitch/pixel-sort/pass1.frag +66 -0
  191. package/skills/agentvfx/templates/glitch/pixel-sort/pass2.frag +66 -0
  192. package/skills/agentvfx/templates/glitch/pixel-sort/pass3.frag +66 -0
  193. package/skills/agentvfx/templates/glitch/pixel-sort/pass4.frag +66 -0
  194. package/skills/agentvfx/templates/glitch/pixel-sort/pass5.frag +66 -0
  195. package/skills/agentvfx/templates/glitch/pixel-sort/pass6.frag +66 -0
  196. package/skills/agentvfx/templates/glitch/pixel-sort/pass7.frag +66 -0
  197. package/skills/agentvfx/templates/glitch/pixel-sort/pass8.frag +66 -0
  198. package/skills/agentvfx/templates/glitch/rgb-split/demo-diagonal-stutter.json +1 -0
  199. package/skills/agentvfx/templates/glitch/rgb-split/demo-hard.json +1 -0
  200. package/skills/agentvfx/templates/glitch/rgb-split/demo-kick.json +1 -0
  201. package/skills/agentvfx/templates/glitch/rgb-split/demo-radial.json +1 -0
  202. package/skills/agentvfx/templates/glitch/rgb-split/fx.json +46 -0
  203. package/skills/agentvfx/templates/glitch/rgb-split/main.frag +76 -0
  204. package/skills/agentvfx/templates/glitch/vhs/demo-clean.json +1 -0
  205. package/skills/agentvfx/templates/glitch/vhs/demo-crash.json +1 -0
  206. package/skills/agentvfx/templates/glitch/vhs/demo-tape.json +1 -0
  207. package/skills/agentvfx/templates/glitch/vhs/demo-worn.json +1 -0
  208. package/skills/agentvfx/templates/glitch/vhs/fx.json +46 -0
  209. package/skills/agentvfx/templates/glitch/vhs/main.frag +96 -0
  210. package/skills/agentvfx/templates/impact/impact-1bit/demo-onebit-bayer.json +1 -0
  211. package/skills/agentvfx/templates/impact/impact-1bit/fx.json +45 -0
  212. package/skills/agentvfx/templates/impact/impact-1bit/main.frag +64 -0
  213. package/skills/agentvfx/templates/impact/impact-invert/demo-invert-snap.json +1 -0
  214. package/skills/agentvfx/templates/impact/impact-invert/fx.json +37 -0
  215. package/skills/agentvfx/templates/impact/impact-invert/main.frag +44 -0
  216. package/skills/agentvfx/templates/impact/punch-shake/demo-punch-hard.json +1 -0
  217. package/skills/agentvfx/templates/impact/punch-shake/fx.json +36 -0
  218. package/skills/agentvfx/templates/impact/punch-shake/main.frag +62 -0
  219. package/skills/agentvfx/templates/impact/rgb-hit/demo-rgb-slam.json +1 -0
  220. package/skills/agentvfx/templates/impact/rgb-hit/fx.json +39 -0
  221. package/skills/agentvfx/templates/impact/rgb-hit/main.frag +62 -0
  222. package/skills/agentvfx/templates/impact/signal-cut/demo-lime-hold.json +1 -0
  223. package/skills/agentvfx/templates/impact/signal-cut/demo-lime.json +1 -0
  224. package/skills/agentvfx/templates/impact/signal-cut/demo-orange.json +1 -0
  225. package/skills/agentvfx/templates/impact/signal-cut/demo-ultramarine.json +1 -0
  226. package/skills/agentvfx/templates/impact/signal-cut/fx.json +83 -0
  227. package/skills/agentvfx/templates/impact/signal-cut/main.frag +101 -0
  228. package/skills/agentvfx/templates/impact/signal-cut/pass0.frag +68 -0
  229. package/skills/agentvfx/templates/impact/speedline-burst/demo-speed-white.json +1 -0
  230. package/skills/agentvfx/templates/impact/speedline-burst/fx.json +44 -0
  231. package/skills/agentvfx/templates/impact/speedline-burst/main.frag +68 -0
  232. package/skills/agentvfx/templates/impact/strobe-burst/demo-strobe-white-16.json +1 -0
  233. package/skills/agentvfx/templates/impact/strobe-burst/fx.json +42 -0
  234. package/skills/agentvfx/templates/impact/strobe-burst/main.frag +43 -0
  235. package/skills/agentvfx/templates/light/anamorphic-streak/demo-anamorphic-cinema.json +10 -0
  236. package/skills/agentvfx/templates/light/anamorphic-streak/demo-data.json +10 -0
  237. package/skills/agentvfx/templates/light/anamorphic-streak/fx.json +47 -0
  238. package/skills/agentvfx/templates/light/anamorphic-streak/main.frag +45 -0
  239. package/skills/agentvfx/templates/light/anamorphic-streak/pass0.frag +22 -0
  240. package/skills/agentvfx/templates/light/anamorphic-streak/pass1.frag +16 -0
  241. package/skills/agentvfx/templates/light/anamorphic-streak/pass2.frag +16 -0
  242. package/skills/agentvfx/templates/light/anamorphic-streak/pass3.frag +16 -0
  243. package/skills/agentvfx/templates/light/bloom-glow/demo-clip01-low.json +11 -0
  244. package/skills/agentvfx/templates/light/bloom-glow/demo-neon-night.json +10 -0
  245. package/skills/agentvfx/templates/light/bloom-glow/demo-phosphor.json +11 -0
  246. package/skills/agentvfx/templates/light/bloom-glow/fx.json +53 -0
  247. package/skills/agentvfx/templates/light/bloom-glow/main.frag +85 -0
  248. package/skills/agentvfx/templates/light/bloom-glow/pass0.frag +21 -0
  249. package/skills/agentvfx/templates/light/bloom-glow/pass1.frag +50 -0
  250. package/skills/agentvfx/templates/light/bloom-glow/pass2.frag +44 -0
  251. package/skills/agentvfx/templates/light/bloom-glow/pass3.frag +32 -0
  252. package/skills/agentvfx/templates/light/bloom-glow/pass4.frag +48 -0
  253. package/skills/agentvfx/templates/light/bloom-glow/pass5.frag +46 -0
  254. package/skills/agentvfx/templates/light/god-rays/demo-golden-hour.json +10 -0
  255. package/skills/agentvfx/templates/light/god-rays/demo-point-lamp.json +10 -0
  256. package/skills/agentvfx/templates/light/god-rays/fx.json +39 -0
  257. package/skills/agentvfx/templates/light/god-rays/main.frag +54 -0
  258. package/skills/agentvfx/templates/light/lens-flare/demo-clip01-bar.json +11 -0
  259. package/skills/agentvfx/templates/light/lens-flare/demo-eye-bar.json +10 -0
  260. package/skills/agentvfx/templates/light/lens-flare/demo-sun-ghosts.json +10 -0
  261. package/skills/agentvfx/templates/light/lens-flare/fx.json +49 -0
  262. package/skills/agentvfx/templates/light/lens-flare/main.frag +86 -0
  263. package/skills/agentvfx/templates/light/lens-flare/pass0.frag +24 -0
  264. package/skills/agentvfx/templates/light/light-leak/demo-slit.json +10 -0
  265. package/skills/agentvfx/templates/light/light-leak/demo-vintage-burn.json +10 -0
  266. package/skills/agentvfx/templates/light/light-leak/fx.json +40 -0
  267. package/skills/agentvfx/templates/light/light-leak/main.frag +46 -0
  268. package/skills/agentvfx/templates/light/light-stage/fx.json +29 -0
  269. package/skills/agentvfx/templates/light/light-stage/main.frag +56 -0
  270. package/skills/agentvfx/templates/light/light-sweep/demo-hard-bar.json +12 -0
  271. package/skills/agentvfx/templates/light/light-sweep/demo-logo-sweep.json +10 -0
  272. package/skills/agentvfx/templates/light/light-sweep/demo-onset.json +11 -0
  273. package/skills/agentvfx/templates/light/light-sweep/fx.json +45 -0
  274. package/skills/agentvfx/templates/light/light-sweep/main.frag +29 -0
  275. package/skills/agentvfx/templates/light/light-sweep/pass0.frag +17 -0
  276. package/skills/agentvfx/templates/light/light-sweep/pass1.frag +15 -0
  277. package/skills/agentvfx/templates/light/neon-saber/demo-hairline.json +10 -0
  278. package/skills/agentvfx/templates/light/neon-saber/demo-saber-laser.json +10 -0
  279. package/skills/agentvfx/templates/light/neon-saber/fx.json +48 -0
  280. package/skills/agentvfx/templates/light/neon-saber/main.frag +27 -0
  281. package/skills/agentvfx/templates/light/neon-saber/pass0.frag +46 -0
  282. package/skills/agentvfx/templates/light/neon-saber/pass1.frag +15 -0
  283. package/skills/agentvfx/templates/psychedelic/echo-flow/demo-trail.json +1 -0
  284. package/skills/agentvfx/templates/psychedelic/echo-flow/fx.json +38 -0
  285. package/skills/agentvfx/templates/psychedelic/echo-flow/main.frag +19 -0
  286. package/skills/agentvfx/templates/psychedelic/echo-flow/pass0.frag +16 -0
  287. package/skills/agentvfx/templates/psychedelic/echo-flow/pass1.frag +20 -0
  288. package/skills/agentvfx/templates/psychedelic/echo-flow/pass2.frag +11 -0
  289. package/skills/agentvfx/templates/psychedelic/echo-flow/pass3.frag +4 -0
  290. package/skills/agentvfx/templates/psychedelic/hologram-scan/demo-cyan.json +1 -0
  291. package/skills/agentvfx/templates/psychedelic/hologram-scan/fx.json +36 -0
  292. package/skills/agentvfx/templates/psychedelic/hologram-scan/main.frag +30 -0
  293. package/skills/agentvfx/templates/psychedelic/kaleido-fold/demo-six.json +1 -0
  294. package/skills/agentvfx/templates/psychedelic/kaleido-fold/fx.json +37 -0
  295. package/skills/agentvfx/templates/psychedelic/kaleido-fold/main.frag +10 -0
  296. package/skills/agentvfx/templates/psychedelic/kaleido-fold/pass0.frag +34 -0
  297. package/skills/agentvfx/templates/psychedelic/mosh-melt/demo-classic.json +1 -0
  298. package/skills/agentvfx/templates/psychedelic/mosh-melt/fx.json +38 -0
  299. package/skills/agentvfx/templates/psychedelic/mosh-melt/main.frag +20 -0
  300. package/skills/agentvfx/templates/psychedelic/mosh-melt/pass0.frag +22 -0
  301. package/skills/agentvfx/templates/psychedelic/sacred/NOTES.md +13 -0
  302. package/skills/agentvfx/templates/psychedelic/sacred/demo-classic.json +1 -0
  303. package/skills/agentvfx/templates/psychedelic/sacred/demo-halo.json +1 -0
  304. package/skills/agentvfx/templates/psychedelic/sacred/demo-slow-tide.json +1 -0
  305. package/skills/agentvfx/templates/psychedelic/sacred/demo-thermal.json +1 -0
  306. package/skills/agentvfx/templates/psychedelic/sacred/fx.json +263 -0
  307. package/skills/agentvfx/templates/psychedelic/sacred/main.frag +109 -0
  308. package/skills/agentvfx/templates/psychedelic/sacred/pass0.frag +25 -0
  309. package/skills/agentvfx/templates/psychedelic/sacred/pass1.frag +23 -0
  310. package/skills/agentvfx/templates/psychedelic/tidal-bands/demo-classic.json +1 -0
  311. package/skills/agentvfx/templates/psychedelic/tidal-bands/fx.json +37 -0
  312. package/skills/agentvfx/templates/psychedelic/tidal-bands/main.frag +54 -0
  313. package/skills/agentvfx/templates/scope/_chrome.glsl +242 -0
  314. package/skills/agentvfx/templates/scope/goniometer/demo-boot-green.json +1 -0
  315. package/skills/agentvfx/templates/scope/goniometer/demo-field-lime.json +1 -0
  316. package/skills/agentvfx/templates/scope/goniometer/demo-field-ultramarine.json +1 -0
  317. package/skills/agentvfx/templates/scope/goniometer/demo-glow-phosphor.json +1 -0
  318. package/skills/agentvfx/templates/scope/goniometer/demo-hud-black.json +1 -0
  319. package/skills/agentvfx/templates/scope/goniometer/fx.json +635 -0
  320. package/skills/agentvfx/templates/scope/goniometer/main.frag +33 -0
  321. package/skills/agentvfx/templates/scope/goniometer/pass0.frag +58 -0
  322. package/skills/agentvfx/templates/scope/goniometer/pass1.frag +43 -0
  323. package/skills/agentvfx/templates/scope/goniometer/pass2.frag +12 -0
  324. package/skills/agentvfx/templates/scope/goniometer/pass3.frag +12 -0
  325. package/skills/agentvfx/templates/scope/goniometer/pass4.frag +12 -0
  326. package/skills/agentvfx/templates/scope/goniometer/pass5.frag +12 -0
  327. package/skills/agentvfx/templates/scope/goniometer/pass6.frag +251 -0
  328. package/skills/agentvfx/templates/scope/scope-polar/demo-boot-green.json +1 -0
  329. package/skills/agentvfx/templates/scope/scope-polar/demo-field-lime.json +1 -0
  330. package/skills/agentvfx/templates/scope/scope-polar/demo-field-ultramarine.json +1 -0
  331. package/skills/agentvfx/templates/scope/scope-polar/demo-glow-phosphor.json +1 -0
  332. package/skills/agentvfx/templates/scope/scope-polar/demo-hud-black.json +1 -0
  333. package/skills/agentvfx/templates/scope/scope-polar/fx.json +686 -0
  334. package/skills/agentvfx/templates/scope/scope-polar/main.frag +39 -0
  335. package/skills/agentvfx/templates/scope/scope-polar/pass0.frag +84 -0
  336. package/skills/agentvfx/templates/scope/scope-polar/pass1.frag +49 -0
  337. package/skills/agentvfx/templates/scope/scope-polar/pass2.frag +12 -0
  338. package/skills/agentvfx/templates/scope/scope-polar/pass3.frag +12 -0
  339. package/skills/agentvfx/templates/scope/scope-polar/pass4.frag +12 -0
  340. package/skills/agentvfx/templates/scope/scope-polar/pass5.frag +12 -0
  341. package/skills/agentvfx/templates/scope/scope-polar/pass6.frag +251 -0
  342. package/skills/agentvfx/templates/scope/scope-triggered/demo-boot-green.json +1 -0
  343. package/skills/agentvfx/templates/scope/scope-triggered/demo-field-lime.json +1 -0
  344. package/skills/agentvfx/templates/scope/scope-triggered/demo-field-ultramarine.json +1 -0
  345. package/skills/agentvfx/templates/scope/scope-triggered/demo-glow-phosphor.json +1 -0
  346. package/skills/agentvfx/templates/scope/scope-triggered/demo-hud-black.json +1 -0
  347. package/skills/agentvfx/templates/scope/scope-triggered/fx.json +712 -0
  348. package/skills/agentvfx/templates/scope/scope-triggered/main.frag +36 -0
  349. package/skills/agentvfx/templates/scope/scope-triggered/pass0.frag +78 -0
  350. package/skills/agentvfx/templates/scope/scope-triggered/pass1.frag +50 -0
  351. package/skills/agentvfx/templates/scope/scope-triggered/pass2.frag +12 -0
  352. package/skills/agentvfx/templates/scope/scope-triggered/pass3.frag +12 -0
  353. package/skills/agentvfx/templates/scope/scope-triggered/pass4.frag +12 -0
  354. package/skills/agentvfx/templates/scope/scope-triggered/pass5.frag +12 -0
  355. package/skills/agentvfx/templates/scope/scope-triggered/pass6.frag +251 -0
  356. package/skills/agentvfx/templates/scope/spectrogram-scroll/demo-boot-green.json +1 -0
  357. package/skills/agentvfx/templates/scope/spectrogram-scroll/demo-field-lime.json +1 -0
  358. package/skills/agentvfx/templates/scope/spectrogram-scroll/demo-field-ultramarine.json +1 -0
  359. package/skills/agentvfx/templates/scope/spectrogram-scroll/demo-glow-phosphor.json +1 -0
  360. package/skills/agentvfx/templates/scope/spectrogram-scroll/demo-hud-black.json +1 -0
  361. package/skills/agentvfx/templates/scope/spectrogram-scroll/fx.json +595 -0
  362. package/skills/agentvfx/templates/scope/spectrogram-scroll/main.frag +83 -0
  363. package/skills/agentvfx/templates/scope/spectrogram-scroll/pass0.frag +52 -0
  364. package/skills/agentvfx/templates/scope/spectrogram-scroll/pass1.frag +251 -0
  365. package/skills/agentvfx/templates/scope/xy-phosphor/demo-boot-green.json +1 -0
  366. package/skills/agentvfx/templates/scope/xy-phosphor/demo-field-lime.json +1 -0
  367. package/skills/agentvfx/templates/scope/xy-phosphor/demo-field-ultramarine.json +1 -0
  368. package/skills/agentvfx/templates/scope/xy-phosphor/demo-glow-phosphor.json +1 -0
  369. package/skills/agentvfx/templates/scope/xy-phosphor/demo-hud-black.json +1 -0
  370. package/skills/agentvfx/templates/scope/xy-phosphor/fx.json +642 -0
  371. package/skills/agentvfx/templates/scope/xy-phosphor/main.frag +33 -0
  372. package/skills/agentvfx/templates/scope/xy-phosphor/pass0.frag +56 -0
  373. package/skills/agentvfx/templates/scope/xy-phosphor/pass1.frag +44 -0
  374. package/skills/agentvfx/templates/scope/xy-phosphor/pass2.frag +12 -0
  375. package/skills/agentvfx/templates/scope/xy-phosphor/pass3.frag +12 -0
  376. package/skills/agentvfx/templates/scope/xy-phosphor/pass4.frag +12 -0
  377. package/skills/agentvfx/templates/scope/xy-phosphor/pass5.frag +12 -0
  378. package/skills/agentvfx/templates/scope/xy-phosphor/pass6.frag +251 -0
  379. package/skills/agentvfx/templates/spectrum/_src/bars-linear/fx.src.json +61 -0
  380. package/skills/agentvfx/templates/spectrum/_src/bars-linear/main.src.frag +112 -0
  381. package/skills/agentvfx/templates/spectrum/_src/bars-linear/pass0.src.frag +2 -0
  382. package/skills/agentvfx/templates/spectrum/_src/bars-mirror/fx.src.json +51 -0
  383. package/skills/agentvfx/templates/spectrum/_src/bars-mirror/main.src.frag +72 -0
  384. package/skills/agentvfx/templates/spectrum/_src/bars-mirror/pass0.src.frag +2 -0
  385. package/skills/agentvfx/templates/spectrum/_src/bass-circle/fx.src.json +56 -0
  386. package/skills/agentvfx/templates/spectrum/_src/bass-circle/main.src.frag +136 -0
  387. package/skills/agentvfx/templates/spectrum/_src/bass-circle/pass0.src.frag +2 -0
  388. package/skills/agentvfx/templates/spectrum/_src/build.mjs +68 -0
  389. package/skills/agentvfx/templates/spectrum/_src/label-bars/fx.src.json +54 -0
  390. package/skills/agentvfx/templates/spectrum/_src/label-bars/main.src.frag +102 -0
  391. package/skills/agentvfx/templates/spectrum/_src/label-bars/pass0.src.frag +2 -0
  392. package/skills/agentvfx/templates/spectrum/_src/shared/bars-fn.glsl +64 -0
  393. package/skills/agentvfx/templates/spectrum/_src/shared/bars-pass.glsl +22 -0
  394. package/skills/agentvfx/templates/spectrum/_src/shared/clock.glsl +7 -0
  395. package/skills/agentvfx/templates/spectrum/_src/shared/hud.glsl +50 -0
  396. package/skills/agentvfx/templates/spectrum/_src/shared/stage.glsl +74 -0
  397. package/skills/agentvfx/templates/spectrum/_src/spectrum-particles/fx.src.json +58 -0
  398. package/skills/agentvfx/templates/spectrum/_src/spectrum-particles/main.src.frag +119 -0
  399. package/skills/agentvfx/templates/spectrum/_src/spectrum-particles/pass0.src.frag +33 -0
  400. package/skills/agentvfx/templates/spectrum/_src/spectrum-radial/fx.src.json +56 -0
  401. package/skills/agentvfx/templates/spectrum/_src/spectrum-radial/main.src.frag +95 -0
  402. package/skills/agentvfx/templates/spectrum/_src/spectrum-radial/pass0.src.frag +2 -0
  403. package/skills/agentvfx/templates/spectrum/_src/waveform-line/fx.src.json +60 -0
  404. package/skills/agentvfx/templates/spectrum/_src/waveform-line/main.src.frag +98 -0
  405. package/skills/agentvfx/templates/spectrum/_src/waveform-line/pass0.src.frag +43 -0
  406. package/skills/agentvfx/templates/spectrum/bars-linear/demo-graph-acid.json +1 -0
  407. package/skills/agentvfx/templates/spectrum/bars-linear/demo-graph-black.json +1 -0
  408. package/skills/agentvfx/templates/spectrum/bars-linear/fx.json +632 -0
  409. package/skills/agentvfx/templates/spectrum/bars-linear/main.frag +233 -0
  410. package/skills/agentvfx/templates/spectrum/bars-linear/pass0.frag +91 -0
  411. package/skills/agentvfx/templates/spectrum/bars-mirror/demo-field-acid.json +1 -0
  412. package/skills/agentvfx/templates/spectrum/bars-mirror/demo-field-ultramarine.json +1 -0
  413. package/skills/agentvfx/templates/spectrum/bars-mirror/fx.json +539 -0
  414. package/skills/agentvfx/templates/spectrum/bars-mirror/main.frag +193 -0
  415. package/skills/agentvfx/templates/spectrum/bars-mirror/pass0.frag +91 -0
  416. package/skills/agentvfx/templates/spectrum/bass-circle/demo-bracket-black.json +1 -0
  417. package/skills/agentvfx/templates/spectrum/bass-circle/demo-bracket-ultramarine.json +1 -0
  418. package/skills/agentvfx/templates/spectrum/bass-circle/fx.json +552 -0
  419. package/skills/agentvfx/templates/spectrum/bass-circle/main.frag +258 -0
  420. package/skills/agentvfx/templates/spectrum/bass-circle/pass0.frag +91 -0
  421. package/skills/agentvfx/templates/spectrum/label-bars/demo-deck-black.json +1 -0
  422. package/skills/agentvfx/templates/spectrum/label-bars/demo-deck-ultramarine.json +1 -0
  423. package/skills/agentvfx/templates/spectrum/label-bars/fx.json +552 -0
  424. package/skills/agentvfx/templates/spectrum/label-bars/main.frag +223 -0
  425. package/skills/agentvfx/templates/spectrum/label-bars/pass0.frag +91 -0
  426. package/skills/agentvfx/templates/spectrum/spectrum-particles/demo-cloud-black.json +1 -0
  427. package/skills/agentvfx/templates/spectrum/spectrum-particles/demo-cloud-ultramarine.json +1 -0
  428. package/skills/agentvfx/templates/spectrum/spectrum-particles/fx.json +584 -0
  429. package/skills/agentvfx/templates/spectrum/spectrum-particles/main.frag +240 -0
  430. package/skills/agentvfx/templates/spectrum/spectrum-particles/pass0.frag +101 -0
  431. package/skills/agentvfx/templates/spectrum/spectrum-radial/demo-starburst-black.json +1 -0
  432. package/skills/agentvfx/templates/spectrum/spectrum-radial/demo-starburst-ultramarine.json +1 -0
  433. package/skills/agentvfx/templates/spectrum/spectrum-radial/fx.json +566 -0
  434. package/skills/agentvfx/templates/spectrum/spectrum-radial/main.frag +217 -0
  435. package/skills/agentvfx/templates/spectrum/spectrum-radial/pass0.frag +91 -0
  436. package/skills/agentvfx/templates/spectrum/waveform-line/demo-strip-acid.json +1 -0
  437. package/skills/agentvfx/templates/spectrum/waveform-line/demo-strip-black.json +1 -0
  438. package/skills/agentvfx/templates/spectrum/waveform-line/fx.json +481 -0
  439. package/skills/agentvfx/templates/spectrum/waveform-line/main.frag +219 -0
  440. package/skills/agentvfx/templates/spectrum/waveform-line/pass0.frag +48 -0
  441. package/skills/agentvfx/templates/spectrum/waveform-line/pass1.frag +86 -0
  442. package/skills/agentvfx/test/_render_light.mjs +38 -0
  443. package/skills/agentvfx/test/audio-stereo.test.mjs +45 -0
  444. package/skills/agentvfx/test/audio.test.mjs +257 -0
  445. package/skills/agentvfx/test/brutal.test.mjs +190 -0
  446. package/skills/agentvfx/test/concept-collage-layout.test.mjs +236 -0
  447. package/skills/agentvfx/test/concept-collage-scenes.test.mjs +305 -0
  448. package/skills/agentvfx/test/concept-collage-typefx.test.mjs +153 -0
  449. package/skills/agentvfx/test/concept-collage.test.mjs +84 -0
  450. package/skills/agentvfx/test/concept-lattice.test.mjs +133 -0
  451. package/skills/agentvfx/test/concept-signal-cut.test.mjs +172 -0
  452. package/skills/agentvfx/test/credit-overlay.test.mjs +58 -0
  453. package/skills/agentvfx/test/credit.test.mjs +54 -0
  454. package/skills/agentvfx/test/doctor.test.mjs +31 -0
  455. package/skills/agentvfx/test/encode.test.mjs +22 -0
  456. package/skills/agentvfx/test/fixtures/r7-collage-LAYOUTS.json +5780 -0
  457. package/skills/agentvfx/test/fixtures/score-bad-duration.json +7 -0
  458. package/skills/agentvfx/test/fixtures/score-bad-safety.json +8 -0
  459. package/skills/agentvfx/test/fixtures/score-identity-footage.json +8 -0
  460. package/skills/agentvfx/test/fixtures/score-missing-template.json +7 -0
  461. package/skills/agentvfx/test/fixtures/score-ok.json +8 -0
  462. package/skills/agentvfx/test/fixtures/score-strobe-12hz.json +8 -0
  463. package/skills/agentvfx/test/fixtures/score-text-probe.json +1 -0
  464. package/skills/agentvfx/test/flash-audit.test.mjs +150 -0
  465. package/skills/agentvfx/test/flash.test.mjs +83 -0
  466. package/skills/agentvfx/test/footage.test.mjs +88 -0
  467. package/skills/agentvfx/test/glitch.test.mjs +272 -0
  468. package/skills/agentvfx/test/impact.test.mjs +231 -0
  469. package/skills/agentvfx/test/imports.test.mjs +39 -0
  470. package/skills/agentvfx/test/light.test.mjs +200 -0
  471. package/skills/agentvfx/test/loop.test.mjs +80 -0
  472. package/skills/agentvfx/test/psychedelic.test.mjs +99 -0
  473. package/skills/agentvfx/test/render.test.mjs +73 -0
  474. package/skills/agentvfx/test/sacred.test.mjs +175 -0
  475. package/skills/agentvfx/test/schema.test.mjs +103 -0
  476. package/skills/agentvfx/test/scope.test.mjs +306 -0
  477. package/skills/agentvfx/test/spectrum.test.mjs +165 -0
  478. package/skills/agentvfx/test/text.test.mjs +142 -0
  479. package/skills/agentvfx/test/web.test.mjs +400 -0
  480. package/skills/agentvfx/test-media/SOURCES.md +39 -0
  481. package/skills/agentvfx/test-media/beat-132.mp3 +0 -0
  482. package/skills/agentvfx/test-media/clip-01.mp4 +0 -0
  483. package/skills/agentvfx/test-media/clip-02.mp4 +0 -0
@@ -0,0 +1,162 @@
1
+ // Regenerates the pixel-sort pass files (pass0..pass8 and main.frag) from the shared GLSL below.
2
+ // The engine gives every pass its own file, so the shared helpers are pasted into each one.
3
+ // node build-passes.mjs
4
+ // Passes: pass0 keyBuf (cell average colour + sort key), pass1..pass8 run lengths by doubling
5
+ // (run<j> holds min(run length, 2^j) to the left in .r and to the right in .g), main = the sort.
6
+ import { writeFileSync } from "node:fs";
7
+ import { fileURLToPath } from "node:url";
8
+ import path from "node:path";
9
+
10
+ const dir = path.dirname(fileURLToPath(import.meta.url));
11
+ const K = 8;
12
+
13
+ const COMMON = `uint pcg(uint v) {
14
+ uint s = v * 747796405u + 2891336453u;
15
+ uint w = ((s >> ((s >> 28u) + 4u)) ^ s) * 277803737u;
16
+ return (w >> 22u) ^ w;
17
+ }
18
+ float h1(uint a) { return float(pcg(a)) / 4294967295.0; }
19
+ float h2(uint a, uint b) { return h1(a * 2654435761u + pcg(b + 1013904223u)); }
20
+
21
+ // SEED is the score seed / 2^32, so small integer seeds are tiny floats; recover the integer.
22
+ uint seedU() { return uint(min(SEED * 4294967296.0 + 0.5, 4294967040.0)); }
23
+
24
+ // The sort works on cells of cellPx x cellPx pixels (1 cell = 1 "pixel" of the sort).
25
+ // Reading order: left to right for the horizontal axis, top to bottom for the vertical one.
26
+ float cellPx() { return max(1.0, floor(cellSize * RENDERSIZE.y / 1080.0 + 0.5)); }
27
+ vec2 axisDir() { return sortAxis == 0 ? vec2(1.0, 0.0) : vec2(0.0, -1.0); }
28
+ vec2 cellDims() { return ceil(RENDERSIZE / cellPx()); }
29
+ bool inCells(vec2 c) { vec2 d = cellDims(); return c.x >= 0.0 && c.y >= 0.0 && c.x < d.x && c.y < d.y; }
30
+ ivec2 cellTexel(vec2 c) { return ivec2(min(c * cellPx(), RENDERSIZE - 1.0)); }
31
+ float acrossOf(vec2 c) { return sortAxis == 0 ? c.y : c.x; }
32
+ float alongOf(vec2 c) { return sortAxis == 0 ? c.x : cellDims().y - 1.0 - c.y; }
33
+
34
+ // Span mask: a cell takes part when its row is gated in and its perceptual luma lies in [lo, hi].
35
+ bool maskOf(vec2 c) {
36
+ if (!inCells(c)) return false;
37
+ uint across = uint(acrossOf(c));
38
+ uint st = uint(floor(TIME * stutterHz));
39
+ uint sd = seedU();
40
+ float kick = clamp(audioKick, 0.0, 2.0);
41
+ if (h2(across + 7u, st * 977u + sd) > clamp(rowsFrac + 0.4 * kick, 0.0, 1.0)) return false;
42
+ float sw = sweep * sin(6.2832 * (TIME * sweepRate + h1(sd + 17u)));
43
+ float lo = threshLo + sw - 0.25 * kick + (h2(across, st + sd + 3u) - 0.5) * rowVar;
44
+ float hi = threshHi + sw + 0.2 * kick + (h2(across, st + sd + 5u) - 0.5) * rowVar;
45
+ float l = linearToSrgb(vec3(luma(texelFetch(keyBuf, cellTexel(c), 0).rgb))).r;
46
+ return l >= lo && l <= hi;
47
+ }
48
+ // Spans are cut at multiples of ${2 ** K} cells; the cut grid is shifted per row so cuts do not line up.
49
+ float cutShift(vec2 c) { return floor(h2(uint(acrossOf(c)), seedU() + 99u) * ${2 ** K}.0) * cutJitter; }
50
+ `;
51
+
52
+ const header = (title) => `// pixel-sort (${title}). Idea: pixel sorting as in ASDFPixelSort by Kim Asendorf (concept only; code written fresh).
53
+ // Spans of cells whose luma lies in a threshold window are sorted along an axis. Span extents come from
54
+ // log2 run-length doubling (pass1..pass${K}); the sort itself ranks ${32} strided samples of the span in the
55
+ // last pass (exact when a span has <= 32 cells, a quantile approximation above that).
56
+ `;
57
+
58
+ const pass0 = `${header("pass0 keyBuf: cell average colour in rgb, sort key in a")}${COMMON}
59
+ float sortKey(vec3 c) {
60
+ if (sortBy == 1) return rgb2hsv(c).x;
61
+ if (sortBy == 2) return rgb2hsv(c).y;
62
+ if (sortBy == 3) return linearToSrgb(c).b;
63
+ return linearToSrgb(vec3(luma(c))).r;
64
+ }
65
+ void main() {
66
+ float cp = cellPx();
67
+ vec2 c = floor(vUv * RENDERSIZE / cp);
68
+ vec2 cen = (c + 0.5) * cp;
69
+ vec3 acc;
70
+ if (cp < 1.5) acc = texture(inputImage, vUv).rgb;
71
+ else {
72
+ acc = vec3(0.0);
73
+ for (int i = 0; i < 4; i++) {
74
+ vec2 o = vec2(i % 2 == 0 ? -0.25 : 0.25, i < 2 ? -0.25 : 0.25) * cp;
75
+ acc += texture(inputImage, (cen + o) / RENDERSIZE).rgb;
76
+ }
77
+ acc *= 0.25;
78
+ }
79
+ fragColor = vec4(acc, sortKey(acc));
80
+ }
81
+ `;
82
+
83
+ function runPass(j) {
84
+ const prevR = j === 1 ? "(maskOf(cn) ? 1.0 : 0.0)" : `texelFetch(run${j - 1}, cellTexel(cn), 0).r`;
85
+ const prevG = j === 1 ? "(maskOf(cn) ? 1.0 : 0.0)" : `texelFetch(run${j - 1}, cellTexel(cn), 0).g`;
86
+ const own = j === 1 ? "vec2(1.0)" : `texelFetch(run${j - 1}, cellTexel(c), 0).rg`;
87
+ return `${header(`pass${j} run${j}: run lengths to the left (r) and right (g), capped at ${2 ** j}`)}${COMMON}
88
+ void main() {
89
+ float cp = cellPx();
90
+ vec2 c = floor(vUv * RENDERSIZE / cp);
91
+ if (!maskOf(c)) { fragColor = vec4(0.0); return; }
92
+ vec2 dv = axisDir();
93
+ float posIn = mod(alongOf(c) + cutShift(c), ${2 ** K}.0);
94
+ float capL = posIn + 1.0;
95
+ float capR = ${2 ** K}.0 - posIn;
96
+ float kk = ${2 ** (j - 1)}.0;
97
+ vec2 own = ${own};
98
+ float L = own.x;
99
+ float R = own.y;
100
+ if (L >= kk) {
101
+ vec2 cn = c - dv * kk;
102
+ float ln = inCells(cn) ? ${prevR} : 0.0;
103
+ L = min(min(2.0 * kk, kk + ln), capL);
104
+ }
105
+ if (R >= kk) {
106
+ vec2 cn = c + dv * kk;
107
+ float rn = inCells(cn) ? ${prevG} : 0.0;
108
+ R = min(min(2.0 * kk, kk + rn), capR);
109
+ }
110
+ fragColor = vec4(L, R, 0.0, 1.0);
111
+ }
112
+ `;
113
+ }
114
+
115
+ const main = `${header("main: sort each span")}${COMMON}
116
+ void main() {
117
+ vec3 orig = texture(inputImage, vUv).rgb;
118
+ float cp = cellPx();
119
+ vec2 c = floor(vUv * RENDERSIZE / cp);
120
+ if (!maskOf(c)) { fragColor = vec4(orig, 1.0); return; }
121
+ vec2 dv = axisDir();
122
+ vec2 rl = texelFetch(run${K}, cellTexel(c), 0).rg;
123
+ float L = max(rl.x + rl.y - 1.0, 1.0);
124
+ float pos = rl.x - 1.0;
125
+ int sn = int(min(L, 32.0));
126
+ float ks[32];
127
+ vec3 cs[32];
128
+ vec2 first = c - dv * pos;
129
+ for (int i = 0; i < 32; i++) {
130
+ if (i >= sn) break;
131
+ float idx = floor((float(i) + 0.5) * L / float(sn));
132
+ vec4 kc = texelFetch(keyBuf, cellTexel(first + dv * idx), 0);
133
+ float key = descend ? -kc.a : kc.a;
134
+ int j = i;
135
+ while (j > 0 && ks[j - 1] > key) {
136
+ ks[j] = ks[j - 1];
137
+ cs[j] = cs[j - 1];
138
+ j--;
139
+ }
140
+ ks[j] = key;
141
+ cs[j] = kc.rgb;
142
+ }
143
+ float fq = clamp((pos + 0.5) / L * float(sn) - 0.5, 0.0, float(sn - 1));
144
+ int i0 = int(floor(fq));
145
+ int i1 = min(i0 + 1, sn - 1);
146
+ float f = fract(fq);
147
+ float w = mix(step(0.5, f), f, softness);
148
+ vec3 col = mix(cs[i0], cs[i1], w);
149
+ float key = mix(ks[i0], ks[i1], w);
150
+ if (descend) key = -key;
151
+ float lm = luma(col);
152
+ col = mix(vec3(lm), col, saturation);
153
+ col = max((col - 0.18) * punch + 0.18, 0.0);
154
+ col = mix(col, paletteRamp(clamp(key, 0.0, 1.0)) * (0.6 + 0.8 * lm), paletteMix);
155
+ fragColor = vec4(mix(orig, col, blend), 1.0);
156
+ }
157
+ `;
158
+
159
+ writeFileSync(path.join(dir, "pass0.frag"), pass0);
160
+ for (let j = 1; j <= K; j++) writeFileSync(path.join(dir, `pass${j}.frag`), runPass(j));
161
+ writeFileSync(path.join(dir, "main.frag"), main);
162
+ console.log(`wrote pass0..pass${K} and main.frag in ${dir}`);
@@ -0,0 +1 @@
1
+ {"version":1,"template":"pixel-sort","preset":"pixel-sort-chunk","input":{"video":"test-media/clip-01.mp4"},"palette":"acid-data","durationSec":4,"seed":53,"out":"pixel-sort-chunk"}
@@ -0,0 +1 @@
1
+ {"version":1,"template":"pixel-sort","preset":"pixel-sort-hue","input":{"video":"test-media/clip-01.mp4"},"durationSec":4,"seed":54,"out":"pixel-sort-hue"}
@@ -0,0 +1 @@
1
+ {"version":1,"template":"pixel-sort","preset":"pixel-sort-kick","input":{"video":"test-media/clip-01.mp4","audio":"test-media/beat-132.mp3"},"bindings":[{"param":"audioKick","feature":"onset","gain":1.5,"offset":0,"attackMs":0,"releaseMs":260}],"durationSec":4,"seed":55,"out":"pixel-sort-kick"}
@@ -0,0 +1 @@
1
+ {"version":1,"template":"pixel-sort","preset":"pixel-sort-streak","input":{"video":"test-media/clip-01.mp4"},"durationSec":4,"seed":51,"out":"pixel-sort-streak"}
@@ -0,0 +1 @@
1
+ {"version":1,"template":"pixel-sort","preset":"pixel-sort-vertical","input":{"video":"test-media/clip-02.mp4"},"durationSec":4,"seed":52,"out":"pixel-sort-vertical"}
@@ -0,0 +1,60 @@
1
+ {
2
+ "DESCRIPTION": "Pixel sorting over footage: luma-threshold spans sorted along an axis into streaks, with sweeping thresholds and row stutter",
3
+ "CREDIT": "agentvfx",
4
+ "ISFVSN": "2",
5
+ "CATEGORIES": ["glitch"],
6
+ "INPUTS": [
7
+ { "NAME": "sortAxis", "TYPE": "long", "MIN": 0, "MAX": 1, "VALUES": [0, 1], "LABELS": ["horizontal", "vertical"], "DEFAULT": 0 },
8
+ { "NAME": "cellSize", "TYPE": "float", "MIN": 1, "MAX": 16, "DEFAULT": 3 },
9
+ { "NAME": "threshLo", "TYPE": "float", "MIN": 0, "MAX": 1, "DEFAULT": 0.28 },
10
+ { "NAME": "threshHi", "TYPE": "float", "MIN": 0, "MAX": 1, "DEFAULT": 0.97 },
11
+ { "NAME": "rowVar", "TYPE": "float", "MIN": 0, "MAX": 1, "DEFAULT": 0.25 },
12
+ { "NAME": "rowsFrac", "TYPE": "float", "MIN": 0, "MAX": 1, "DEFAULT": 0.9 },
13
+ { "NAME": "sweep", "TYPE": "float", "MIN": 0, "MAX": 0.5, "DEFAULT": 0.12 },
14
+ { "NAME": "sweepRate", "TYPE": "float", "MIN": 0, "MAX": 4, "DEFAULT": 0.35 },
15
+ { "NAME": "stutterHz", "TYPE": "float", "MIN": 1, "MAX": 30, "DEFAULT": 8 },
16
+ { "NAME": "sortBy", "TYPE": "long", "MIN": 0, "MAX": 3, "VALUES": [0, 1, 2, 3], "LABELS": ["luma", "hue", "saturation", "blue"], "DEFAULT": 0 },
17
+ { "NAME": "descend", "TYPE": "bool", "DEFAULT": false },
18
+ { "NAME": "softness", "TYPE": "float", "MIN": 0, "MAX": 1, "DEFAULT": 0.4 },
19
+ { "NAME": "cutJitter", "TYPE": "float", "MIN": 0, "MAX": 1, "DEFAULT": 1 },
20
+ { "NAME": "paletteMix", "TYPE": "float", "MIN": 0, "MAX": 1, "DEFAULT": 0 },
21
+ { "NAME": "saturation", "TYPE": "float", "MIN": 0, "MAX": 3, "DEFAULT": 1.5 },
22
+ { "NAME": "punch", "TYPE": "float", "MIN": 0.5, "MAX": 3, "DEFAULT": 1.3 },
23
+ { "NAME": "blend", "TYPE": "float", "MIN": 0, "MAX": 1, "DEFAULT": 1 },
24
+ { "NAME": "audioKick", "TYPE": "float", "MIN": 0, "MAX": 2, "DEFAULT": 0 }
25
+ ],
26
+ "PASSES": [
27
+ { "TARGET": "keyBuf", "FLOAT": true },
28
+ { "TARGET": "run1", "FLOAT": true },
29
+ { "TARGET": "run2", "FLOAT": true },
30
+ { "TARGET": "run3", "FLOAT": true },
31
+ { "TARGET": "run4", "FLOAT": true },
32
+ { "TARGET": "run5", "FLOAT": true },
33
+ { "TARGET": "run6", "FLOAT": true },
34
+ { "TARGET": "run7", "FLOAT": true },
35
+ { "TARGET": "run8", "FLOAT": true },
36
+ {}
37
+ ],
38
+ "X_AGENTVFX": {
39
+ "id": "pixel-sort",
40
+ "family": "glitch",
41
+ "input": "footage",
42
+ "spdx": "Apache-2.0",
43
+ "flash": "possible",
44
+ "fps": 30,
45
+ "palette": true,
46
+ "presets": {
47
+ "pixel-sort-streak": {},
48
+ "pixel-sort-vertical": { "sortAxis": 1, "cellSize": 2, "threshLo": 0.2, "threshHi": 0.85, "sweep": 0.2, "sweepRate": 0.5, "descend": true, "rowVar": 0.35 },
49
+ "pixel-sort-chunk": { "cellSize": 9, "threshLo": 0.18, "threshHi": 1, "softness": 0, "rowVar": 0.4, "stutterHz": 12, "paletteMix": 0.5, "saturation": 1.5 },
50
+ "pixel-sort-hue": { "sortBy": 1, "cellSize": 2, "threshLo": 0.1, "threshHi": 0.92, "rowsFrac": 1, "rowVar": 0.1, "sweep": 0.18, "saturation": 1.6 },
51
+ "pixel-sort-kick": { "rowsFrac": 0.25, "threshLo": 0.45, "threshHi": 0.8, "sweep": 0.05, "cellSize": 3 }
52
+ },
53
+ "audioBind": { "audioKick": "onset" },
54
+ "credits": [
55
+ "ASDFPixelSort by Kim Asendorf (the pixel-sorting idea, by name only; no code used)",
56
+ "Run-length doubling (pointer jumping), https://en.wikipedia.org/wiki/Pointer_jumping",
57
+ "PCG integer hash, M. E. O'Neill, https://www.pcg-random.org/"
58
+ ]
59
+ }
60
+ }
@@ -0,0 +1,83 @@
1
+ // pixel-sort (main: sort each span). Idea: pixel sorting as in ASDFPixelSort by Kim Asendorf (concept only; code written fresh).
2
+ // Spans of cells whose luma lies in a threshold window are sorted along an axis. Span extents come from
3
+ // log2 run-length doubling (pass1..pass8); the sort itself ranks 32 strided samples of the span in the
4
+ // last pass (exact when a span has <= 32 cells, a quantile approximation above that).
5
+ uint pcg(uint v) {
6
+ uint s = v * 747796405u + 2891336453u;
7
+ uint w = ((s >> ((s >> 28u) + 4u)) ^ s) * 277803737u;
8
+ return (w >> 22u) ^ w;
9
+ }
10
+ float h1(uint a) { return float(pcg(a)) / 4294967295.0; }
11
+ float h2(uint a, uint b) { return h1(a * 2654435761u + pcg(b + 1013904223u)); }
12
+
13
+ // SEED is the score seed / 2^32, so small integer seeds are tiny floats; recover the integer.
14
+ uint seedU() { return uint(min(SEED * 4294967296.0 + 0.5, 4294967040.0)); }
15
+
16
+ // The sort works on cells of cellPx x cellPx pixels (1 cell = 1 "pixel" of the sort).
17
+ // Reading order: left to right for the horizontal axis, top to bottom for the vertical one.
18
+ float cellPx() { return max(1.0, floor(cellSize * RENDERSIZE.y / 1080.0 + 0.5)); }
19
+ vec2 axisDir() { return sortAxis == 0 ? vec2(1.0, 0.0) : vec2(0.0, -1.0); }
20
+ vec2 cellDims() { return ceil(RENDERSIZE / cellPx()); }
21
+ bool inCells(vec2 c) { vec2 d = cellDims(); return c.x >= 0.0 && c.y >= 0.0 && c.x < d.x && c.y < d.y; }
22
+ ivec2 cellTexel(vec2 c) { return ivec2(min(c * cellPx(), RENDERSIZE - 1.0)); }
23
+ float acrossOf(vec2 c) { return sortAxis == 0 ? c.y : c.x; }
24
+ float alongOf(vec2 c) { return sortAxis == 0 ? c.x : cellDims().y - 1.0 - c.y; }
25
+
26
+ // Span mask: a cell takes part when its row is gated in and its perceptual luma lies in [lo, hi].
27
+ bool maskOf(vec2 c) {
28
+ if (!inCells(c)) return false;
29
+ uint across = uint(acrossOf(c));
30
+ uint st = uint(floor(TIME * stutterHz));
31
+ uint sd = seedU();
32
+ float kick = clamp(audioKick, 0.0, 2.0);
33
+ if (h2(across + 7u, st * 977u + sd) > clamp(rowsFrac + 0.4 * kick, 0.0, 1.0)) return false;
34
+ float sw = sweep * sin(6.2832 * (TIME * sweepRate + h1(sd + 17u)));
35
+ float lo = threshLo + sw - 0.25 * kick + (h2(across, st + sd + 3u) - 0.5) * rowVar;
36
+ float hi = threshHi + sw + 0.2 * kick + (h2(across, st + sd + 5u) - 0.5) * rowVar;
37
+ float l = linearToSrgb(vec3(luma(texelFetch(keyBuf, cellTexel(c), 0).rgb))).r;
38
+ return l >= lo && l <= hi;
39
+ }
40
+ // Spans are cut at multiples of 256 cells; the cut grid is shifted per row so cuts do not line up.
41
+ float cutShift(vec2 c) { return floor(h2(uint(acrossOf(c)), seedU() + 99u) * 256.0) * cutJitter; }
42
+
43
+ void main() {
44
+ vec3 orig = texture(inputImage, vUv).rgb;
45
+ float cp = cellPx();
46
+ vec2 c = floor(vUv * RENDERSIZE / cp);
47
+ if (!maskOf(c)) { fragColor = vec4(orig, 1.0); return; }
48
+ vec2 dv = axisDir();
49
+ vec2 rl = texelFetch(run8, cellTexel(c), 0).rg;
50
+ float L = max(rl.x + rl.y - 1.0, 1.0);
51
+ float pos = rl.x - 1.0;
52
+ int sn = int(min(L, 32.0));
53
+ float ks[32];
54
+ vec3 cs[32];
55
+ vec2 first = c - dv * pos;
56
+ for (int i = 0; i < 32; i++) {
57
+ if (i >= sn) break;
58
+ float idx = floor((float(i) + 0.5) * L / float(sn));
59
+ vec4 kc = texelFetch(keyBuf, cellTexel(first + dv * idx), 0);
60
+ float key = descend ? -kc.a : kc.a;
61
+ int j = i;
62
+ while (j > 0 && ks[j - 1] > key) {
63
+ ks[j] = ks[j - 1];
64
+ cs[j] = cs[j - 1];
65
+ j--;
66
+ }
67
+ ks[j] = key;
68
+ cs[j] = kc.rgb;
69
+ }
70
+ float fq = clamp((pos + 0.5) / L * float(sn) - 0.5, 0.0, float(sn - 1));
71
+ int i0 = int(floor(fq));
72
+ int i1 = min(i0 + 1, sn - 1);
73
+ float f = fract(fq);
74
+ float w = mix(step(0.5, f), f, softness);
75
+ vec3 col = mix(cs[i0], cs[i1], w);
76
+ float key = mix(ks[i0], ks[i1], w);
77
+ if (descend) key = -key;
78
+ float lm = luma(col);
79
+ col = mix(vec3(lm), col, saturation);
80
+ col = max((col - 0.18) * punch + 0.18, 0.0);
81
+ col = mix(col, paletteRamp(clamp(key, 0.0, 1.0)) * (0.6 + 0.8 * lm), paletteMix);
82
+ fragColor = vec4(mix(orig, col, blend), 1.0);
83
+ }
@@ -0,0 +1,64 @@
1
+ // pixel-sort (pass0 keyBuf: cell average colour in rgb, sort key in a). Idea: pixel sorting as in ASDFPixelSort by Kim Asendorf (concept only; code written fresh).
2
+ // Spans of cells whose luma lies in a threshold window are sorted along an axis. Span extents come from
3
+ // log2 run-length doubling (pass1..pass8); the sort itself ranks 32 strided samples of the span in the
4
+ // last pass (exact when a span has <= 32 cells, a quantile approximation above that).
5
+ uint pcg(uint v) {
6
+ uint s = v * 747796405u + 2891336453u;
7
+ uint w = ((s >> ((s >> 28u) + 4u)) ^ s) * 277803737u;
8
+ return (w >> 22u) ^ w;
9
+ }
10
+ float h1(uint a) { return float(pcg(a)) / 4294967295.0; }
11
+ float h2(uint a, uint b) { return h1(a * 2654435761u + pcg(b + 1013904223u)); }
12
+
13
+ // SEED is the score seed / 2^32, so small integer seeds are tiny floats; recover the integer.
14
+ uint seedU() { return uint(min(SEED * 4294967296.0 + 0.5, 4294967040.0)); }
15
+
16
+ // The sort works on cells of cellPx x cellPx pixels (1 cell = 1 "pixel" of the sort).
17
+ // Reading order: left to right for the horizontal axis, top to bottom for the vertical one.
18
+ float cellPx() { return max(1.0, floor(cellSize * RENDERSIZE.y / 1080.0 + 0.5)); }
19
+ vec2 axisDir() { return sortAxis == 0 ? vec2(1.0, 0.0) : vec2(0.0, -1.0); }
20
+ vec2 cellDims() { return ceil(RENDERSIZE / cellPx()); }
21
+ bool inCells(vec2 c) { vec2 d = cellDims(); return c.x >= 0.0 && c.y >= 0.0 && c.x < d.x && c.y < d.y; }
22
+ ivec2 cellTexel(vec2 c) { return ivec2(min(c * cellPx(), RENDERSIZE - 1.0)); }
23
+ float acrossOf(vec2 c) { return sortAxis == 0 ? c.y : c.x; }
24
+ float alongOf(vec2 c) { return sortAxis == 0 ? c.x : cellDims().y - 1.0 - c.y; }
25
+
26
+ // Span mask: a cell takes part when its row is gated in and its perceptual luma lies in [lo, hi].
27
+ bool maskOf(vec2 c) {
28
+ if (!inCells(c)) return false;
29
+ uint across = uint(acrossOf(c));
30
+ uint st = uint(floor(TIME * stutterHz));
31
+ uint sd = seedU();
32
+ float kick = clamp(audioKick, 0.0, 2.0);
33
+ if (h2(across + 7u, st * 977u + sd) > clamp(rowsFrac + 0.4 * kick, 0.0, 1.0)) return false;
34
+ float sw = sweep * sin(6.2832 * (TIME * sweepRate + h1(sd + 17u)));
35
+ float lo = threshLo + sw - 0.25 * kick + (h2(across, st + sd + 3u) - 0.5) * rowVar;
36
+ float hi = threshHi + sw + 0.2 * kick + (h2(across, st + sd + 5u) - 0.5) * rowVar;
37
+ float l = linearToSrgb(vec3(luma(texelFetch(keyBuf, cellTexel(c), 0).rgb))).r;
38
+ return l >= lo && l <= hi;
39
+ }
40
+ // Spans are cut at multiples of 256 cells; the cut grid is shifted per row so cuts do not line up.
41
+ float cutShift(vec2 c) { return floor(h2(uint(acrossOf(c)), seedU() + 99u) * 256.0) * cutJitter; }
42
+
43
+ float sortKey(vec3 c) {
44
+ if (sortBy == 1) return rgb2hsv(c).x;
45
+ if (sortBy == 2) return rgb2hsv(c).y;
46
+ if (sortBy == 3) return linearToSrgb(c).b;
47
+ return linearToSrgb(vec3(luma(c))).r;
48
+ }
49
+ void main() {
50
+ float cp = cellPx();
51
+ vec2 c = floor(vUv * RENDERSIZE / cp);
52
+ vec2 cen = (c + 0.5) * cp;
53
+ vec3 acc;
54
+ if (cp < 1.5) acc = texture(inputImage, vUv).rgb;
55
+ else {
56
+ acc = vec3(0.0);
57
+ for (int i = 0; i < 4; i++) {
58
+ vec2 o = vec2(i % 2 == 0 ? -0.25 : 0.25, i < 2 ? -0.25 : 0.25) * cp;
59
+ acc += texture(inputImage, (cen + o) / RENDERSIZE).rgb;
60
+ }
61
+ acc *= 0.25;
62
+ }
63
+ fragColor = vec4(acc, sortKey(acc));
64
+ }
@@ -0,0 +1,66 @@
1
+ // pixel-sort (pass1 run1: run lengths to the left (r) and right (g), capped at 2). Idea: pixel sorting as in ASDFPixelSort by Kim Asendorf (concept only; code written fresh).
2
+ // Spans of cells whose luma lies in a threshold window are sorted along an axis. Span extents come from
3
+ // log2 run-length doubling (pass1..pass8); the sort itself ranks 32 strided samples of the span in the
4
+ // last pass (exact when a span has <= 32 cells, a quantile approximation above that).
5
+ uint pcg(uint v) {
6
+ uint s = v * 747796405u + 2891336453u;
7
+ uint w = ((s >> ((s >> 28u) + 4u)) ^ s) * 277803737u;
8
+ return (w >> 22u) ^ w;
9
+ }
10
+ float h1(uint a) { return float(pcg(a)) / 4294967295.0; }
11
+ float h2(uint a, uint b) { return h1(a * 2654435761u + pcg(b + 1013904223u)); }
12
+
13
+ // SEED is the score seed / 2^32, so small integer seeds are tiny floats; recover the integer.
14
+ uint seedU() { return uint(min(SEED * 4294967296.0 + 0.5, 4294967040.0)); }
15
+
16
+ // The sort works on cells of cellPx x cellPx pixels (1 cell = 1 "pixel" of the sort).
17
+ // Reading order: left to right for the horizontal axis, top to bottom for the vertical one.
18
+ float cellPx() { return max(1.0, floor(cellSize * RENDERSIZE.y / 1080.0 + 0.5)); }
19
+ vec2 axisDir() { return sortAxis == 0 ? vec2(1.0, 0.0) : vec2(0.0, -1.0); }
20
+ vec2 cellDims() { return ceil(RENDERSIZE / cellPx()); }
21
+ bool inCells(vec2 c) { vec2 d = cellDims(); return c.x >= 0.0 && c.y >= 0.0 && c.x < d.x && c.y < d.y; }
22
+ ivec2 cellTexel(vec2 c) { return ivec2(min(c * cellPx(), RENDERSIZE - 1.0)); }
23
+ float acrossOf(vec2 c) { return sortAxis == 0 ? c.y : c.x; }
24
+ float alongOf(vec2 c) { return sortAxis == 0 ? c.x : cellDims().y - 1.0 - c.y; }
25
+
26
+ // Span mask: a cell takes part when its row is gated in and its perceptual luma lies in [lo, hi].
27
+ bool maskOf(vec2 c) {
28
+ if (!inCells(c)) return false;
29
+ uint across = uint(acrossOf(c));
30
+ uint st = uint(floor(TIME * stutterHz));
31
+ uint sd = seedU();
32
+ float kick = clamp(audioKick, 0.0, 2.0);
33
+ if (h2(across + 7u, st * 977u + sd) > clamp(rowsFrac + 0.4 * kick, 0.0, 1.0)) return false;
34
+ float sw = sweep * sin(6.2832 * (TIME * sweepRate + h1(sd + 17u)));
35
+ float lo = threshLo + sw - 0.25 * kick + (h2(across, st + sd + 3u) - 0.5) * rowVar;
36
+ float hi = threshHi + sw + 0.2 * kick + (h2(across, st + sd + 5u) - 0.5) * rowVar;
37
+ float l = linearToSrgb(vec3(luma(texelFetch(keyBuf, cellTexel(c), 0).rgb))).r;
38
+ return l >= lo && l <= hi;
39
+ }
40
+ // Spans are cut at multiples of 256 cells; the cut grid is shifted per row so cuts do not line up.
41
+ float cutShift(vec2 c) { return floor(h2(uint(acrossOf(c)), seedU() + 99u) * 256.0) * cutJitter; }
42
+
43
+ void main() {
44
+ float cp = cellPx();
45
+ vec2 c = floor(vUv * RENDERSIZE / cp);
46
+ if (!maskOf(c)) { fragColor = vec4(0.0); return; }
47
+ vec2 dv = axisDir();
48
+ float posIn = mod(alongOf(c) + cutShift(c), 256.0);
49
+ float capL = posIn + 1.0;
50
+ float capR = 256.0 - posIn;
51
+ float kk = 1.0;
52
+ vec2 own = vec2(1.0);
53
+ float L = own.x;
54
+ float R = own.y;
55
+ if (L >= kk) {
56
+ vec2 cn = c - dv * kk;
57
+ float ln = inCells(cn) ? (maskOf(cn) ? 1.0 : 0.0) : 0.0;
58
+ L = min(min(2.0 * kk, kk + ln), capL);
59
+ }
60
+ if (R >= kk) {
61
+ vec2 cn = c + dv * kk;
62
+ float rn = inCells(cn) ? (maskOf(cn) ? 1.0 : 0.0) : 0.0;
63
+ R = min(min(2.0 * kk, kk + rn), capR);
64
+ }
65
+ fragColor = vec4(L, R, 0.0, 1.0);
66
+ }
@@ -0,0 +1,66 @@
1
+ // pixel-sort (pass2 run2: run lengths to the left (r) and right (g), capped at 4). Idea: pixel sorting as in ASDFPixelSort by Kim Asendorf (concept only; code written fresh).
2
+ // Spans of cells whose luma lies in a threshold window are sorted along an axis. Span extents come from
3
+ // log2 run-length doubling (pass1..pass8); the sort itself ranks 32 strided samples of the span in the
4
+ // last pass (exact when a span has <= 32 cells, a quantile approximation above that).
5
+ uint pcg(uint v) {
6
+ uint s = v * 747796405u + 2891336453u;
7
+ uint w = ((s >> ((s >> 28u) + 4u)) ^ s) * 277803737u;
8
+ return (w >> 22u) ^ w;
9
+ }
10
+ float h1(uint a) { return float(pcg(a)) / 4294967295.0; }
11
+ float h2(uint a, uint b) { return h1(a * 2654435761u + pcg(b + 1013904223u)); }
12
+
13
+ // SEED is the score seed / 2^32, so small integer seeds are tiny floats; recover the integer.
14
+ uint seedU() { return uint(min(SEED * 4294967296.0 + 0.5, 4294967040.0)); }
15
+
16
+ // The sort works on cells of cellPx x cellPx pixels (1 cell = 1 "pixel" of the sort).
17
+ // Reading order: left to right for the horizontal axis, top to bottom for the vertical one.
18
+ float cellPx() { return max(1.0, floor(cellSize * RENDERSIZE.y / 1080.0 + 0.5)); }
19
+ vec2 axisDir() { return sortAxis == 0 ? vec2(1.0, 0.0) : vec2(0.0, -1.0); }
20
+ vec2 cellDims() { return ceil(RENDERSIZE / cellPx()); }
21
+ bool inCells(vec2 c) { vec2 d = cellDims(); return c.x >= 0.0 && c.y >= 0.0 && c.x < d.x && c.y < d.y; }
22
+ ivec2 cellTexel(vec2 c) { return ivec2(min(c * cellPx(), RENDERSIZE - 1.0)); }
23
+ float acrossOf(vec2 c) { return sortAxis == 0 ? c.y : c.x; }
24
+ float alongOf(vec2 c) { return sortAxis == 0 ? c.x : cellDims().y - 1.0 - c.y; }
25
+
26
+ // Span mask: a cell takes part when its row is gated in and its perceptual luma lies in [lo, hi].
27
+ bool maskOf(vec2 c) {
28
+ if (!inCells(c)) return false;
29
+ uint across = uint(acrossOf(c));
30
+ uint st = uint(floor(TIME * stutterHz));
31
+ uint sd = seedU();
32
+ float kick = clamp(audioKick, 0.0, 2.0);
33
+ if (h2(across + 7u, st * 977u + sd) > clamp(rowsFrac + 0.4 * kick, 0.0, 1.0)) return false;
34
+ float sw = sweep * sin(6.2832 * (TIME * sweepRate + h1(sd + 17u)));
35
+ float lo = threshLo + sw - 0.25 * kick + (h2(across, st + sd + 3u) - 0.5) * rowVar;
36
+ float hi = threshHi + sw + 0.2 * kick + (h2(across, st + sd + 5u) - 0.5) * rowVar;
37
+ float l = linearToSrgb(vec3(luma(texelFetch(keyBuf, cellTexel(c), 0).rgb))).r;
38
+ return l >= lo && l <= hi;
39
+ }
40
+ // Spans are cut at multiples of 256 cells; the cut grid is shifted per row so cuts do not line up.
41
+ float cutShift(vec2 c) { return floor(h2(uint(acrossOf(c)), seedU() + 99u) * 256.0) * cutJitter; }
42
+
43
+ void main() {
44
+ float cp = cellPx();
45
+ vec2 c = floor(vUv * RENDERSIZE / cp);
46
+ if (!maskOf(c)) { fragColor = vec4(0.0); return; }
47
+ vec2 dv = axisDir();
48
+ float posIn = mod(alongOf(c) + cutShift(c), 256.0);
49
+ float capL = posIn + 1.0;
50
+ float capR = 256.0 - posIn;
51
+ float kk = 2.0;
52
+ vec2 own = texelFetch(run1, cellTexel(c), 0).rg;
53
+ float L = own.x;
54
+ float R = own.y;
55
+ if (L >= kk) {
56
+ vec2 cn = c - dv * kk;
57
+ float ln = inCells(cn) ? texelFetch(run1, cellTexel(cn), 0).r : 0.0;
58
+ L = min(min(2.0 * kk, kk + ln), capL);
59
+ }
60
+ if (R >= kk) {
61
+ vec2 cn = c + dv * kk;
62
+ float rn = inCells(cn) ? texelFetch(run1, cellTexel(cn), 0).g : 0.0;
63
+ R = min(min(2.0 * kk, kk + rn), capR);
64
+ }
65
+ fragColor = vec4(L, R, 0.0, 1.0);
66
+ }
@@ -0,0 +1,66 @@
1
+ // pixel-sort (pass3 run3: run lengths to the left (r) and right (g), capped at 8). Idea: pixel sorting as in ASDFPixelSort by Kim Asendorf (concept only; code written fresh).
2
+ // Spans of cells whose luma lies in a threshold window are sorted along an axis. Span extents come from
3
+ // log2 run-length doubling (pass1..pass8); the sort itself ranks 32 strided samples of the span in the
4
+ // last pass (exact when a span has <= 32 cells, a quantile approximation above that).
5
+ uint pcg(uint v) {
6
+ uint s = v * 747796405u + 2891336453u;
7
+ uint w = ((s >> ((s >> 28u) + 4u)) ^ s) * 277803737u;
8
+ return (w >> 22u) ^ w;
9
+ }
10
+ float h1(uint a) { return float(pcg(a)) / 4294967295.0; }
11
+ float h2(uint a, uint b) { return h1(a * 2654435761u + pcg(b + 1013904223u)); }
12
+
13
+ // SEED is the score seed / 2^32, so small integer seeds are tiny floats; recover the integer.
14
+ uint seedU() { return uint(min(SEED * 4294967296.0 + 0.5, 4294967040.0)); }
15
+
16
+ // The sort works on cells of cellPx x cellPx pixels (1 cell = 1 "pixel" of the sort).
17
+ // Reading order: left to right for the horizontal axis, top to bottom for the vertical one.
18
+ float cellPx() { return max(1.0, floor(cellSize * RENDERSIZE.y / 1080.0 + 0.5)); }
19
+ vec2 axisDir() { return sortAxis == 0 ? vec2(1.0, 0.0) : vec2(0.0, -1.0); }
20
+ vec2 cellDims() { return ceil(RENDERSIZE / cellPx()); }
21
+ bool inCells(vec2 c) { vec2 d = cellDims(); return c.x >= 0.0 && c.y >= 0.0 && c.x < d.x && c.y < d.y; }
22
+ ivec2 cellTexel(vec2 c) { return ivec2(min(c * cellPx(), RENDERSIZE - 1.0)); }
23
+ float acrossOf(vec2 c) { return sortAxis == 0 ? c.y : c.x; }
24
+ float alongOf(vec2 c) { return sortAxis == 0 ? c.x : cellDims().y - 1.0 - c.y; }
25
+
26
+ // Span mask: a cell takes part when its row is gated in and its perceptual luma lies in [lo, hi].
27
+ bool maskOf(vec2 c) {
28
+ if (!inCells(c)) return false;
29
+ uint across = uint(acrossOf(c));
30
+ uint st = uint(floor(TIME * stutterHz));
31
+ uint sd = seedU();
32
+ float kick = clamp(audioKick, 0.0, 2.0);
33
+ if (h2(across + 7u, st * 977u + sd) > clamp(rowsFrac + 0.4 * kick, 0.0, 1.0)) return false;
34
+ float sw = sweep * sin(6.2832 * (TIME * sweepRate + h1(sd + 17u)));
35
+ float lo = threshLo + sw - 0.25 * kick + (h2(across, st + sd + 3u) - 0.5) * rowVar;
36
+ float hi = threshHi + sw + 0.2 * kick + (h2(across, st + sd + 5u) - 0.5) * rowVar;
37
+ float l = linearToSrgb(vec3(luma(texelFetch(keyBuf, cellTexel(c), 0).rgb))).r;
38
+ return l >= lo && l <= hi;
39
+ }
40
+ // Spans are cut at multiples of 256 cells; the cut grid is shifted per row so cuts do not line up.
41
+ float cutShift(vec2 c) { return floor(h2(uint(acrossOf(c)), seedU() + 99u) * 256.0) * cutJitter; }
42
+
43
+ void main() {
44
+ float cp = cellPx();
45
+ vec2 c = floor(vUv * RENDERSIZE / cp);
46
+ if (!maskOf(c)) { fragColor = vec4(0.0); return; }
47
+ vec2 dv = axisDir();
48
+ float posIn = mod(alongOf(c) + cutShift(c), 256.0);
49
+ float capL = posIn + 1.0;
50
+ float capR = 256.0 - posIn;
51
+ float kk = 4.0;
52
+ vec2 own = texelFetch(run2, cellTexel(c), 0).rg;
53
+ float L = own.x;
54
+ float R = own.y;
55
+ if (L >= kk) {
56
+ vec2 cn = c - dv * kk;
57
+ float ln = inCells(cn) ? texelFetch(run2, cellTexel(cn), 0).r : 0.0;
58
+ L = min(min(2.0 * kk, kk + ln), capL);
59
+ }
60
+ if (R >= kk) {
61
+ vec2 cn = c + dv * kk;
62
+ float rn = inCells(cn) ? texelFetch(run2, cellTexel(cn), 0).g : 0.0;
63
+ R = min(min(2.0 * kk, kk + rn), capR);
64
+ }
65
+ fragColor = vec4(L, R, 0.0, 1.0);
66
+ }
@@ -0,0 +1,66 @@
1
+ // pixel-sort (pass4 run4: run lengths to the left (r) and right (g), capped at 16). Idea: pixel sorting as in ASDFPixelSort by Kim Asendorf (concept only; code written fresh).
2
+ // Spans of cells whose luma lies in a threshold window are sorted along an axis. Span extents come from
3
+ // log2 run-length doubling (pass1..pass8); the sort itself ranks 32 strided samples of the span in the
4
+ // last pass (exact when a span has <= 32 cells, a quantile approximation above that).
5
+ uint pcg(uint v) {
6
+ uint s = v * 747796405u + 2891336453u;
7
+ uint w = ((s >> ((s >> 28u) + 4u)) ^ s) * 277803737u;
8
+ return (w >> 22u) ^ w;
9
+ }
10
+ float h1(uint a) { return float(pcg(a)) / 4294967295.0; }
11
+ float h2(uint a, uint b) { return h1(a * 2654435761u + pcg(b + 1013904223u)); }
12
+
13
+ // SEED is the score seed / 2^32, so small integer seeds are tiny floats; recover the integer.
14
+ uint seedU() { return uint(min(SEED * 4294967296.0 + 0.5, 4294967040.0)); }
15
+
16
+ // The sort works on cells of cellPx x cellPx pixels (1 cell = 1 "pixel" of the sort).
17
+ // Reading order: left to right for the horizontal axis, top to bottom for the vertical one.
18
+ float cellPx() { return max(1.0, floor(cellSize * RENDERSIZE.y / 1080.0 + 0.5)); }
19
+ vec2 axisDir() { return sortAxis == 0 ? vec2(1.0, 0.0) : vec2(0.0, -1.0); }
20
+ vec2 cellDims() { return ceil(RENDERSIZE / cellPx()); }
21
+ bool inCells(vec2 c) { vec2 d = cellDims(); return c.x >= 0.0 && c.y >= 0.0 && c.x < d.x && c.y < d.y; }
22
+ ivec2 cellTexel(vec2 c) { return ivec2(min(c * cellPx(), RENDERSIZE - 1.0)); }
23
+ float acrossOf(vec2 c) { return sortAxis == 0 ? c.y : c.x; }
24
+ float alongOf(vec2 c) { return sortAxis == 0 ? c.x : cellDims().y - 1.0 - c.y; }
25
+
26
+ // Span mask: a cell takes part when its row is gated in and its perceptual luma lies in [lo, hi].
27
+ bool maskOf(vec2 c) {
28
+ if (!inCells(c)) return false;
29
+ uint across = uint(acrossOf(c));
30
+ uint st = uint(floor(TIME * stutterHz));
31
+ uint sd = seedU();
32
+ float kick = clamp(audioKick, 0.0, 2.0);
33
+ if (h2(across + 7u, st * 977u + sd) > clamp(rowsFrac + 0.4 * kick, 0.0, 1.0)) return false;
34
+ float sw = sweep * sin(6.2832 * (TIME * sweepRate + h1(sd + 17u)));
35
+ float lo = threshLo + sw - 0.25 * kick + (h2(across, st + sd + 3u) - 0.5) * rowVar;
36
+ float hi = threshHi + sw + 0.2 * kick + (h2(across, st + sd + 5u) - 0.5) * rowVar;
37
+ float l = linearToSrgb(vec3(luma(texelFetch(keyBuf, cellTexel(c), 0).rgb))).r;
38
+ return l >= lo && l <= hi;
39
+ }
40
+ // Spans are cut at multiples of 256 cells; the cut grid is shifted per row so cuts do not line up.
41
+ float cutShift(vec2 c) { return floor(h2(uint(acrossOf(c)), seedU() + 99u) * 256.0) * cutJitter; }
42
+
43
+ void main() {
44
+ float cp = cellPx();
45
+ vec2 c = floor(vUv * RENDERSIZE / cp);
46
+ if (!maskOf(c)) { fragColor = vec4(0.0); return; }
47
+ vec2 dv = axisDir();
48
+ float posIn = mod(alongOf(c) + cutShift(c), 256.0);
49
+ float capL = posIn + 1.0;
50
+ float capR = 256.0 - posIn;
51
+ float kk = 8.0;
52
+ vec2 own = texelFetch(run3, cellTexel(c), 0).rg;
53
+ float L = own.x;
54
+ float R = own.y;
55
+ if (L >= kk) {
56
+ vec2 cn = c - dv * kk;
57
+ float ln = inCells(cn) ? texelFetch(run3, cellTexel(cn), 0).r : 0.0;
58
+ L = min(min(2.0 * kk, kk + ln), capL);
59
+ }
60
+ if (R >= kk) {
61
+ vec2 cn = c + dv * kk;
62
+ float rn = inCells(cn) ? texelFetch(run3, cellTexel(cn), 0).g : 0.0;
63
+ R = min(min(2.0 * kk, kk + rn), capR);
64
+ }
65
+ fragColor = vec4(L, R, 0.0, 1.0);
66
+ }