@paper-design/shaders 0.0.66 → 0.0.68

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 (80) hide show
  1. package/dist/index.d.ts +27 -18
  2. package/dist/index.js.map +2 -2
  3. package/dist/shader-sizing.d.ts +0 -2
  4. package/dist/shader-sizing.js +0 -165
  5. package/dist/shader-sizing.js.map +2 -2
  6. package/dist/shaders/color-panels.d.ts +32 -12
  7. package/dist/shaders/color-panels.js +3 -3
  8. package/dist/shaders/color-panels.js.map +2 -2
  9. package/dist/shaders/dithering.d.ts +14 -19
  10. package/dist/shaders/dithering.js +105 -64
  11. package/dist/shaders/dithering.js.map +2 -2
  12. package/dist/shaders/dot-grid.d.ts +28 -14
  13. package/dist/shaders/dot-grid.js.map +2 -2
  14. package/dist/shaders/dot-orbit.d.ts +27 -9
  15. package/dist/shaders/dot-orbit.js +6 -6
  16. package/dist/shaders/dot-orbit.js.map +2 -2
  17. package/dist/shaders/fluted-glass.d.ts +36 -18
  18. package/dist/shaders/fluted-glass.js +9 -9
  19. package/dist/shaders/fluted-glass.js.map +2 -2
  20. package/dist/shaders/god-rays.d.ts +32 -10
  21. package/dist/shaders/god-rays.js.map +2 -2
  22. package/dist/shaders/grain-gradient.d.ts +41 -17
  23. package/dist/shaders/grain-gradient.js +44 -21
  24. package/dist/shaders/grain-gradient.js.map +2 -2
  25. package/dist/shaders/halftone-dots.d.ts +30 -6
  26. package/dist/shaders/halftone-dots.js +12 -12
  27. package/dist/shaders/halftone-dots.js.map +2 -2
  28. package/dist/shaders/heatmap.d.ts +36 -0
  29. package/dist/shaders/heatmap.js +98 -16
  30. package/dist/shaders/heatmap.js.map +2 -2
  31. package/dist/shaders/image-dithering.d.ts +24 -15
  32. package/dist/shaders/image-dithering.js +68 -37
  33. package/dist/shaders/image-dithering.js.map +2 -2
  34. package/dist/shaders/liquid-metal.d.ts +38 -14
  35. package/dist/shaders/liquid-metal.js.map +2 -2
  36. package/dist/shaders/mesh-gradient.d.ts +27 -8
  37. package/dist/shaders/mesh-gradient.js +6 -6
  38. package/dist/shaders/mesh-gradient.js.map +2 -2
  39. package/dist/shaders/metaballs.d.ts +24 -8
  40. package/dist/shaders/metaballs.js.map +2 -2
  41. package/dist/shaders/neuro-noise.d.ts +27 -5
  42. package/dist/shaders/neuro-noise.js.map +2 -2
  43. package/dist/shaders/paper-texture.d.ts +37 -12
  44. package/dist/shaders/paper-texture.js +18 -18
  45. package/dist/shaders/paper-texture.js.map +2 -2
  46. package/dist/shaders/perlin-noise.d.ts +27 -8
  47. package/dist/shaders/perlin-noise.js +5 -5
  48. package/dist/shaders/perlin-noise.js.map +2 -2
  49. package/dist/shaders/pulsing-border.d.ts +39 -13
  50. package/dist/shaders/pulsing-border.js +5 -5
  51. package/dist/shaders/pulsing-border.js.map +2 -2
  52. package/dist/shaders/simplex-noise.d.ts +25 -6
  53. package/dist/shaders/simplex-noise.js +19 -19
  54. package/dist/shaders/simplex-noise.js.map +2 -2
  55. package/dist/shaders/smoke-ring.d.ts +29 -7
  56. package/dist/shaders/smoke-ring.js.map +2 -2
  57. package/dist/shaders/spiral.d.ts +30 -10
  58. package/dist/shaders/spiral.js +2 -2
  59. package/dist/shaders/spiral.js.map +2 -2
  60. package/dist/shaders/static-mesh-gradient.d.ts +30 -9
  61. package/dist/shaders/static-mesh-gradient.js +3 -3
  62. package/dist/shaders/static-mesh-gradient.js.map +2 -2
  63. package/dist/shaders/static-radial-gradient.d.ts +33 -11
  64. package/dist/shaders/static-radial-gradient.js +8 -8
  65. package/dist/shaders/static-radial-gradient.js.map +2 -2
  66. package/dist/shaders/swirl.d.ts +29 -8
  67. package/dist/shaders/swirl.js +2 -2
  68. package/dist/shaders/swirl.js.map +2 -2
  69. package/dist/shaders/voronoi.d.ts +31 -10
  70. package/dist/shaders/voronoi.js +6 -6
  71. package/dist/shaders/voronoi.js.map +2 -2
  72. package/dist/shaders/warp.d.ts +31 -13
  73. package/dist/shaders/warp.js +1 -1
  74. package/dist/shaders/warp.js.map +2 -2
  75. package/dist/shaders/water.d.ts +30 -10
  76. package/dist/shaders/water.js.map +2 -2
  77. package/dist/shaders/waves.d.ts +27 -12
  78. package/dist/shaders/waves.js +1 -1
  79. package/dist/shaders/waves.js.map +2 -2
  80. package/package.json +1 -1
@@ -4,9 +4,7 @@
4
4
  * * * * * * * * * * * * * * * * * * * * * * * * * * * */
5
5
 
6
6
  import {
7
- sizingUniformsDeclaration,
8
- sizingUV,
9
- drawSizingHelpers
7
+ sizingUniformsDeclaration
10
8
  } from "../shader-sizing.js";
11
9
  import { simplexNoise, declarePI, proceduralHash11, proceduralHash21 } from "../shader-utils.js";
12
10
  const ditheringFragmentShader = `#version 300 es
@@ -18,11 +16,11 @@ uniform float u_pixelRatio;
18
16
 
19
17
  ${sizingUniformsDeclaration}
20
18
 
19
+ uniform float u_pxSize;
21
20
  uniform vec4 u_colorBack;
22
21
  uniform vec4 u_colorFront;
23
22
  uniform float u_shape;
24
23
  uniform float u_type;
25
- uniform float u_pxSize;
26
24
 
27
25
  out vec4 fragColor;
28
26
 
@@ -40,21 +38,21 @@ float getSimplexNoise(vec2 uv, float t) {
40
38
 
41
39
  const int bayer2x2[4] = int[4](0, 2, 3, 1);
42
40
  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
41
+ 0, 8, 2, 10,
42
+ 12, 4, 14, 6,
43
+ 3, 11, 1, 9,
44
+ 15, 7, 13, 5
47
45
  );
48
46
 
49
47
  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
48
+ 0, 32, 8, 40, 2, 34, 10, 42,
49
+ 48, 16, 56, 24, 50, 18, 58, 26,
50
+ 12, 44, 4, 36, 14, 46, 6, 38,
51
+ 60, 28, 52, 20, 62, 30, 54, 22,
52
+ 3, 35, 11, 43, 1, 33, 9, 41,
53
+ 51, 19, 59, 27, 49, 17, 57, 25,
54
+ 15, 47, 7, 39, 13, 45, 5, 37,
55
+ 63, 31, 55, 23, 61, 29, 53, 21
58
56
  );
59
57
 
60
58
  float getBayerValue(vec2 uv, int size) {
@@ -75,69 +73,122 @@ float getBayerValue(vec2 uv, int size) {
75
73
  void main() {
76
74
  float t = .5 * u_time;
77
75
 
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;
76
+ float pxSize = u_pxSize * u_pixelRatio;
77
+ vec2 pxSizeUV = gl_FragCoord.xy - .5 * u_resolution;
78
+ pxSizeUV /= pxSize;
79
+ vec2 canvasPixelizedUV = (floor(pxSizeUV) + .5) * pxSize;
80
+ vec2 normalizedUV = canvasPixelizedUV / u_resolution;
81
+
82
+ vec2 ditheringNoiseUV = canvasPixelizedUV;
83
+ vec2 shapeUV = normalizedUV;
84
+
85
+ vec2 boxOrigin = vec2(.5 - u_originX, u_originY - .5);
86
+ vec2 givenBoxSize = vec2(u_worldWidth, u_worldHeight);
87
+ givenBoxSize = max(givenBoxSize, vec2(1.)) * u_pixelRatio;
88
+ float r = u_rotation * PI / 180.;
89
+ mat2 graphicRotation = mat2(cos(r), sin(r), -sin(r), cos(r));
90
+ vec2 graphicOffset = vec2(-u_offsetX, u_offsetY);
91
+
92
+ float patternBoxRatio = givenBoxSize.x / givenBoxSize.y;
93
+ vec2 boxSize = vec2(
94
+ (u_worldWidth == 0.) ? u_resolution.x : givenBoxSize.x,
95
+ (u_worldHeight == 0.) ? u_resolution.y : givenBoxSize.y
96
+ );
97
+
98
+ if (u_shape > 3.5) {
99
+ vec2 objectBoxSize = vec2(0.);
100
+ // fit = none
101
+ objectBoxSize.x = min(boxSize.x, boxSize.y);
102
+ if (u_fit == 1.) { // fit = contain
103
+ objectBoxSize.x = min(u_resolution.x, u_resolution.y);
104
+ } else if (u_fit == 2.) { // fit = cover
105
+ objectBoxSize.x = max(u_resolution.x, u_resolution.y);
106
+ }
107
+ objectBoxSize.y = objectBoxSize.x;
108
+ vec2 objectWorldScale = u_resolution.xy / objectBoxSize;
109
+
110
+ shapeUV *= objectWorldScale;
111
+ shapeUV += boxOrigin * (objectWorldScale - 1.);
112
+ shapeUV += vec2(-u_offsetX, u_offsetY);
113
+ shapeUV /= u_scale;
114
+ shapeUV = graphicRotation * shapeUV;
115
+ } else {
116
+ vec2 patternBoxSize = vec2(0.);
117
+ // fit = none
118
+ patternBoxSize.x = patternBoxRatio * min(boxSize.x / patternBoxRatio, boxSize.y);
119
+ float patternWorldNoFitBoxWidth = patternBoxSize.x;
120
+ if (u_fit == 1.) { // fit = contain
121
+ patternBoxSize.x = patternBoxRatio * min(u_resolution.x / patternBoxRatio, u_resolution.y);
122
+ } else if (u_fit == 2.) { // fit = cover
123
+ patternBoxSize.x = patternBoxRatio * max(u_resolution.x / patternBoxRatio, u_resolution.y);
124
+ }
125
+ patternBoxSize.y = patternBoxSize.x / patternBoxRatio;
126
+ vec2 patternWorldScale = u_resolution.xy / patternBoxSize;
127
+
128
+ shapeUV += vec2(-u_offsetX, u_offsetY) / patternWorldScale;
129
+ shapeUV += boxOrigin;
130
+ shapeUV -= boxOrigin / patternWorldScale;
131
+ shapeUV *= u_resolution.xy;
132
+ shapeUV /= u_pixelRatio;
133
+ if (u_fit > 0.) {
134
+ shapeUV *= (patternWorldNoFitBoxWidth / patternBoxSize.x);
135
+ }
136
+ shapeUV /= u_scale;
137
+ shapeUV = graphicRotation * shapeUV;
138
+ shapeUV += boxOrigin / patternWorldScale;
139
+ shapeUV -= boxOrigin;
140
+ shapeUV += .5;
90
141
  }
91
142
 
92
143
  float shape = 0.;
93
144
  if (u_shape < 1.5) {
94
145
  // Simplex noise
95
- shape_uv *= .001;
146
+ shapeUV *= .001;
96
147
 
97
- shape = 0.5 + 0.5 * getSimplexNoise(shape_uv, t);
148
+ shape = 0.5 + 0.5 * getSimplexNoise(shapeUV, t);
98
149
  shape = smoothstep(0.3, 0.9, shape);
99
150
 
100
151
  } else if (u_shape < 2.5) {
101
152
  // Warp
102
- shape_uv *= .003;
153
+ shapeUV *= .003;
103
154
 
104
155
  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);
156
+ shapeUV.x += 0.6 / i * cos(i * 2.5 * shapeUV.y + t);
157
+ shapeUV.y += 0.6 / i * cos(i * 1.5 * shapeUV.x + t);
107
158
  }
108
159
 
109
- shape = .15 / max(0.001, abs(sin(t - shape_uv.y - shape_uv.x)));
160
+ shape = .15 / max(0.001, abs(sin(t - shapeUV.y - shapeUV.x)));
110
161
  shape = smoothstep(0.02, 1., shape);
111
162
 
112
163
  } else if (u_shape < 3.5) {
113
164
  // Dots
114
- shape_uv *= .05;
165
+ shapeUV *= .05;
115
166
 
116
- float stripeIdx = floor(2. * shape_uv.x / TWO_PI);
167
+ float stripeIdx = floor(2. * shapeUV.x / TWO_PI);
117
168
  float rand = hash11(stripeIdx * 10.);
118
169
  rand = sign(rand - .5) * pow(.1 + abs(rand), .4);
119
- shape = sin(shape_uv.x) * cos(shape_uv.y - 5. * rand * t);
170
+ shape = sin(shapeUV.x) * cos(shapeUV.y - 5. * rand * t);
120
171
  shape = pow(abs(shape), 6.);
121
172
 
122
173
  } else if (u_shape < 4.5) {
123
174
  // Sine wave
124
- shape_uv *= 4.;
175
+ shapeUV *= 4.;
125
176
 
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);
177
+ float wave = cos(.5 * shapeUV.x - 2. * t) * sin(1.5 * shapeUV.x + t) * (.75 + .25 * cos(3. * t));
178
+ shape = 1. - smoothstep(-1., 1., shapeUV.y + wave);
128
179
 
129
180
  } else if (u_shape < 5.5) {
130
181
  // Ripple
131
182
 
132
- float dist = length(shape_uv);
183
+ float dist = length(shapeUV);
133
184
  float waves = sin(pow(dist, 1.7) * 7. - 3. * t) * .5 + .5;
134
185
  shape = waves;
135
186
 
136
187
  } else if (u_shape < 6.5) {
137
188
  // Swirl
138
189
 
139
- float l = length(shape_uv);
140
- float angle = 6. * atan(shape_uv.y, shape_uv.x) + 4. * t;
190
+ float l = length(shapeUV);
191
+ float angle = 6. * atan(shapeUV.y, shapeUV.x) + 4. * t;
141
192
  float twist = 1.2;
142
193
  float offset = 1. / pow(max(l, 1e-6), twist) + angle / TWO_PI;
143
194
  float mid = smoothstep(0., 1., pow(l, twist));
@@ -145,10 +196,10 @@ void main() {
145
196
 
146
197
  } else {
147
198
  // Sphere
148
- shape_uv *= 2.;
199
+ shapeUV *= 2.;
149
200
 
150
- float d = 1. - pow(length(shape_uv), 2.);
151
- vec3 pos = vec3(shape_uv, sqrt(max(0., d)));
201
+ float d = 1. - pow(length(shapeUV), 2.);
202
+ vec3 pos = vec3(shapeUV, sqrt(max(0., d)));
152
203
  vec3 lightPos = normalize(vec3(cos(1.5 * t), .8, sin(1.25 * t)));
153
204
  shape = .5 + .5 * dot(lightPos, pos);
154
205
  shape *= step(0., d);
@@ -160,17 +211,17 @@ void main() {
160
211
 
161
212
  switch (type) {
162
213
  case 1: {
163
- dithering = step(hash21(ditheringNoise_uv), shape);
214
+ dithering = step(hash21(ditheringNoiseUV), shape);
164
215
  } break;
165
216
  case 2:
166
- dithering = getBayerValue(dithering_uv, 2);
167
- break;
217
+ dithering = getBayerValue(pxSizeUV, 2);
218
+ break;
168
219
  case 3:
169
- dithering = getBayerValue(dithering_uv, 4);
170
- break;
171
- default:
172
- dithering = getBayerValue(dithering_uv, 8);
173
- break;
220
+ dithering = getBayerValue(pxSizeUV, 4);
221
+ break;
222
+ default :
223
+ dithering = getBayerValue(pxSizeUV, 8);
224
+ break;
174
225
  }
175
226
 
176
227
  dithering -= .5;
@@ -187,16 +238,6 @@ void main() {
187
238
  color += bgColor * (1. - opacity);
188
239
  opacity += bgOpacity * (1. - opacity);
189
240
 
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
241
  fragColor = vec4(color, opacity);
201
242
  }
202
243
  `;
@@ -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 sizingUniformsDeclaration,\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 * Great for retro, print-like, or stylized UI textures.\n *\n * Note: pixelization is applied to the shapes BEFORE dithering, meaning pixels don't react to scaling and fit\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_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; duplicate, not currently used)\n *\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 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,EACE;AAAA,OAGK;AACP,SAAS,cAAc,WAAW,kBAAkB,wBAAwB;AAqBrE,MAAM,0BAAkC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO5C,yBAA0B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAU1B,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;
@@ -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 { sizingVariablesDeclaration, 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\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;AAoCjC,MAAM,wBAAgC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAc1C,0BAA2B;AAAA;AAAA;AAAA;AAAA,EAI3B,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;
@@ -86,12 +86,12 @@ void main() {
86
86
  vec4 gradient = u_colors[0];
87
87
  gradient.rgb *= gradient.a;
88
88
  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);
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);
95
95
  }
96
96
 
97
97
  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 { 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 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\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;AAoCO,MAAM,yBAAiC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAQrB,aAAa,aAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOjD,0BAA2B;AAAA;AAAA;AAAA;AAAA,EAI3B,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;AAAA,wBAuDE,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
  }
@@ -1,26 +1,44 @@
1
1
  import type { ShaderMotionParams } from '../shader-mount.js';
2
2
  import { type ShaderSizingParams, type ShaderSizingUniforms } from '../shader-sizing.js';
3
3
  /**
4
- * Mimicking glass surface distortion over the image by distorting the texture
5
- * coordinates within line patterns
4
+ * Fluted glass image filter that transforms an image into streaked, ribbed distortions,
5
+ * giving a mix of clarity and obscurity.
6
6
  *
7
- * Uniforms:
8
- * - u_size, u_angle - size and direction of grid relative to the image
9
- * - u_shape (float used as integer):
10
- * ---- 1: uniformly spaced stripes
11
- * ---- 2: randomly spaced stripes
12
- * ---- 3: sine wave stripes
13
- * ---- 4: zigzag stripes
14
- * ---- 5: wave-based pattern
15
- * - u_distortion - the power of distortion applied along within each stripe
16
- * - u_distortionShape (float used as integer):
17
- * ---- 5 shapes available
18
- * - u_shift - texture shift in direction opposite to the grid
19
- * - u_blur - one-directional blur applied over the main distortion
20
- * - u_edges -
21
- * - u_marginLeft, u_marginRight, u_marginTop, u_marginBottom - paddings
22
- * within picture to be shown without any distortion
7
+ * Fragment shader uniforms:
8
+ * - u_resolution (vec2): Canvas resolution in pixels
9
+ * - u_pixelRatio (float): Device pixel ratio
10
+ * - u_originX (float): Reference point for positioning world width in the canvas (0 to 1)
11
+ * - u_originY (float): Reference point for positioning world height in the canvas (0 to 1)
12
+ * - u_fit (float): How to fit the rendered shader into the canvas dimensions (1 = contain, 2 = cover)
13
+ * - u_scale (float): Overall zoom level of the graphics (0.01 to 4)
14
+ * - u_rotation (float): Overall rotation angle of the graphics in degrees (0 to 360)
15
+ * - u_offsetX (float): Horizontal offset of the graphics center (-1 to 1)
16
+ * - u_offsetY (float): Vertical offset of the graphics center (-1 to 1)
17
+ * - u_image (sampler2D): Source image texture
18
+ * - u_imageAspectRatio (float): Aspect ratio of the source image
19
+ * - u_colorBack (vec4): Background color in RGBA
20
+ * - u_colorShadow (vec4): Shadows color in RGBA
21
+ * - u_colorHighlight (vec4): Highlights color in RGBA
22
+ * - u_shadows (float): Color gradient added over image and background, following distortion shape (0 to 1)
23
+ * - u_highlights (float): Thin strokes along distortion shape, useful for antialiasing on small grid (0 to 1)
24
+ * - u_size (float): Size of the distortion shape grid (0 to 1)
25
+ * - u_shape (float): Grid shape (1 = lines, 2 = linesIrregular, 3 = wave, 4 = zigzag, 5 = pattern)
26
+ * - u_angle (float): Direction of the grid relative to the image in degrees (0 to 180)
27
+ * - u_distortionShape (float): Shape of distortion (1 = prism, 2 = lens, 3 = contour, 4 = cascade, 5 = flat)
28
+ * - u_distortion (float): Power of distortion applied within each stripe (0 to 1)
29
+ * - u_shift (float): Texture shift in direction opposite to the grid (-1 to 1)
30
+ * - u_stretch (float): Extra distortion along the grid lines (0 to 1)
31
+ * - u_blur (float): One-directional blur over the image and extra blur around edges (0 to 1)
32
+ * - u_edges (float): Glass distortion and softness on the image edges (0 to 1)
33
+ * - u_marginLeft (float): Distance from the left edge to the effect (0 to 1)
34
+ * - u_marginRight (float): Distance from the right edge to the effect (0 to 1)
35
+ * - u_marginTop (float): Distance from the top edge to the effect (0 to 1)
36
+ * - u_marginBottom (float): Distance from the bottom edge to the effect (0 to 1)
37
+ * - u_grainMixer (float): Strength of grain distortion applied to shape edges (0 to 1)
38
+ * - u_grainOverlay (float): Post-processing black/white grain overlay (0 to 1)
23
39
  *
40
+ * Note: This shader calculates image UVs directly in the fragment shader using gl_FragCoord,
41
+ * rather than relying on vertex shader outputs.
24
42
  */
25
43
  export declare const flutedGlassFragmentShader: string;
26
44
  export interface FlutedGlassUniforms extends ShaderSizingUniforms {
@@ -132,7 +132,7 @@ vec4 getBlur(sampler2D tex, vec2 uv, vec2 texelSize, vec2 dir, float sigma) {
132
132
  if (result.a > 0.) {
133
133
  result.rgb /= result.a;
134
134
  }
135
-
135
+
136
136
  return result;
137
137
  }
138
138
 
@@ -167,10 +167,10 @@ void main() {
167
167
  vec2 sw = vec2(.005);
168
168
  vec4 margins = vec4(u_marginLeft, u_marginTop, u_marginRight, u_marginBottom);
169
169
  float mask =
170
- smoothstep(margins[0], margins[0] + sw.x, uvMask.x + sw.x) *
171
- smoothstep(margins[2], margins[2] + sw.x, 1.0 - uvMask.x + sw.x) *
172
- smoothstep(margins[1], margins[1] + sw.y, uvMask.y + sw.y) *
173
- smoothstep(margins[3], margins[3] + sw.y, 1.0 - uvMask.y + sw.y);
170
+ smoothstep(margins[0], margins[0] + sw.x, uvMask.x + sw.x) *
171
+ smoothstep(margins[2], margins[2] + sw.x, 1.0 - uvMask.x + sw.x) *
172
+ smoothstep(margins[1], margins[1] + sw.y, uvMask.y + sw.y) *
173
+ smoothstep(margins[3], margins[3] + sw.y, 1.0 - uvMask.y + sw.y);
174
174
  float maskOuter =
175
175
  smoothstep(margins[0] - sw.x, margins[0], uvMask.x + sw.x) *
176
176
  smoothstep(margins[2] - sw.x, margins[2], 1.0 - uvMask.x + sw.x) *
@@ -178,10 +178,10 @@ void main() {
178
178
  smoothstep(margins[3] - sw.y, margins[3], 1.0 - uvMask.y + sw.y);
179
179
  float maskStroke = maskOuter - mask;
180
180
  float maskInner =
181
- smoothstep(margins[0] - 2. * sw.x, margins[0], uvMask.x) *
182
- smoothstep(margins[2] - 2. * sw.x, margins[2], 1.0 - uvMask.x) *
183
- smoothstep(margins[1] - 2. * sw.y, margins[1], uvMask.y) *
184
- smoothstep(margins[3] - 2. * sw.y, margins[3], 1.0 - uvMask.y);
181
+ smoothstep(margins[0] - 2. * sw.x, margins[0], uvMask.x) *
182
+ smoothstep(margins[2] - 2. * sw.x, margins[2], 1.0 - uvMask.x) *
183
+ smoothstep(margins[1] - 2. * sw.y, margins[1], uvMask.y) *
184
+ smoothstep(margins[3] - 2. * sw.y, margins[3], 1.0 - uvMask.y);
185
185
  float maskStrokeInner = maskInner - mask;
186
186
 
187
187
  uv -= .5;