interactive-bg 0.0.0-stage → 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 (237) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +202 -2
  3. package/dist/core/canvas2d-renderer.cjs +119 -0
  4. package/dist/core/canvas2d-renderer.cjs.map +1 -0
  5. package/dist/core/canvas2d-renderer.d.cts +7 -0
  6. package/dist/core/canvas2d-renderer.d.ts +7 -0
  7. package/dist/core/canvas2d-renderer.js +119 -0
  8. package/dist/core/canvas2d-renderer.js.map +1 -0
  9. package/dist/core/color.cjs +46 -0
  10. package/dist/core/color.cjs.map +1 -0
  11. package/dist/core/color.d.cts +6 -0
  12. package/dist/core/color.d.ts +6 -0
  13. package/dist/core/color.js +46 -0
  14. package/dist/core/color.js.map +1 -0
  15. package/dist/core/engine.cjs +367 -0
  16. package/dist/core/engine.cjs.map +1 -0
  17. package/dist/core/engine.d.cts +69 -0
  18. package/dist/core/engine.d.ts +69 -0
  19. package/dist/core/engine.js +366 -0
  20. package/dist/core/engine.js.map +1 -0
  21. package/dist/core/style.cjs +21 -0
  22. package/dist/core/style.cjs.map +1 -0
  23. package/dist/core/style.d.cts +85 -0
  24. package/dist/core/style.d.ts +85 -0
  25. package/dist/core/style.js +21 -0
  26. package/dist/core/style.js.map +1 -0
  27. package/dist/core/surface.cjs +25 -0
  28. package/dist/core/surface.cjs.map +1 -0
  29. package/dist/core/surface.d.cts +42 -0
  30. package/dist/core/surface.d.ts +42 -0
  31. package/dist/core/surface.js +24 -0
  32. package/dist/core/surface.js.map +1 -0
  33. package/dist/core/webgl-renderer.cjs +137 -0
  34. package/dist/core/webgl-renderer.cjs.map +1 -0
  35. package/dist/core/webgl-renderer.d.cts +8 -0
  36. package/dist/core/webgl-renderer.d.ts +8 -0
  37. package/dist/core/webgl-renderer.js +137 -0
  38. package/dist/core/webgl-renderer.js.map +1 -0
  39. package/dist/core/webgl.cjs +62 -0
  40. package/dist/core/webgl.cjs.map +1 -0
  41. package/dist/core/webgl.d.cts +15 -0
  42. package/dist/core/webgl.d.ts +15 -0
  43. package/dist/core/webgl.js +60 -0
  44. package/dist/core/webgl.js.map +1 -0
  45. package/dist/dots/canvas2d.cjs +14 -0
  46. package/dist/dots/canvas2d.cjs.map +1 -0
  47. package/dist/dots/canvas2d.d.cts +5 -0
  48. package/dist/dots/canvas2d.d.ts +5 -0
  49. package/dist/dots/canvas2d.js +13 -0
  50. package/dist/dots/canvas2d.js.map +1 -0
  51. package/dist/dots/index.cjs +16 -0
  52. package/dist/dots/index.cjs.map +1 -0
  53. package/dist/dots/index.d.cts +5 -0
  54. package/dist/dots/index.d.ts +5 -0
  55. package/dist/dots/index.js +15 -0
  56. package/dist/dots/index.js.map +1 -0
  57. package/dist/dots/webgl.cjs +14 -0
  58. package/dist/dots/webgl.cjs.map +1 -0
  59. package/dist/dots/webgl.d.cts +5 -0
  60. package/dist/dots/webgl.d.ts +5 -0
  61. package/dist/dots/webgl.js +13 -0
  62. package/dist/dots/webgl.js.map +1 -0
  63. package/dist/index.cjs +24 -0
  64. package/dist/index.d.cts +18 -0
  65. package/dist/index.d.ts +18 -0
  66. package/dist/index.js +11 -0
  67. package/dist/index.umd.js +211 -0
  68. package/dist/index.umd.js.map +1 -0
  69. package/dist/plus/canvas2d.cjs +14 -0
  70. package/dist/plus/canvas2d.cjs.map +1 -0
  71. package/dist/plus/canvas2d.d.cts +5 -0
  72. package/dist/plus/canvas2d.d.ts +5 -0
  73. package/dist/plus/canvas2d.js +13 -0
  74. package/dist/plus/canvas2d.js.map +1 -0
  75. package/dist/plus/index.cjs +16 -0
  76. package/dist/plus/index.cjs.map +1 -0
  77. package/dist/plus/index.d.cts +5 -0
  78. package/dist/plus/index.d.ts +5 -0
  79. package/dist/plus/index.js +15 -0
  80. package/dist/plus/index.js.map +1 -0
  81. package/dist/plus/webgl.cjs +14 -0
  82. package/dist/plus/webgl.cjs.map +1 -0
  83. package/dist/plus/webgl.d.cts +5 -0
  84. package/dist/plus/webgl.d.ts +5 -0
  85. package/dist/plus/webgl.js +13 -0
  86. package/dist/plus/webgl.js.map +1 -0
  87. package/dist/shared/buffer.cjs +20 -0
  88. package/dist/shared/buffer.cjs.map +1 -0
  89. package/dist/shared/buffer.d.cts +11 -0
  90. package/dist/shared/buffer.d.ts +11 -0
  91. package/dist/shared/buffer.js +19 -0
  92. package/dist/shared/buffer.js.map +1 -0
  93. package/dist/shared/grid-webgl.cjs +63 -0
  94. package/dist/shared/grid-webgl.cjs.map +1 -0
  95. package/dist/shared/grid-webgl.d.cts +10 -0
  96. package/dist/shared/grid-webgl.d.ts +10 -0
  97. package/dist/shared/grid-webgl.js +61 -0
  98. package/dist/shared/grid-webgl.js.map +1 -0
  99. package/dist/shared/grid.cjs +133 -0
  100. package/dist/shared/grid.cjs.map +1 -0
  101. package/dist/shared/grid.d.cts +72 -0
  102. package/dist/shared/grid.d.ts +72 -0
  103. package/dist/shared/grid.js +123 -0
  104. package/dist/shared/grid.js.map +1 -0
  105. package/dist/shared/noise.cjs +166 -0
  106. package/dist/shared/noise.cjs.map +1 -0
  107. package/dist/shared/noise.d.cts +4 -0
  108. package/dist/shared/noise.d.ts +4 -0
  109. package/dist/shared/noise.js +166 -0
  110. package/dist/shared/noise.js.map +1 -0
  111. package/dist/styles/dots/canvas2d.cjs +99 -0
  112. package/dist/styles/dots/canvas2d.cjs.map +1 -0
  113. package/dist/styles/dots/canvas2d.d.cts +7 -0
  114. package/dist/styles/dots/canvas2d.d.ts +7 -0
  115. package/dist/styles/dots/canvas2d.js +99 -0
  116. package/dist/styles/dots/canvas2d.js.map +1 -0
  117. package/dist/styles/dots/definition.cjs +15 -0
  118. package/dist/styles/dots/definition.cjs.map +1 -0
  119. package/dist/styles/dots/definition.d.cts +7 -0
  120. package/dist/styles/dots/definition.d.ts +7 -0
  121. package/dist/styles/dots/definition.js +16 -0
  122. package/dist/styles/dots/definition.js.map +1 -0
  123. package/dist/styles/dots/motion.cjs +6 -0
  124. package/dist/styles/dots/motion.cjs.map +1 -0
  125. package/dist/styles/dots/motion.d.cts +2 -0
  126. package/dist/styles/dots/motion.d.ts +2 -0
  127. package/dist/styles/dots/motion.js +6 -0
  128. package/dist/styles/dots/motion.js.map +1 -0
  129. package/dist/styles/dots/options.cjs +33 -0
  130. package/dist/styles/dots/options.cjs.map +1 -0
  131. package/dist/styles/dots/options.d.cts +33 -0
  132. package/dist/styles/dots/options.d.ts +33 -0
  133. package/dist/styles/dots/options.js +32 -0
  134. package/dist/styles/dots/options.js.map +1 -0
  135. package/dist/styles/dots/webgl.cjs +113 -0
  136. package/dist/styles/dots/webgl.cjs.map +1 -0
  137. package/dist/styles/dots/webgl.d.cts +4 -0
  138. package/dist/styles/dots/webgl.d.ts +4 -0
  139. package/dist/styles/dots/webgl.js +113 -0
  140. package/dist/styles/dots/webgl.js.map +1 -0
  141. package/dist/styles/plus/canvas2d.cjs +88 -0
  142. package/dist/styles/plus/canvas2d.cjs.map +1 -0
  143. package/dist/styles/plus/canvas2d.d.cts +8 -0
  144. package/dist/styles/plus/canvas2d.d.ts +8 -0
  145. package/dist/styles/plus/canvas2d.js +88 -0
  146. package/dist/styles/plus/canvas2d.js.map +1 -0
  147. package/dist/styles/plus/definition.cjs +17 -0
  148. package/dist/styles/plus/definition.cjs.map +1 -0
  149. package/dist/styles/plus/definition.d.cts +9 -0
  150. package/dist/styles/plus/definition.d.ts +9 -0
  151. package/dist/styles/plus/definition.js +18 -0
  152. package/dist/styles/plus/definition.js.map +1 -0
  153. package/dist/styles/plus/motion.cjs +18 -0
  154. package/dist/styles/plus/motion.cjs.map +1 -0
  155. package/dist/styles/plus/motion.d.cts +5 -0
  156. package/dist/styles/plus/motion.d.ts +5 -0
  157. package/dist/styles/plus/motion.js +18 -0
  158. package/dist/styles/plus/motion.js.map +1 -0
  159. package/dist/styles/plus/options.cjs +45 -0
  160. package/dist/styles/plus/options.cjs.map +1 -0
  161. package/dist/styles/plus/options.d.cts +45 -0
  162. package/dist/styles/plus/options.d.ts +45 -0
  163. package/dist/styles/plus/options.js +43 -0
  164. package/dist/styles/plus/options.js.map +1 -0
  165. package/dist/styles/plus/turns.cjs +102 -0
  166. package/dist/styles/plus/turns.cjs.map +1 -0
  167. package/dist/styles/plus/turns.d.cts +17 -0
  168. package/dist/styles/plus/turns.d.ts +17 -0
  169. package/dist/styles/plus/turns.js +102 -0
  170. package/dist/styles/plus/turns.js.map +1 -0
  171. package/dist/styles/plus/webgl.cjs +121 -0
  172. package/dist/styles/plus/webgl.cjs.map +1 -0
  173. package/dist/styles/plus/webgl.d.cts +8 -0
  174. package/dist/styles/plus/webgl.d.ts +8 -0
  175. package/dist/styles/plus/webgl.js +121 -0
  176. package/dist/styles/plus/webgl.js.map +1 -0
  177. package/dist/styles/topo/canvas2d.cjs +77 -0
  178. package/dist/styles/topo/canvas2d.cjs.map +1 -0
  179. package/dist/styles/topo/canvas2d.d.cts +4 -0
  180. package/dist/styles/topo/canvas2d.d.ts +4 -0
  181. package/dist/styles/topo/canvas2d.js +77 -0
  182. package/dist/styles/topo/canvas2d.js.map +1 -0
  183. package/dist/styles/topo/contours.cjs +83 -0
  184. package/dist/styles/topo/contours.cjs.map +1 -0
  185. package/dist/styles/topo/contours.d.cts +9 -0
  186. package/dist/styles/topo/contours.d.ts +9 -0
  187. package/dist/styles/topo/contours.js +83 -0
  188. package/dist/styles/topo/contours.js.map +1 -0
  189. package/dist/styles/topo/definition.cjs +13 -0
  190. package/dist/styles/topo/definition.cjs.map +1 -0
  191. package/dist/styles/topo/definition.d.cts +7 -0
  192. package/dist/styles/topo/definition.d.ts +7 -0
  193. package/dist/styles/topo/definition.js +14 -0
  194. package/dist/styles/topo/definition.js.map +1 -0
  195. package/dist/styles/topo/field.cjs +118 -0
  196. package/dist/styles/topo/field.cjs.map +1 -0
  197. package/dist/styles/topo/field.d.cts +26 -0
  198. package/dist/styles/topo/field.d.ts +26 -0
  199. package/dist/styles/topo/field.js +118 -0
  200. package/dist/styles/topo/field.js.map +1 -0
  201. package/dist/styles/topo/options.cjs +39 -0
  202. package/dist/styles/topo/options.cjs.map +1 -0
  203. package/dist/styles/topo/options.d.cts +52 -0
  204. package/dist/styles/topo/options.d.ts +52 -0
  205. package/dist/styles/topo/options.js +38 -0
  206. package/dist/styles/topo/options.js.map +1 -0
  207. package/dist/styles/topo/terrain.cjs +22 -0
  208. package/dist/styles/topo/terrain.cjs.map +1 -0
  209. package/dist/styles/topo/terrain.d.cts +11 -0
  210. package/dist/styles/topo/terrain.d.ts +11 -0
  211. package/dist/styles/topo/terrain.js +22 -0
  212. package/dist/styles/topo/terrain.js.map +1 -0
  213. package/dist/styles/topo/webgl.cjs +150 -0
  214. package/dist/styles/topo/webgl.cjs.map +1 -0
  215. package/dist/styles/topo/webgl.d.cts +7 -0
  216. package/dist/styles/topo/webgl.d.ts +7 -0
  217. package/dist/styles/topo/webgl.js +150 -0
  218. package/dist/styles/topo/webgl.js.map +1 -0
  219. package/dist/topo/canvas2d.cjs +14 -0
  220. package/dist/topo/canvas2d.cjs.map +1 -0
  221. package/dist/topo/canvas2d.d.cts +5 -0
  222. package/dist/topo/canvas2d.d.ts +5 -0
  223. package/dist/topo/canvas2d.js +13 -0
  224. package/dist/topo/canvas2d.js.map +1 -0
  225. package/dist/topo/index.cjs +16 -0
  226. package/dist/topo/index.cjs.map +1 -0
  227. package/dist/topo/index.d.cts +5 -0
  228. package/dist/topo/index.d.ts +5 -0
  229. package/dist/topo/index.js +15 -0
  230. package/dist/topo/index.js.map +1 -0
  231. package/dist/topo/webgl.cjs +14 -0
  232. package/dist/topo/webgl.cjs.map +1 -0
  233. package/dist/topo/webgl.d.cts +5 -0
  234. package/dist/topo/webgl.d.ts +5 -0
  235. package/dist/topo/webgl.js +13 -0
  236. package/dist/topo/webgl.js.map +1 -0
  237. package/package.json +192 -4
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Numbers collected during a frame, in an array that's reused from frame to
3
+ * frame and only ever grows, so drawing allocates nothing once it's warm.
4
+ */
5
+ export interface FloatBuffer {
6
+ data: Float32Array<ArrayBuffer>;
7
+ length: number;
8
+ }
9
+ export declare function createFloatBuffer(capacity: number): FloatBuffer;
10
+ /** Make room for `count` more values (doubling the array if needed) and return the array to write into. */
11
+ export declare function reserve(buffer: FloatBuffer, count: number): Float32Array<ArrayBuffer>;
@@ -0,0 +1,19 @@
1
+ // src/shared/buffer.ts
2
+ function createFloatBuffer(capacity) {
3
+ return {
4
+ data: new Float32Array(capacity),
5
+ length: 0
6
+ };
7
+ }
8
+ /** Make room for `count` more values (doubling the array if needed) and return the array to write into. */
9
+ function reserve(buffer, count) {
10
+ if (buffer.length + count > buffer.data.length) {
11
+ const grown = new Float32Array(Math.max(buffer.data.length * 2, buffer.length + count));
12
+ grown.set(buffer.data);
13
+ buffer.data = grown;
14
+ }
15
+ return buffer.data;
16
+ }
17
+ export { createFloatBuffer, reserve };
18
+
19
+ //# sourceMappingURL=buffer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"buffer.js","names":[],"sources":["../../src/shared/buffer.ts"],"sourcesContent":["/**\n * Numbers collected during a frame, in an array that's reused from frame to\n * frame and only ever grows, so drawing allocates nothing once it's warm.\n */\nexport interface FloatBuffer {\n data: Float32Array<ArrayBuffer>;\n length: number;\n}\n\nexport function createFloatBuffer(capacity: number): FloatBuffer {\n return { data: new Float32Array(capacity), length: 0 };\n}\n\n/** Make room for `count` more values (doubling the array if needed) and return the array to write into. */\nexport function reserve(buffer: FloatBuffer, count: number): Float32Array<ArrayBuffer> {\n if (buffer.length + count > buffer.data.length) {\n const grown = new Float32Array(Math.max(buffer.data.length * 2, buffer.length + count));\n grown.set(buffer.data);\n buffer.data = grown;\n }\n return buffer.data;\n}\n"],"mappings":";AASA,SAAgB,kBAAkB,UAA+B;CAC/D,OAAO;EAAE,MAAM,IAAI,aAAa,QAAQ;EAAG,QAAQ;CAAE;AACvD;;AAGA,SAAgB,QAAQ,QAAqB,OAA0C;CACrF,IAAI,OAAO,SAAS,QAAQ,OAAO,KAAK,QAAQ;EAC9C,MAAM,QAAQ,IAAI,aAAa,KAAK,IAAI,OAAO,KAAK,SAAS,GAAG,OAAO,SAAS,KAAK,CAAC;EACtF,MAAM,IAAI,OAAO,IAAI;EACrB,OAAO,OAAO;CAChB;CACA,OAAO,OAAO;AAChB"}
@@ -0,0 +1,63 @@
1
+ const require_grid = require("./grid.cjs");
2
+ // src/shared/grid-webgl.ts
3
+ /** The uniforms GRID_VERTEX_GLSL declares; set them with setGridUniforms(). */
4
+ var GRID_UNIFORMS = [
5
+ "uCols",
6
+ "uOrigin",
7
+ "uSpacing",
8
+ "uViewport",
9
+ "uDpr",
10
+ "uClock",
11
+ "uJitter"
12
+ ];
13
+ /**
14
+ * Vertex-shader preamble for the grid styles, which draw one GL point per mark.
15
+ * Mirrors gridLayout, cellPhase and the wander in grid.ts; keep them in step.
16
+ */
17
+ var GRID_VERTEX_GLSL = `
18
+ uniform int uCols;
19
+ uniform vec2 uOrigin; // CSS px of mark (0, 0)
20
+ uniform float uSpacing;
21
+ uniform vec2 uViewport; // canvas size in CSS px
22
+ uniform float uDpr;
23
+ uniform float uClock; // wander phase, radians
24
+ uniform float uJitter;
25
+
26
+ float phase(vec2 ij, float salt) {
27
+ return fract(sin(ij.x * 12.9898 + ij.y * 78.233 + salt) * 43758.5453) * ${require_grid.TAU.toFixed(6)};
28
+ }
29
+
30
+ // This vertex's mark as (column, row). Integer maths: float division can put the first
31
+ // mark of a row at the end of the previous one on some GPUs.
32
+ vec2 markCell() {
33
+ return vec2(float(gl_VertexID % uCols), float(gl_VertexID / uCols));
34
+ }
35
+
36
+ vec2 restPosition(vec2 ij) {
37
+ return uOrigin + ij * uSpacing;
38
+ }
39
+
40
+ vec2 wander(vec2 ij) {
41
+ return uJitter * vec2(sin(uClock + phase(ij, 0.0)), cos(uClock * 1.3 + phase(ij, 1.0)));
42
+ }
43
+
44
+ // CSS px (origin top left) to clip space.
45
+ vec4 toClip(vec2 p) {
46
+ vec2 clip = p / uViewport * 2.0 - 1.0;
47
+ return vec4(clip.x, -clip.y, 0.0, 1.0);
48
+ }
49
+ `;
50
+ function setGridUniforms(gl, uniforms, grid, frame, spacing, clock, jitter) {
51
+ gl.uniform1i(uniforms.uCols, grid.cols);
52
+ gl.uniform2f(uniforms.uOrigin, grid.originX, grid.originY);
53
+ gl.uniform1f(uniforms.uSpacing, spacing);
54
+ gl.uniform2f(uniforms.uViewport, frame.width, frame.height);
55
+ gl.uniform1f(uniforms.uDpr, frame.dpr);
56
+ gl.uniform1f(uniforms.uClock, clock);
57
+ gl.uniform1f(uniforms.uJitter, jitter);
58
+ }
59
+ exports.GRID_UNIFORMS = GRID_UNIFORMS;
60
+ exports.GRID_VERTEX_GLSL = GRID_VERTEX_GLSL;
61
+ exports.setGridUniforms = setGridUniforms;
62
+
63
+ //# sourceMappingURL=grid-webgl.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grid-webgl.cjs","names":["TAU"],"sources":["../../src/shared/grid-webgl.ts"],"sourcesContent":["import type { Frame } from '../core/style';\nimport { TAU, type Grid } from './grid';\n\n/** The uniforms GRID_VERTEX_GLSL declares; set them with setGridUniforms(). */\nexport const GRID_UNIFORMS = ['uCols', 'uOrigin', 'uSpacing', 'uViewport', 'uDpr', 'uClock', 'uJitter'] as const;\n\n/**\n * Vertex-shader preamble for the grid styles, which draw one GL point per mark.\n * Mirrors gridLayout, cellPhase and the wander in grid.ts; keep them in step.\n */\nexport const GRID_VERTEX_GLSL = `\nuniform int uCols;\nuniform vec2 uOrigin; // CSS px of mark (0, 0)\nuniform float uSpacing;\nuniform vec2 uViewport; // canvas size in CSS px\nuniform float uDpr;\nuniform float uClock; // wander phase, radians\nuniform float uJitter;\n\nfloat phase(vec2 ij, float salt) {\n return fract(sin(ij.x * 12.9898 + ij.y * 78.233 + salt) * 43758.5453) * ${TAU.toFixed(6)};\n}\n\n// This vertex's mark as (column, row). Integer maths: float division can put the first\n// mark of a row at the end of the previous one on some GPUs.\nvec2 markCell() {\n return vec2(float(gl_VertexID % uCols), float(gl_VertexID / uCols));\n}\n\nvec2 restPosition(vec2 ij) {\n return uOrigin + ij * uSpacing;\n}\n\nvec2 wander(vec2 ij) {\n return uJitter * vec2(sin(uClock + phase(ij, 0.0)), cos(uClock * 1.3 + phase(ij, 1.0)));\n}\n\n// CSS px (origin top left) to clip space.\nvec4 toClip(vec2 p) {\n vec2 clip = p / uViewport * 2.0 - 1.0;\n return vec4(clip.x, -clip.y, 0.0, 1.0);\n}\n`;\n\nexport function setGridUniforms(\n gl: WebGL2RenderingContext,\n uniforms: Record<(typeof GRID_UNIFORMS)[number], WebGLUniformLocation | null>,\n grid: Grid,\n frame: Frame,\n spacing: number,\n clock: number,\n jitter: number,\n): void {\n gl.uniform1i(uniforms.uCols, grid.cols);\n gl.uniform2f(uniforms.uOrigin, grid.originX, grid.originY);\n gl.uniform1f(uniforms.uSpacing, spacing);\n gl.uniform2f(uniforms.uViewport, frame.width, frame.height);\n gl.uniform1f(uniforms.uDpr, frame.dpr);\n gl.uniform1f(uniforms.uClock, clock);\n gl.uniform1f(uniforms.uJitter, jitter);\n}\n"],"mappings":";;;AAIA,IAAa,gBAAgB;CAAC;CAAS;CAAW;CAAY;CAAa;CAAQ;CAAU;AAAS;;;;;AAMtG,IAAa,mBAAmB;;;;;;;;;;4EAU4CA,aAAAA,IAAI,QAAQ,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;AAwB3F,SAAgB,gBACd,IACA,UACA,MACA,OACA,SACA,OACA,QACM;CACN,GAAG,UAAU,SAAS,OAAO,KAAK,IAAI;CACtC,GAAG,UAAU,SAAS,SAAS,KAAK,SAAS,KAAK,OAAO;CACzD,GAAG,UAAU,SAAS,UAAU,OAAO;CACvC,GAAG,UAAU,SAAS,WAAW,MAAM,OAAO,MAAM,MAAM;CAC1D,GAAG,UAAU,SAAS,MAAM,MAAM,GAAG;CACrC,GAAG,UAAU,SAAS,QAAQ,KAAK;CACnC,GAAG,UAAU,SAAS,SAAS,MAAM;AACvC"}
@@ -0,0 +1,10 @@
1
+ import type { Frame } from '../core/style.cjs';
2
+ import { type Grid } from './grid.cjs';
3
+ /** The uniforms GRID_VERTEX_GLSL declares; set them with setGridUniforms(). */
4
+ export declare const GRID_UNIFORMS: readonly ['uCols', 'uOrigin', 'uSpacing', 'uViewport', 'uDpr', 'uClock', 'uJitter'];
5
+ /**
6
+ * Vertex-shader preamble for the grid styles, which draw one GL point per mark.
7
+ * Mirrors gridLayout, cellPhase and the wander in grid.ts; keep them in step.
8
+ */
9
+ export declare const GRID_VERTEX_GLSL: string;
10
+ export declare function setGridUniforms(gl: WebGL2RenderingContext, uniforms: Record<(typeof GRID_UNIFORMS)[number], WebGLUniformLocation | null>, grid: Grid, frame: Frame, spacing: number, clock: number, jitter: number): void;
@@ -0,0 +1,10 @@
1
+ import type { Frame } from '../core/style.js';
2
+ import { type Grid } from './grid.js';
3
+ /** The uniforms GRID_VERTEX_GLSL declares; set them with setGridUniforms(). */
4
+ export declare const GRID_UNIFORMS: readonly ['uCols', 'uOrigin', 'uSpacing', 'uViewport', 'uDpr', 'uClock', 'uJitter'];
5
+ /**
6
+ * Vertex-shader preamble for the grid styles, which draw one GL point per mark.
7
+ * Mirrors gridLayout, cellPhase and the wander in grid.ts; keep them in step.
8
+ */
9
+ export declare const GRID_VERTEX_GLSL: string;
10
+ export declare function setGridUniforms(gl: WebGL2RenderingContext, uniforms: Record<(typeof GRID_UNIFORMS)[number], WebGLUniformLocation | null>, grid: Grid, frame: Frame, spacing: number, clock: number, jitter: number): void;
@@ -0,0 +1,61 @@
1
+ import { TAU } from "./grid.js";
2
+ // src/shared/grid-webgl.ts
3
+ /** The uniforms GRID_VERTEX_GLSL declares; set them with setGridUniforms(). */
4
+ var GRID_UNIFORMS = [
5
+ "uCols",
6
+ "uOrigin",
7
+ "uSpacing",
8
+ "uViewport",
9
+ "uDpr",
10
+ "uClock",
11
+ "uJitter"
12
+ ];
13
+ /**
14
+ * Vertex-shader preamble for the grid styles, which draw one GL point per mark.
15
+ * Mirrors gridLayout, cellPhase and the wander in grid.ts; keep them in step.
16
+ */
17
+ var GRID_VERTEX_GLSL = `
18
+ uniform int uCols;
19
+ uniform vec2 uOrigin; // CSS px of mark (0, 0)
20
+ uniform float uSpacing;
21
+ uniform vec2 uViewport; // canvas size in CSS px
22
+ uniform float uDpr;
23
+ uniform float uClock; // wander phase, radians
24
+ uniform float uJitter;
25
+
26
+ float phase(vec2 ij, float salt) {
27
+ return fract(sin(ij.x * 12.9898 + ij.y * 78.233 + salt) * 43758.5453) * ${TAU.toFixed(6)};
28
+ }
29
+
30
+ // This vertex's mark as (column, row). Integer maths: float division can put the first
31
+ // mark of a row at the end of the previous one on some GPUs.
32
+ vec2 markCell() {
33
+ return vec2(float(gl_VertexID % uCols), float(gl_VertexID / uCols));
34
+ }
35
+
36
+ vec2 restPosition(vec2 ij) {
37
+ return uOrigin + ij * uSpacing;
38
+ }
39
+
40
+ vec2 wander(vec2 ij) {
41
+ return uJitter * vec2(sin(uClock + phase(ij, 0.0)), cos(uClock * 1.3 + phase(ij, 1.0)));
42
+ }
43
+
44
+ // CSS px (origin top left) to clip space.
45
+ vec4 toClip(vec2 p) {
46
+ vec2 clip = p / uViewport * 2.0 - 1.0;
47
+ return vec4(clip.x, -clip.y, 0.0, 1.0);
48
+ }
49
+ `;
50
+ function setGridUniforms(gl, uniforms, grid, frame, spacing, clock, jitter) {
51
+ gl.uniform1i(uniforms.uCols, grid.cols);
52
+ gl.uniform2f(uniforms.uOrigin, grid.originX, grid.originY);
53
+ gl.uniform1f(uniforms.uSpacing, spacing);
54
+ gl.uniform2f(uniforms.uViewport, frame.width, frame.height);
55
+ gl.uniform1f(uniforms.uDpr, frame.dpr);
56
+ gl.uniform1f(uniforms.uClock, clock);
57
+ gl.uniform1f(uniforms.uJitter, jitter);
58
+ }
59
+ export { GRID_UNIFORMS, GRID_VERTEX_GLSL, setGridUniforms };
60
+
61
+ //# sourceMappingURL=grid-webgl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grid-webgl.js","names":[],"sources":["../../src/shared/grid-webgl.ts"],"sourcesContent":["import type { Frame } from '../core/style';\nimport { TAU, type Grid } from './grid';\n\n/** The uniforms GRID_VERTEX_GLSL declares; set them with setGridUniforms(). */\nexport const GRID_UNIFORMS = ['uCols', 'uOrigin', 'uSpacing', 'uViewport', 'uDpr', 'uClock', 'uJitter'] as const;\n\n/**\n * Vertex-shader preamble for the grid styles, which draw one GL point per mark.\n * Mirrors gridLayout, cellPhase and the wander in grid.ts; keep them in step.\n */\nexport const GRID_VERTEX_GLSL = `\nuniform int uCols;\nuniform vec2 uOrigin; // CSS px of mark (0, 0)\nuniform float uSpacing;\nuniform vec2 uViewport; // canvas size in CSS px\nuniform float uDpr;\nuniform float uClock; // wander phase, radians\nuniform float uJitter;\n\nfloat phase(vec2 ij, float salt) {\n return fract(sin(ij.x * 12.9898 + ij.y * 78.233 + salt) * 43758.5453) * ${TAU.toFixed(6)};\n}\n\n// This vertex's mark as (column, row). Integer maths: float division can put the first\n// mark of a row at the end of the previous one on some GPUs.\nvec2 markCell() {\n return vec2(float(gl_VertexID % uCols), float(gl_VertexID / uCols));\n}\n\nvec2 restPosition(vec2 ij) {\n return uOrigin + ij * uSpacing;\n}\n\nvec2 wander(vec2 ij) {\n return uJitter * vec2(sin(uClock + phase(ij, 0.0)), cos(uClock * 1.3 + phase(ij, 1.0)));\n}\n\n// CSS px (origin top left) to clip space.\nvec4 toClip(vec2 p) {\n vec2 clip = p / uViewport * 2.0 - 1.0;\n return vec4(clip.x, -clip.y, 0.0, 1.0);\n}\n`;\n\nexport function setGridUniforms(\n gl: WebGL2RenderingContext,\n uniforms: Record<(typeof GRID_UNIFORMS)[number], WebGLUniformLocation | null>,\n grid: Grid,\n frame: Frame,\n spacing: number,\n clock: number,\n jitter: number,\n): void {\n gl.uniform1i(uniforms.uCols, grid.cols);\n gl.uniform2f(uniforms.uOrigin, grid.originX, grid.originY);\n gl.uniform1f(uniforms.uSpacing, spacing);\n gl.uniform2f(uniforms.uViewport, frame.width, frame.height);\n gl.uniform1f(uniforms.uDpr, frame.dpr);\n gl.uniform1f(uniforms.uClock, clock);\n gl.uniform1f(uniforms.uJitter, jitter);\n}\n"],"mappings":";;;AAIA,IAAa,gBAAgB;CAAC;CAAS;CAAW;CAAY;CAAa;CAAQ;CAAU;AAAS;;;;;AAMtG,IAAa,mBAAmB;;;;;;;;;;4EAU4C,IAAI,QAAQ,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;AAwB3F,SAAgB,gBACd,IACA,UACA,MACA,OACA,SACA,OACA,QACM;CACN,GAAG,UAAU,SAAS,OAAO,KAAK,IAAI;CACtC,GAAG,UAAU,SAAS,SAAS,KAAK,SAAS,KAAK,OAAO;CACzD,GAAG,UAAU,SAAS,UAAU,OAAO;CACvC,GAAG,UAAU,SAAS,WAAW,MAAM,OAAO,MAAM,MAAM;CAC1D,GAAG,UAAU,SAAS,MAAM,MAAM,GAAG;CACrC,GAAG,UAAU,SAAS,QAAQ,KAAK;CACnC,GAAG,UAAU,SAAS,SAAS,MAAM;AACvC"}
@@ -0,0 +1,133 @@
1
+ // src/shared/grid.ts
2
+ var TAU = Math.PI * 2;
3
+ /**
4
+ * A grid that fits inside the canvas, centred, leaving at least half a
5
+ * `spacing` of padding on every side so marks at the edges are never clipped.
6
+ * Any space left over is shared equally between opposite sides. A canvas too
7
+ * small for the padding still gets one mark, in its centre.
8
+ */
9
+ function gridLayout(width, height, spacing) {
10
+ const cols = Math.max(1, Math.floor(width / spacing));
11
+ const rows = Math.max(1, Math.floor(height / spacing));
12
+ return {
13
+ cols,
14
+ rows,
15
+ originX: (width - (cols - 1) * spacing) / 2,
16
+ originY: (height - (rows - 1) * spacing) / 2
17
+ };
18
+ }
19
+ /** A stable pseudo-random phase in [0, 2π) for mark (i, j). */
20
+ function cellPhase(i, j, salt) {
21
+ const s = Math.sin(i * 12.9898 + j * 78.233 + salt) * 43758.5453;
22
+ return (s - Math.floor(s)) * TAU;
23
+ }
24
+ /**
25
+ * Each mark's wander phases (px, py) as cos px, sin px, cos py, sin py,
26
+ * recomputed only when the grid changes size. The wander offset is
27
+ * `jitter × (sin(clock + px), cos(clock × 1.3 + py))`; see wanderClock.
28
+ */
29
+ function createPhaseCache() {
30
+ let phases = /* @__PURE__ */ new Float32Array(0);
31
+ let phaseCols = 0;
32
+ return (cols, rows) => {
33
+ if (phaseCols === cols && phases.length === cols * rows * 4) return phases;
34
+ phases = new Float32Array(cols * rows * 4);
35
+ for (let j = 0; j < rows; j++) for (let i = 0; i < cols; i++) {
36
+ const k = (j * cols + i) * 4;
37
+ const px = cellPhase(i, j, 0);
38
+ const py = cellPhase(i, j, 1);
39
+ phases[k] = Math.cos(px);
40
+ phases[k + 1] = Math.sin(px);
41
+ phases[k + 2] = Math.cos(py);
42
+ phases[k + 3] = Math.sin(py);
43
+ }
44
+ phaseCols = cols;
45
+ return phases;
46
+ };
47
+ }
48
+ /**
49
+ * The trig of the wander clock for one frame. With a mark's cached phases
50
+ * (createPhaseCache), its offset is
51
+ * x = jitter × (sx × cos px + cx × sin px) = jitter × sin(clock + px)
52
+ * y = jitter × (cy × cos py − sy × sin py) = jitter × cos(clock × 1.3 + py)
53
+ * so a frame needs four trig calls in all instead of two per mark.
54
+ */
55
+ function wanderClock(clock) {
56
+ return {
57
+ sx: Math.sin(clock),
58
+ cx: Math.cos(clock),
59
+ sy: Math.sin(clock * 1.3),
60
+ cy: Math.cos(clock * 1.3)
61
+ };
62
+ }
63
+ /** How strongly the pointer affects a mark `distance` away: 1 at the pointer, easing to 0 at `radius`. */
64
+ function pointerFalloff(distance, radius) {
65
+ const k = Math.max(0, 1 - distance / radius);
66
+ return k * k;
67
+ }
68
+ /** Height of a wave's ring at `distance` from its centre: 1 on the ring, fading over `width` either side. */
69
+ function waveRing(distance, ringRadius, width) {
70
+ const x = (distance - ringRadius) / width;
71
+ return Math.exp(-x * x);
72
+ }
73
+ /** How much of a wave is left at `age`: 1 when it starts, easing out to 0 at `duration`. */
74
+ function waveEnvelope(age, duration) {
75
+ const k = Math.max(0, 1 - age / duration);
76
+ return k * k;
77
+ }
78
+ /** The wander moves each mark at most this far between frames, in CSS pixels; finer steps can't be seen. */
79
+ var WANDER_STEP = .25;
80
+ /**
81
+ * Frame rate that keeps every wander step below WANDER_STEP. The fastest a mark
82
+ * wanders is along y: amplitude × angular speed × 1.3.
83
+ */
84
+ function wanderFps(jitter, jitterSpeed) {
85
+ const maxSpeed = jitter * jitterSpeed * TAU * 1.3;
86
+ return Math.ceil(maxSpeed / WANDER_STEP);
87
+ }
88
+ /** Idle frame rate for a wandering grid: just enough for a smooth wander, at least 5 fps. */
89
+ function wanderIdleFps(options) {
90
+ return Math.max(5, wanderFps(options.jitter, options.jitterSpeed));
91
+ }
92
+ function createWaveList() {
93
+ const waves = [];
94
+ return {
95
+ waves,
96
+ advance(frame, duration, enabled) {
97
+ for (const wave of waves) wave.age += frame.dt;
98
+ for (let k = waves.length - 1; k >= 0; k--) if (waves[k].age >= duration) waves.splice(k, 1);
99
+ if (!enabled) return;
100
+ for (const click of frame.clicks) {
101
+ if (waves.length === 8) waves.shift();
102
+ waves.push({
103
+ x: click.x,
104
+ y: click.y,
105
+ age: 0
106
+ });
107
+ }
108
+ },
109
+ pack(out, speed, duration) {
110
+ out.fill(0);
111
+ for (let k = 0; k < waves.length; k++) {
112
+ const wave = waves[k];
113
+ out[k * 4] = wave.x;
114
+ out[k * 4 + 1] = wave.y;
115
+ out[k * 4 + 2] = speed * wave.age;
116
+ out[k * 4 + 3] = waveEnvelope(wave.age, duration);
117
+ }
118
+ }
119
+ };
120
+ }
121
+ exports.TAU = TAU;
122
+ exports.cellPhase = cellPhase;
123
+ exports.createPhaseCache = createPhaseCache;
124
+ exports.createWaveList = createWaveList;
125
+ exports.gridLayout = gridLayout;
126
+ exports.pointerFalloff = pointerFalloff;
127
+ exports.wanderClock = wanderClock;
128
+ exports.wanderFps = wanderFps;
129
+ exports.wanderIdleFps = wanderIdleFps;
130
+ exports.waveEnvelope = waveEnvelope;
131
+ exports.waveRing = waveRing;
132
+
133
+ //# sourceMappingURL=grid.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grid.cjs","names":[],"sources":["../../src/shared/grid.ts"],"sourcesContent":["import type { Frame } from '../core/style';\n\n// The motion model shared by the grid styles (dots, plus): a grid of marks that\n// wander around their places, react to the pointer and to click waves. The\n// WebGL vertex shaders mirror parts of it in GLSL (grid-webgl.ts); keep them in step.\n\nexport const TAU = Math.PI * 2;\n\n/** At most this many waves play at once; a new click replaces the oldest. */\nexport const MAX_WAVES = 8;\n\nexport interface Grid {\n cols: number;\n rows: number;\n /** Position of mark (0, 0), in CSS pixels. */\n originX: number;\n originY: number;\n}\n\n/**\n * A grid that fits inside the canvas, centred, leaving at least half a\n * `spacing` of padding on every side so marks at the edges are never clipped.\n * Any space left over is shared equally between opposite sides. A canvas too\n * small for the padding still gets one mark, in its centre.\n */\nexport function gridLayout(width: number, height: number, spacing: number): Grid {\n const cols = Math.max(1, Math.floor(width / spacing));\n const rows = Math.max(1, Math.floor(height / spacing));\n return {\n cols,\n rows,\n originX: (width - (cols - 1) * spacing) / 2,\n originY: (height - (rows - 1) * spacing) / 2,\n };\n}\n\n/** A stable pseudo-random phase in [0, 2π) for mark (i, j). */\nexport function cellPhase(i: number, j: number, salt: number): number {\n const s = Math.sin(i * 12.9898 + j * 78.233 + salt) * 43758.5453;\n return (s - Math.floor(s)) * TAU;\n}\n\n/**\n * Each mark's wander phases (px, py) as cos px, sin px, cos py, sin py,\n * recomputed only when the grid changes size. The wander offset is\n * `jitter × (sin(clock + px), cos(clock × 1.3 + py))`; see wanderClock.\n */\nexport function createPhaseCache(): (cols: number, rows: number) => Float32Array {\n let phases = new Float32Array(0);\n let phaseCols = 0;\n return (cols, rows) => {\n if (phaseCols === cols && phases.length === cols * rows * 4) return phases;\n phases = new Float32Array(cols * rows * 4);\n for (let j = 0; j < rows; j++) {\n for (let i = 0; i < cols; i++) {\n const k = (j * cols + i) * 4;\n const px = cellPhase(i, j, 0);\n const py = cellPhase(i, j, 1);\n phases[k] = Math.cos(px);\n phases[k + 1] = Math.sin(px);\n phases[k + 2] = Math.cos(py);\n phases[k + 3] = Math.sin(py);\n }\n }\n phaseCols = cols;\n return phases;\n };\n}\n\n/**\n * The trig of the wander clock for one frame. With a mark's cached phases\n * (createPhaseCache), its offset is\n * x = jitter × (sx × cos px + cx × sin px) = jitter × sin(clock + px)\n * y = jitter × (cy × cos py − sy × sin py) = jitter × cos(clock × 1.3 + py)\n * so a frame needs four trig calls in all instead of two per mark.\n */\nexport function wanderClock(clock: number): { sx: number; cx: number; sy: number; cy: number } {\n return { sx: Math.sin(clock), cx: Math.cos(clock), sy: Math.sin(clock * 1.3), cy: Math.cos(clock * 1.3) };\n}\n\n/** How strongly the pointer affects a mark `distance` away: 1 at the pointer, easing to 0 at `radius`. */\nexport function pointerFalloff(distance: number, radius: number): number {\n const k = Math.max(0, 1 - distance / radius);\n return k * k;\n}\n\n/** Height of a wave's ring at `distance` from its centre: 1 on the ring, fading over `width` either side. */\nexport function waveRing(distance: number, ringRadius: number, width: number): number {\n const x = (distance - ringRadius) / width;\n return Math.exp(-x * x);\n}\n\n/** How much of a wave is left at `age`: 1 when it starts, easing out to 0 at `duration`. */\nexport function waveEnvelope(age: number, duration: number): number {\n const k = Math.max(0, 1 - age / duration);\n return k * k;\n}\n\n/** The wander moves each mark at most this far between frames, in CSS pixels; finer steps can't be seen. */\nconst WANDER_STEP = 0.25;\n\n/**\n * Frame rate that keeps every wander step below WANDER_STEP. The fastest a mark\n * wanders is along y: amplitude × angular speed × 1.3.\n */\nexport function wanderFps(jitter: number, jitterSpeed: number): number {\n const maxSpeed = jitter * jitterSpeed * TAU * 1.3;\n return Math.ceil(maxSpeed / WANDER_STEP);\n}\n\n/** Idle frame rate for a wandering grid: just enough for a smooth wander, at least 5 fps. */\nexport function wanderIdleFps(options: { jitter: number; jitterSpeed: number }): number {\n return Math.max(5, wanderFps(options.jitter, options.jitterSpeed));\n}\n\nexport interface Wave {\n x: number;\n y: number;\n age: number;\n}\n\n/** The click waves currently playing. */\nexport interface WaveList {\n readonly waves: readonly Wave[];\n /**\n * Start waves for this frame's clicks (unless `enabled` is false), age the\n * rest, and drop those older than `duration` seconds.\n */\n advance(frame: Frame, duration: number, enabled: boolean): void;\n /** Writes each wave as x, y, ring radius, envelope into `out` (MAX_WAVES × 4), zeroing unused slots. */\n pack(out: Float32Array, speed: number, duration: number): void;\n}\n\nexport function createWaveList(): WaveList {\n const waves: Wave[] = [];\n return {\n waves,\n advance(frame, duration, enabled) {\n for (const wave of waves) wave.age += frame.dt;\n for (let k = waves.length - 1; k >= 0; k--) {\n if (waves[k].age >= duration) waves.splice(k, 1);\n }\n if (!enabled) return;\n for (const click of frame.clicks) {\n if (waves.length === MAX_WAVES) waves.shift();\n waves.push({ x: click.x, y: click.y, age: 0 });\n }\n },\n pack(out, speed, duration) {\n out.fill(0);\n for (let k = 0; k < waves.length; k++) {\n const wave = waves[k];\n out[k * 4] = wave.x;\n out[k * 4 + 1] = wave.y;\n out[k * 4 + 2] = speed * wave.age;\n out[k * 4 + 3] = waveEnvelope(wave.age, duration);\n }\n },\n };\n}\n"],"mappings":";AAMA,IAAa,MAAM,KAAK,KAAK;;;;;;;AAmB7B,SAAgB,WAAW,OAAe,QAAgB,SAAuB;CAC/E,MAAM,OAAO,KAAK,IAAI,GAAG,KAAK,MAAM,QAAQ,OAAO,CAAC;CACpD,MAAM,OAAO,KAAK,IAAI,GAAG,KAAK,MAAM,SAAS,OAAO,CAAC;CACrD,OAAO;EACL;EACA;EACA,UAAU,SAAS,OAAO,KAAK,WAAW;EAC1C,UAAU,UAAU,OAAO,KAAK,WAAW;CAC7C;AACF;;AAGA,SAAgB,UAAU,GAAW,GAAW,MAAsB;CACpE,MAAM,IAAI,KAAK,IAAI,IAAI,UAAU,IAAI,SAAS,IAAI,IAAI;CACtD,QAAQ,IAAI,KAAK,MAAM,CAAC,KAAK;AAC/B;;;;;;AAOA,SAAgB,mBAAiE;CAC/E,IAAI,yBAAS,IAAI,aAAa,CAAC;CAC/B,IAAI,YAAY;CAChB,QAAQ,MAAM,SAAS;EACrB,IAAI,cAAc,QAAQ,OAAO,WAAW,OAAO,OAAO,GAAG,OAAO;EACpE,SAAS,IAAI,aAAa,OAAO,OAAO,CAAC;EACzC,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,KACxB,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,KAAK;GAC7B,MAAM,KAAK,IAAI,OAAO,KAAK;GAC3B,MAAM,KAAK,UAAU,GAAG,GAAG,CAAC;GAC5B,MAAM,KAAK,UAAU,GAAG,GAAG,CAAC;GAC5B,OAAO,KAAK,KAAK,IAAI,EAAE;GACvB,OAAO,IAAI,KAAK,KAAK,IAAI,EAAE;GAC3B,OAAO,IAAI,KAAK,KAAK,IAAI,EAAE;GAC3B,OAAO,IAAI,KAAK,KAAK,IAAI,EAAE;EAC7B;EAEF,YAAY;EACZ,OAAO;CACT;AACF;;;;;;;;AASA,SAAgB,YAAY,OAAmE;CAC7F,OAAO;EAAE,IAAI,KAAK,IAAI,KAAK;EAAG,IAAI,KAAK,IAAI,KAAK;EAAG,IAAI,KAAK,IAAI,QAAQ,GAAG;EAAG,IAAI,KAAK,IAAI,QAAQ,GAAG;CAAE;AAC1G;;AAGA,SAAgB,eAAe,UAAkB,QAAwB;CACvE,MAAM,IAAI,KAAK,IAAI,GAAG,IAAI,WAAW,MAAM;CAC3C,OAAO,IAAI;AACb;;AAGA,SAAgB,SAAS,UAAkB,YAAoB,OAAuB;CACpF,MAAM,KAAK,WAAW,cAAc;CACpC,OAAO,KAAK,IAAI,CAAC,IAAI,CAAC;AACxB;;AAGA,SAAgB,aAAa,KAAa,UAA0B;CAClE,MAAM,IAAI,KAAK,IAAI,GAAG,IAAI,MAAM,QAAQ;CACxC,OAAO,IAAI;AACb;;AAGA,IAAM,cAAc;;;;;AAMpB,SAAgB,UAAU,QAAgB,aAA6B;CACrE,MAAM,WAAW,SAAS,cAAc,MAAM;CAC9C,OAAO,KAAK,KAAK,WAAW,WAAW;AACzC;;AAGA,SAAgB,cAAc,SAA0D;CACtF,OAAO,KAAK,IAAI,GAAG,UAAU,QAAQ,QAAQ,QAAQ,WAAW,CAAC;AACnE;AAoBA,SAAgB,iBAA2B;CACzC,MAAM,QAAgB,CAAC;CACvB,OAAO;EACL;EACA,QAAQ,OAAO,UAAU,SAAS;GAChC,KAAK,MAAM,QAAQ,OAAO,KAAK,OAAO,MAAM;GAC5C,KAAK,IAAI,IAAI,MAAM,SAAS,GAAG,KAAK,GAAG,KACrC,IAAI,MAAM,EAAE,CAAC,OAAO,UAAU,MAAM,OAAO,GAAG,CAAC;GAEjD,IAAI,CAAC,SAAS;GACd,KAAK,MAAM,SAAS,MAAM,QAAQ;IAChC,IAAI,MAAM,WAAA,GAAsB,MAAM,MAAM;IAC5C,MAAM,KAAK;KAAE,GAAG,MAAM;KAAG,GAAG,MAAM;KAAG,KAAK;IAAE,CAAC;GAC/C;EACF;EACA,KAAK,KAAK,OAAO,UAAU;GACzB,IAAI,KAAK,CAAC;GACV,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;IACrC,MAAM,OAAO,MAAM;IACnB,IAAI,IAAI,KAAK,KAAK;IAClB,IAAI,IAAI,IAAI,KAAK,KAAK;IACtB,IAAI,IAAI,IAAI,KAAK,QAAQ,KAAK;IAC9B,IAAI,IAAI,IAAI,KAAK,aAAa,KAAK,KAAK,QAAQ;GAClD;EACF;CACF;AACF"}
@@ -0,0 +1,72 @@
1
+ import type { Frame } from '../core/style.cjs';
2
+ export declare const TAU: number;
3
+ /** At most this many waves play at once; a new click replaces the oldest. */
4
+ export declare const MAX_WAVES = 8;
5
+ export interface Grid {
6
+ cols: number;
7
+ rows: number;
8
+ /** Position of mark (0, 0), in CSS pixels. */
9
+ originX: number;
10
+ originY: number;
11
+ }
12
+ /**
13
+ * A grid that fits inside the canvas, centred, leaving at least half a
14
+ * `spacing` of padding on every side so marks at the edges are never clipped.
15
+ * Any space left over is shared equally between opposite sides. A canvas too
16
+ * small for the padding still gets one mark, in its centre.
17
+ */
18
+ export declare function gridLayout(width: number, height: number, spacing: number): Grid;
19
+ /** A stable pseudo-random phase in [0, 2π) for mark (i, j). */
20
+ export declare function cellPhase(i: number, j: number, salt: number): number;
21
+ /**
22
+ * Each mark's wander phases (px, py) as cos px, sin px, cos py, sin py,
23
+ * recomputed only when the grid changes size. The wander offset is
24
+ * `jitter × (sin(clock + px), cos(clock × 1.3 + py))`; see wanderClock.
25
+ */
26
+ export declare function createPhaseCache(): (cols: number, rows: number) => Float32Array;
27
+ /**
28
+ * The trig of the wander clock for one frame. With a mark's cached phases
29
+ * (createPhaseCache), its offset is
30
+ * x = jitter × (sx × cos px + cx × sin px) = jitter × sin(clock + px)
31
+ * y = jitter × (cy × cos py − sy × sin py) = jitter × cos(clock × 1.3 + py)
32
+ * so a frame needs four trig calls in all instead of two per mark.
33
+ */
34
+ export declare function wanderClock(clock: number): {
35
+ sx: number;
36
+ cx: number;
37
+ sy: number;
38
+ cy: number;
39
+ };
40
+ /** How strongly the pointer affects a mark `distance` away: 1 at the pointer, easing to 0 at `radius`. */
41
+ export declare function pointerFalloff(distance: number, radius: number): number;
42
+ /** Height of a wave's ring at `distance` from its centre: 1 on the ring, fading over `width` either side. */
43
+ export declare function waveRing(distance: number, ringRadius: number, width: number): number;
44
+ /** How much of a wave is left at `age`: 1 when it starts, easing out to 0 at `duration`. */
45
+ export declare function waveEnvelope(age: number, duration: number): number;
46
+ /**
47
+ * Frame rate that keeps every wander step below WANDER_STEP. The fastest a mark
48
+ * wanders is along y: amplitude × angular speed × 1.3.
49
+ */
50
+ export declare function wanderFps(jitter: number, jitterSpeed: number): number;
51
+ /** Idle frame rate for a wandering grid: just enough for a smooth wander, at least 5 fps. */
52
+ export declare function wanderIdleFps(options: {
53
+ jitter: number;
54
+ jitterSpeed: number;
55
+ }): number;
56
+ export interface Wave {
57
+ x: number;
58
+ y: number;
59
+ age: number;
60
+ }
61
+ /** The click waves currently playing. */
62
+ export interface WaveList {
63
+ readonly waves: readonly Wave[];
64
+ /**
65
+ * Start waves for this frame's clicks (unless `enabled` is false), age the
66
+ * rest, and drop those older than `duration` seconds.
67
+ */
68
+ advance(frame: Frame, duration: number, enabled: boolean): void;
69
+ /** Writes each wave as x, y, ring radius, envelope into `out` (MAX_WAVES × 4), zeroing unused slots. */
70
+ pack(out: Float32Array, speed: number, duration: number): void;
71
+ }
72
+ export declare function createWaveList(): WaveList;
@@ -0,0 +1,72 @@
1
+ import type { Frame } from '../core/style.js';
2
+ export declare const TAU: number;
3
+ /** At most this many waves play at once; a new click replaces the oldest. */
4
+ export declare const MAX_WAVES = 8;
5
+ export interface Grid {
6
+ cols: number;
7
+ rows: number;
8
+ /** Position of mark (0, 0), in CSS pixels. */
9
+ originX: number;
10
+ originY: number;
11
+ }
12
+ /**
13
+ * A grid that fits inside the canvas, centred, leaving at least half a
14
+ * `spacing` of padding on every side so marks at the edges are never clipped.
15
+ * Any space left over is shared equally between opposite sides. A canvas too
16
+ * small for the padding still gets one mark, in its centre.
17
+ */
18
+ export declare function gridLayout(width: number, height: number, spacing: number): Grid;
19
+ /** A stable pseudo-random phase in [0, 2π) for mark (i, j). */
20
+ export declare function cellPhase(i: number, j: number, salt: number): number;
21
+ /**
22
+ * Each mark's wander phases (px, py) as cos px, sin px, cos py, sin py,
23
+ * recomputed only when the grid changes size. The wander offset is
24
+ * `jitter × (sin(clock + px), cos(clock × 1.3 + py))`; see wanderClock.
25
+ */
26
+ export declare function createPhaseCache(): (cols: number, rows: number) => Float32Array;
27
+ /**
28
+ * The trig of the wander clock for one frame. With a mark's cached phases
29
+ * (createPhaseCache), its offset is
30
+ * x = jitter × (sx × cos px + cx × sin px) = jitter × sin(clock + px)
31
+ * y = jitter × (cy × cos py − sy × sin py) = jitter × cos(clock × 1.3 + py)
32
+ * so a frame needs four trig calls in all instead of two per mark.
33
+ */
34
+ export declare function wanderClock(clock: number): {
35
+ sx: number;
36
+ cx: number;
37
+ sy: number;
38
+ cy: number;
39
+ };
40
+ /** How strongly the pointer affects a mark `distance` away: 1 at the pointer, easing to 0 at `radius`. */
41
+ export declare function pointerFalloff(distance: number, radius: number): number;
42
+ /** Height of a wave's ring at `distance` from its centre: 1 on the ring, fading over `width` either side. */
43
+ export declare function waveRing(distance: number, ringRadius: number, width: number): number;
44
+ /** How much of a wave is left at `age`: 1 when it starts, easing out to 0 at `duration`. */
45
+ export declare function waveEnvelope(age: number, duration: number): number;
46
+ /**
47
+ * Frame rate that keeps every wander step below WANDER_STEP. The fastest a mark
48
+ * wanders is along y: amplitude × angular speed × 1.3.
49
+ */
50
+ export declare function wanderFps(jitter: number, jitterSpeed: number): number;
51
+ /** Idle frame rate for a wandering grid: just enough for a smooth wander, at least 5 fps. */
52
+ export declare function wanderIdleFps(options: {
53
+ jitter: number;
54
+ jitterSpeed: number;
55
+ }): number;
56
+ export interface Wave {
57
+ x: number;
58
+ y: number;
59
+ age: number;
60
+ }
61
+ /** The click waves currently playing. */
62
+ export interface WaveList {
63
+ readonly waves: readonly Wave[];
64
+ /**
65
+ * Start waves for this frame's clicks (unless `enabled` is false), age the
66
+ * rest, and drop those older than `duration` seconds.
67
+ */
68
+ advance(frame: Frame, duration: number, enabled: boolean): void;
69
+ /** Writes each wave as x, y, ring radius, envelope into `out` (MAX_WAVES × 4), zeroing unused slots. */
70
+ pack(out: Float32Array, speed: number, duration: number): void;
71
+ }
72
+ export declare function createWaveList(): WaveList;
@@ -0,0 +1,123 @@
1
+ // src/shared/grid.ts
2
+ var TAU = Math.PI * 2;
3
+ /**
4
+ * A grid that fits inside the canvas, centred, leaving at least half a
5
+ * `spacing` of padding on every side so marks at the edges are never clipped.
6
+ * Any space left over is shared equally between opposite sides. A canvas too
7
+ * small for the padding still gets one mark, in its centre.
8
+ */
9
+ function gridLayout(width, height, spacing) {
10
+ const cols = Math.max(1, Math.floor(width / spacing));
11
+ const rows = Math.max(1, Math.floor(height / spacing));
12
+ return {
13
+ cols,
14
+ rows,
15
+ originX: (width - (cols - 1) * spacing) / 2,
16
+ originY: (height - (rows - 1) * spacing) / 2
17
+ };
18
+ }
19
+ /** A stable pseudo-random phase in [0, 2π) for mark (i, j). */
20
+ function cellPhase(i, j, salt) {
21
+ const s = Math.sin(i * 12.9898 + j * 78.233 + salt) * 43758.5453;
22
+ return (s - Math.floor(s)) * TAU;
23
+ }
24
+ /**
25
+ * Each mark's wander phases (px, py) as cos px, sin px, cos py, sin py,
26
+ * recomputed only when the grid changes size. The wander offset is
27
+ * `jitter × (sin(clock + px), cos(clock × 1.3 + py))`; see wanderClock.
28
+ */
29
+ function createPhaseCache() {
30
+ let phases = /* @__PURE__ */ new Float32Array(0);
31
+ let phaseCols = 0;
32
+ return (cols, rows) => {
33
+ if (phaseCols === cols && phases.length === cols * rows * 4) return phases;
34
+ phases = new Float32Array(cols * rows * 4);
35
+ for (let j = 0; j < rows; j++) for (let i = 0; i < cols; i++) {
36
+ const k = (j * cols + i) * 4;
37
+ const px = cellPhase(i, j, 0);
38
+ const py = cellPhase(i, j, 1);
39
+ phases[k] = Math.cos(px);
40
+ phases[k + 1] = Math.sin(px);
41
+ phases[k + 2] = Math.cos(py);
42
+ phases[k + 3] = Math.sin(py);
43
+ }
44
+ phaseCols = cols;
45
+ return phases;
46
+ };
47
+ }
48
+ /**
49
+ * The trig of the wander clock for one frame. With a mark's cached phases
50
+ * (createPhaseCache), its offset is
51
+ * x = jitter × (sx × cos px + cx × sin px) = jitter × sin(clock + px)
52
+ * y = jitter × (cy × cos py − sy × sin py) = jitter × cos(clock × 1.3 + py)
53
+ * so a frame needs four trig calls in all instead of two per mark.
54
+ */
55
+ function wanderClock(clock) {
56
+ return {
57
+ sx: Math.sin(clock),
58
+ cx: Math.cos(clock),
59
+ sy: Math.sin(clock * 1.3),
60
+ cy: Math.cos(clock * 1.3)
61
+ };
62
+ }
63
+ /** How strongly the pointer affects a mark `distance` away: 1 at the pointer, easing to 0 at `radius`. */
64
+ function pointerFalloff(distance, radius) {
65
+ const k = Math.max(0, 1 - distance / radius);
66
+ return k * k;
67
+ }
68
+ /** Height of a wave's ring at `distance` from its centre: 1 on the ring, fading over `width` either side. */
69
+ function waveRing(distance, ringRadius, width) {
70
+ const x = (distance - ringRadius) / width;
71
+ return Math.exp(-x * x);
72
+ }
73
+ /** How much of a wave is left at `age`: 1 when it starts, easing out to 0 at `duration`. */
74
+ function waveEnvelope(age, duration) {
75
+ const k = Math.max(0, 1 - age / duration);
76
+ return k * k;
77
+ }
78
+ /** The wander moves each mark at most this far between frames, in CSS pixels; finer steps can't be seen. */
79
+ var WANDER_STEP = .25;
80
+ /**
81
+ * Frame rate that keeps every wander step below WANDER_STEP. The fastest a mark
82
+ * wanders is along y: amplitude × angular speed × 1.3.
83
+ */
84
+ function wanderFps(jitter, jitterSpeed) {
85
+ const maxSpeed = jitter * jitterSpeed * TAU * 1.3;
86
+ return Math.ceil(maxSpeed / WANDER_STEP);
87
+ }
88
+ /** Idle frame rate for a wandering grid: just enough for a smooth wander, at least 5 fps. */
89
+ function wanderIdleFps(options) {
90
+ return Math.max(5, wanderFps(options.jitter, options.jitterSpeed));
91
+ }
92
+ function createWaveList() {
93
+ const waves = [];
94
+ return {
95
+ waves,
96
+ advance(frame, duration, enabled) {
97
+ for (const wave of waves) wave.age += frame.dt;
98
+ for (let k = waves.length - 1; k >= 0; k--) if (waves[k].age >= duration) waves.splice(k, 1);
99
+ if (!enabled) return;
100
+ for (const click of frame.clicks) {
101
+ if (waves.length === 8) waves.shift();
102
+ waves.push({
103
+ x: click.x,
104
+ y: click.y,
105
+ age: 0
106
+ });
107
+ }
108
+ },
109
+ pack(out, speed, duration) {
110
+ out.fill(0);
111
+ for (let k = 0; k < waves.length; k++) {
112
+ const wave = waves[k];
113
+ out[k * 4] = wave.x;
114
+ out[k * 4 + 1] = wave.y;
115
+ out[k * 4 + 2] = speed * wave.age;
116
+ out[k * 4 + 3] = waveEnvelope(wave.age, duration);
117
+ }
118
+ }
119
+ };
120
+ }
121
+ export { TAU, cellPhase, createPhaseCache, createWaveList, gridLayout, pointerFalloff, wanderClock, wanderFps, wanderIdleFps, waveEnvelope, waveRing };
122
+
123
+ //# sourceMappingURL=grid.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grid.js","names":[],"sources":["../../src/shared/grid.ts"],"sourcesContent":["import type { Frame } from '../core/style';\n\n// The motion model shared by the grid styles (dots, plus): a grid of marks that\n// wander around their places, react to the pointer and to click waves. The\n// WebGL vertex shaders mirror parts of it in GLSL (grid-webgl.ts); keep them in step.\n\nexport const TAU = Math.PI * 2;\n\n/** At most this many waves play at once; a new click replaces the oldest. */\nexport const MAX_WAVES = 8;\n\nexport interface Grid {\n cols: number;\n rows: number;\n /** Position of mark (0, 0), in CSS pixels. */\n originX: number;\n originY: number;\n}\n\n/**\n * A grid that fits inside the canvas, centred, leaving at least half a\n * `spacing` of padding on every side so marks at the edges are never clipped.\n * Any space left over is shared equally between opposite sides. A canvas too\n * small for the padding still gets one mark, in its centre.\n */\nexport function gridLayout(width: number, height: number, spacing: number): Grid {\n const cols = Math.max(1, Math.floor(width / spacing));\n const rows = Math.max(1, Math.floor(height / spacing));\n return {\n cols,\n rows,\n originX: (width - (cols - 1) * spacing) / 2,\n originY: (height - (rows - 1) * spacing) / 2,\n };\n}\n\n/** A stable pseudo-random phase in [0, 2π) for mark (i, j). */\nexport function cellPhase(i: number, j: number, salt: number): number {\n const s = Math.sin(i * 12.9898 + j * 78.233 + salt) * 43758.5453;\n return (s - Math.floor(s)) * TAU;\n}\n\n/**\n * Each mark's wander phases (px, py) as cos px, sin px, cos py, sin py,\n * recomputed only when the grid changes size. The wander offset is\n * `jitter × (sin(clock + px), cos(clock × 1.3 + py))`; see wanderClock.\n */\nexport function createPhaseCache(): (cols: number, rows: number) => Float32Array {\n let phases = new Float32Array(0);\n let phaseCols = 0;\n return (cols, rows) => {\n if (phaseCols === cols && phases.length === cols * rows * 4) return phases;\n phases = new Float32Array(cols * rows * 4);\n for (let j = 0; j < rows; j++) {\n for (let i = 0; i < cols; i++) {\n const k = (j * cols + i) * 4;\n const px = cellPhase(i, j, 0);\n const py = cellPhase(i, j, 1);\n phases[k] = Math.cos(px);\n phases[k + 1] = Math.sin(px);\n phases[k + 2] = Math.cos(py);\n phases[k + 3] = Math.sin(py);\n }\n }\n phaseCols = cols;\n return phases;\n };\n}\n\n/**\n * The trig of the wander clock for one frame. With a mark's cached phases\n * (createPhaseCache), its offset is\n * x = jitter × (sx × cos px + cx × sin px) = jitter × sin(clock + px)\n * y = jitter × (cy × cos py − sy × sin py) = jitter × cos(clock × 1.3 + py)\n * so a frame needs four trig calls in all instead of two per mark.\n */\nexport function wanderClock(clock: number): { sx: number; cx: number; sy: number; cy: number } {\n return { sx: Math.sin(clock), cx: Math.cos(clock), sy: Math.sin(clock * 1.3), cy: Math.cos(clock * 1.3) };\n}\n\n/** How strongly the pointer affects a mark `distance` away: 1 at the pointer, easing to 0 at `radius`. */\nexport function pointerFalloff(distance: number, radius: number): number {\n const k = Math.max(0, 1 - distance / radius);\n return k * k;\n}\n\n/** Height of a wave's ring at `distance` from its centre: 1 on the ring, fading over `width` either side. */\nexport function waveRing(distance: number, ringRadius: number, width: number): number {\n const x = (distance - ringRadius) / width;\n return Math.exp(-x * x);\n}\n\n/** How much of a wave is left at `age`: 1 when it starts, easing out to 0 at `duration`. */\nexport function waveEnvelope(age: number, duration: number): number {\n const k = Math.max(0, 1 - age / duration);\n return k * k;\n}\n\n/** The wander moves each mark at most this far between frames, in CSS pixels; finer steps can't be seen. */\nconst WANDER_STEP = 0.25;\n\n/**\n * Frame rate that keeps every wander step below WANDER_STEP. The fastest a mark\n * wanders is along y: amplitude × angular speed × 1.3.\n */\nexport function wanderFps(jitter: number, jitterSpeed: number): number {\n const maxSpeed = jitter * jitterSpeed * TAU * 1.3;\n return Math.ceil(maxSpeed / WANDER_STEP);\n}\n\n/** Idle frame rate for a wandering grid: just enough for a smooth wander, at least 5 fps. */\nexport function wanderIdleFps(options: { jitter: number; jitterSpeed: number }): number {\n return Math.max(5, wanderFps(options.jitter, options.jitterSpeed));\n}\n\nexport interface Wave {\n x: number;\n y: number;\n age: number;\n}\n\n/** The click waves currently playing. */\nexport interface WaveList {\n readonly waves: readonly Wave[];\n /**\n * Start waves for this frame's clicks (unless `enabled` is false), age the\n * rest, and drop those older than `duration` seconds.\n */\n advance(frame: Frame, duration: number, enabled: boolean): void;\n /** Writes each wave as x, y, ring radius, envelope into `out` (MAX_WAVES × 4), zeroing unused slots. */\n pack(out: Float32Array, speed: number, duration: number): void;\n}\n\nexport function createWaveList(): WaveList {\n const waves: Wave[] = [];\n return {\n waves,\n advance(frame, duration, enabled) {\n for (const wave of waves) wave.age += frame.dt;\n for (let k = waves.length - 1; k >= 0; k--) {\n if (waves[k].age >= duration) waves.splice(k, 1);\n }\n if (!enabled) return;\n for (const click of frame.clicks) {\n if (waves.length === MAX_WAVES) waves.shift();\n waves.push({ x: click.x, y: click.y, age: 0 });\n }\n },\n pack(out, speed, duration) {\n out.fill(0);\n for (let k = 0; k < waves.length; k++) {\n const wave = waves[k];\n out[k * 4] = wave.x;\n out[k * 4 + 1] = wave.y;\n out[k * 4 + 2] = speed * wave.age;\n out[k * 4 + 3] = waveEnvelope(wave.age, duration);\n }\n },\n };\n}\n"],"mappings":"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"}