@basementstudio/shader-lab 0.1.0

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 (261) hide show
  1. package/.biome/plugins/README.md +21 -0
  2. package/.biome/plugins/no-anchor-element.grit +12 -0
  3. package/.biome/plugins/no-relative-parent-imports.grit +10 -0
  4. package/.biome/plugins/no-unnecessary-forwardref.grit +9 -0
  5. package/.changeset/README.md +17 -0
  6. package/.changeset/config.json +11 -0
  7. package/.editorconfig +40 -0
  8. package/.env.example +81 -0
  9. package/.gitattributes +19 -0
  10. package/.github/workflows/canary.yml +80 -0
  11. package/.github/workflows/ci.yml +37 -0
  12. package/.github/workflows/release.yml +56 -0
  13. package/.tldrignore +84 -0
  14. package/.vscode/extensions.json +20 -0
  15. package/.vscode/settings.json +105 -0
  16. package/README.md +119 -0
  17. package/biome.json +249 -0
  18. package/bun.lock +1224 -0
  19. package/next.config.ts +131 -0
  20. package/package.json +73 -0
  21. package/packages/shader-lab-react/CHANGELOG.md +9 -0
  22. package/packages/shader-lab-react/README.md +119 -0
  23. package/packages/shader-lab-react/assets/patterns/bars/1.svg +3 -0
  24. package/packages/shader-lab-react/assets/patterns/bars/2.svg +3 -0
  25. package/packages/shader-lab-react/assets/patterns/bars/3.svg +3 -0
  26. package/packages/shader-lab-react/assets/patterns/bars/4.svg +3 -0
  27. package/packages/shader-lab-react/assets/patterns/bars/5.svg +3 -0
  28. package/packages/shader-lab-react/assets/patterns/bars/6.svg +3 -0
  29. package/packages/shader-lab-react/assets/patterns/candles/1.svg +3 -0
  30. package/packages/shader-lab-react/assets/patterns/candles/2.svg +3 -0
  31. package/packages/shader-lab-react/assets/patterns/candles/3.svg +3 -0
  32. package/packages/shader-lab-react/assets/patterns/candles/4.svg +3 -0
  33. package/packages/shader-lab-react/assets/patterns/shapes/1.svg +3 -0
  34. package/packages/shader-lab-react/assets/patterns/shapes/2.svg +3 -0
  35. package/packages/shader-lab-react/assets/patterns/shapes/3.svg +3 -0
  36. package/packages/shader-lab-react/assets/patterns/shapes/4.svg +4 -0
  37. package/packages/shader-lab-react/assets/patterns/shapes/5.svg +3 -0
  38. package/packages/shader-lab-react/assets/patterns/shapes/6.svg +4 -0
  39. package/packages/shader-lab-react/assets/textures/blue-noise.png +0 -0
  40. package/packages/shader-lab-react/package.json +36 -0
  41. package/packages/shader-lab-react/scripts/fix-esm-specifiers.mjs +57 -0
  42. package/packages/shader-lab-react/scripts/prepare-dist.mjs +4 -0
  43. package/packages/shader-lab-react/src/ambient/three-tsl.d.ts +146 -0
  44. package/packages/shader-lab-react/src/ambient/three-webgpu.d.ts +51 -0
  45. package/packages/shader-lab-react/src/easings.ts +4 -0
  46. package/packages/shader-lab-react/src/index.ts +35 -0
  47. package/packages/shader-lab-react/src/lib/editor/custom-shader/shared.ts +2 -0
  48. package/packages/shader-lab-react/src/renderer/ascii-atlas.ts +83 -0
  49. package/packages/shader-lab-react/src/renderer/ascii-pass.ts +416 -0
  50. package/packages/shader-lab-react/src/renderer/asset-url.ts +3 -0
  51. package/packages/shader-lab-react/src/renderer/blend-modes.ts +229 -0
  52. package/packages/shader-lab-react/src/renderer/contracts.ts +54 -0
  53. package/packages/shader-lab-react/src/renderer/create-webgpu-renderer.ts +48 -0
  54. package/packages/shader-lab-react/src/renderer/crt-pass.ts +1040 -0
  55. package/packages/shader-lab-react/src/renderer/custom-shader-pass.ts +108 -0
  56. package/packages/shader-lab-react/src/renderer/custom-shader-runtime.ts +309 -0
  57. package/packages/shader-lab-react/src/renderer/dither-textures.ts +99 -0
  58. package/packages/shader-lab-react/src/renderer/dithering-pass.ts +322 -0
  59. package/packages/shader-lab-react/src/renderer/gradient-pass.ts +521 -0
  60. package/packages/shader-lab-react/src/renderer/halftone-pass.ts +932 -0
  61. package/packages/shader-lab-react/src/renderer/ink-pass.ts +802 -0
  62. package/packages/shader-lab-react/src/renderer/live-pass.ts +194 -0
  63. package/packages/shader-lab-react/src/renderer/media-pass.ts +187 -0
  64. package/packages/shader-lab-react/src/renderer/media-texture.ts +66 -0
  65. package/packages/shader-lab-react/src/renderer/particle-grid-pass.ts +389 -0
  66. package/packages/shader-lab-react/src/renderer/pass-node.ts +209 -0
  67. package/packages/shader-lab-react/src/renderer/pattern-atlas.ts +133 -0
  68. package/packages/shader-lab-react/src/renderer/pattern-pass.ts +552 -0
  69. package/packages/shader-lab-react/src/renderer/pipeline-manager.ts +369 -0
  70. package/packages/shader-lab-react/src/renderer/pixel-sorting-pass.ts +277 -0
  71. package/packages/shader-lab-react/src/renderer/shaders/tsl/color/tonemapping.ts +87 -0
  72. package/packages/shader-lab-react/src/renderer/shaders/tsl/cosine-palette.ts +9 -0
  73. package/packages/shader-lab-react/src/renderer/shaders/tsl/noise/common.ts +31 -0
  74. package/packages/shader-lab-react/src/renderer/shaders/tsl/noise/curl-noise-3d.ts +36 -0
  75. package/packages/shader-lab-react/src/renderer/shaders/tsl/noise/curl-noise-4d.ts +36 -0
  76. package/packages/shader-lab-react/src/renderer/shaders/tsl/noise/fbm.ts +13 -0
  77. package/packages/shader-lab-react/src/renderer/shaders/tsl/noise/perlin-noise-3d.ts +96 -0
  78. package/packages/shader-lab-react/src/renderer/shaders/tsl/noise/ridge-noise.ts +24 -0
  79. package/packages/shader-lab-react/src/renderer/shaders/tsl/noise/simplex-noise-3d.ts +79 -0
  80. package/packages/shader-lab-react/src/renderer/shaders/tsl/noise/simplex-noise-4d.ts +89 -0
  81. package/packages/shader-lab-react/src/renderer/shaders/tsl/noise/turbulence.ts +56 -0
  82. package/packages/shader-lab-react/src/renderer/shaders/tsl/noise/value-noise-3d.ts +32 -0
  83. package/packages/shader-lab-react/src/renderer/shaders/tsl/noise/voronoi-noise-3d.ts +60 -0
  84. package/packages/shader-lab-react/src/renderer/shaders/tsl/patterns/bloom-edge-pattern.ts +15 -0
  85. package/packages/shader-lab-react/src/renderer/shaders/tsl/patterns/bloom.ts +11 -0
  86. package/packages/shader-lab-react/src/renderer/shaders/tsl/patterns/canvas-weave-pattern.ts +24 -0
  87. package/packages/shader-lab-react/src/renderer/shaders/tsl/patterns/grain-texture-pattern.ts +9 -0
  88. package/packages/shader-lab-react/src/renderer/shaders/tsl/patterns/repeating-pattern.ts +11 -0
  89. package/packages/shader-lab-react/src/renderer/shaders/tsl/utils/atan2.ts +9 -0
  90. package/packages/shader-lab-react/src/renderer/shaders/tsl/utils/complex-conj.ts +9 -0
  91. package/packages/shader-lab-react/src/renderer/shaders/tsl/utils/complex-cos.ts +10 -0
  92. package/packages/shader-lab-react/src/renderer/shaders/tsl/utils/complex-div.ts +11 -0
  93. package/packages/shader-lab-react/src/renderer/shaders/tsl/utils/complex-log.ts +7 -0
  94. package/packages/shader-lab-react/src/renderer/shaders/tsl/utils/complex-mobius.ts +12 -0
  95. package/packages/shader-lab-react/src/renderer/shaders/tsl/utils/complex-mul.ts +9 -0
  96. package/packages/shader-lab-react/src/renderer/shaders/tsl/utils/complex-pow.ts +16 -0
  97. package/packages/shader-lab-react/src/renderer/shaders/tsl/utils/complex-sin.ts +10 -0
  98. package/packages/shader-lab-react/src/renderer/shaders/tsl/utils/complex-sqrt.ts +18 -0
  99. package/packages/shader-lab-react/src/renderer/shaders/tsl/utils/complex-tan.ts +12 -0
  100. package/packages/shader-lab-react/src/renderer/shaders/tsl/utils/complex-to-polar.ts +10 -0
  101. package/packages/shader-lab-react/src/renderer/shaders/tsl/utils/hyperbolic.ts +20 -0
  102. package/packages/shader-lab-react/src/renderer/shaders/tsl/utils/index.ts +48 -0
  103. package/packages/shader-lab-react/src/renderer/shaders/tsl/utils/rotate.ts +15 -0
  104. package/packages/shader-lab-react/src/renderer/shaders/tsl/utils/screen-aspect-uv.ts +15 -0
  105. package/packages/shader-lab-react/src/renderer/shaders/tsl/utils/sd-box-2d.ts +6 -0
  106. package/packages/shader-lab-react/src/renderer/shaders/tsl/utils/sd-diamond.ts +6 -0
  107. package/packages/shader-lab-react/src/renderer/shaders/tsl/utils/sd-rhombus.ts +27 -0
  108. package/packages/shader-lab-react/src/renderer/shaders/tsl/utils/sd-sphere.ts +6 -0
  109. package/packages/shader-lab-react/src/renderer/shaders/tsl/utils/smax.ts +7 -0
  110. package/packages/shader-lab-react/src/renderer/shaders/tsl/utils/smin.ts +7 -0
  111. package/packages/shader-lab-react/src/renderer/text-pass.ts +176 -0
  112. package/packages/shader-lab-react/src/runtime-clock.ts +42 -0
  113. package/packages/shader-lab-react/src/runtime-frame.ts +29 -0
  114. package/packages/shader-lab-react/src/shader-lab-composition.tsx +163 -0
  115. package/packages/shader-lab-react/src/timeline.ts +283 -0
  116. package/packages/shader-lab-react/src/types/editor.ts +5 -0
  117. package/packages/shader-lab-react/src/types.ts +141 -0
  118. package/packages/shader-lab-react/tsconfig.build.json +8 -0
  119. package/packages/shader-lab-react/tsconfig.json +21 -0
  120. package/postcss.config.mjs +5 -0
  121. package/public/assets/fonts/msdf/geist-mono/GeistMono-Regular-msdf-atlas.png +0 -0
  122. package/public/assets/fonts/msdf/geist-mono/GeistMono-Regular-msdf.json +1412 -0
  123. package/public/assets/patterns/bars/1.svg +3 -0
  124. package/public/assets/patterns/bars/2.svg +3 -0
  125. package/public/assets/patterns/bars/3.svg +3 -0
  126. package/public/assets/patterns/bars/4.svg +3 -0
  127. package/public/assets/patterns/bars/5.svg +3 -0
  128. package/public/assets/patterns/bars/6.svg +3 -0
  129. package/public/assets/patterns/candles/1.svg +3 -0
  130. package/public/assets/patterns/candles/2.svg +3 -0
  131. package/public/assets/patterns/candles/3.svg +3 -0
  132. package/public/assets/patterns/candles/4.svg +3 -0
  133. package/public/assets/patterns/shapes/1.svg +3 -0
  134. package/public/assets/patterns/shapes/2.svg +3 -0
  135. package/public/assets/patterns/shapes/3.svg +3 -0
  136. package/public/assets/patterns/shapes/4.svg +4 -0
  137. package/public/assets/patterns/shapes/5.svg +3 -0
  138. package/public/assets/patterns/shapes/6.svg +4 -0
  139. package/public/fonts/geist/Geist-Mono.woff2 +0 -0
  140. package/public/textures/blue-noise.png +0 -0
  141. package/public/textures/crt-mask.png +0 -0
  142. package/src/app/design/page.tsx +398 -0
  143. package/src/app/favicon.ico +0 -0
  144. package/src/app/globals.css +280 -0
  145. package/src/app/layout.tsx +89 -0
  146. package/src/app/page.tsx +20 -0
  147. package/src/app/robots.ts +13 -0
  148. package/src/app/sitemap.ts +13 -0
  149. package/src/components/editor/editor-canvas-viewport.tsx +116 -0
  150. package/src/components/editor/editor-export-dialog.tsx +1177 -0
  151. package/src/components/editor/editor-timeline-overlay.tsx +983 -0
  152. package/src/components/editor/editor-topbar.tsx +287 -0
  153. package/src/components/editor/layer-sidebar.tsx +738 -0
  154. package/src/components/editor/properties-sidebar-content.tsx +574 -0
  155. package/src/components/editor/properties-sidebar-fields.tsx +389 -0
  156. package/src/components/editor/properties-sidebar-utils.ts +178 -0
  157. package/src/components/editor/properties-sidebar.tsx +421 -0
  158. package/src/components/ui/button/index.tsx +57 -0
  159. package/src/components/ui/color-picker/index.tsx +358 -0
  160. package/src/components/ui/glass-panel/index.tsx +45 -0
  161. package/src/components/ui/icon-button/index.tsx +46 -0
  162. package/src/components/ui/select/index.tsx +136 -0
  163. package/src/components/ui/slider/index.tsx +192 -0
  164. package/src/components/ui/toggle/index.tsx +34 -0
  165. package/src/components/ui/typography/index.tsx +61 -0
  166. package/src/components/ui/xy-pad/index.tsx +160 -0
  167. package/src/features/editor/components/editor-export-dialog.module.css +271 -0
  168. package/src/hooks/use-editor-renderer.ts +182 -0
  169. package/src/lib/app.ts +6 -0
  170. package/src/lib/cn.ts +7 -0
  171. package/src/lib/easings.ts +240 -0
  172. package/src/lib/editor/config/layer-registry.ts +2434 -0
  173. package/src/lib/editor/custom-shader/shared.ts +28 -0
  174. package/src/lib/editor/export.ts +420 -0
  175. package/src/lib/editor/history.ts +71 -0
  176. package/src/lib/editor/layers.ts +76 -0
  177. package/src/lib/editor/parameter-schema.ts +75 -0
  178. package/src/lib/editor/project-file.ts +145 -0
  179. package/src/lib/editor/shader-export-snippet.ts +37 -0
  180. package/src/lib/editor/shader-export.ts +315 -0
  181. package/src/lib/editor/timeline/evaluate.ts +252 -0
  182. package/src/lib/editor/view-transform.ts +58 -0
  183. package/src/lib/fonts.ts +28 -0
  184. package/src/renderer/ascii-atlas.ts +83 -0
  185. package/src/renderer/ascii-pass.ts +416 -0
  186. package/src/renderer/blend-modes.ts +229 -0
  187. package/src/renderer/contracts.ts +161 -0
  188. package/src/renderer/create-webgpu-renderer.ts +48 -0
  189. package/src/renderer/crt-pass.ts +1040 -0
  190. package/src/renderer/custom-shader-pass.ts +117 -0
  191. package/src/renderer/custom-shader-runtime.ts +309 -0
  192. package/src/renderer/dither-textures.ts +99 -0
  193. package/src/renderer/dithering-pass.ts +322 -0
  194. package/src/renderer/gradient-pass.ts +520 -0
  195. package/src/renderer/halftone-pass.ts +932 -0
  196. package/src/renderer/ink-pass.ts +683 -0
  197. package/src/renderer/live-pass.ts +194 -0
  198. package/src/renderer/media-pass.ts +187 -0
  199. package/src/renderer/media-texture.ts +66 -0
  200. package/src/renderer/particle-grid-pass.ts +389 -0
  201. package/src/renderer/pass-node-factory.ts +33 -0
  202. package/src/renderer/pass-node.ts +209 -0
  203. package/src/renderer/pattern-atlas.ts +97 -0
  204. package/src/renderer/pattern-pass.ts +552 -0
  205. package/src/renderer/pipeline-manager.ts +343 -0
  206. package/src/renderer/pixel-sorting-pass.ts +277 -0
  207. package/src/renderer/project-clock.ts +57 -0
  208. package/src/renderer/shaders/tsl/color/tonemapping.ts +86 -0
  209. package/src/renderer/shaders/tsl/cosine-palette.ts +8 -0
  210. package/src/renderer/shaders/tsl/noise/common.ts +30 -0
  211. package/src/renderer/shaders/tsl/noise/curl-noise-3d.ts +35 -0
  212. package/src/renderer/shaders/tsl/noise/curl-noise-4d.ts +35 -0
  213. package/src/renderer/shaders/tsl/noise/fbm.ts +12 -0
  214. package/src/renderer/shaders/tsl/noise/perlin-noise-3d.ts +97 -0
  215. package/src/renderer/shaders/tsl/noise/ridge-noise.ts +23 -0
  216. package/src/renderer/shaders/tsl/noise/simplex-noise-3d.ts +78 -0
  217. package/src/renderer/shaders/tsl/noise/simplex-noise-4d.ts +88 -0
  218. package/src/renderer/shaders/tsl/noise/turbulence.ts +55 -0
  219. package/src/renderer/shaders/tsl/noise/value-noise-3d.ts +31 -0
  220. package/src/renderer/shaders/tsl/noise/voronoi-noise-3d.ts +59 -0
  221. package/src/renderer/shaders/tsl/patterns/bloom-edge-pattern.ts +14 -0
  222. package/src/renderer/shaders/tsl/patterns/bloom.ts +10 -0
  223. package/src/renderer/shaders/tsl/patterns/canvas-weave-pattern.ts +23 -0
  224. package/src/renderer/shaders/tsl/patterns/grain-texture-pattern.ts +8 -0
  225. package/src/renderer/shaders/tsl/patterns/repeating-pattern.ts +10 -0
  226. package/src/renderer/shaders/tsl/utils/atan2.ts +8 -0
  227. package/src/renderer/shaders/tsl/utils/complex-conj.ts +8 -0
  228. package/src/renderer/shaders/tsl/utils/complex-cos.ts +9 -0
  229. package/src/renderer/shaders/tsl/utils/complex-div.ts +10 -0
  230. package/src/renderer/shaders/tsl/utils/complex-log.ts +6 -0
  231. package/src/renderer/shaders/tsl/utils/complex-mobius.ts +11 -0
  232. package/src/renderer/shaders/tsl/utils/complex-mul.ts +8 -0
  233. package/src/renderer/shaders/tsl/utils/complex-pow.ts +15 -0
  234. package/src/renderer/shaders/tsl/utils/complex-sin.ts +9 -0
  235. package/src/renderer/shaders/tsl/utils/complex-sqrt.ts +17 -0
  236. package/src/renderer/shaders/tsl/utils/complex-tan.ts +11 -0
  237. package/src/renderer/shaders/tsl/utils/complex-to-polar.ts +9 -0
  238. package/src/renderer/shaders/tsl/utils/hyperbolic.ts +19 -0
  239. package/src/renderer/shaders/tsl/utils/index.ts +47 -0
  240. package/src/renderer/shaders/tsl/utils/rotate.ts +14 -0
  241. package/src/renderer/shaders/tsl/utils/screen-aspect-uv.ts +14 -0
  242. package/src/renderer/shaders/tsl/utils/sd-box-2d.ts +5 -0
  243. package/src/renderer/shaders/tsl/utils/sd-diamond.ts +5 -0
  244. package/src/renderer/shaders/tsl/utils/sd-rhombus.ts +26 -0
  245. package/src/renderer/shaders/tsl/utils/sd-sphere.ts +5 -0
  246. package/src/renderer/shaders/tsl/utils/smax.ts +7 -0
  247. package/src/renderer/shaders/tsl/utils/smin.ts +6 -0
  248. package/src/renderer/text-pass.ts +176 -0
  249. package/src/store/asset-store.ts +193 -0
  250. package/src/store/editor-store.ts +223 -0
  251. package/src/store/history-store.ts +172 -0
  252. package/src/store/index.ts +31 -0
  253. package/src/store/layer-store.ts +675 -0
  254. package/src/store/timeline-store.ts +572 -0
  255. package/src/types/assets.d.ts +6 -0
  256. package/src/types/css.d.ts +21 -0
  257. package/src/types/editor.ts +357 -0
  258. package/src/types/react.d.ts +15 -0
  259. package/src/types/three-tsl.d.ts +146 -0
  260. package/src/types/three-webgpu.d.ts +51 -0
  261. package/tsconfig.json +49 -0
@@ -0,0 +1,24 @@
1
+ // @ts-nocheck
2
+ import { Fn, PI, mix, sin, smoothstep, vec3 } from "three/tsl"
3
+ import { fbm } from "../noise/fbm"
4
+
5
+ /**
6
+ * Returns a canvas weave pattern value for a given UV coordinate.
7
+ */
8
+ export const canvasWeavePattern = Fn(([uv]) => {
9
+ const grid = uv.mul(200.0).fract()
10
+ const noiseOffset = fbm(vec3(uv.mul(30.0), 0.0), { octaves: 3 }).mul(0.1)
11
+ const warpedGrid = grid.add(noiseOffset)
12
+
13
+ const weaveX = sin(
14
+ warpedGrid.x.mul(PI).add(fbm(vec3(uv.mul(100.0), 0.0), { octaves: 2 }).mul(0.5)),
15
+ )
16
+ const weaveY = sin(
17
+ warpedGrid.y.mul(PI).add(fbm(vec3(uv.mul(100.0).add(0.5), 0.0), { octaves: 2 }).mul(0.5)),
18
+ )
19
+
20
+ const weave = weaveX.mul(weaveY)
21
+ const smoothedWeave = smoothstep(-0.3, 0.3, weave)
22
+
23
+ return mix(0.9, 1.0, smoothedWeave)
24
+ })
@@ -0,0 +1,9 @@
1
+ // @ts-nocheck
2
+ import { Fn, dot, fract, sin, vec2 } from "three/tsl"
3
+
4
+ /**
5
+ * Returns a grain texture pattern value for a given UV coordinate.
6
+ */
7
+ export const grainTexturePattern = Fn(([uv]) => {
8
+ return fract(sin(dot(uv, vec2(12.9898, 78.233))).mul(43758.5453123))
9
+ })
@@ -0,0 +1,11 @@
1
+ // @ts-nocheck
2
+ import { Fn, float, sin } from "three/tsl"
3
+
4
+ /**
5
+ * Returns a repeating pattern of a sine function.
6
+ */
7
+ export const repeatingPattern = Fn(([pattern, repeat, time = float(0)]) => {
8
+ pattern.assign(sin(pattern.mul(repeat).add(time)).div(repeat))
9
+
10
+ return pattern
11
+ })
@@ -0,0 +1,9 @@
1
+ // @ts-nocheck
2
+ import { atan, Fn, PI, select, sign } from "three/tsl"
3
+
4
+ export const atan2 = Fn(([y, x]) => {
5
+ const base = atan(y.div(x))
6
+ const offset = sign(y).mul(PI)
7
+
8
+ return select(x.greaterThanEqual(0), base, base.add(offset))
9
+ })
@@ -0,0 +1,9 @@
1
+ // @ts-nocheck
2
+ import { Fn, vec2 } from "three/tsl"
3
+
4
+ /**
5
+ * Complex conjugate: conj(a + bi) = a - bi
6
+ */
7
+ export const complexConj = Fn(([z]) => {
8
+ return vec2(z.x, z.y.negate())
9
+ })
@@ -0,0 +1,10 @@
1
+ // @ts-nocheck
2
+ import { cos, Fn, sin, vec2 } from "three/tsl"
3
+ import { cosh, sinh } from "./hyperbolic"
4
+
5
+ /**
6
+ * Complex cosine: cos(a + bi) = cos(a)cosh(b) - i sin(a)sinh(b)
7
+ */
8
+ export const complexCos = Fn(([z]) => {
9
+ return vec2(cos(z.x).mul(cosh(z.y)), sin(z.x).mul(sinh(z.y)).negate())
10
+ })
@@ -0,0 +1,11 @@
1
+ // @ts-nocheck
2
+ import { div, dot, Fn, vec2 } from "three/tsl"
3
+
4
+ export const complexDiv = Fn(([a, b]) => {
5
+ const denominator = dot(b, b)
6
+
7
+ return vec2(
8
+ div(a.x.mul(b.x).add(a.y.mul(b.y)), denominator),
9
+ div(a.y.mul(b.x).sub(a.x.mul(b.y)), denominator)
10
+ )
11
+ })
@@ -0,0 +1,7 @@
1
+ // @ts-nocheck
2
+ import { Fn, length, log, vec2 } from "three/tsl"
3
+ import { atan2 } from "./atan2"
4
+
5
+ export const complexLog = Fn(([z]) => {
6
+ return vec2(log(length(z)), atan2(z.y, z.x))
7
+ })
@@ -0,0 +1,12 @@
1
+ // @ts-nocheck
2
+ import { Fn, vec2 } from "three/tsl"
3
+ import { complexDiv } from "./complex-div"
4
+
5
+ /**
6
+ * Möbius transformation: (z - 1) / (z + 1)
7
+ */
8
+ export const complexMobius = Fn(([z]) => {
9
+ const one = vec2(1.0, 0.0)
10
+
11
+ return complexDiv(z.sub(one), z.add(one))
12
+ })
@@ -0,0 +1,9 @@
1
+ // @ts-nocheck
2
+ import { Fn, vec2 } from "three/tsl"
3
+
4
+ /**
5
+ * Complex multiplication: (a + bi)(c + di) = (ac - bd) + (ad + bc)i
6
+ */
7
+ export const complexMul = Fn(([a, b]) => {
8
+ return vec2(a.x.mul(b.x).sub(a.y.mul(b.y)), a.x.mul(b.y).add(a.y.mul(b.x)))
9
+ })
@@ -0,0 +1,16 @@
1
+ // @ts-nocheck
2
+ import { cos, Fn, length, pow, sin, vec2 } from "three/tsl"
3
+ import { atan2 } from "./atan2"
4
+
5
+ /**
6
+ * Complex power: z^n
7
+ * Let z = r(cos θ + i sin θ), then z^n = r^n (cos nθ + i sin nθ)
8
+ */
9
+ export const complexPow = Fn(([z, n]) => {
10
+ const angle = atan2(z.y, z.x)
11
+ const r = length(z)
12
+ const rn = pow(r, n)
13
+ const nAngle = n.mul(angle)
14
+
15
+ return vec2(rn.mul(cos(nAngle)), rn.mul(sin(nAngle)))
16
+ })
@@ -0,0 +1,10 @@
1
+ // @ts-nocheck
2
+ import { cos, Fn, sin, vec2 } from "three/tsl"
3
+ import { cosh, sinh } from "./hyperbolic"
4
+
5
+ /**
6
+ * Complex sine: sin(a + bi) = sin(a)cosh(b) + i cos(a)sinh(b)
7
+ */
8
+ export const complexSin = Fn(([z]) => {
9
+ return vec2(sin(z.x).mul(cosh(z.y)), cos(z.x).mul(sinh(z.y)))
10
+ })
@@ -0,0 +1,18 @@
1
+ // @ts-nocheck
2
+ import { Fn, length, select, sqrt, vec2 } from "three/tsl"
3
+
4
+ /**
5
+ * Complex square root.
6
+ * sqrt(a + bi) = (sqrt((r+a)/2), sign(b) * sqrt((r-a)/2))
7
+ */
8
+ export const complexSqrt = Fn(([z]) => {
9
+ const r = length(z)
10
+ const rpart = sqrt(r.add(z.x).mul(0.5))
11
+ const ipart = sqrt(r.sub(z.x).mul(0.5))
12
+
13
+ return select(
14
+ z.y.greaterThanEqual(0),
15
+ vec2(rpart, ipart),
16
+ vec2(rpart, ipart.negate())
17
+ )
18
+ })
@@ -0,0 +1,12 @@
1
+ // @ts-nocheck
2
+ import { Fn } from "three/tsl"
3
+ import { complexCos } from "./complex-cos"
4
+ import { complexDiv } from "./complex-div"
5
+ import { complexSin } from "./complex-sin"
6
+
7
+ /**
8
+ * Complex tangent: tan(z) = sin(z) / cos(z)
9
+ */
10
+ export const complexTan = Fn(([z]) => {
11
+ return complexDiv(complexSin(z), complexCos(z))
12
+ })
@@ -0,0 +1,10 @@
1
+ // @ts-nocheck
2
+ import { Fn, length, vec2 } from "three/tsl"
3
+ import { atan2 } from "./atan2"
4
+
5
+ /**
6
+ * Convert complex number to polar form: (r, θ)
7
+ */
8
+ export const complexToPolar = Fn(([z]) => {
9
+ return vec2(length(z), atan2(z.y, z.x))
10
+ })
@@ -0,0 +1,20 @@
1
+ // @ts-nocheck
2
+ import { exp, Fn, float } from "three/tsl"
3
+
4
+ /**
5
+ * Hyperbolic cosine: cosh(x) = (e^x + e^-x) / 2
6
+ */
7
+ export const cosh = Fn(([x]) => {
8
+ const ex = exp(x)
9
+
10
+ return ex.add(float(1).div(ex)).mul(0.5)
11
+ })
12
+
13
+ /**
14
+ * Hyperbolic sine: sinh(x) = (e^x - e^-x) / 2
15
+ */
16
+ export const sinh = Fn(([x]) => {
17
+ const ex = exp(x)
18
+
19
+ return ex.sub(float(1).div(ex)).mul(0.5)
20
+ })
@@ -0,0 +1,48 @@
1
+ // @ts-nocheck
2
+ export {
3
+ acesTonemap,
4
+ bleachBypassTonemap,
5
+ cinematicTonemap,
6
+ crossProcessTonemap,
7
+ reinhardTonemap,
8
+ tanh,
9
+ technicolorTonemap,
10
+ totosTonemap,
11
+ } from "../color/tonemapping"
12
+ export { cosinePalette } from "../cosine-palette"
13
+ export { curlNoise3d } from "../noise/curl-noise-3d"
14
+ export { curlNoise4d } from "../noise/curl-noise-4d"
15
+ export { fbm } from "../noise/fbm"
16
+ export { perlinNoise3d } from "../noise/perlin-noise-3d"
17
+ export { ridgeNoise } from "../noise/ridge-noise"
18
+ export { simplexNoise3d } from "../noise/simplex-noise-3d"
19
+ export { simplexNoise4d } from "../noise/simplex-noise-4d"
20
+ export { turbulence } from "../noise/turbulence"
21
+ export { valueNoise3d } from "../noise/value-noise-3d"
22
+ export { voronoiNoise3d } from "../noise/voronoi-noise-3d"
23
+ export { bloom } from "../patterns/bloom"
24
+ export { bloomEdgePattern } from "../patterns/bloom-edge-pattern"
25
+ export { canvasWeavePattern } from "../patterns/canvas-weave-pattern"
26
+ export { grainTexturePattern } from "../patterns/grain-texture-pattern"
27
+ export { repeatingPattern } from "../patterns/repeating-pattern"
28
+ export { atan2 } from "./atan2"
29
+ export { complexConj } from "./complex-conj"
30
+ export { complexCos } from "./complex-cos"
31
+ export { complexDiv } from "./complex-div"
32
+ export { complexLog } from "./complex-log"
33
+ export { complexMobius } from "./complex-mobius"
34
+ export { complexMul } from "./complex-mul"
35
+ export { complexPow } from "./complex-pow"
36
+ export { complexSin } from "./complex-sin"
37
+ export { complexSqrt } from "./complex-sqrt"
38
+ export { complexTan } from "./complex-tan"
39
+ export { complexToPolar } from "./complex-to-polar"
40
+ export { cosh, sinh } from "./hyperbolic"
41
+ export { rotate } from "./rotate"
42
+ export { screenAspectUV } from "./screen-aspect-uv"
43
+ export { sdBox2d } from "./sd-box-2d"
44
+ export { sdDiamond } from "./sd-diamond"
45
+ export { sdRhombus } from "./sd-rhombus"
46
+ export { sdSphere } from "./sd-sphere"
47
+ export { smax } from "./smax"
48
+ export { smin } from "./smin"
@@ -0,0 +1,15 @@
1
+ // @ts-nocheck
2
+ import { cos, sin, vec2 } from "three/tsl"
3
+
4
+ export function rotate(
5
+ uvNode: ReturnType<typeof vec2>,
6
+ angle: unknown
7
+ ): ReturnType<typeof vec2> {
8
+ const cosAngle = cos(angle)
9
+ const sinAngle = sin(angle)
10
+
11
+ return vec2(
12
+ uvNode.x.mul(cosAngle).sub(uvNode.y.mul(sinAngle)),
13
+ uvNode.x.mul(sinAngle).add(uvNode.y.mul(cosAngle))
14
+ )
15
+ }
@@ -0,0 +1,15 @@
1
+ // @ts-nocheck
2
+ import { float, select, uv, vec2 } from "three/tsl"
3
+
4
+ export const screenAspectUV = (
5
+ renderSize: ReturnType<typeof vec2>,
6
+ range = float(0.5)
7
+ ) => {
8
+ const baseUv = uv().sub(range)
9
+
10
+ return select(
11
+ renderSize.x.greaterThan(renderSize.y),
12
+ vec2(baseUv.x.mul(renderSize.x.div(renderSize.y)), baseUv.y),
13
+ vec2(baseUv.x, baseUv.y.mul(renderSize.y.div(renderSize.x)))
14
+ )
15
+ }
@@ -0,0 +1,6 @@
1
+ // @ts-nocheck
2
+ import { abs, Fn, float, max } from "three/tsl"
3
+
4
+ export const sdBox2d = Fn(([_uv, size = float(0)]) => {
5
+ return max(abs(_uv.x), abs(_uv.y)).sub(float(size))
6
+ })
@@ -0,0 +1,6 @@
1
+ // @ts-nocheck
2
+ import { abs, Fn, float } from "three/tsl"
3
+
4
+ export const sdDiamond = Fn(([uvNode, radius = float(0)]) => {
5
+ return abs(uvNode.x).add(abs(uvNode.y)).sub(radius)
6
+ })
@@ -0,0 +1,27 @@
1
+ // @ts-nocheck
2
+ import { abs, clamp, dot, Fn, float, length, sign, vec2 } from "three/tsl"
3
+
4
+ const ndot = Fn(([left, right]) => {
5
+ return left.x.mul(right.x).sub(left.y.mul(right.y))
6
+ })
7
+
8
+ export const sdRhombus = Fn(([pointNode, bounds = vec2(0.4)]) => {
9
+ const point = abs(pointNode).toVar()
10
+ const h = clamp(
11
+ ndot(bounds.sub(point.mul(2)), bounds).div(dot(bounds, bounds)),
12
+ -1,
13
+ 1
14
+ )
15
+ const distance = length(
16
+ point.sub(bounds.mul(0.5).mul(vec2(float(1).sub(h), float(1).add(h))))
17
+ )
18
+
19
+ return distance.mul(
20
+ sign(
21
+ point.x
22
+ .mul(bounds.y)
23
+ .add(point.y.mul(bounds.x))
24
+ .sub(bounds.x.mul(bounds.y))
25
+ )
26
+ )
27
+ })
@@ -0,0 +1,6 @@
1
+ // @ts-nocheck
2
+ import { Fn, float, length } from "three/tsl"
3
+
4
+ export const sdSphere = Fn(([_uv, radius = float(0)]) => {
5
+ return length(_uv).sub(float(radius))
6
+ })
@@ -0,0 +1,7 @@
1
+ // @ts-nocheck
2
+ import { abs, Fn, float, max } from "three/tsl"
3
+
4
+ export const smax = Fn(([left, right, factor = float(0)]) => {
5
+ const h = max(factor.sub(abs(left.sub(right))), 0).div(factor)
6
+ return max(left, right).add(h.mul(h).mul(factor).mul(0.25))
7
+ })
@@ -0,0 +1,7 @@
1
+ // @ts-nocheck
2
+ import { abs, Fn, max, min } from "three/tsl"
3
+
4
+ export const smin = Fn(([left, right, factor]) => {
5
+ const h = max(factor.sub(abs(left.sub(right))), 0).div(factor)
6
+ return min(left, right).sub(h.mul(h).mul(factor).mul(0.25))
7
+ })
@@ -0,0 +1,176 @@
1
+ import {
2
+ float,
3
+ type TSLNode,
4
+ texture as tslTexture,
5
+ uv,
6
+ vec2,
7
+ vec4,
8
+ } from "three/tsl"
9
+ import * as THREE from "three/webgpu"
10
+ import { PassNode } from "./pass-node"
11
+ import type { LayerParameterValues } from "../types/editor"
12
+
13
+ type Node = TSLNode
14
+
15
+ function resolveFontFamily(value: string): string {
16
+ switch (value) {
17
+ case "mono":
18
+ return '"Geist Mono", ui-monospace, monospace'
19
+ case "sans":
20
+ return "Geist, Arial, sans-serif"
21
+ case "impact":
22
+ return 'Impact, Haettenschweiler, "Arial Narrow Bold", sans-serif'
23
+ default:
24
+ return 'Georgia, "Times New Roman", serif'
25
+ }
26
+ }
27
+
28
+ export class TextPass extends PassNode {
29
+ private readonly placeholder: THREE.Texture
30
+ private textureNode: Node
31
+ private textTexture: THREE.CanvasTexture | null = null
32
+ private canvas: HTMLCanvasElement | null = null
33
+ private width = 1
34
+ private height = 1
35
+ private params: LayerParameterValues = {}
36
+ private dirty = true
37
+
38
+ constructor(layerId: string) {
39
+ super(layerId)
40
+ this.placeholder = new THREE.Texture()
41
+ this.textureNode = tslTexture(
42
+ this.placeholder,
43
+ vec2(uv().x, float(1).sub(uv().y))
44
+ )
45
+ this.rebuildEffectNode()
46
+ }
47
+
48
+ override render(
49
+ renderer: THREE.WebGPURenderer,
50
+ inputTexture: THREE.Texture,
51
+ outputTarget: THREE.WebGLRenderTarget,
52
+ time: number,
53
+ delta: number
54
+ ): void {
55
+ if (!this.textTexture || this.dirty) {
56
+ this.rebuildTextTexture()
57
+ }
58
+
59
+ this.textureNode.value = this.textTexture ?? this.placeholder
60
+ super.render(renderer, inputTexture, outputTarget, time, delta)
61
+ }
62
+
63
+ override updateParams(params: LayerParameterValues): void {
64
+ this.params = params
65
+ this.dirty = true
66
+ }
67
+
68
+ override resize(width: number, height: number): void {
69
+ this.width = Math.max(1, width)
70
+ this.height = Math.max(1, height)
71
+ this.dirty = true
72
+ }
73
+
74
+ override dispose(): void {
75
+ this.textTexture?.dispose()
76
+ this.placeholder.dispose()
77
+ super.dispose()
78
+ }
79
+
80
+ protected override buildEffectNode(): Node {
81
+ if (!this.textureNode) {
82
+ return vec4(float(0), float(0), float(0), float(1))
83
+ }
84
+
85
+ return vec4(this.textureNode.rgb, float(1))
86
+ }
87
+
88
+ private rebuildTextTexture(): void {
89
+ if (!this.canvas) {
90
+ this.canvas = document.createElement("canvas")
91
+ }
92
+
93
+ const canvas = this.canvas
94
+ canvas.width = this.width
95
+ canvas.height = this.height
96
+ const context = canvas.getContext("2d")
97
+
98
+ if (!context) {
99
+ return
100
+ }
101
+
102
+ const text =
103
+ typeof this.params.text === "string" && this.params.text.length > 0
104
+ ? this.params.text
105
+ : "basement.studio"
106
+ const fontSize =
107
+ typeof this.params.fontSize === "number"
108
+ ? Math.max(48, this.params.fontSize)
109
+ : 280
110
+ const fontWeight =
111
+ typeof this.params.fontWeight === "number"
112
+ ? Math.round(this.params.fontWeight)
113
+ : 700
114
+ const letterSpacing =
115
+ typeof this.params.letterSpacing === "number"
116
+ ? this.params.letterSpacing
117
+ : -0.02
118
+ const fontFamily = resolveFontFamily(
119
+ typeof this.params.fontFamily === "string"
120
+ ? this.params.fontFamily
121
+ : "display-serif"
122
+ )
123
+ const textColor =
124
+ typeof this.params.textColor === "string"
125
+ ? this.params.textColor
126
+ : "#ffffff"
127
+ const backgroundColor =
128
+ typeof this.params.backgroundColor === "string"
129
+ ? this.params.backgroundColor
130
+ : "#000000"
131
+
132
+ context.clearRect(0, 0, this.width, this.height)
133
+ context.fillStyle = backgroundColor
134
+ context.fillRect(0, 0, this.width, this.height)
135
+ context.fillStyle = textColor
136
+ context.textAlign = "center"
137
+ context.textBaseline = "middle"
138
+ context.font = `${fontWeight} ${fontSize}px ${fontFamily}`
139
+
140
+ const characters = [...text]
141
+ const spacing = fontSize * letterSpacing
142
+ let totalWidth = 0
143
+
144
+ for (const [index, char] of characters.entries()) {
145
+ totalWidth += context.measureText(char).width
146
+ if (index < characters.length - 1) {
147
+ totalWidth += spacing
148
+ }
149
+ }
150
+
151
+ let x = this.width * 0.5 - totalWidth * 0.5
152
+ const y = this.height * 0.5
153
+
154
+ for (const char of characters) {
155
+ const charWidth = context.measureText(char).width
156
+ context.fillText(char, x + charWidth * 0.5, y)
157
+ x += charWidth + spacing
158
+ }
159
+
160
+ if (!this.textTexture) {
161
+ this.textTexture = new THREE.CanvasTexture(canvas)
162
+ this.textTexture.flipY = false
163
+ this.textTexture.generateMipmaps = false
164
+ this.textTexture.magFilter = THREE.LinearFilter
165
+ this.textTexture.minFilter = THREE.LinearFilter
166
+ this.textTexture.wrapS = THREE.ClampToEdgeWrapping
167
+ this.textTexture.wrapT = THREE.ClampToEdgeWrapping
168
+ this.textTexture.colorSpace = THREE.SRGBColorSpace
169
+ } else {
170
+ this.textTexture.image = canvas
171
+ }
172
+
173
+ this.textTexture.needsUpdate = true
174
+ this.dirty = false
175
+ }
176
+ }
@@ -0,0 +1,42 @@
1
+ import type { ShaderLabTimelineConfig } from "./types"
2
+
3
+ export interface ShaderLabRuntimeClock {
4
+ delta: number
5
+ duration: number
6
+ loop: boolean
7
+ time: number
8
+ }
9
+
10
+ const MIN_DURATION = 0.25
11
+
12
+ export function createRuntimeClock(
13
+ timeline: Pick<ShaderLabTimelineConfig, "duration" | "loop">,
14
+ time: number,
15
+ delta: number,
16
+ ): ShaderLabRuntimeClock {
17
+ return {
18
+ delta,
19
+ duration: Math.max(timeline.duration, MIN_DURATION),
20
+ loop: timeline.loop,
21
+ time,
22
+ }
23
+ }
24
+
25
+ export function advanceRuntimeClock(
26
+ currentTime: number,
27
+ timeline: Pick<ShaderLabTimelineConfig, "duration" | "loop">,
28
+ delta: number,
29
+ ): number {
30
+ if (!Number.isFinite(delta) || delta <= 0) {
31
+ return currentTime
32
+ }
33
+
34
+ const duration = Math.max(timeline.duration, MIN_DURATION)
35
+ const nextTime = currentTime + delta
36
+
37
+ if (timeline.loop) {
38
+ return nextTime % duration
39
+ }
40
+
41
+ return Math.min(nextTime, duration)
42
+ }
@@ -0,0 +1,29 @@
1
+ import { createRuntimeClock } from "./runtime-clock"
2
+ import { resolveEvaluatedLayers } from "./timeline"
3
+ import type { ShaderLabConfig, ShaderLabLayerConfig } from "./types"
4
+
5
+ export interface ShaderLabRenderableLayer {
6
+ layer: ShaderLabLayerConfig
7
+ }
8
+
9
+ export interface ShaderLabRuntimeFrame {
10
+ clock: ReturnType<typeof createRuntimeClock>
11
+ composition: ShaderLabConfig["composition"]
12
+ layers: ShaderLabRenderableLayer[]
13
+ }
14
+
15
+ export function buildRuntimeFrame(
16
+ config: ShaderLabConfig,
17
+ time: number,
18
+ delta: number,
19
+ ): ShaderLabRuntimeFrame {
20
+ const layers = resolveEvaluatedLayers(config.layers, config.timeline.tracks, time)
21
+ .filter((layer) => layer.visible)
22
+ .map((layer) => ({ layer }))
23
+
24
+ return {
25
+ clock: createRuntimeClock(config.timeline, time, delta),
26
+ composition: config.composition,
27
+ layers,
28
+ }
29
+ }