@paper-design/shaders 0.0.67 → 0.0.69

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 (94) hide show
  1. package/dist/index.d.ts +29 -18
  2. package/dist/index.js +6 -0
  3. package/dist/index.js.map +2 -2
  4. package/dist/shader-sizing.d.ts +0 -5
  5. package/dist/shader-sizing.js +1 -193
  6. package/dist/shader-sizing.js.map +2 -2
  7. package/dist/shaders/color-panels.d.ts +32 -12
  8. package/dist/shaders/color-panels.js +5 -5
  9. package/dist/shaders/color-panels.js.map +2 -2
  10. package/dist/shaders/dithering.d.ts +25 -19
  11. package/dist/shaders/dithering.js +114 -66
  12. package/dist/shaders/dithering.js.map +2 -2
  13. package/dist/shaders/dot-grid.d.ts +28 -14
  14. package/dist/shaders/dot-grid.js +2 -2
  15. package/dist/shaders/dot-grid.js.map +2 -2
  16. package/dist/shaders/dot-orbit.d.ts +27 -9
  17. package/dist/shaders/dot-orbit.js +8 -9
  18. package/dist/shaders/dot-orbit.js.map +2 -2
  19. package/dist/shaders/fluted-glass.d.ts +43 -18
  20. package/dist/shaders/fluted-glass.js +20 -51
  21. package/dist/shaders/fluted-glass.js.map +2 -2
  22. package/dist/shaders/god-rays.d.ts +32 -10
  23. package/dist/shaders/god-rays.js +2 -2
  24. package/dist/shaders/god-rays.js.map +2 -2
  25. package/dist/shaders/grain-gradient.d.ts +41 -17
  26. package/dist/shaders/grain-gradient.js +47 -33
  27. package/dist/shaders/grain-gradient.js.map +2 -2
  28. package/dist/shaders/halftone-cmyk.d.ts +105 -0
  29. package/dist/shaders/halftone-cmyk.js +290 -0
  30. package/dist/shaders/halftone-cmyk.js.map +7 -0
  31. package/dist/shaders/halftone-dots.d.ts +35 -6
  32. package/dist/shaders/halftone-dots.js +18 -55
  33. package/dist/shaders/halftone-dots.js.map +2 -2
  34. package/dist/shaders/heatmap.d.ts +36 -0
  35. package/dist/shaders/heatmap.js +98 -16
  36. package/dist/shaders/heatmap.js.map +2 -2
  37. package/dist/shaders/image-dithering.d.ts +29 -15
  38. package/dist/shaders/image-dithering.js +68 -37
  39. package/dist/shaders/image-dithering.js.map +2 -2
  40. package/dist/shaders/liquid-metal.d.ts +38 -14
  41. package/dist/shaders/liquid-metal.js +5 -2
  42. package/dist/shaders/liquid-metal.js.map +2 -2
  43. package/dist/shaders/mesh-gradient.d.ts +27 -8
  44. package/dist/shaders/mesh-gradient.js +1 -7
  45. package/dist/shaders/mesh-gradient.js.map +2 -2
  46. package/dist/shaders/metaballs.d.ts +24 -8
  47. package/dist/shaders/metaballs.js +2 -2
  48. package/dist/shaders/metaballs.js.map +2 -2
  49. package/dist/shaders/neuro-noise.d.ts +27 -5
  50. package/dist/shaders/neuro-noise.js +2 -3
  51. package/dist/shaders/neuro-noise.js.map +2 -2
  52. package/dist/shaders/paper-texture.d.ts +37 -12
  53. package/dist/shaders/paper-texture.js +20 -20
  54. package/dist/shaders/paper-texture.js.map +2 -2
  55. package/dist/shaders/perlin-noise.d.ts +27 -8
  56. package/dist/shaders/perlin-noise.js +13 -35
  57. package/dist/shaders/perlin-noise.js.map +2 -2
  58. package/dist/shaders/pulsing-border.d.ts +39 -13
  59. package/dist/shaders/pulsing-border.js +9 -7
  60. package/dist/shaders/pulsing-border.js.map +2 -2
  61. package/dist/shaders/simplex-noise.d.ts +25 -6
  62. package/dist/shaders/simplex-noise.js +21 -21
  63. package/dist/shaders/simplex-noise.js.map +2 -2
  64. package/dist/shaders/smoke-ring.d.ts +29 -7
  65. package/dist/shaders/smoke-ring.js +20 -17
  66. package/dist/shaders/smoke-ring.js.map +2 -2
  67. package/dist/shaders/spiral.d.ts +30 -10
  68. package/dist/shaders/spiral.js +4 -4
  69. package/dist/shaders/spiral.js.map +2 -2
  70. package/dist/shaders/static-mesh-gradient.d.ts +30 -9
  71. package/dist/shaders/static-mesh-gradient.js +9 -17
  72. package/dist/shaders/static-mesh-gradient.js.map +2 -2
  73. package/dist/shaders/static-radial-gradient.d.ts +33 -11
  74. package/dist/shaders/static-radial-gradient.js +18 -25
  75. package/dist/shaders/static-radial-gradient.js.map +2 -2
  76. package/dist/shaders/swirl.d.ts +29 -8
  77. package/dist/shaders/swirl.js +4 -4
  78. package/dist/shaders/swirl.js.map +2 -2
  79. package/dist/shaders/voronoi.d.ts +31 -10
  80. package/dist/shaders/voronoi.js +8 -8
  81. package/dist/shaders/voronoi.js.map +2 -2
  82. package/dist/shaders/warp.d.ts +31 -13
  83. package/dist/shaders/warp.js +3 -3
  84. package/dist/shaders/warp.js.map +2 -2
  85. package/dist/shaders/water.d.ts +30 -10
  86. package/dist/shaders/water.js +2 -2
  87. package/dist/shaders/water.js.map +2 -2
  88. package/dist/shaders/waves.d.ts +27 -12
  89. package/dist/shaders/waves.js +3 -3
  90. package/dist/shaders/waves.js.map +2 -2
  91. package/dist/vertex-shader.d.ts +1 -1
  92. package/dist/vertex-shader.js +2 -53
  93. package/dist/vertex-shader.js.map +2 -2
  94. package/package.json +1 -1
@@ -1,27 +1,33 @@
1
1
  import type { ShaderMotionParams } from '../shader-mount.js';
2
2
  import { type ShaderSizingParams, type ShaderSizingUniforms } from '../shader-sizing.js';
3
3
  /**
4
- * 2-color dithering effect over animated abstract shapes
4
+ * Animated 2-color dithering over multiple pattern sources (noise, warp, dots, waves, ripple, swirl, sphere).
5
5
  *
6
- * Uniforms:
7
- * - u_colorBack, u_colorFront (RGBA)
8
- * - pxSize: px size relative to canvas resolution
9
- * - u_shape (float used as integer):
10
- * ---- 1: simplex noise pattern
11
- * ---- 2: warp noise pattern
12
- * ---- 3: columns of dots moving vertically
13
- * ---- 4: sine wave
14
- * ---- 5: ripple effect
15
- * ---- 6: swirl animation
16
- * ---- 7: rotating sphere
17
- * - u_type (float used as integer)
18
- * ---- 1: random dithering
19
- * ---- 2: 2x2 Bayer matrix
20
- * ---- 3: 4x4 Bayer matrix
21
- * ---- 4: 8x8 Bayer matrix
6
+ * SIZING NOTE: This shader performs sizing in the fragment shader (not vertex shader) to keep
7
+ * u_pxSize in consistent actual pixels. The pixel grid is computed from gl_FragCoord before any
8
+ * transforms, so scaling/rotating only affects the underlying pattern shape.
9
+ * No vertex shader outputs (v_objectUV, v_patternUV, etc.) are used.
22
10
  *
23
- * Note: pixelization is applied to the shapes BEFORE dithering, meaning pixels don't react to scaling and fit
24
- */
11
+ * Fragment shader uniforms:
12
+ * - u_time (float): Animation time
13
+ * - u_resolution (vec2): Canvas resolution in pixels
14
+ * - u_pixelRatio (float): Device pixel ratio
15
+ * - u_originX (float): Reference point for positioning world width in the canvas (0 to 1)
16
+ * - u_originY (float): Reference point for positioning world height in the canvas (0 to 1)
17
+ * - u_worldWidth (float): Virtual width of the graphic before it's scaled to fit the canvas
18
+ * - u_worldHeight (float): Virtual height of the graphic before it's scaled to fit the canvas
19
+ * - u_fit (float): How to fit the rendered shader into the canvas dimensions (0 = none, 1 = contain, 2 = cover)
20
+ * - u_scale (float): Overall zoom level of the graphics (0.01 to 4)
21
+ * - u_rotation (float): Overall rotation angle of the graphics in degrees (0 to 360)
22
+ * - u_offsetX (float): Horizontal offset of the graphics center (-1 to 1)
23
+ * - u_offsetY (float): Vertical offset of the graphics center (-1 to 1)
24
+ * - u_colorBack (vec4): Background color in RGBA
25
+ * - u_colorFront (vec4): Foreground (ink) color in RGBA
26
+ * - u_shape (float): Shape pattern type (1 = simplex, 2 = warp, 3 = dots, 4 = wave, 5 = ripple, 6 = swirl, 7 = sphere)
27
+ * - u_type (float): Dithering type (1 = random, 2 = 2x2 Bayer, 3 = 4x4 Bayer, 4 = 8x8 Bayer)
28
+ * - u_pxSize (float): Pixel size of dithering grid (0.5 to 20)
29
+ *
30
+ * */
25
31
  export declare const ditheringFragmentShader: string;
26
32
  export interface DitheringUniforms extends ShaderSizingUniforms {
27
33
  u_colorBack: [number, number, number, number];
@@ -4,25 +4,30 @@
4
4
  * * * * * * * * * * * * * * * * * * * * * * * * * * * */
5
5
 
6
6
  import {
7
- sizingUniformsDeclaration,
8
- sizingUV,
9
- drawSizingHelpers
10
7
  } from "../shader-sizing.js";
11
8
  import { simplexNoise, declarePI, proceduralHash11, proceduralHash21 } from "../shader-utils.js";
12
9
  const ditheringFragmentShader = `#version 300 es
13
10
  precision mediump float;
14
11
 
15
12
  uniform float u_time;
13
+
16
14
  uniform vec2 u_resolution;
17
15
  uniform float u_pixelRatio;
16
+ uniform float u_originX;
17
+ uniform float u_originY;
18
+ uniform float u_worldWidth;
19
+ uniform float u_worldHeight;
20
+ uniform float u_fit;
21
+ uniform float u_scale;
22
+ uniform float u_rotation;
23
+ uniform float u_offsetX;
24
+ uniform float u_offsetY;
18
25
 
19
- ${sizingUniformsDeclaration}
20
-
26
+ uniform float u_pxSize;
21
27
  uniform vec4 u_colorBack;
22
28
  uniform vec4 u_colorFront;
23
29
  uniform float u_shape;
24
30
  uniform float u_type;
25
- uniform float u_pxSize;
26
31
 
27
32
  out vec4 fragColor;
28
33
 
@@ -40,21 +45,21 @@ float getSimplexNoise(vec2 uv, float t) {
40
45
 
41
46
  const int bayer2x2[4] = int[4](0, 2, 3, 1);
42
47
  const int bayer4x4[16] = int[16](
43
- 0, 8, 2, 10,
44
- 12, 4, 14, 6,
45
- 3, 11, 1, 9,
46
- 15, 7, 13, 5
48
+ 0, 8, 2, 10,
49
+ 12, 4, 14, 6,
50
+ 3, 11, 1, 9,
51
+ 15, 7, 13, 5
47
52
  );
48
53
 
49
54
  const int bayer8x8[64] = int[64](
50
- 0, 32, 8, 40, 2, 34, 10, 42,
51
- 48, 16, 56, 24, 50, 18, 58, 26,
52
- 12, 44, 4, 36, 14, 46, 6, 38,
53
- 60, 28, 52, 20, 62, 30, 54, 22,
54
- 3, 35, 11, 43, 1, 33, 9, 41,
55
- 51, 19, 59, 27, 49, 17, 57, 25,
56
- 15, 47, 7, 39, 13, 45, 5, 37,
57
- 63, 31, 55, 23, 61, 29, 53, 21
55
+ 0, 32, 8, 40, 2, 34, 10, 42,
56
+ 48, 16, 56, 24, 50, 18, 58, 26,
57
+ 12, 44, 4, 36, 14, 46, 6, 38,
58
+ 60, 28, 52, 20, 62, 30, 54, 22,
59
+ 3, 35, 11, 43, 1, 33, 9, 41,
60
+ 51, 19, 59, 27, 49, 17, 57, 25,
61
+ 15, 47, 7, 39, 13, 45, 5, 37,
62
+ 63, 31, 55, 23, 61, 29, 53, 21
58
63
  );
59
64
 
60
65
  float getBayerValue(vec2 uv, int size) {
@@ -75,69 +80,122 @@ float getBayerValue(vec2 uv, int size) {
75
80
  void main() {
76
81
  float t = .5 * u_time;
77
82
 
78
- #define USE_PATTERN_SIZING
79
- #define USE_OBJECT_SIZING
80
- #define USE_PIXELIZATION
81
- // #define ADD_HELPERS
82
-
83
- ${sizingUV}
84
-
85
- vec2 dithering_uv = pxSizeUv;
86
- vec2 ditheringNoise_uv = uv * u_resolution;
87
- vec2 shape_uv = objectUV;
88
- if (u_shape < 3.5) {
89
- shape_uv = patternUV;
83
+ float pxSize = u_pxSize * u_pixelRatio;
84
+ vec2 pxSizeUV = gl_FragCoord.xy - .5 * u_resolution;
85
+ pxSizeUV /= pxSize;
86
+ vec2 canvasPixelizedUV = (floor(pxSizeUV) + .5) * pxSize;
87
+ vec2 normalizedUV = canvasPixelizedUV / u_resolution;
88
+
89
+ vec2 ditheringNoiseUV = canvasPixelizedUV;
90
+ vec2 shapeUV = normalizedUV;
91
+
92
+ vec2 boxOrigin = vec2(.5 - u_originX, u_originY - .5);
93
+ vec2 givenBoxSize = vec2(u_worldWidth, u_worldHeight);
94
+ givenBoxSize = max(givenBoxSize, vec2(1.)) * u_pixelRatio;
95
+ float r = u_rotation * PI / 180.;
96
+ mat2 graphicRotation = mat2(cos(r), sin(r), -sin(r), cos(r));
97
+ vec2 graphicOffset = vec2(-u_offsetX, u_offsetY);
98
+
99
+ float patternBoxRatio = givenBoxSize.x / givenBoxSize.y;
100
+ vec2 boxSize = vec2(
101
+ (u_worldWidth == 0.) ? u_resolution.x : givenBoxSize.x,
102
+ (u_worldHeight == 0.) ? u_resolution.y : givenBoxSize.y
103
+ );
104
+
105
+ if (u_shape > 3.5) {
106
+ vec2 objectBoxSize = vec2(0.);
107
+ // fit = none
108
+ objectBoxSize.x = min(boxSize.x, boxSize.y);
109
+ if (u_fit == 1.) { // fit = contain
110
+ objectBoxSize.x = min(u_resolution.x, u_resolution.y);
111
+ } else if (u_fit == 2.) { // fit = cover
112
+ objectBoxSize.x = max(u_resolution.x, u_resolution.y);
113
+ }
114
+ objectBoxSize.y = objectBoxSize.x;
115
+ vec2 objectWorldScale = u_resolution.xy / objectBoxSize;
116
+
117
+ shapeUV *= objectWorldScale;
118
+ shapeUV += boxOrigin * (objectWorldScale - 1.);
119
+ shapeUV += vec2(-u_offsetX, u_offsetY);
120
+ shapeUV /= u_scale;
121
+ shapeUV = graphicRotation * shapeUV;
122
+ } else {
123
+ vec2 patternBoxSize = vec2(0.);
124
+ // fit = none
125
+ patternBoxSize.x = patternBoxRatio * min(boxSize.x / patternBoxRatio, boxSize.y);
126
+ float patternWorldNoFitBoxWidth = patternBoxSize.x;
127
+ if (u_fit == 1.) { // fit = contain
128
+ patternBoxSize.x = patternBoxRatio * min(u_resolution.x / patternBoxRatio, u_resolution.y);
129
+ } else if (u_fit == 2.) { // fit = cover
130
+ patternBoxSize.x = patternBoxRatio * max(u_resolution.x / patternBoxRatio, u_resolution.y);
131
+ }
132
+ patternBoxSize.y = patternBoxSize.x / patternBoxRatio;
133
+ vec2 patternWorldScale = u_resolution.xy / patternBoxSize;
134
+
135
+ shapeUV += vec2(-u_offsetX, u_offsetY) / patternWorldScale;
136
+ shapeUV += boxOrigin;
137
+ shapeUV -= boxOrigin / patternWorldScale;
138
+ shapeUV *= u_resolution.xy;
139
+ shapeUV /= u_pixelRatio;
140
+ if (u_fit > 0.) {
141
+ shapeUV *= (patternWorldNoFitBoxWidth / patternBoxSize.x);
142
+ }
143
+ shapeUV /= u_scale;
144
+ shapeUV = graphicRotation * shapeUV;
145
+ shapeUV += boxOrigin / patternWorldScale;
146
+ shapeUV -= boxOrigin;
147
+ shapeUV += .5;
90
148
  }
91
149
 
92
150
  float shape = 0.;
93
151
  if (u_shape < 1.5) {
94
152
  // Simplex noise
95
- shape_uv *= .001;
153
+ shapeUV *= .001;
96
154
 
97
- shape = 0.5 + 0.5 * getSimplexNoise(shape_uv, t);
155
+ shape = 0.5 + 0.5 * getSimplexNoise(shapeUV, t);
98
156
  shape = smoothstep(0.3, 0.9, shape);
99
157
 
100
158
  } else if (u_shape < 2.5) {
101
159
  // Warp
102
- shape_uv *= .003;
160
+ shapeUV *= .003;
103
161
 
104
162
  for (float i = 1.0; i < 6.0; i++) {
105
- shape_uv.x += 0.6 / i * cos(i * 2.5 * shape_uv.y + t);
106
- shape_uv.y += 0.6 / i * cos(i * 1.5 * shape_uv.x + t);
163
+ shapeUV.x += 0.6 / i * cos(i * 2.5 * shapeUV.y + t);
164
+ shapeUV.y += 0.6 / i * cos(i * 1.5 * shapeUV.x + t);
107
165
  }
108
166
 
109
- shape = .15 / max(0.001, abs(sin(t - shape_uv.y - shape_uv.x)));
167
+ shape = .15 / max(0.001, abs(sin(t - shapeUV.y - shapeUV.x)));
110
168
  shape = smoothstep(0.02, 1., shape);
111
169
 
112
170
  } else if (u_shape < 3.5) {
113
171
  // Dots
114
- shape_uv *= .05;
172
+ shapeUV *= .05;
115
173
 
116
- float stripeIdx = floor(2. * shape_uv.x / TWO_PI);
174
+ float stripeIdx = floor(2. * shapeUV.x / TWO_PI);
117
175
  float rand = hash11(stripeIdx * 10.);
118
176
  rand = sign(rand - .5) * pow(.1 + abs(rand), .4);
119
- shape = sin(shape_uv.x) * cos(shape_uv.y - 5. * rand * t);
177
+ shape = sin(shapeUV.x) * cos(shapeUV.y - 5. * rand * t);
120
178
  shape = pow(abs(shape), 6.);
121
179
 
122
180
  } else if (u_shape < 4.5) {
123
181
  // Sine wave
124
- shape_uv *= 4.;
182
+ shapeUV *= 4.;
125
183
 
126
- float wave = cos(.5 * shape_uv.x - 2. * t) * sin(1.5 * shape_uv.x + t) * (.75 + .25 * cos(3. * t));
127
- shape = 1. - smoothstep(-1., 1., shape_uv.y + wave);
184
+ float wave = cos(.5 * shapeUV.x - 2. * t) * sin(1.5 * shapeUV.x + t) * (.75 + .25 * cos(3. * t));
185
+ shape = 1. - smoothstep(-1., 1., shapeUV.y + wave);
128
186
 
129
187
  } else if (u_shape < 5.5) {
130
188
  // Ripple
131
189
 
132
- float dist = length(shape_uv);
190
+ float dist = length(shapeUV);
133
191
  float waves = sin(pow(dist, 1.7) * 7. - 3. * t) * .5 + .5;
134
192
  shape = waves;
135
193
 
136
194
  } else if (u_shape < 6.5) {
137
195
  // Swirl
138
196
 
139
- float l = length(shape_uv);
140
- float angle = 6. * atan(shape_uv.y, shape_uv.x) + 4. * t;
197
+ float l = length(shapeUV);
198
+ float angle = 6. * atan(shapeUV.y, shapeUV.x) + 4. * t;
141
199
  float twist = 1.2;
142
200
  float offset = 1. / pow(max(l, 1e-6), twist) + angle / TWO_PI;
143
201
  float mid = smoothstep(0., 1., pow(l, twist));
@@ -145,10 +203,10 @@ void main() {
145
203
 
146
204
  } else {
147
205
  // Sphere
148
- shape_uv *= 2.;
206
+ shapeUV *= 2.;
149
207
 
150
- float d = 1. - pow(length(shape_uv), 2.);
151
- vec3 pos = vec3(shape_uv, sqrt(max(0., d)));
208
+ float d = 1. - pow(length(shapeUV), 2.);
209
+ vec3 pos = vec3(shapeUV, sqrt(max(0., d)));
152
210
  vec3 lightPos = normalize(vec3(cos(1.5 * t), .8, sin(1.25 * t)));
153
211
  shape = .5 + .5 * dot(lightPos, pos);
154
212
  shape *= step(0., d);
@@ -160,17 +218,17 @@ void main() {
160
218
 
161
219
  switch (type) {
162
220
  case 1: {
163
- dithering = step(hash21(ditheringNoise_uv), shape);
221
+ dithering = step(hash21(ditheringNoiseUV), shape);
164
222
  } break;
165
223
  case 2:
166
- dithering = getBayerValue(dithering_uv, 2);
167
- break;
224
+ dithering = getBayerValue(pxSizeUV, 2);
225
+ break;
168
226
  case 3:
169
- dithering = getBayerValue(dithering_uv, 4);
170
- break;
171
- default:
172
- dithering = getBayerValue(dithering_uv, 8);
173
- break;
227
+ dithering = getBayerValue(pxSizeUV, 4);
228
+ break;
229
+ default :
230
+ dithering = getBayerValue(pxSizeUV, 8);
231
+ break;
174
232
  }
175
233
 
176
234
  dithering -= .5;
@@ -187,16 +245,6 @@ void main() {
187
245
  color += bgColor * (1. - opacity);
188
246
  opacity += bgOpacity * (1. - opacity);
189
247
 
190
- #ifdef ADD_HELPERS
191
- vec2 helperBox = objectHelperBox;
192
- vec2 boxSize = objectBoxSize;
193
- if (u_shape < 3.5) {
194
- helperBox = patternHelperBox;
195
- boxSize = patternBoxSize;
196
- }
197
- ${drawSizingHelpers}
198
- #endif
199
-
200
248
  fragColor = vec4(color, opacity);
201
249
  }
202
250
  `;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/shaders/dithering.ts"],
4
- "sourcesContent": ["import type { ShaderMotionParams } from '../shader-mount.js';\nimport {\n sizingUniformsDeclaration,\n type ShaderSizingParams,\n type ShaderSizingUniforms,\n sizingUV,\n drawSizingHelpers,\n} from '../shader-sizing.js';\nimport { simplexNoise, declarePI, proceduralHash11, proceduralHash21 } from '../shader-utils.js';\n\n/**\n * 2-color dithering effect over animated abstract shapes\n *\n * Uniforms:\n * - u_colorBack, u_colorFront (RGBA)\n * - pxSize: px size relative to canvas resolution\n * - u_shape (float used as integer):\n * ---- 1: simplex noise pattern\n * ---- 2: warp noise pattern\n * ---- 3: columns of dots moving vertically\n * ---- 4: sine wave\n * ---- 5: ripple effect\n * ---- 6: swirl animation\n * ---- 7: rotating sphere\n * - u_type (float used as integer)\n * ---- 1: random dithering\n * ---- 2: 2x2 Bayer matrix\n * ---- 3: 4x4 Bayer matrix\n * ---- 4: 8x8 Bayer matrix\n *\n * Note: pixelization is applied to the shapes BEFORE dithering, meaning pixels don't react to scaling and fit\n */\n\n// language=GLSL\nexport const ditheringFragmentShader: string = `#version 300 es\nprecision mediump float;\n\nuniform float u_time;\nuniform vec2 u_resolution;\nuniform float u_pixelRatio;\n\n${sizingUniformsDeclaration}\n\nuniform vec4 u_colorBack;\nuniform vec4 u_colorFront;\nuniform float u_shape;\nuniform float u_type;\nuniform float u_pxSize;\n\nout vec4 fragColor;\n\n${simplexNoise}\n${declarePI}\n${proceduralHash11}\n${proceduralHash21}\n\nfloat getSimplexNoise(vec2 uv, float t) {\n float noise = .5 * snoise(uv - vec2(0., .3 * t));\n noise += .5 * snoise(2. * uv + vec2(0., .32 * t));\n\n return noise;\n}\n\nconst int bayer2x2[4] = int[4](0, 2, 3, 1);\nconst int bayer4x4[16] = int[16](\n 0, 8, 2, 10,\n 12, 4, 14, 6,\n 3, 11, 1, 9,\n 15, 7, 13, 5\n);\n\nconst int bayer8x8[64] = int[64](\n 0, 32, 8, 40, 2, 34, 10, 42,\n 48, 16, 56, 24, 50, 18, 58, 26,\n 12, 44, 4, 36, 14, 46, 6, 38,\n 60, 28, 52, 20, 62, 30, 54, 22,\n 3, 35, 11, 43, 1, 33, 9, 41,\n 51, 19, 59, 27, 49, 17, 57, 25,\n 15, 47, 7, 39, 13, 45, 5, 37,\n 63, 31, 55, 23, 61, 29, 53, 21\n);\n\nfloat getBayerValue(vec2 uv, int size) {\n ivec2 pos = ivec2(fract(uv / float(size)) * float(size));\n int index = pos.y * size + pos.x;\n\n if (size == 2) {\n return float(bayer2x2[index]) / 4.0;\n } else if (size == 4) {\n return float(bayer4x4[index]) / 16.0;\n } else if (size == 8) {\n return float(bayer8x8[index]) / 64.0;\n }\n return 0.0;\n}\n\n\nvoid main() {\n float t = .5 * u_time;\n\n #define USE_PATTERN_SIZING\n #define USE_OBJECT_SIZING\n #define USE_PIXELIZATION\n // #define ADD_HELPERS\n\n ${sizingUV}\n\n vec2 dithering_uv = pxSizeUv;\n vec2 ditheringNoise_uv = uv * u_resolution;\n vec2 shape_uv = objectUV;\n if (u_shape < 3.5) {\n shape_uv = patternUV;\n }\n\n float shape = 0.;\n if (u_shape < 1.5) {\n // Simplex noise\n shape_uv *= .001;\n\n shape = 0.5 + 0.5 * getSimplexNoise(shape_uv, t);\n shape = smoothstep(0.3, 0.9, shape);\n\n } else if (u_shape < 2.5) {\n // Warp\n shape_uv *= .003;\n\n for (float i = 1.0; i < 6.0; i++) {\n shape_uv.x += 0.6 / i * cos(i * 2.5 * shape_uv.y + t);\n shape_uv.y += 0.6 / i * cos(i * 1.5 * shape_uv.x + t);\n }\n\n shape = .15 / max(0.001, abs(sin(t - shape_uv.y - shape_uv.x)));\n shape = smoothstep(0.02, 1., shape);\n\n } else if (u_shape < 3.5) {\n // Dots\n shape_uv *= .05;\n\n float stripeIdx = floor(2. * shape_uv.x / TWO_PI);\n float rand = hash11(stripeIdx * 10.);\n rand = sign(rand - .5) * pow(.1 + abs(rand), .4);\n shape = sin(shape_uv.x) * cos(shape_uv.y - 5. * rand * t);\n shape = pow(abs(shape), 6.);\n\n } else if (u_shape < 4.5) {\n // Sine wave\n shape_uv *= 4.;\n\n float wave = cos(.5 * shape_uv.x - 2. * t) * sin(1.5 * shape_uv.x + t) * (.75 + .25 * cos(3. * t));\n shape = 1. - smoothstep(-1., 1., shape_uv.y + wave);\n\n } else if (u_shape < 5.5) {\n // Ripple\n\n float dist = length(shape_uv);\n float waves = sin(pow(dist, 1.7) * 7. - 3. * t) * .5 + .5;\n shape = waves;\n\n } else if (u_shape < 6.5) {\n // Swirl\n\n float l = length(shape_uv);\n float angle = 6. * atan(shape_uv.y, shape_uv.x) + 4. * t;\n float twist = 1.2;\n float offset = 1. / pow(max(l, 1e-6), twist) + angle / TWO_PI;\n float mid = smoothstep(0., 1., pow(l, twist));\n shape = mix(0., fract(offset), mid);\n\n } else {\n // Sphere\n shape_uv *= 2.;\n\n float d = 1. - pow(length(shape_uv), 2.);\n vec3 pos = vec3(shape_uv, sqrt(max(0., d)));\n vec3 lightPos = normalize(vec3(cos(1.5 * t), .8, sin(1.25 * t)));\n shape = .5 + .5 * dot(lightPos, pos);\n shape *= step(0., d);\n }\n\n\n int type = int(floor(u_type));\n float dithering = 0.0;\n\n switch (type) {\n case 1: {\n dithering = step(hash21(ditheringNoise_uv), shape);\n } break;\n case 2:\n dithering = getBayerValue(dithering_uv, 2);\n break;\n case 3:\n dithering = getBayerValue(dithering_uv, 4);\n break;\n default:\n dithering = getBayerValue(dithering_uv, 8);\n break;\n }\n\n dithering -= .5;\n float res = step(.5, shape + dithering);\n\n vec3 fgColor = u_colorFront.rgb * u_colorFront.a;\n float fgOpacity = u_colorFront.a;\n vec3 bgColor = u_colorBack.rgb * u_colorBack.a;\n float bgOpacity = u_colorBack.a;\n\n vec3 color = fgColor * res;\n float opacity = fgOpacity * res;\n\n color += bgColor * (1. - opacity);\n opacity += bgOpacity * (1. - opacity);\n\n #ifdef ADD_HELPERS\n vec2 helperBox = objectHelperBox;\n vec2 boxSize = objectBoxSize;\n if (u_shape < 3.5) {\n helperBox = patternHelperBox;\n boxSize = patternBoxSize;\n }\n ${drawSizingHelpers}\n #endif\n\n fragColor = vec4(color, opacity);\n}\n`;\n\nexport interface DitheringUniforms extends ShaderSizingUniforms {\n u_colorBack: [number, number, number, number];\n u_colorFront: [number, number, number, number];\n u_shape: (typeof DitheringShapes)[DitheringShape];\n u_type: (typeof DitheringTypes)[DitheringType];\n u_pxSize: number;\n}\n\nexport interface DitheringParams extends ShaderSizingParams, ShaderMotionParams {\n colorBack?: string;\n colorFront?: string;\n shape?: DitheringShape;\n type?: DitheringType;\n size?: number;\n}\n\nexport const DitheringShapes = {\n simplex: 1,\n warp: 2,\n dots: 3,\n wave: 4,\n ripple: 5,\n swirl: 6,\n sphere: 7,\n} as const;\n\nexport type DitheringShape = keyof typeof DitheringShapes;\n\nexport const DitheringTypes = {\n 'random': 1,\n '2x2': 2,\n '4x4': 3,\n '8x8': 4,\n} as const;\n\nexport type DitheringType = keyof typeof DitheringTypes;\n"],
5
- "mappings": ";;;;;AACA;AAAA,EACE;AAAA,EAGA;AAAA,EACA;AAAA,OACK;AACP,SAAS,cAAc,WAAW,kBAAkB,wBAAwB;AA0BrE,MAAM,0BAAkC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO7C,yBAAyB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUzB,YAAY;AAAA,EACZ,SAAS;AAAA,EACT,gBAAgB;AAAA,EAChB,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAmDd,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAkHN,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAuBhB,MAAM,kBAAkB;AAAA,EAC7B,SAAS;AAAA,EACT,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,QAAQ;AACV;AAIO,MAAM,iBAAiB;AAAA,EAC5B,UAAU;AAAA,EACV,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AACT;",
4
+ "sourcesContent": ["import type { ShaderMotionParams } from '../shader-mount.js';\nimport {\n type ShaderSizingParams,\n type ShaderSizingUniforms,\n} from '../shader-sizing.js';\nimport { simplexNoise, declarePI, proceduralHash11, proceduralHash21 } from '../shader-utils.js';\n\n/**\n * Animated 2-color dithering over multiple pattern sources (noise, warp, dots, waves, ripple, swirl, sphere).\n *\n * SIZING NOTE: This shader performs sizing in the fragment shader (not vertex shader) to keep\n * u_pxSize in consistent actual pixels. The pixel grid is computed from gl_FragCoord before any\n * transforms, so scaling/rotating only affects the underlying pattern shape.\n * No vertex shader outputs (v_objectUV, v_patternUV, etc.) are used.\n *\n * Fragment shader uniforms:\n * - u_time (float): Animation time\n * - u_resolution (vec2): Canvas resolution in pixels\n * - u_pixelRatio (float): Device pixel ratio\n * - u_originX (float): Reference point for positioning world width in the canvas (0 to 1)\n * - u_originY (float): Reference point for positioning world height in the canvas (0 to 1)\n * - u_worldWidth (float): Virtual width of the graphic before it's scaled to fit the canvas\n * - u_worldHeight (float): Virtual height of the graphic before it's scaled to fit the canvas\n * - u_fit (float): How to fit the rendered shader into the canvas dimensions (0 = none, 1 = contain, 2 = cover)\n * - u_scale (float): Overall zoom level of the graphics (0.01 to 4)\n * - u_rotation (float): Overall rotation angle of the graphics in degrees (0 to 360)\n * - u_offsetX (float): Horizontal offset of the graphics center (-1 to 1)\n * - u_offsetY (float): Vertical offset of the graphics center (-1 to 1)\n * - u_colorBack (vec4): Background color in RGBA\n * - u_colorFront (vec4): Foreground (ink) color in RGBA\n * - u_shape (float): Shape pattern type (1 = simplex, 2 = warp, 3 = dots, 4 = wave, 5 = ripple, 6 = swirl, 7 = sphere)\n * - u_type (float): Dithering type (1 = random, 2 = 2x2 Bayer, 3 = 4x4 Bayer, 4 = 8x8 Bayer)\n * - u_pxSize (float): Pixel size of dithering grid (0.5 to 20)\n *\n * */\n\n// language=GLSL\nexport const ditheringFragmentShader: string = `#version 300 es\nprecision mediump float;\n\nuniform float u_time;\n\nuniform vec2 u_resolution;\nuniform float u_pixelRatio;\nuniform float u_originX;\nuniform float u_originY;\nuniform float u_worldWidth;\nuniform float u_worldHeight;\nuniform float u_fit;\nuniform float u_scale;\nuniform float u_rotation;\nuniform float u_offsetX;\nuniform float u_offsetY;\n\nuniform float u_pxSize;\nuniform vec4 u_colorBack;\nuniform vec4 u_colorFront;\nuniform float u_shape;\nuniform float u_type;\n\nout vec4 fragColor;\n\n${ simplexNoise }\n${ declarePI }\n${ proceduralHash11 }\n${ proceduralHash21 }\n\nfloat getSimplexNoise(vec2 uv, float t) {\n float noise = .5 * snoise(uv - vec2(0., .3 * t));\n noise += .5 * snoise(2. * uv + vec2(0., .32 * t));\n\n return noise;\n}\n\nconst int bayer2x2[4] = int[4](0, 2, 3, 1);\nconst int bayer4x4[16] = int[16](\n0, 8, 2, 10,\n12, 4, 14, 6,\n3, 11, 1, 9,\n15, 7, 13, 5\n);\n\nconst int bayer8x8[64] = int[64](\n0, 32, 8, 40, 2, 34, 10, 42,\n48, 16, 56, 24, 50, 18, 58, 26,\n12, 44, 4, 36, 14, 46, 6, 38,\n60, 28, 52, 20, 62, 30, 54, 22,\n3, 35, 11, 43, 1, 33, 9, 41,\n51, 19, 59, 27, 49, 17, 57, 25,\n15, 47, 7, 39, 13, 45, 5, 37,\n63, 31, 55, 23, 61, 29, 53, 21\n);\n\nfloat getBayerValue(vec2 uv, int size) {\n ivec2 pos = ivec2(fract(uv / float(size)) * float(size));\n int index = pos.y * size + pos.x;\n\n if (size == 2) {\n return float(bayer2x2[index]) / 4.0;\n } else if (size == 4) {\n return float(bayer4x4[index]) / 16.0;\n } else if (size == 8) {\n return float(bayer8x8[index]) / 64.0;\n }\n return 0.0;\n}\n\n\nvoid main() {\n float t = .5 * u_time;\n\n float pxSize = u_pxSize * u_pixelRatio;\n vec2 pxSizeUV = gl_FragCoord.xy - .5 * u_resolution;\n pxSizeUV /= pxSize;\n vec2 canvasPixelizedUV = (floor(pxSizeUV) + .5) * pxSize;\n vec2 normalizedUV = canvasPixelizedUV / u_resolution;\n\n vec2 ditheringNoiseUV = canvasPixelizedUV;\n vec2 shapeUV = normalizedUV;\n\n vec2 boxOrigin = vec2(.5 - u_originX, u_originY - .5);\n vec2 givenBoxSize = vec2(u_worldWidth, u_worldHeight);\n givenBoxSize = max(givenBoxSize, vec2(1.)) * u_pixelRatio;\n float r = u_rotation * PI / 180.;\n mat2 graphicRotation = mat2(cos(r), sin(r), -sin(r), cos(r));\n vec2 graphicOffset = vec2(-u_offsetX, u_offsetY);\n\n float patternBoxRatio = givenBoxSize.x / givenBoxSize.y;\n vec2 boxSize = vec2(\n (u_worldWidth == 0.) ? u_resolution.x : givenBoxSize.x,\n (u_worldHeight == 0.) ? u_resolution.y : givenBoxSize.y\n );\n \n if (u_shape > 3.5) {\n vec2 objectBoxSize = vec2(0.);\n // fit = none\n objectBoxSize.x = min(boxSize.x, boxSize.y);\n if (u_fit == 1.) { // fit = contain\n objectBoxSize.x = min(u_resolution.x, u_resolution.y);\n } else if (u_fit == 2.) { // fit = cover\n objectBoxSize.x = max(u_resolution.x, u_resolution.y);\n }\n objectBoxSize.y = objectBoxSize.x;\n vec2 objectWorldScale = u_resolution.xy / objectBoxSize;\n\n shapeUV *= objectWorldScale;\n shapeUV += boxOrigin * (objectWorldScale - 1.);\n shapeUV += vec2(-u_offsetX, u_offsetY);\n shapeUV /= u_scale;\n shapeUV = graphicRotation * shapeUV;\n } else {\n vec2 patternBoxSize = vec2(0.);\n // fit = none\n patternBoxSize.x = patternBoxRatio * min(boxSize.x / patternBoxRatio, boxSize.y);\n float patternWorldNoFitBoxWidth = patternBoxSize.x;\n if (u_fit == 1.) { // fit = contain\n patternBoxSize.x = patternBoxRatio * min(u_resolution.x / patternBoxRatio, u_resolution.y);\n } else if (u_fit == 2.) { // fit = cover\n patternBoxSize.x = patternBoxRatio * max(u_resolution.x / patternBoxRatio, u_resolution.y);\n }\n patternBoxSize.y = patternBoxSize.x / patternBoxRatio;\n vec2 patternWorldScale = u_resolution.xy / patternBoxSize;\n\n shapeUV += vec2(-u_offsetX, u_offsetY) / patternWorldScale;\n shapeUV += boxOrigin;\n shapeUV -= boxOrigin / patternWorldScale;\n shapeUV *= u_resolution.xy;\n shapeUV /= u_pixelRatio;\n if (u_fit > 0.) {\n shapeUV *= (patternWorldNoFitBoxWidth / patternBoxSize.x);\n }\n shapeUV /= u_scale;\n shapeUV = graphicRotation * shapeUV;\n shapeUV += boxOrigin / patternWorldScale;\n shapeUV -= boxOrigin;\n shapeUV += .5;\n }\n\n float shape = 0.;\n if (u_shape < 1.5) {\n // Simplex noise\n shapeUV *= .001;\n\n shape = 0.5 + 0.5 * getSimplexNoise(shapeUV, t);\n shape = smoothstep(0.3, 0.9, shape);\n\n } else if (u_shape < 2.5) {\n // Warp\n shapeUV *= .003;\n\n for (float i = 1.0; i < 6.0; i++) {\n shapeUV.x += 0.6 / i * cos(i * 2.5 * shapeUV.y + t);\n shapeUV.y += 0.6 / i * cos(i * 1.5 * shapeUV.x + t);\n }\n\n shape = .15 / max(0.001, abs(sin(t - shapeUV.y - shapeUV.x)));\n shape = smoothstep(0.02, 1., shape);\n\n } else if (u_shape < 3.5) {\n // Dots\n shapeUV *= .05;\n\n float stripeIdx = floor(2. * shapeUV.x / TWO_PI);\n float rand = hash11(stripeIdx * 10.);\n rand = sign(rand - .5) * pow(.1 + abs(rand), .4);\n shape = sin(shapeUV.x) * cos(shapeUV.y - 5. * rand * t);\n shape = pow(abs(shape), 6.);\n\n } else if (u_shape < 4.5) {\n // Sine wave\n shapeUV *= 4.;\n\n float wave = cos(.5 * shapeUV.x - 2. * t) * sin(1.5 * shapeUV.x + t) * (.75 + .25 * cos(3. * t));\n shape = 1. - smoothstep(-1., 1., shapeUV.y + wave);\n\n } else if (u_shape < 5.5) {\n // Ripple\n\n float dist = length(shapeUV);\n float waves = sin(pow(dist, 1.7) * 7. - 3. * t) * .5 + .5;\n shape = waves;\n\n } else if (u_shape < 6.5) {\n // Swirl\n\n float l = length(shapeUV);\n float angle = 6. * atan(shapeUV.y, shapeUV.x) + 4. * t;\n float twist = 1.2;\n float offset = 1. / pow(max(l, 1e-6), twist) + angle / TWO_PI;\n float mid = smoothstep(0., 1., pow(l, twist));\n shape = mix(0., fract(offset), mid);\n\n } else {\n // Sphere\n shapeUV *= 2.;\n\n float d = 1. - pow(length(shapeUV), 2.);\n vec3 pos = vec3(shapeUV, sqrt(max(0., d)));\n vec3 lightPos = normalize(vec3(cos(1.5 * t), .8, sin(1.25 * t)));\n shape = .5 + .5 * dot(lightPos, pos);\n shape *= step(0., d);\n }\n\n\n int type = int(floor(u_type));\n float dithering = 0.0;\n\n switch (type) {\n case 1: {\n dithering = step(hash21(ditheringNoiseUV), shape);\n } break;\n case 2:\n dithering = getBayerValue(pxSizeUV, 2);\n break;\n case 3:\n dithering = getBayerValue(pxSizeUV, 4);\n break;\n default :\n dithering = getBayerValue(pxSizeUV, 8);\n break;\n }\n\n dithering -= .5;\n float res = step(.5, shape + dithering);\n\n vec3 fgColor = u_colorFront.rgb * u_colorFront.a;\n float fgOpacity = u_colorFront.a;\n vec3 bgColor = u_colorBack.rgb * u_colorBack.a;\n float bgOpacity = u_colorBack.a;\n\n vec3 color = fgColor * res;\n float opacity = fgOpacity * res;\n\n color += bgColor * (1. - opacity);\n opacity += bgOpacity * (1. - opacity);\n\n fragColor = vec4(color, opacity);\n}\n`;\n\nexport interface DitheringUniforms extends ShaderSizingUniforms {\n u_colorBack: [number, number, number, number];\n u_colorFront: [number, number, number, number];\n u_shape: (typeof DitheringShapes)[DitheringShape];\n u_type: (typeof DitheringTypes)[DitheringType];\n u_pxSize: number;\n}\n\nexport interface DitheringParams extends ShaderSizingParams, ShaderMotionParams {\n colorBack?: string;\n colorFront?: string;\n shape?: DitheringShape;\n type?: DitheringType;\n size?: number;\n}\n\nexport const DitheringShapes = {\n simplex: 1,\n warp: 2,\n dots: 3,\n wave: 4,\n ripple: 5,\n swirl: 6,\n sphere: 7,\n} as const;\n\nexport type DitheringShape = keyof typeof DitheringShapes;\n\nexport const DitheringTypes = {\n 'random': 1,\n '2x2': 2,\n '4x4': 3,\n '8x8': 4,\n} as const;\n\nexport type DitheringType = keyof typeof DitheringTypes;\n"],
5
+ "mappings": ";;;;;AACA;AAAA,OAGO;AACP,SAAS,cAAc,WAAW,kBAAkB,wBAAwB;AAgCrE,MAAM,0BAAkC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAyB5C,YAAa;AAAA,EACb,SAAU;AAAA,EACV,gBAAiB;AAAA,EACjB,gBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAuOb,MAAM,kBAAkB;AAAA,EAC7B,SAAS;AAAA,EACT,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,QAAQ;AACV;AAIO,MAAM,iBAAiB;AAAA,EAC5B,UAAU;AAAA,EACV,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AACT;",
6
6
  "names": []
7
7
  }
@@ -1,20 +1,34 @@
1
1
  import { type ShaderSizingParams, type ShaderSizingUniforms } from '../shader-sizing.js';
2
2
  /**
3
- * Static grid pattern
3
+ * Static grid pattern made of circles, diamonds, squares or triangles.
4
4
  *
5
- * Uniforms:
6
- * - u_colorBack, u_colorFill, u_colorStroke (vec4 RGBA)
7
- * - u_dotSize (px): base shape size
8
- * - u_sizeRange (0..1): randomizes the size of shape between 0 and u_dotSize
9
- * - u_strokeWidth (px): the stroke (to be added to u_dotSize)
10
- * - u_gapX, u_gapY (px): pattern spacing
11
- * - u_opacityRange (0..1): variety of shape opacity
12
- * - u_shape (float used as integer):
13
- * ---- 1: circle
14
- * ---- 2: square
15
- * ---- 3: triangle
16
- * ---- 4: diamond
17
- * ---- 5: cross
5
+ * Fragment shader uniforms:
6
+ * - u_colorBack (vec4): Background color in RGBA
7
+ * - u_colorFill (vec4): Shape fill color in RGBA
8
+ * - u_colorStroke (vec4): Shape stroke color in RGBA
9
+ * - u_dotSize (float): Base size of each shape in pixels (1 to 100)
10
+ * - u_gapX (float): Pattern horizontal spacing in pixels (2 to 500)
11
+ * - u_gapY (float): Pattern vertical spacing in pixels (2 to 500)
12
+ * - u_strokeWidth (float): Outline stroke width in pixels (0 to 50)
13
+ * - u_sizeRange (float): Random variation in shape size, 0 = uniform, higher = random up to base size (0 to 1)
14
+ * - u_opacityRange (float): Random variation in shape opacity, 0 = opaque, higher = semi-transparent (0 to 1)
15
+ * - u_shape (float): Shape type (0 = circle, 1 = diamond, 2 = square, 3 = triangle)
16
+ *
17
+ * Vertex shader outputs (used in fragment shader):
18
+ * - v_patternUV (vec2): UV coordinates in pixels (scaled by 0.01 for precision), with scale, rotation and offset applied
19
+ *
20
+ * Vertex shader uniforms:
21
+ * - u_resolution (vec2): Canvas resolution in pixels
22
+ * - u_pixelRatio (float): Device pixel ratio
23
+ * - u_originX (float): Reference point for positioning world width in the canvas (0 to 1)
24
+ * - u_originY (float): Reference point for positioning world height in the canvas (0 to 1)
25
+ * - u_worldWidth (float): Virtual width of the graphic before it's scaled to fit the canvas
26
+ * - u_worldHeight (float): Virtual height of the graphic before it's scaled to fit the canvas
27
+ * - u_fit (float): How to fit the rendered shader into the canvas dimensions (0 = none, 1 = contain, 2 = cover)
28
+ * - u_scale (float): Overall zoom level of the graphics (0.01 to 4)
29
+ * - u_rotation (float): Overall rotation angle of the graphics in degrees (0 to 360)
30
+ * - u_offsetX (float): Horizontal offset of the graphics center (-1 to 1)
31
+ * - u_offsetY (float): Vertical offset of the graphics center (-1 to 1)
18
32
  *
19
33
  */
20
34
  export declare const dotGridFragmentShader: string;
@@ -3,7 +3,7 @@
3
3
  * https://github.com/paper-design/shaders *
4
4
  * * * * * * * * * * * * * * * * * * * * * * * * * * * */
5
5
 
6
- import { sizingVariablesDeclaration } from "../shader-sizing.js";
6
+ import {} from "../shader-sizing.js";
7
7
  import { declarePI, simplexNoise } from "../shader-utils.js";
8
8
  const dotGridFragmentShader = `#version 300 es
9
9
  precision mediump float;
@@ -19,7 +19,7 @@ uniform float u_sizeRange;
19
19
  uniform float u_opacityRange;
20
20
  uniform float u_shape;
21
21
 
22
- ${sizingVariablesDeclaration}
22
+ in vec2 v_patternUV;
23
23
 
24
24
  out vec4 fragColor;
25
25
 
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/shaders/dot-grid.ts"],
4
- "sourcesContent": ["import { sizingVariablesDeclaration, type ShaderSizingParams, type ShaderSizingUniforms } from '../shader-sizing.js';\nimport { declarePI, simplexNoise } from '../shader-utils.js';\n\n/**\n * Static grid pattern\n *\n * Uniforms:\n * - u_colorBack, u_colorFill, u_colorStroke (vec4 RGBA)\n * - u_dotSize (px): base shape size\n * - u_sizeRange (0..1): randomizes the size of shape between 0 and u_dotSize\n * - u_strokeWidth (px): the stroke (to be added to u_dotSize)\n * - u_gapX, u_gapY (px): pattern spacing\n * - u_opacityRange (0..1): variety of shape opacity\n * - u_shape (float used as integer):\n * ---- 1: circle\n * ---- 2: square\n * ---- 3: triangle\n * ---- 4: diamond\n * ---- 5: cross\n *\n */\n\n// language=GLSL\nexport const dotGridFragmentShader: string = `#version 300 es\nprecision mediump float;\n\nuniform vec4 u_colorBack;\nuniform vec4 u_colorFill;\nuniform vec4 u_colorStroke;\nuniform float u_dotSize;\nuniform float u_gapX;\nuniform float u_gapY;\nuniform float u_strokeWidth;\nuniform float u_sizeRange;\nuniform float u_opacityRange;\nuniform float u_shape;\n\n${sizingVariablesDeclaration}\n\nout vec4 fragColor;\n\n${declarePI}\n${simplexNoise}\n\nfloat polygon(vec2 p, float N, float rot) {\n float a = atan(p.x, p.y) + rot;\n float r = TWO_PI / float(N);\n\n return cos(floor(.5 + a / r) * r - a) * length(p);\n}\n\nvoid main() {\n\n // x100 is a default multiplier between vertex and fragmant shaders\n // we use it to avoid UV presision issues\n vec2 shape_uv = 100. * v_patternUV;\n\n vec2 gap = max(abs(vec2(u_gapX, u_gapY)), vec2(1e-6));\n vec2 grid = fract(shape_uv / gap) + 1e-4;\n vec2 grid_idx = floor(shape_uv / gap);\n float sizeRandomizer = .5 + .8 * snoise(2. * vec2(grid_idx.x * 100., grid_idx.y));\n float opacity_randomizer = .5 + .7 * snoise(2. * vec2(grid_idx.y, grid_idx.x));\n\n vec2 center = vec2(0.5) - 1e-3;\n vec2 p = (grid - center) * vec2(u_gapX, u_gapY);\n\n float baseSize = u_dotSize * (1. - sizeRandomizer * u_sizeRange);\n float strokeWidth = u_strokeWidth * (1. - sizeRandomizer * u_sizeRange);\n\n float dist;\n if (u_shape < 0.5) {\n // Circle\n dist = length(p);\n } else if (u_shape < 1.5) {\n // Diamond\n strokeWidth *= 1.5;\n dist = polygon(1.5 * p, 4., .25 * PI);\n } else if (u_shape < 2.5) {\n // Square\n dist = polygon(1.03 * p, 4., 1e-3);\n } else {\n // Triangle\n strokeWidth *= 1.5;\n p = p * 2. - 1.;\n p *= .9;\n p.y = 1. - p.y;\n p.y -= .75 * baseSize;\n dist = polygon(p, 3., 1e-3);\n }\n\n float edgeWidth = fwidth(dist);\n float shapeOuter = 1. - smoothstep(baseSize - edgeWidth, baseSize + edgeWidth, dist - strokeWidth);\n float shapeInner = 1. - smoothstep(baseSize - edgeWidth, baseSize + edgeWidth, dist);\n float stroke = shapeOuter - shapeInner;\n\n float dotOpacity = max(0., 1. - opacity_randomizer * u_opacityRange);\n stroke *= dotOpacity;\n shapeInner *= dotOpacity;\n\n stroke *= u_colorStroke.a;\n shapeInner *= u_colorFill.a;\n\n vec3 color = vec3(0.);\n color += stroke * u_colorStroke.rgb;\n color += shapeInner * u_colorFill.rgb;\n color += (1. - shapeInner - stroke) * u_colorBack.rgb * u_colorBack.a;\n\n float opacity = 0.;\n opacity += stroke;\n opacity += shapeInner;\n opacity += (1. - opacity) * u_colorBack.a;\n\n fragColor = vec4(color, opacity);\n}\n`;\n\nexport interface DotGridUniforms extends ShaderSizingUniforms {\n u_colorBack: [number, number, number, number];\n u_colorFill: [number, number, number, number];\n u_colorStroke: [number, number, number, number];\n u_dotSize: number;\n u_gapX: number;\n u_gapY: number;\n u_strokeWidth: number;\n u_sizeRange: number;\n u_opacityRange: number;\n u_shape: (typeof DotGridShapes)[DotGridShape];\n}\n\nexport interface DotGridParams extends ShaderSizingParams {\n colorBack?: string;\n colorFill?: string;\n colorStroke?: string;\n size?: number;\n gapX?: number;\n gapY?: number;\n strokeWidth?: number;\n sizeRange?: number;\n opacityRange?: number;\n shape?: DotGridShape;\n}\n\nexport const DotGridShapes = {\n circle: 0,\n diamond: 1,\n square: 2,\n triangle: 3,\n} as const;\n\nexport type DotGridShape = keyof typeof DotGridShapes;\n"],
5
- "mappings": ";;;;;AAAA,SAAS,kCAAsF;AAC/F,SAAS,WAAW,oBAAoB;AAsBjC,MAAM,wBAAgC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAc3C,0BAA0B;AAAA;AAAA;AAAA;AAAA,EAI1B,SAAS;AAAA,EACT,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAoGP,MAAM,gBAAgB;AAAA,EAC3B,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,UAAU;AACZ;",
4
+ "sourcesContent": ["import { type ShaderSizingParams, type ShaderSizingUniforms } from '../shader-sizing.js';\nimport { declarePI, simplexNoise } from '../shader-utils.js';\n\n/**\n * Static grid pattern made of circles, diamonds, squares or triangles.\n *\n * Fragment shader uniforms:\n * - u_colorBack (vec4): Background color in RGBA\n * - u_colorFill (vec4): Shape fill color in RGBA\n * - u_colorStroke (vec4): Shape stroke color in RGBA\n * - u_dotSize (float): Base size of each shape in pixels (1 to 100)\n * - u_gapX (float): Pattern horizontal spacing in pixels (2 to 500)\n * - u_gapY (float): Pattern vertical spacing in pixels (2 to 500)\n * - u_strokeWidth (float): Outline stroke width in pixels (0 to 50)\n * - u_sizeRange (float): Random variation in shape size, 0 = uniform, higher = random up to base size (0 to 1)\n * - u_opacityRange (float): Random variation in shape opacity, 0 = opaque, higher = semi-transparent (0 to 1)\n * - u_shape (float): Shape type (0 = circle, 1 = diamond, 2 = square, 3 = triangle)\n *\n * Vertex shader outputs (used in fragment shader):\n * - v_patternUV (vec2): UV coordinates in pixels (scaled by 0.01 for precision), with scale, rotation and offset applied\n *\n * Vertex shader uniforms:\n * - u_resolution (vec2): Canvas resolution in pixels\n * - u_pixelRatio (float): Device pixel ratio\n * - u_originX (float): Reference point for positioning world width in the canvas (0 to 1)\n * - u_originY (float): Reference point for positioning world height in the canvas (0 to 1)\n * - u_worldWidth (float): Virtual width of the graphic before it's scaled to fit the canvas\n * - u_worldHeight (float): Virtual height of the graphic before it's scaled to fit the canvas\n * - u_fit (float): How to fit the rendered shader into the canvas dimensions (0 = none, 1 = contain, 2 = cover)\n * - u_scale (float): Overall zoom level of the graphics (0.01 to 4)\n * - u_rotation (float): Overall rotation angle of the graphics in degrees (0 to 360)\n * - u_offsetX (float): Horizontal offset of the graphics center (-1 to 1)\n * - u_offsetY (float): Vertical offset of the graphics center (-1 to 1)\n *\n */\n\n// language=GLSL\nexport const dotGridFragmentShader: string = `#version 300 es\nprecision mediump float;\n\nuniform vec4 u_colorBack;\nuniform vec4 u_colorFill;\nuniform vec4 u_colorStroke;\nuniform float u_dotSize;\nuniform float u_gapX;\nuniform float u_gapY;\nuniform float u_strokeWidth;\nuniform float u_sizeRange;\nuniform float u_opacityRange;\nuniform float u_shape;\n\nin vec2 v_patternUV;\n\nout vec4 fragColor;\n\n${ declarePI }\n${ simplexNoise }\n\nfloat polygon(vec2 p, float N, float rot) {\n float a = atan(p.x, p.y) + rot;\n float r = TWO_PI / float(N);\n\n return cos(floor(.5 + a / r) * r - a) * length(p);\n}\n\nvoid main() {\n\n // x100 is a default multiplier between vertex and fragmant shaders\n // we use it to avoid UV presision issues\n vec2 shape_uv = 100. * v_patternUV;\n\n vec2 gap = max(abs(vec2(u_gapX, u_gapY)), vec2(1e-6));\n vec2 grid = fract(shape_uv / gap) + 1e-4;\n vec2 grid_idx = floor(shape_uv / gap);\n float sizeRandomizer = .5 + .8 * snoise(2. * vec2(grid_idx.x * 100., grid_idx.y));\n float opacity_randomizer = .5 + .7 * snoise(2. * vec2(grid_idx.y, grid_idx.x));\n\n vec2 center = vec2(0.5) - 1e-3;\n vec2 p = (grid - center) * vec2(u_gapX, u_gapY);\n\n float baseSize = u_dotSize * (1. - sizeRandomizer * u_sizeRange);\n float strokeWidth = u_strokeWidth * (1. - sizeRandomizer * u_sizeRange);\n\n float dist;\n if (u_shape < 0.5) {\n // Circle\n dist = length(p);\n } else if (u_shape < 1.5) {\n // Diamond\n strokeWidth *= 1.5;\n dist = polygon(1.5 * p, 4., .25 * PI);\n } else if (u_shape < 2.5) {\n // Square\n dist = polygon(1.03 * p, 4., 1e-3);\n } else {\n // Triangle\n strokeWidth *= 1.5;\n p = p * 2. - 1.;\n p *= .9;\n p.y = 1. - p.y;\n p.y -= .75 * baseSize;\n dist = polygon(p, 3., 1e-3);\n }\n\n float edgeWidth = fwidth(dist);\n float shapeOuter = 1. - smoothstep(baseSize - edgeWidth, baseSize + edgeWidth, dist - strokeWidth);\n float shapeInner = 1. - smoothstep(baseSize - edgeWidth, baseSize + edgeWidth, dist);\n float stroke = shapeOuter - shapeInner;\n\n float dotOpacity = max(0., 1. - opacity_randomizer * u_opacityRange);\n stroke *= dotOpacity;\n shapeInner *= dotOpacity;\n\n stroke *= u_colorStroke.a;\n shapeInner *= u_colorFill.a;\n\n vec3 color = vec3(0.);\n color += stroke * u_colorStroke.rgb;\n color += shapeInner * u_colorFill.rgb;\n color += (1. - shapeInner - stroke) * u_colorBack.rgb * u_colorBack.a;\n\n float opacity = 0.;\n opacity += stroke;\n opacity += shapeInner;\n opacity += (1. - opacity) * u_colorBack.a;\n\n fragColor = vec4(color, opacity);\n}\n`;\n\nexport interface DotGridUniforms extends ShaderSizingUniforms {\n u_colorBack: [number, number, number, number];\n u_colorFill: [number, number, number, number];\n u_colorStroke: [number, number, number, number];\n u_dotSize: number;\n u_gapX: number;\n u_gapY: number;\n u_strokeWidth: number;\n u_sizeRange: number;\n u_opacityRange: number;\n u_shape: (typeof DotGridShapes)[DotGridShape];\n}\n\nexport interface DotGridParams extends ShaderSizingParams {\n colorBack?: string;\n colorFill?: string;\n colorStroke?: string;\n size?: number;\n gapX?: number;\n gapY?: number;\n strokeWidth?: number;\n sizeRange?: number;\n opacityRange?: number;\n shape?: DotGridShape;\n}\n\nexport const DotGridShapes = {\n circle: 0,\n diamond: 1,\n square: 2,\n triangle: 3,\n} as const;\n\nexport type DotGridShape = keyof typeof DotGridShapes;\n"],
5
+ "mappings": ";;;;;AAAA,eAAmE;AACnE,SAAS,WAAW,oBAAoB;AAoCjC,MAAM,wBAAgC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkB1C,SAAU;AAAA,EACV,YAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAoGT,MAAM,gBAAgB;AAAA,EAC3B,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,UAAU;AACZ;",
6
6
  "names": []
7
7
  }
@@ -5,17 +5,35 @@ export declare const dotOrbitMeta: {
5
5
  readonly maxColorCount: 10;
6
6
  };
7
7
  /**
8
- * Animated dot pattern with dots orbiting around their grid positions
8
+ * Animated multi-color dots pattern with each dot orbiting around its cell center.
9
+ * Supports up to 10 colors and various shape and motion controls.
9
10
  *
10
- * Uniforms:
11
- * - u_colorBack (RGBA)
12
- * - u_colors (vec4[]), u_colorsCount (float used as integer)
13
- * - u_stepsPerColor: discrete color steps between u_colors
14
- * - u_size (0..1): dot radius (relative to cell size)
15
- * - u_sizeRange (0..1): randomizes dot radius between 0 and u_size
16
- * - u_spreading (0..1): max orbit distance of each dot around the cell center
11
+ * Fragment shader uniforms:
12
+ * - u_time (float): Animation time
13
+ * - u_colorBack (vec4): Background color in RGBA
14
+ * - u_colors (vec4[]): Up to 10 base colors in RGBA
15
+ * - u_colorsCount (float): Number of active colors
16
+ * - u_stepsPerColor (float): Number of extra colors between base colors, 1 = N colors, 2 = 2×N, etc. (1 to 4)
17
+ * - u_size (float): Dot radius relative to cell size (0 to 1)
18
+ * - u_sizeRange (float): Random variation in shape size, 0 = uniform, higher = random up to base size (0 to 1)
19
+ * - u_spreading (float): Maximum orbit distance around cell center (0 to 1)
20
+ * - u_noiseTexture (sampler2D): Pre-computed randomizer source texture
17
21
  *
18
- * - u_noiseTexture (sampler2D): pre-computed randomizer source
22
+ * Vertex shader outputs (used in fragment shader):
23
+ * - v_patternUV (vec2): UV coordinates in pixels (scaled by 0.01 for precision), with rotation and offset applied
24
+ *
25
+ * Vertex shader uniforms:
26
+ * - u_resolution (vec2): Canvas resolution in pixels
27
+ * - u_pixelRatio (float): Device pixel ratio
28
+ * - u_originX (float): Reference point for positioning world width in the canvas (0 to 1)
29
+ * - u_originY (float): Reference point for positioning world height in the canvas (0 to 1)
30
+ * - u_worldWidth (float): Virtual width of the graphic before it's scaled to fit the canvas
31
+ * - u_worldHeight (float): Virtual height of the graphic before it's scaled to fit the canvas
32
+ * - u_fit (float): How to fit the rendered shader into the canvas dimensions (0 = none, 1 = contain, 2 = cover)
33
+ * - u_scale (float): Overall zoom level of the graphics (0.01 to 4)
34
+ * - u_rotation (float): Overall rotation angle of the graphics in degrees (0 to 360)
35
+ * - u_offsetX (float): Horizontal offset of the graphics center (-1 to 1)
36
+ * - u_offsetY (float): Vertical offset of the graphics center (-1 to 1)
19
37
  *
20
38
  */
21
39
  export declare const dotOrbitFragmentShader: string;
@@ -3,7 +3,7 @@
3
3
  * https://github.com/paper-design/shaders *
4
4
  * * * * * * * * * * * * * * * * * * * * * * * * * * * */
5
5
 
6
- import { sizingVariablesDeclaration } from "../shader-sizing.js";
6
+ import {} from "../shader-sizing.js";
7
7
  import { declarePI, rotation2, textureRandomizerR, textureRandomizerGB } from "../shader-utils.js";
8
8
  const dotOrbitMeta = {
9
9
  maxColorCount: 10
@@ -23,7 +23,7 @@ uniform float u_size;
23
23
  uniform float u_sizeRange;
24
24
  uniform float u_spreading;
25
25
 
26
- ${sizingVariablesDeclaration}
26
+ in vec2 v_patternUV;
27
27
 
28
28
  out vec4 fragColor;
29
29
 
@@ -55,7 +55,6 @@ vec3 voronoiShape(vec2 uv, float time) {
55
55
  minDist = dist;
56
56
  randomizer = rand;
57
57
  }
58
- minDist = min(minDist, dist);
59
58
  }
60
59
  }
61
60
 
@@ -86,12 +85,12 @@ void main() {
86
85
  vec4 gradient = u_colors[0];
87
86
  gradient.rgb *= gradient.a;
88
87
  for (int i = 1; i < ${dotOrbitMeta.maxColorCount}; i++) {
89
- if (i >= int(u_colorsCount)) break;
90
- float localT = clamp(mixer - float(i - 1), 0.0, 1.0);
91
- localT = round(localT * steps) / steps;
92
- vec4 c = u_colors[i];
93
- c.rgb *= c.a;
94
- gradient = mix(gradient, c, localT);
88
+ if (i >= int(u_colorsCount)) break;
89
+ float localT = clamp(mixer - float(i - 1), 0.0, 1.0);
90
+ localT = round(localT * steps) / steps;
91
+ vec4 c = u_colors[i];
92
+ c.rgb *= c.a;
93
+ gradient = mix(gradient, c, localT);
95
94
  }
96
95
 
97
96
  if ((mixer < 0.) || (mixer > (u_colorsCount - 1.))) {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/shaders/dot-orbit.ts"],
4
- "sourcesContent": ["import type { vec4 } from '../types.js';\nimport type { ShaderMotionParams } from '../shader-mount.js';\nimport { sizingVariablesDeclaration, type ShaderSizingParams, type ShaderSizingUniforms } from '../shader-sizing.js';\nimport { declarePI, rotation2, textureRandomizerR, textureRandomizerGB } from '../shader-utils.js';\n\nexport const dotOrbitMeta = {\n maxColorCount: 10,\n} as const;\n\n/**\n * Animated dot pattern with dots orbiting around their grid positions\n *\n * Uniforms:\n * - u_colorBack (RGBA)\n * - u_colors (vec4[]), u_colorsCount (float used as integer)\n * - u_stepsPerColor: discrete color steps between u_colors\n * - u_size (0..1): dot radius (relative to cell size)\n * - u_sizeRange (0..1): randomizes dot radius between 0 and u_size\n * - u_spreading (0..1): max orbit distance of each dot around the cell center\n *\n * - u_noiseTexture (sampler2D): pre-computed randomizer source\n *\n */\n\n// language=GLSL\nexport const dotOrbitFragmentShader: string = `#version 300 es\nprecision mediump float;\n\nuniform float u_time;\n\nuniform sampler2D u_noiseTexture;\n\nuniform vec4 u_colorBack;\nuniform vec4 u_colors[${dotOrbitMeta.maxColorCount}];\nuniform float u_colorsCount;\nuniform float u_stepsPerColor;\nuniform float u_size;\nuniform float u_sizeRange;\nuniform float u_spreading;\n\n${sizingVariablesDeclaration}\n\nout vec4 fragColor;\n\n${declarePI}\n${rotation2}\n${textureRandomizerR}\n${textureRandomizerGB}\n\n\nvec3 voronoiShape(vec2 uv, float time) {\n vec2 i_uv = floor(uv);\n vec2 f_uv = fract(uv);\n\n float spreading = .25 * clamp(u_spreading, 0., 1.);\n\n float minDist = 1.;\n vec2 randomizer = vec2(0.);\n for (int y = -1; y <= 1; y++) {\n for (int x = -1; x <= 1; x++) {\n vec2 tileOffset = vec2(float(x), float(y));\n vec2 rand = randomGB(i_uv + tileOffset);\n vec2 cellCenter = vec2(.5 + 1e-4);\n cellCenter += spreading * cos(time + TWO_PI * rand);\n cellCenter -= .5;\n cellCenter = rotate(cellCenter, randomR(vec2(rand.x, rand.y)) + .1 * time);\n cellCenter += .5;\n float dist = length(tileOffset + cellCenter - f_uv);\n if (dist < minDist) {\n minDist = dist;\n randomizer = rand;\n }\n minDist = min(minDist, dist);\n }\n }\n\n return vec3(minDist, randomizer);\n}\n\nvoid main() {\n\n vec2 shape_uv = v_patternUV;\n shape_uv *= 1.5;\n\n const float firstFrameOffset = -10.;\n float t = u_time + firstFrameOffset;\n\n vec3 voronoi = voronoiShape(shape_uv, t) + 1e-4;\n\n float radius = .25 * clamp(u_size, 0., 1.) - .5 * clamp(u_sizeRange, 0., 1.) * voronoi[2];\n float dist = voronoi[0];\n float edgeWidth = fwidth(dist);\n float dots = 1. - smoothstep(radius - edgeWidth, radius + edgeWidth, dist);\n\n float shape = voronoi[1];\n\n float mixer = shape * (u_colorsCount - 1.);\n mixer = (shape - .5 / u_colorsCount) * u_colorsCount;\n float steps = max(1., u_stepsPerColor);\n\n vec4 gradient = u_colors[0];\n gradient.rgb *= gradient.a;\n for (int i = 1; i < ${dotOrbitMeta.maxColorCount}; i++) {\n if (i >= int(u_colorsCount)) break;\n float localT = clamp(mixer - float(i - 1), 0.0, 1.0);\n localT = round(localT * steps) / steps;\n vec4 c = u_colors[i];\n c.rgb *= c.a;\n gradient = mix(gradient, c, localT);\n }\n\n if ((mixer < 0.) || (mixer > (u_colorsCount - 1.))) {\n float localT = mixer + 1.;\n if (mixer > (u_colorsCount - 1.)) {\n localT = mixer - (u_colorsCount - 1.);\n }\n localT = round(localT * steps) / steps;\n vec4 cFst = u_colors[0];\n cFst.rgb *= cFst.a;\n vec4 cLast = u_colors[int(u_colorsCount - 1.)];\n cLast.rgb *= cLast.a;\n gradient = mix(cLast, cFst, localT);\n }\n\n vec3 color = gradient.rgb * dots;\n float opacity = gradient.a * dots;\n\n vec3 bgColor = u_colorBack.rgb * u_colorBack.a;\n color = color + bgColor * (1. - opacity);\n opacity = opacity + u_colorBack.a * (1. - opacity);\n\n fragColor = vec4(color, opacity);\n}\n`;\n\nexport interface DotOrbitUniforms extends ShaderSizingUniforms {\n u_colorBack: [number, number, number, number];\n u_colors: vec4[];\n u_colorsCount: number;\n u_size: number;\n u_sizeRange: number;\n u_spreading: number;\n u_stepsPerColor: number;\n u_noiseTexture?: HTMLImageElement;\n}\n\nexport interface DotOrbitParams extends ShaderSizingParams, ShaderMotionParams {\n colorBack?: string;\n colors?: string[];\n size?: number;\n sizeRange?: number;\n spreading?: number;\n stepsPerColor?: number;\n}\n"],
5
- "mappings": ";;;;;AAEA,SAAS,kCAAsF;AAC/F,SAAS,WAAW,WAAW,oBAAoB,2BAA2B;AAEvE,MAAM,eAAe;AAAA,EAC1B,eAAe;AACjB;AAkBO,MAAM,yBAAiC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAQtB,aAAa,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOhD,0BAA0B;AAAA;AAAA;AAAA;AAAA,EAI1B,SAAS;AAAA,EACT,SAAS;AAAA,EACT,kBAAkB;AAAA,EAClB,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAuDG,aAAa,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;",
4
+ "sourcesContent": ["import type { vec4 } from '../types.js';\nimport type { ShaderMotionParams } from '../shader-mount.js';\nimport { type ShaderSizingParams, type ShaderSizingUniforms } from '../shader-sizing.js';\nimport { declarePI, rotation2, textureRandomizerR, textureRandomizerGB } from '../shader-utils.js';\n\nexport const dotOrbitMeta = {\n maxColorCount: 10,\n} as const;\n\n/**\n * Animated multi-color dots pattern with each dot orbiting around its cell center.\n * Supports up to 10 colors and various shape and motion controls.\n *\n * Fragment shader uniforms:\n * - u_time (float): Animation time\n * - u_colorBack (vec4): Background color in RGBA\n * - u_colors (vec4[]): Up to 10 base colors in RGBA\n * - u_colorsCount (float): Number of active colors\n * - u_stepsPerColor (float): Number of extra colors between base colors, 1 = N colors, 2 = 2\u00D7N, etc. (1 to 4)\n * - u_size (float): Dot radius relative to cell size (0 to 1)\n * - u_sizeRange (float): Random variation in shape size, 0 = uniform, higher = random up to base size (0 to 1)\n * - u_spreading (float): Maximum orbit distance around cell center (0 to 1)\n * - u_noiseTexture (sampler2D): Pre-computed randomizer source texture\n *\n * Vertex shader outputs (used in fragment shader):\n * - v_patternUV (vec2): UV coordinates in pixels (scaled by 0.01 for precision), with rotation and offset applied\n *\n * Vertex shader uniforms:\n * - u_resolution (vec2): Canvas resolution in pixels\n * - u_pixelRatio (float): Device pixel ratio\n * - u_originX (float): Reference point for positioning world width in the canvas (0 to 1)\n * - u_originY (float): Reference point for positioning world height in the canvas (0 to 1)\n * - u_worldWidth (float): Virtual width of the graphic before it's scaled to fit the canvas\n * - u_worldHeight (float): Virtual height of the graphic before it's scaled to fit the canvas\n * - u_fit (float): How to fit the rendered shader into the canvas dimensions (0 = none, 1 = contain, 2 = cover)\n * - u_scale (float): Overall zoom level of the graphics (0.01 to 4)\n * - u_rotation (float): Overall rotation angle of the graphics in degrees (0 to 360)\n * - u_offsetX (float): Horizontal offset of the graphics center (-1 to 1)\n * - u_offsetY (float): Vertical offset of the graphics center (-1 to 1)\n *\n */\n\n// language=GLSL\nexport const dotOrbitFragmentShader: string = `#version 300 es\nprecision mediump float;\n\nuniform float u_time;\n\nuniform sampler2D u_noiseTexture;\n\nuniform vec4 u_colorBack;\nuniform vec4 u_colors[${ dotOrbitMeta.maxColorCount }];\nuniform float u_colorsCount;\nuniform float u_stepsPerColor;\nuniform float u_size;\nuniform float u_sizeRange;\nuniform float u_spreading;\n\nin vec2 v_patternUV;\n\nout vec4 fragColor;\n\n${ declarePI }\n${ rotation2 }\n${ textureRandomizerR }\n${ textureRandomizerGB }\n\n\nvec3 voronoiShape(vec2 uv, float time) {\n vec2 i_uv = floor(uv);\n vec2 f_uv = fract(uv);\n\n float spreading = .25 * clamp(u_spreading, 0., 1.);\n\n float minDist = 1.;\n vec2 randomizer = vec2(0.);\n for (int y = -1; y <= 1; y++) {\n for (int x = -1; x <= 1; x++) {\n vec2 tileOffset = vec2(float(x), float(y));\n vec2 rand = randomGB(i_uv + tileOffset);\n vec2 cellCenter = vec2(.5 + 1e-4);\n cellCenter += spreading * cos(time + TWO_PI * rand);\n cellCenter -= .5;\n cellCenter = rotate(cellCenter, randomR(vec2(rand.x, rand.y)) + .1 * time);\n cellCenter += .5;\n float dist = length(tileOffset + cellCenter - f_uv);\n if (dist < minDist) {\n minDist = dist;\n randomizer = rand;\n }\n }\n }\n\n return vec3(minDist, randomizer);\n}\n\nvoid main() {\n\n vec2 shape_uv = v_patternUV;\n shape_uv *= 1.5;\n\n const float firstFrameOffset = -10.;\n float t = u_time + firstFrameOffset;\n\n vec3 voronoi = voronoiShape(shape_uv, t) + 1e-4;\n\n float radius = .25 * clamp(u_size, 0., 1.) - .5 * clamp(u_sizeRange, 0., 1.) * voronoi[2];\n float dist = voronoi[0];\n float edgeWidth = fwidth(dist);\n float dots = 1. - smoothstep(radius - edgeWidth, radius + edgeWidth, dist);\n\n float shape = voronoi[1];\n\n float mixer = shape * (u_colorsCount - 1.);\n mixer = (shape - .5 / u_colorsCount) * u_colorsCount;\n float steps = max(1., u_stepsPerColor);\n\n vec4 gradient = u_colors[0];\n gradient.rgb *= gradient.a;\n for (int i = 1; i < ${ dotOrbitMeta.maxColorCount }; i++) {\n if (i >= int(u_colorsCount)) break;\n float localT = clamp(mixer - float(i - 1), 0.0, 1.0);\n localT = round(localT * steps) / steps;\n vec4 c = u_colors[i];\n c.rgb *= c.a;\n gradient = mix(gradient, c, localT);\n }\n\n if ((mixer < 0.) || (mixer > (u_colorsCount - 1.))) {\n float localT = mixer + 1.;\n if (mixer > (u_colorsCount - 1.)) {\n localT = mixer - (u_colorsCount - 1.);\n }\n localT = round(localT * steps) / steps;\n vec4 cFst = u_colors[0];\n cFst.rgb *= cFst.a;\n vec4 cLast = u_colors[int(u_colorsCount - 1.)];\n cLast.rgb *= cLast.a;\n gradient = mix(cLast, cFst, localT);\n }\n\n vec3 color = gradient.rgb * dots;\n float opacity = gradient.a * dots;\n\n vec3 bgColor = u_colorBack.rgb * u_colorBack.a;\n color = color + bgColor * (1. - opacity);\n opacity = opacity + u_colorBack.a * (1. - opacity);\n\n fragColor = vec4(color, opacity);\n}\n`;\n\nexport interface DotOrbitUniforms extends ShaderSizingUniforms {\n u_colorBack: [number, number, number, number];\n u_colors: vec4[];\n u_colorsCount: number;\n u_size: number;\n u_sizeRange: number;\n u_spreading: number;\n u_stepsPerColor: number;\n u_noiseTexture?: HTMLImageElement;\n}\n\nexport interface DotOrbitParams extends ShaderSizingParams, ShaderMotionParams {\n colorBack?: string;\n colors?: string[];\n size?: number;\n sizeRange?: number;\n spreading?: number;\n stepsPerColor?: number;\n}\n"],
5
+ "mappings": ";;;;;AAEA,eAAmE;AACnE,SAAS,WAAW,WAAW,oBAAoB,2BAA2B;AAEvE,MAAM,eAAe;AAAA,EAC1B,eAAe;AACjB;AAoCO,MAAM,yBAAiC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAQrB,aAAa,aAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWjD,SAAU;AAAA,EACV,SAAU;AAAA,EACV,kBAAmB;AAAA,EACnB,mBAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAsDE,aAAa,aAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;",
6
6
  "names": []
7
7
  }