shaders-oneshot 0.0.81-shared.1

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 (129) hide show
  1. package/LICENSE +201 -0
  2. package/NOTICE +5 -0
  3. package/README.md +7 -0
  4. package/dist/empty-pixel.d.ts +1 -0
  5. package/dist/empty-pixel.js +10 -0
  6. package/dist/empty-pixel.js.map +7 -0
  7. package/dist/get-shader-color-from-string.d.ts +3 -0
  8. package/dist/get-shader-color-from-string.js +101 -0
  9. package/dist/get-shader-color-from-string.js.map +7 -0
  10. package/dist/get-shader-color-from-string.test.d.ts +1 -0
  11. package/dist/get-shader-color-from-string.test.js +69 -0
  12. package/dist/get-shader-noise-texture.d.ts +1 -0
  13. package/dist/get-shader-noise-texture.js +18 -0
  14. package/dist/get-shader-noise-texture.js.map +7 -0
  15. package/dist/index.d.ts +68 -0
  16. package/dist/index.js +194 -0
  17. package/dist/index.js.map +7 -0
  18. package/dist/shader-color-spaces.d.ts +6 -0
  19. package/dist/shader-color-spaces.js +96 -0
  20. package/dist/shader-color-spaces.js.map +7 -0
  21. package/dist/shader-mount.d.ts +199 -0
  22. package/dist/shader-mount.js +735 -0
  23. package/dist/shader-mount.js.map +7 -0
  24. package/dist/shader-sizing.d.ts +30 -0
  25. package/dist/shader-sizing.js +38 -0
  26. package/dist/shader-sizing.js.map +7 -0
  27. package/dist/shader-utils.d.ts +10 -0
  28. package/dist/shader-utils.js +131 -0
  29. package/dist/shader-utils.js.map +7 -0
  30. package/dist/shaders/color-panels.d.ts +70 -0
  31. package/dist/shaders/color-panels.js +224 -0
  32. package/dist/shaders/color-panels.js.map +7 -0
  33. package/dist/shaders/dithering.d.ts +62 -0
  34. package/dist/shaders/dithering.js +271 -0
  35. package/dist/shaders/dithering.js.map +7 -0
  36. package/dist/shaders/dot-grid.d.ts +65 -0
  37. package/dist/shaders/dot-grid.js +110 -0
  38. package/dist/shaders/dot-grid.js.map +7 -0
  39. package/dist/shaders/dot-orbit.d.ts +57 -0
  40. package/dist/shaders/dot-orbit.js +123 -0
  41. package/dist/shaders/dot-orbit.js.map +7 -0
  42. package/dist/shaders/fluted-glass.d.ts +112 -0
  43. package/dist/shaders/fluted-glass.js +361 -0
  44. package/dist/shaders/fluted-glass.js.map +7 -0
  45. package/dist/shaders/gem-smoke.d.ts +96 -0
  46. package/dist/shaders/gem-smoke.js +573 -0
  47. package/dist/shaders/gem-smoke.js.map +7 -0
  48. package/dist/shaders/god-rays.d.ts +67 -0
  49. package/dist/shaders/god-rays.js +133 -0
  50. package/dist/shaders/god-rays.js.map +7 -0
  51. package/dist/shaders/grain-gradient.d.ts +80 -0
  52. package/dist/shaders/grain-gradient.js +301 -0
  53. package/dist/shaders/grain-gradient.js.map +7 -0
  54. package/dist/shaders/halftone-cmyk.d.ts +104 -0
  55. package/dist/shaders/halftone-cmyk.js +295 -0
  56. package/dist/shaders/halftone-cmyk.js.map +7 -0
  57. package/dist/shaders/halftone-dots.d.ts +80 -0
  58. package/dist/shaders/halftone-dots.js +321 -0
  59. package/dist/shaders/halftone-dots.js.map +7 -0
  60. package/dist/shaders/heatmap.d.ts +66 -0
  61. package/dist/shaders/heatmap.js +384 -0
  62. package/dist/shaders/heatmap.js.map +7 -0
  63. package/dist/shaders/image-dithering.d.ts +64 -0
  64. package/dist/shaders/image-dithering.js +199 -0
  65. package/dist/shaders/image-dithering.js.map +7 -0
  66. package/dist/shaders/lens-distortion.d.ts +97 -0
  67. package/dist/shaders/lens-distortion.js +276 -0
  68. package/dist/shaders/lens-distortion.js.map +7 -0
  69. package/dist/shaders/liquid-metal.d.ts +89 -0
  70. package/dist/shaders/liquid-metal.js +633 -0
  71. package/dist/shaders/liquid-metal.js.map +7 -0
  72. package/dist/shaders/mesh-gradient.d.ts +52 -0
  73. package/dist/shaders/mesh-gradient.js +131 -0
  74. package/dist/shaders/mesh-gradient.js.map +7 -0
  75. package/dist/shaders/metaballs.d.ts +51 -0
  76. package/dist/shaders/metaballs.js +111 -0
  77. package/dist/shaders/metaballs.js.map +7 -0
  78. package/dist/shaders/neuro-noise.d.ts +47 -0
  79. package/dist/shaders/neuro-noise.js +77 -0
  80. package/dist/shaders/neuro-noise.js.map +7 -0
  81. package/dist/shaders/paper-texture.d.ts +109 -0
  82. package/dist/shaders/paper-texture.js +527 -0
  83. package/dist/shaders/paper-texture.js.map +7 -0
  84. package/dist/shaders/perlin-noise.d.ts +52 -0
  85. package/dist/shaders/perlin-noise.js +167 -0
  86. package/dist/shaders/perlin-noise.js.map +7 -0
  87. package/dist/shaders/pulsing-border.d.ts +98 -0
  88. package/dist/shaders/pulsing-border.js +239 -0
  89. package/dist/shaders/pulsing-border.js.map +7 -0
  90. package/dist/shaders/simplex-noise.d.ts +45 -0
  91. package/dist/shaders/simplex-noise.js +92 -0
  92. package/dist/shaders/simplex-noise.js.map +7 -0
  93. package/dist/shaders/smoke-ring.d.ts +61 -0
  94. package/dist/shaders/smoke-ring.js +133 -0
  95. package/dist/shaders/smoke-ring.js.map +7 -0
  96. package/dist/shaders/spiral.d.ts +61 -0
  97. package/dist/shaders/spiral.js +83 -0
  98. package/dist/shaders/spiral.js.map +7 -0
  99. package/dist/shaders/static-mesh-gradient.d.ts +63 -0
  100. package/dist/shaders/static-mesh-gradient.js +131 -0
  101. package/dist/shaders/static-mesh-gradient.js.map +7 -0
  102. package/dist/shaders/static-radial-gradient.d.ts +72 -0
  103. package/dist/shaders/static-radial-gradient.js +188 -0
  104. package/dist/shaders/static-radial-gradient.js.map +7 -0
  105. package/dist/shaders/swirl.d.ts +63 -0
  106. package/dist/shaders/swirl.js +104 -0
  107. package/dist/shaders/swirl.js.map +7 -0
  108. package/dist/shaders/voronoi.d.ts +65 -0
  109. package/dist/shaders/voronoi.js +139 -0
  110. package/dist/shaders/voronoi.js.map +7 -0
  111. package/dist/shaders/warp.d.ts +70 -0
  112. package/dist/shaders/warp.js +130 -0
  113. package/dist/shaders/warp.js.map +7 -0
  114. package/dist/shaders/water.d.ts +59 -0
  115. package/dist/shaders/water.js +122 -0
  116. package/dist/shaders/water.js.map +7 -0
  117. package/dist/shaders/waves.d.ts +53 -0
  118. package/dist/shaders/waves.js +66 -0
  119. package/dist/shaders/waves.js.map +7 -0
  120. package/dist/shared-webgl-renderer.d.ts +63 -0
  121. package/dist/shared-webgl-renderer.js +262 -0
  122. package/dist/shared-webgl-renderer.js.map +7 -0
  123. package/dist/types.d.ts +3 -0
  124. package/dist/types.js +6 -0
  125. package/dist/types.js.map +7 -0
  126. package/dist/vertex-shader.d.ts +2 -0
  127. package/dist/vertex-shader.js +160 -0
  128. package/dist/vertex-shader.js.map +7 -0
  129. package/package.json +29 -0
@@ -0,0 +1,224 @@
1
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * *
2
+ * Paper Shaders *
3
+ * https://github.com/paper-design/shaders *
4
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * */
5
+
6
+ import {} from "../shader-sizing.js";
7
+ import { declarePI, colorBandingFix } from "../shader-utils.js";
8
+ const colorPanelsMeta = {
9
+ maxColorCount: 7
10
+ };
11
+ const colorPanelsFragmentShader = `#version 300 es
12
+ precision lowp float;
13
+
14
+ uniform float u_time;
15
+ uniform mediump float u_scale;
16
+
17
+ uniform vec4 u_colors[${colorPanelsMeta.maxColorCount}];
18
+ uniform float u_colorsCount;
19
+ uniform vec4 u_colorBack;
20
+ uniform float u_density;
21
+ uniform float u_angle1;
22
+ uniform float u_angle2;
23
+ uniform float u_length;
24
+ uniform bool u_edges;
25
+ uniform float u_blur;
26
+ uniform float u_fadeIn;
27
+ uniform float u_fadeOut;
28
+ uniform float u_gradient;
29
+
30
+ in vec2 v_objectUV;
31
+
32
+ out vec4 fragColor;
33
+
34
+ ${declarePI}
35
+
36
+ const float zLimit = .5;
37
+
38
+ vec2 getPanel(float angle, vec2 uv, float invLength, float aa) {
39
+ float sinA = sin(angle);
40
+ float cosA = cos(angle);
41
+
42
+ float denom = sinA - uv.y * cosA;
43
+ if (abs(denom) < .01) return vec2(0.);
44
+
45
+ float z = uv.y / denom;
46
+
47
+ if (z <= 0. || z > zLimit) return vec2(0.);
48
+
49
+ float zRatio = z / zLimit;
50
+ float panelMap = 1. - zRatio;
51
+ float x = uv.x * (cosA * z + 1.) * invLength;
52
+
53
+ float zOffset = zRatio - .5;
54
+ float left = -.5 + zOffset * u_angle1;
55
+ float right = .5 - zOffset * u_angle2;
56
+ float blurX = aa + 2. * panelMap * u_blur;
57
+
58
+ float leftEdge1 = left - blurX;
59
+ float leftEdge2 = left + .25 * blurX;
60
+ float rightEdge1 = right - .25 * blurX;
61
+ float rightEdge2 = right + blurX;
62
+
63
+ float panel = smoothstep(leftEdge1, leftEdge2, x) * (1.0 - smoothstep(rightEdge1, rightEdge2, x));
64
+ panel *= mix(0., panel, smoothstep(0., .01 / u_scale, panelMap));
65
+
66
+ float midScreen = abs(sinA);
67
+ if (u_edges == true) {
68
+ panelMap = mix(.99, panelMap, panel * clamp(panelMap / (.15 * (1. - pow(midScreen, .1))), 0.0, 1.0));
69
+ } else if (midScreen < .07) {
70
+ panel *= (midScreen * 15.);
71
+ }
72
+
73
+ return vec2(panel, panelMap);
74
+ }
75
+
76
+ vec4 blendColor(vec4 colorA, float panelMask, float panelMap) {
77
+ float fade = 1. - smoothstep(.97 - .97 * u_fadeIn, 1., panelMap);
78
+
79
+ fade *= smoothstep(-.2 * (1. - u_fadeOut), u_fadeOut, panelMap);
80
+
81
+ vec3 blendedRGB = mix(vec3(0.), colorA.rgb, fade);
82
+ float blendedAlpha = mix(0., colorA.a, fade);
83
+
84
+ return vec4(blendedRGB, blendedAlpha) * panelMask;
85
+ }
86
+
87
+ void main() {
88
+ vec2 uv = v_objectUV;
89
+ uv *= 1.25;
90
+
91
+ float t = .02 * u_time;
92
+ t = fract(t);
93
+ bool reverseTime = (t < 0.5);
94
+
95
+ vec3 color = vec3(0.);
96
+ float opacity = 0.;
97
+
98
+ float aa = .005 / u_scale;
99
+ int colorsCount = int(u_colorsCount);
100
+
101
+ vec4 premultipliedColors[${colorPanelsMeta.maxColorCount}];
102
+ for (int i = 0; i < ${colorPanelsMeta.maxColorCount}; i++) {
103
+ if (i >= colorsCount) break;
104
+ vec4 c = u_colors[i];
105
+ c.rgb *= c.a;
106
+ premultipliedColors[i] = c;
107
+ }
108
+
109
+ float invLength = 1.5 / max(u_length, .001);
110
+
111
+ float totalColorWeight = 0.;
112
+ int panelsNumber = 12;
113
+
114
+ float densityNormalizer = 1.;
115
+ if (colorsCount == 4) {
116
+ panelsNumber = 16;
117
+ densityNormalizer = 1.34;
118
+ } else if (colorsCount == 5) {
119
+ panelsNumber = 20;
120
+ densityNormalizer = 1.67;
121
+ } else if (colorsCount == 7) {
122
+ panelsNumber = 14;
123
+ densityNormalizer = 1.17;
124
+ }
125
+
126
+ float fPanelsNumber = float(panelsNumber);
127
+
128
+ float totalPanelsShape = 0.;
129
+ float panelGrad = 1. - clamp(u_gradient, 0., 1.);
130
+
131
+ for (int set = 0; set < 2; set++) {
132
+ bool isForward = (set == 0 && !reverseTime) || (set == 1 && reverseTime);
133
+ if (!isForward) continue;
134
+
135
+ for (int i = 0; i <= 20; i++) {
136
+ if (i >= panelsNumber) break;
137
+
138
+ int idx = panelsNumber - 1 - i;
139
+
140
+ float offset = float(idx) / fPanelsNumber;
141
+ if (set == 1) {
142
+ offset += .5;
143
+ }
144
+
145
+ float densityFract = densityNormalizer * fract(t + offset);
146
+ float angleNorm = densityFract / u_density;
147
+ if (densityFract >= .5 || angleNorm >= .3) continue;
148
+
149
+ float smoothDensity = clamp((.5 - densityFract) / .1, 0., 1.) * clamp(densityFract / .01, 0., 1.);
150
+ float smoothAngle = clamp((.3 - angleNorm) / .05, 0., 1.);
151
+ if (smoothDensity * smoothAngle < .001) continue;
152
+
153
+ if (angleNorm > .5) {
154
+ angleNorm = 0.5;
155
+ }
156
+ vec2 panel = getPanel(angleNorm * TWO_PI + PI, uv, invLength, aa);
157
+ if (panel[0] <= .001) continue;
158
+ float panelMask = panel[0] * smoothDensity * smoothAngle;
159
+ float panelMap = panel[1];
160
+
161
+ int colorIdx = idx % colorsCount;
162
+ int nextColorIdx = (idx + 1) % colorsCount;
163
+
164
+ vec4 colorA = premultipliedColors[colorIdx];
165
+ vec4 colorB = premultipliedColors[nextColorIdx];
166
+
167
+ colorA = mix(colorA, colorB, max(0., smoothstep(.0, .45, panelMap) - panelGrad));
168
+ vec4 blended = blendColor(colorA, panelMask, panelMap);
169
+ color = blended.rgb + color * (1. - blended.a);
170
+ opacity = blended.a + opacity * (1. - blended.a);
171
+ }
172
+
173
+
174
+ for (int i = 0; i <= 20; i++) {
175
+ if (i >= panelsNumber) break;
176
+
177
+ int idx = panelsNumber - 1 - i;
178
+
179
+ float offset = float(idx) / fPanelsNumber;
180
+ if (set == 0) {
181
+ offset += .5;
182
+ }
183
+
184
+ float densityFract = densityNormalizer * fract(-t + offset);
185
+ float angleNorm = -densityFract / u_density;
186
+ if (densityFract >= .5 || angleNorm < -.3) continue;
187
+
188
+ float smoothDensity = clamp((.5 - densityFract) / .1, 0., 1.) * clamp(densityFract / .01, 0., 1.);
189
+ float smoothAngle = clamp((angleNorm + .3) / .05, 0., 1.);
190
+ if (smoothDensity * smoothAngle < .001) continue;
191
+
192
+ vec2 panel = getPanel(angleNorm * TWO_PI + PI, uv, invLength, aa);
193
+ float panelMask = panel[0] * smoothDensity * smoothAngle;
194
+ if (panelMask <= .001) continue;
195
+ float panelMap = panel[1];
196
+
197
+ int colorIdx = (colorsCount - (idx % colorsCount)) % colorsCount;
198
+ if (colorIdx < 0) colorIdx += colorsCount;
199
+ int nextColorIdx = (colorIdx + 1) % colorsCount;
200
+
201
+ vec4 colorA = premultipliedColors[colorIdx];
202
+ vec4 colorB = premultipliedColors[nextColorIdx];
203
+
204
+ colorA = mix(colorA, colorB, max(0., smoothstep(.0, .45, panelMap) - panelGrad));
205
+ vec4 blended = blendColor(colorA, panelMask, panelMap);
206
+ color = blended.rgb + color * (1. - blended.a);
207
+ opacity = blended.a + opacity * (1. - blended.a);
208
+ }
209
+ }
210
+
211
+ vec3 bgColor = u_colorBack.rgb * u_colorBack.a;
212
+ color = color + bgColor * (1.0 - opacity);
213
+ opacity = opacity + u_colorBack.a * (1.0 - opacity);
214
+
215
+ ${colorBandingFix}
216
+
217
+ fragColor = vec4(color, opacity);
218
+ }
219
+ `;
220
+ export {
221
+ colorPanelsFragmentShader,
222
+ colorPanelsMeta
223
+ };
224
+ //# sourceMappingURL=color-panels.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/shaders/color-panels.ts"],
4
+ "sourcesContent": ["import type { vec4 } from '../types.js';\r\nimport type { ShaderMotionParams } from '../shader-mount.js';\r\nimport { type ShaderSizingParams, type ShaderSizingUniforms } from '../shader-sizing.js';\r\nimport { declarePI, colorBandingFix } from '../shader-utils.js';\r\n\r\nexport const colorPanelsMeta = {\r\n maxColorCount: 7,\r\n} as const;\r\n\r\n/**\r\n * Pseudo-3D semi-transparent panels rotating around a central axis\r\n *\r\n * Fragment shader uniforms:\r\n * - u_time (float): Animation time\r\n * - u_scale (float): Overall zoom level, used for anti-aliasing calculations\r\n * - u_colors (vec4[]): Up to 7 RGBA colors used to color the panels\r\n * - u_colorsCount (float): Number of active colors\r\n * - u_colorBack (vec4): Background color in RGBA\r\n * - u_density (float): Angle between every 2 panels (0.25 to 7)\r\n * - u_angle1 (float): Skew angle applied to all panes (-1 to 1)\r\n * - u_angle2 (float): Skew angle applied to all panes (-1 to 1)\r\n * - u_length (float): Panel length relative to total height (0 to 3)\r\n * - u_edges (bool): Color highlight on the panels edges\r\n * - u_blur (float): Side blur, 0 for sharp edges (0 to 0.5)\r\n * - u_fadeIn (float): Transparency near central axis (0 to 1)\r\n * - u_fadeOut (float): Transparency near viewer (0 to 1)\r\n * - u_gradient (float): Color mixing within a panel, 0 = solid, 1 = gradient, needs 2+ colors (0 to 1)\r\n *\r\n * Vertex shader outputs (used in fragment shader):\r\n * - v_objectUV (vec2): Object box UV coordinates with global sizing (scale, rotation, offsets, etc) applied\r\n *\r\n * Vertex shader uniforms:\r\n * - u_resolution (vec2): Canvas resolution in pixels\r\n * - u_pixelRatio (float): Device pixel ratio\r\n * - u_originX (float): Reference point for positioning world width in the canvas (0 to 1)\r\n * - u_originY (float): Reference point for positioning world height in the canvas (0 to 1)\r\n * - u_worldWidth (float): Virtual width of the graphic before it's scaled to fit the canvas\r\n * - u_worldHeight (float): Virtual height of the graphic before it's scaled to fit the canvas\r\n * - u_fit (float): How to fit the rendered shader into the canvas dimensions (0 = none, 1 = contain, 2 = cover)\r\n * - u_scale (float): Overall zoom level of the graphics (0.01 to 4)\r\n * - u_rotation (float): Overall rotation angle of the graphics in degrees (0 to 360)\r\n * - u_offsetX (float): Horizontal offset of the graphics center (-1 to 1)\r\n * - u_offsetY (float): Vertical offset of the graphics center (-1 to 1)\r\n *\r\n */\r\n\r\n// language=GLSL\r\nexport const colorPanelsFragmentShader: string = `#version 300 es\r\nprecision lowp float;\r\n\r\nuniform float u_time;\r\nuniform mediump float u_scale;\r\n\r\nuniform vec4 u_colors[${ colorPanelsMeta.maxColorCount }];\r\nuniform float u_colorsCount;\r\nuniform vec4 u_colorBack;\r\nuniform float u_density;\r\nuniform float u_angle1;\r\nuniform float u_angle2;\r\nuniform float u_length;\r\nuniform bool u_edges;\r\nuniform float u_blur;\r\nuniform float u_fadeIn;\r\nuniform float u_fadeOut;\r\nuniform float u_gradient;\r\n\r\nin vec2 v_objectUV;\r\n\r\nout vec4 fragColor;\r\n\r\n${ declarePI }\r\n\r\nconst float zLimit = .5;\r\n\r\nvec2 getPanel(float angle, vec2 uv, float invLength, float aa) {\r\n float sinA = sin(angle);\r\n float cosA = cos(angle);\r\n\r\n float denom = sinA - uv.y * cosA;\r\n if (abs(denom) < .01) return vec2(0.);\r\n\r\n float z = uv.y / denom;\r\n\r\n if (z <= 0. || z > zLimit) return vec2(0.);\r\n\r\n float zRatio = z / zLimit;\r\n float panelMap = 1. - zRatio;\r\n float x = uv.x * (cosA * z + 1.) * invLength;\r\n\r\n float zOffset = zRatio - .5;\r\n float left = -.5 + zOffset * u_angle1;\r\n float right = .5 - zOffset * u_angle2;\r\n float blurX = aa + 2. * panelMap * u_blur;\r\n\r\n float leftEdge1 = left - blurX;\r\n float leftEdge2 = left + .25 * blurX;\r\n float rightEdge1 = right - .25 * blurX;\r\n float rightEdge2 = right + blurX;\r\n\r\n float panel = smoothstep(leftEdge1, leftEdge2, x) * (1.0 - smoothstep(rightEdge1, rightEdge2, x));\r\n panel *= mix(0., panel, smoothstep(0., .01 / u_scale, panelMap));\r\n\r\n float midScreen = abs(sinA);\r\n if (u_edges == true) {\r\n panelMap = mix(.99, panelMap, panel * clamp(panelMap / (.15 * (1. - pow(midScreen, .1))), 0.0, 1.0));\r\n } else if (midScreen < .07) {\r\n panel *= (midScreen * 15.);\r\n }\r\n\r\n return vec2(panel, panelMap);\r\n}\r\n\r\nvec4 blendColor(vec4 colorA, float panelMask, float panelMap) {\r\n float fade = 1. - smoothstep(.97 - .97 * u_fadeIn, 1., panelMap);\r\n\r\n fade *= smoothstep(-.2 * (1. - u_fadeOut), u_fadeOut, panelMap);\r\n\r\n vec3 blendedRGB = mix(vec3(0.), colorA.rgb, fade);\r\n float blendedAlpha = mix(0., colorA.a, fade);\r\n\r\n return vec4(blendedRGB, blendedAlpha) * panelMask;\r\n}\r\n\r\nvoid main() {\r\n vec2 uv = v_objectUV;\r\n uv *= 1.25;\r\n\r\n float t = .02 * u_time;\r\n t = fract(t);\r\n bool reverseTime = (t < 0.5);\r\n\r\n vec3 color = vec3(0.);\r\n float opacity = 0.;\r\n\r\n float aa = .005 / u_scale;\r\n int colorsCount = int(u_colorsCount);\r\n\r\n vec4 premultipliedColors[${ colorPanelsMeta.maxColorCount }];\r\n for (int i = 0; i < ${ colorPanelsMeta.maxColorCount }; i++) {\r\n if (i >= colorsCount) break;\r\n vec4 c = u_colors[i];\r\n c.rgb *= c.a;\r\n premultipliedColors[i] = c;\r\n }\r\n\r\n float invLength = 1.5 / max(u_length, .001);\r\n\r\n float totalColorWeight = 0.;\r\n int panelsNumber = 12;\r\n\r\n float densityNormalizer = 1.;\r\n if (colorsCount == 4) {\r\n panelsNumber = 16;\r\n densityNormalizer = 1.34;\r\n } else if (colorsCount == 5) {\r\n panelsNumber = 20;\r\n densityNormalizer = 1.67;\r\n } else if (colorsCount == 7) {\r\n panelsNumber = 14;\r\n densityNormalizer = 1.17;\r\n }\r\n\r\n float fPanelsNumber = float(panelsNumber);\r\n\r\n float totalPanelsShape = 0.;\r\n float panelGrad = 1. - clamp(u_gradient, 0., 1.);\r\n\r\n for (int set = 0; set < 2; set++) {\r\n bool isForward = (set == 0 && !reverseTime) || (set == 1 && reverseTime);\r\n if (!isForward) continue;\r\n\r\n for (int i = 0; i <= 20; i++) {\r\n if (i >= panelsNumber) break;\r\n\r\n int idx = panelsNumber - 1 - i;\r\n\r\n float offset = float(idx) / fPanelsNumber;\r\n if (set == 1) {\r\n offset += .5;\r\n }\r\n\r\n float densityFract = densityNormalizer * fract(t + offset);\r\n float angleNorm = densityFract / u_density;\r\n if (densityFract >= .5 || angleNorm >= .3) continue;\r\n\r\n float smoothDensity = clamp((.5 - densityFract) / .1, 0., 1.) * clamp(densityFract / .01, 0., 1.);\r\n float smoothAngle = clamp((.3 - angleNorm) / .05, 0., 1.);\r\n if (smoothDensity * smoothAngle < .001) continue;\r\n\r\n if (angleNorm > .5) {\r\n angleNorm = 0.5;\r\n }\r\n vec2 panel = getPanel(angleNorm * TWO_PI + PI, uv, invLength, aa);\r\n if (panel[0] <= .001) continue;\r\n float panelMask = panel[0] * smoothDensity * smoothAngle;\r\n float panelMap = panel[1];\r\n\r\n int colorIdx = idx % colorsCount;\r\n int nextColorIdx = (idx + 1) % colorsCount;\r\n\r\n vec4 colorA = premultipliedColors[colorIdx];\r\n vec4 colorB = premultipliedColors[nextColorIdx];\r\n\r\n colorA = mix(colorA, colorB, max(0., smoothstep(.0, .45, panelMap) - panelGrad));\r\n vec4 blended = blendColor(colorA, panelMask, panelMap);\r\n color = blended.rgb + color * (1. - blended.a);\r\n opacity = blended.a + opacity * (1. - blended.a);\r\n }\r\n\r\n\r\n for (int i = 0; i <= 20; i++) {\r\n if (i >= panelsNumber) break;\r\n\r\n int idx = panelsNumber - 1 - i;\r\n\r\n float offset = float(idx) / fPanelsNumber;\r\n if (set == 0) {\r\n offset += .5;\r\n }\r\n\r\n float densityFract = densityNormalizer * fract(-t + offset);\r\n float angleNorm = -densityFract / u_density;\r\n if (densityFract >= .5 || angleNorm < -.3) continue;\r\n\r\n float smoothDensity = clamp((.5 - densityFract) / .1, 0., 1.) * clamp(densityFract / .01, 0., 1.);\r\n float smoothAngle = clamp((angleNorm + .3) / .05, 0., 1.);\r\n if (smoothDensity * smoothAngle < .001) continue;\r\n\r\n vec2 panel = getPanel(angleNorm * TWO_PI + PI, uv, invLength, aa);\r\n float panelMask = panel[0] * smoothDensity * smoothAngle;\r\n if (panelMask <= .001) continue;\r\n float panelMap = panel[1];\r\n\r\n int colorIdx = (colorsCount - (idx % colorsCount)) % colorsCount;\r\n if (colorIdx < 0) colorIdx += colorsCount;\r\n int nextColorIdx = (colorIdx + 1) % colorsCount;\r\n\r\n vec4 colorA = premultipliedColors[colorIdx];\r\n vec4 colorB = premultipliedColors[nextColorIdx];\r\n\r\n colorA = mix(colorA, colorB, max(0., smoothstep(.0, .45, panelMap) - panelGrad));\r\n vec4 blended = blendColor(colorA, panelMask, panelMap);\r\n color = blended.rgb + color * (1. - blended.a);\r\n opacity = blended.a + opacity * (1. - blended.a);\r\n }\r\n }\r\n\r\n vec3 bgColor = u_colorBack.rgb * u_colorBack.a;\r\n color = color + bgColor * (1.0 - opacity);\r\n opacity = opacity + u_colorBack.a * (1.0 - opacity);\r\n\r\n ${ colorBandingFix }\r\n\r\n fragColor = vec4(color, opacity);\r\n}\r\n`;\r\n\r\nexport interface ColorPanelsUniforms extends ShaderSizingUniforms {\r\n u_colors: vec4[];\r\n u_colorsCount: number;\r\n u_colorBack: [number, number, number, number];\r\n u_angle1: number;\r\n u_angle2: number;\r\n u_length: number;\r\n u_edges: boolean;\r\n u_blur: number;\r\n u_fadeIn: number;\r\n u_fadeOut: number;\r\n u_density: number;\r\n u_gradient: number;\r\n}\r\n\r\nexport interface ColorPanelsParams extends ShaderSizingParams, ShaderMotionParams {\r\n colors?: string[];\r\n colorBack?: string;\r\n angle1?: number;\r\n angle2?: number;\r\n length?: number;\r\n edges?: boolean;\r\n blur?: number;\r\n fadeIn?: number;\r\n fadeOut?: number;\r\n density?: number;\r\n gradient?: number;\r\n}\r\n"],
5
+ "mappings": ";;;;;AAEA,eAAmE;AACnE,SAAS,WAAW,uBAAuB;AAEpC,MAAM,kBAAkB;AAAA,EAC7B,eAAe;AACjB;AAwCO,MAAM,4BAAoC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAMxB,gBAAgB,aAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBpD,SAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,6BAmEiB,gBAAgB,aAAc;AAAA,wBACnC,gBAAgB,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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAiHlD,eAAgB;AAAA;AAAA;AAAA;AAAA;",
6
+ "names": []
7
+ }
@@ -0,0 +1,62 @@
1
+ import type { ShaderMotionParams } from '../shader-mount.js';
2
+ import { type ShaderSizingParams, type ShaderSizingUniforms } from '../shader-sizing.js';
3
+ /**
4
+ * Animated 2-color dithering over multiple pattern sources (noise, warp, dots, waves, ripple, swirl, sphere).
5
+ *
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.
10
+ *
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
+ * */
31
+ export declare const ditheringFragmentShader: string;
32
+ export interface DitheringUniforms extends ShaderSizingUniforms {
33
+ u_colorBack: [number, number, number, number];
34
+ u_colorFront: [number, number, number, number];
35
+ u_shape: (typeof DitheringShapes)[DitheringShape];
36
+ u_type: (typeof DitheringTypes)[DitheringType];
37
+ u_pxSize: number;
38
+ }
39
+ export interface DitheringParams extends ShaderSizingParams, ShaderMotionParams {
40
+ colorBack?: string;
41
+ colorFront?: string;
42
+ shape?: DitheringShape;
43
+ type?: DitheringType;
44
+ size?: number;
45
+ }
46
+ export declare const DitheringShapes: {
47
+ readonly simplex: 1;
48
+ readonly warp: 2;
49
+ readonly dots: 3;
50
+ readonly wave: 4;
51
+ readonly ripple: 5;
52
+ readonly swirl: 6;
53
+ readonly sphere: 7;
54
+ };
55
+ export type DitheringShape = keyof typeof DitheringShapes;
56
+ export declare const DitheringTypes: {
57
+ readonly random: 1;
58
+ readonly '2x2': 2;
59
+ readonly '4x4': 3;
60
+ readonly '8x8': 4;
61
+ };
62
+ export type DitheringType = keyof typeof DitheringTypes;
@@ -0,0 +1,271 @@
1
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * *
2
+ * Paper Shaders *
3
+ * https://github.com/paper-design/shaders *
4
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * */
5
+
6
+ import {
7
+ } from "../shader-sizing.js";
8
+ import { simplexNoise, declarePI, proceduralHash11, proceduralHash21 } from "../shader-utils.js";
9
+ const ditheringFragmentShader = `#version 300 es
10
+ precision mediump float;
11
+
12
+ uniform float u_time;
13
+
14
+ uniform vec2 u_resolution;
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;
25
+
26
+ uniform float u_pxSize;
27
+ uniform vec4 u_colorBack;
28
+ uniform vec4 u_colorFront;
29
+ uniform float u_shape;
30
+ uniform float u_type;
31
+
32
+ out vec4 fragColor;
33
+
34
+ ${simplexNoise}
35
+ ${declarePI}
36
+ ${proceduralHash11}
37
+ ${proceduralHash21}
38
+
39
+ float getSimplexNoise(vec2 uv, float t) {
40
+ float noise = .5 * snoise(uv - vec2(0., .3 * t));
41
+ noise += .5 * snoise(2. * uv + vec2(0., .32 * t));
42
+
43
+ return noise;
44
+ }
45
+
46
+ const int bayer2x2[4] = int[4](0, 2, 3, 1);
47
+ const int bayer4x4[16] = int[16](
48
+ 0, 8, 2, 10,
49
+ 12, 4, 14, 6,
50
+ 3, 11, 1, 9,
51
+ 15, 7, 13, 5
52
+ );
53
+
54
+ const int bayer8x8[64] = int[64](
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
63
+ );
64
+
65
+ float getBayerValue(vec2 uv, int size) {
66
+ ivec2 pos = ivec2(fract(uv / float(size)) * float(size));
67
+ int index = pos.y * size + pos.x;
68
+
69
+ if (size == 2) {
70
+ return float(bayer2x2[index]) / 4.0;
71
+ } else if (size == 4) {
72
+ return float(bayer4x4[index]) / 16.0;
73
+ } else if (size == 8) {
74
+ return float(bayer8x8[index]) / 64.0;
75
+ }
76
+ return 0.0;
77
+ }
78
+
79
+
80
+ void main() {
81
+ float t = .5 * u_time;
82
+
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;
148
+ }
149
+
150
+ float shape = 0.;
151
+ if (u_shape < 1.5) {
152
+ // Simplex noise
153
+ shapeUV *= .001;
154
+
155
+ shape = 0.5 + 0.5 * getSimplexNoise(shapeUV, t);
156
+ shape = smoothstep(0.3, 0.9, shape);
157
+
158
+ } else if (u_shape < 2.5) {
159
+ // Warp
160
+ shapeUV *= .003;
161
+
162
+ for (float i = 1.0; i < 6.0; i++) {
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);
165
+ }
166
+
167
+ shape = .15 / max(0.001, abs(sin(t - shapeUV.y - shapeUV.x)));
168
+ shape = smoothstep(0.02, 1., shape);
169
+
170
+ } else if (u_shape < 3.5) {
171
+ // Dots
172
+ shapeUV *= .05;
173
+
174
+ float stripeIdx = floor(2. * shapeUV.x / TWO_PI);
175
+ float rand = hash11(stripeIdx * 10.);
176
+ rand = sign(rand - .5) * pow(.1 + abs(rand), .4);
177
+ shape = sin(shapeUV.x) * cos(shapeUV.y - 5. * rand * t);
178
+ shape = pow(abs(shape), 6.);
179
+
180
+ } else if (u_shape < 4.5) {
181
+ // Sine wave
182
+ shapeUV *= 4.;
183
+
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);
186
+
187
+ } else if (u_shape < 5.5) {
188
+ // Ripple
189
+
190
+ float dist = length(shapeUV);
191
+ float waves = sin(pow(dist, 1.7) * 7. - 3. * t) * .5 + .5;
192
+ shape = waves;
193
+
194
+ } else if (u_shape < 6.5) {
195
+ // Swirl
196
+
197
+ float l = length(shapeUV);
198
+ float angle = 6. * atan(shapeUV.y, shapeUV.x) + 4. * t;
199
+ float twist = 1.2;
200
+ float offset = 1. / pow(max(l, 1e-6), twist) + angle / TWO_PI;
201
+ float mid = smoothstep(0., 1., pow(l, twist));
202
+ shape = mix(0., fract(offset), mid);
203
+
204
+ } else {
205
+ // Sphere
206
+ shapeUV *= 2.;
207
+
208
+ float d = 1. - pow(length(shapeUV), 2.);
209
+ vec3 pos = vec3(shapeUV, sqrt(max(0., d)));
210
+ vec3 lightPos = normalize(vec3(cos(1.5 * t), .8, sin(1.25 * t)));
211
+ shape = .5 + .5 * dot(lightPos, pos);
212
+ shape *= step(0., d);
213
+ }
214
+
215
+
216
+ int type = int(floor(u_type));
217
+ float dithering = 0.0;
218
+
219
+ switch (type) {
220
+ case 1: {
221
+ dithering = step(hash21(ditheringNoiseUV), shape);
222
+ } break;
223
+ case 2:
224
+ dithering = getBayerValue(pxSizeUV, 2);
225
+ break;
226
+ case 3:
227
+ dithering = getBayerValue(pxSizeUV, 4);
228
+ break;
229
+ default :
230
+ dithering = getBayerValue(pxSizeUV, 8);
231
+ break;
232
+ }
233
+
234
+ dithering -= .5;
235
+ float res = step(.5, shape + dithering);
236
+
237
+ vec3 fgColor = u_colorFront.rgb * u_colorFront.a;
238
+ float fgOpacity = u_colorFront.a;
239
+ vec3 bgColor = u_colorBack.rgb * u_colorBack.a;
240
+ float bgOpacity = u_colorBack.a;
241
+
242
+ vec3 color = fgColor * res;
243
+ float opacity = fgOpacity * res;
244
+
245
+ color += bgColor * (1. - opacity);
246
+ opacity += bgOpacity * (1. - opacity);
247
+
248
+ fragColor = vec4(color, opacity);
249
+ }
250
+ `;
251
+ const DitheringShapes = {
252
+ simplex: 1,
253
+ warp: 2,
254
+ dots: 3,
255
+ wave: 4,
256
+ ripple: 5,
257
+ swirl: 6,
258
+ sphere: 7
259
+ };
260
+ const DitheringTypes = {
261
+ "random": 1,
262
+ "2x2": 2,
263
+ "4x4": 3,
264
+ "8x8": 4
265
+ };
266
+ export {
267
+ DitheringShapes,
268
+ DitheringTypes,
269
+ ditheringFragmentShader
270
+ };
271
+ //# sourceMappingURL=dithering.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/shaders/dithering.ts"],
4
+ "sourcesContent": ["import type { ShaderMotionParams } from '../shader-mount.js';\r\nimport {\r\n type ShaderSizingParams,\r\n type ShaderSizingUniforms,\r\n} from '../shader-sizing.js';\r\nimport { simplexNoise, declarePI, proceduralHash11, proceduralHash21 } from '../shader-utils.js';\r\n\r\n/**\r\n * Animated 2-color dithering over multiple pattern sources (noise, warp, dots, waves, ripple, swirl, sphere).\r\n *\r\n * SIZING NOTE: This shader performs sizing in the fragment shader (not vertex shader) to keep\r\n * u_pxSize in consistent actual pixels. The pixel grid is computed from gl_FragCoord before any\r\n * transforms, so scaling/rotating only affects the underlying pattern shape.\r\n * No vertex shader outputs (v_objectUV, v_patternUV, etc.) are used.\r\n *\r\n * Fragment shader uniforms:\r\n * - u_time (float): Animation time\r\n * - u_resolution (vec2): Canvas resolution in pixels\r\n * - u_pixelRatio (float): Device pixel ratio\r\n * - u_originX (float): Reference point for positioning world width in the canvas (0 to 1)\r\n * - u_originY (float): Reference point for positioning world height in the canvas (0 to 1)\r\n * - u_worldWidth (float): Virtual width of the graphic before it's scaled to fit the canvas\r\n * - u_worldHeight (float): Virtual height of the graphic before it's scaled to fit the canvas\r\n * - u_fit (float): How to fit the rendered shader into the canvas dimensions (0 = none, 1 = contain, 2 = cover)\r\n * - u_scale (float): Overall zoom level of the graphics (0.01 to 4)\r\n * - u_rotation (float): Overall rotation angle of the graphics in degrees (0 to 360)\r\n * - u_offsetX (float): Horizontal offset of the graphics center (-1 to 1)\r\n * - u_offsetY (float): Vertical offset of the graphics center (-1 to 1)\r\n * - u_colorBack (vec4): Background color in RGBA\r\n * - u_colorFront (vec4): Foreground (ink) color in RGBA\r\n * - u_shape (float): Shape pattern type (1 = simplex, 2 = warp, 3 = dots, 4 = wave, 5 = ripple, 6 = swirl, 7 = sphere)\r\n * - u_type (float): Dithering type (1 = random, 2 = 2x2 Bayer, 3 = 4x4 Bayer, 4 = 8x8 Bayer)\r\n * - u_pxSize (float): Pixel size of dithering grid (0.5 to 20)\r\n *\r\n * */\r\n\r\n// language=GLSL\r\nexport const ditheringFragmentShader: string = `#version 300 es\r\nprecision mediump float;\r\n\r\nuniform float u_time;\r\n\r\nuniform vec2 u_resolution;\r\nuniform float u_pixelRatio;\r\nuniform float u_originX;\r\nuniform float u_originY;\r\nuniform float u_worldWidth;\r\nuniform float u_worldHeight;\r\nuniform float u_fit;\r\nuniform float u_scale;\r\nuniform float u_rotation;\r\nuniform float u_offsetX;\r\nuniform float u_offsetY;\r\n\r\nuniform float u_pxSize;\r\nuniform vec4 u_colorBack;\r\nuniform vec4 u_colorFront;\r\nuniform float u_shape;\r\nuniform float u_type;\r\n\r\nout vec4 fragColor;\r\n\r\n${ simplexNoise }\r\n${ declarePI }\r\n${ proceduralHash11 }\r\n${ proceduralHash21 }\r\n\r\nfloat getSimplexNoise(vec2 uv, float t) {\r\n float noise = .5 * snoise(uv - vec2(0., .3 * t));\r\n noise += .5 * snoise(2. * uv + vec2(0., .32 * t));\r\n\r\n return noise;\r\n}\r\n\r\nconst int bayer2x2[4] = int[4](0, 2, 3, 1);\r\nconst int bayer4x4[16] = int[16](\r\n0, 8, 2, 10,\r\n12, 4, 14, 6,\r\n3, 11, 1, 9,\r\n15, 7, 13, 5\r\n);\r\n\r\nconst int bayer8x8[64] = int[64](\r\n0, 32, 8, 40, 2, 34, 10, 42,\r\n48, 16, 56, 24, 50, 18, 58, 26,\r\n12, 44, 4, 36, 14, 46, 6, 38,\r\n60, 28, 52, 20, 62, 30, 54, 22,\r\n3, 35, 11, 43, 1, 33, 9, 41,\r\n51, 19, 59, 27, 49, 17, 57, 25,\r\n15, 47, 7, 39, 13, 45, 5, 37,\r\n63, 31, 55, 23, 61, 29, 53, 21\r\n);\r\n\r\nfloat getBayerValue(vec2 uv, int size) {\r\n ivec2 pos = ivec2(fract(uv / float(size)) * float(size));\r\n int index = pos.y * size + pos.x;\r\n\r\n if (size == 2) {\r\n return float(bayer2x2[index]) / 4.0;\r\n } else if (size == 4) {\r\n return float(bayer4x4[index]) / 16.0;\r\n } else if (size == 8) {\r\n return float(bayer8x8[index]) / 64.0;\r\n }\r\n return 0.0;\r\n}\r\n\r\n\r\nvoid main() {\r\n float t = .5 * u_time;\r\n\r\n float pxSize = u_pxSize * u_pixelRatio;\r\n vec2 pxSizeUV = gl_FragCoord.xy - .5 * u_resolution;\r\n pxSizeUV /= pxSize;\r\n vec2 canvasPixelizedUV = (floor(pxSizeUV) + .5) * pxSize;\r\n vec2 normalizedUV = canvasPixelizedUV / u_resolution;\r\n\r\n vec2 ditheringNoiseUV = canvasPixelizedUV;\r\n vec2 shapeUV = normalizedUV;\r\n\r\n vec2 boxOrigin = vec2(.5 - u_originX, u_originY - .5);\r\n vec2 givenBoxSize = vec2(u_worldWidth, u_worldHeight);\r\n givenBoxSize = max(givenBoxSize, vec2(1.)) * u_pixelRatio;\r\n float r = u_rotation * PI / 180.;\r\n mat2 graphicRotation = mat2(cos(r), sin(r), -sin(r), cos(r));\r\n vec2 graphicOffset = vec2(-u_offsetX, u_offsetY);\r\n\r\n float patternBoxRatio = givenBoxSize.x / givenBoxSize.y;\r\n vec2 boxSize = vec2(\r\n (u_worldWidth == 0.) ? u_resolution.x : givenBoxSize.x,\r\n (u_worldHeight == 0.) ? u_resolution.y : givenBoxSize.y\r\n );\r\n \r\n if (u_shape > 3.5) {\r\n vec2 objectBoxSize = vec2(0.);\r\n // fit = none\r\n objectBoxSize.x = min(boxSize.x, boxSize.y);\r\n if (u_fit == 1.) { // fit = contain\r\n objectBoxSize.x = min(u_resolution.x, u_resolution.y);\r\n } else if (u_fit == 2.) { // fit = cover\r\n objectBoxSize.x = max(u_resolution.x, u_resolution.y);\r\n }\r\n objectBoxSize.y = objectBoxSize.x;\r\n vec2 objectWorldScale = u_resolution.xy / objectBoxSize;\r\n\r\n shapeUV *= objectWorldScale;\r\n shapeUV += boxOrigin * (objectWorldScale - 1.);\r\n shapeUV += vec2(-u_offsetX, u_offsetY);\r\n shapeUV /= u_scale;\r\n shapeUV = graphicRotation * shapeUV;\r\n } else {\r\n vec2 patternBoxSize = vec2(0.);\r\n // fit = none\r\n patternBoxSize.x = patternBoxRatio * min(boxSize.x / patternBoxRatio, boxSize.y);\r\n float patternWorldNoFitBoxWidth = patternBoxSize.x;\r\n if (u_fit == 1.) { // fit = contain\r\n patternBoxSize.x = patternBoxRatio * min(u_resolution.x / patternBoxRatio, u_resolution.y);\r\n } else if (u_fit == 2.) { // fit = cover\r\n patternBoxSize.x = patternBoxRatio * max(u_resolution.x / patternBoxRatio, u_resolution.y);\r\n }\r\n patternBoxSize.y = patternBoxSize.x / patternBoxRatio;\r\n vec2 patternWorldScale = u_resolution.xy / patternBoxSize;\r\n\r\n shapeUV += vec2(-u_offsetX, u_offsetY) / patternWorldScale;\r\n shapeUV += boxOrigin;\r\n shapeUV -= boxOrigin / patternWorldScale;\r\n shapeUV *= u_resolution.xy;\r\n shapeUV /= u_pixelRatio;\r\n if (u_fit > 0.) {\r\n shapeUV *= (patternWorldNoFitBoxWidth / patternBoxSize.x);\r\n }\r\n shapeUV /= u_scale;\r\n shapeUV = graphicRotation * shapeUV;\r\n shapeUV += boxOrigin / patternWorldScale;\r\n shapeUV -= boxOrigin;\r\n shapeUV += .5;\r\n }\r\n\r\n float shape = 0.;\r\n if (u_shape < 1.5) {\r\n // Simplex noise\r\n shapeUV *= .001;\r\n\r\n shape = 0.5 + 0.5 * getSimplexNoise(shapeUV, t);\r\n shape = smoothstep(0.3, 0.9, shape);\r\n\r\n } else if (u_shape < 2.5) {\r\n // Warp\r\n shapeUV *= .003;\r\n\r\n for (float i = 1.0; i < 6.0; i++) {\r\n shapeUV.x += 0.6 / i * cos(i * 2.5 * shapeUV.y + t);\r\n shapeUV.y += 0.6 / i * cos(i * 1.5 * shapeUV.x + t);\r\n }\r\n\r\n shape = .15 / max(0.001, abs(sin(t - shapeUV.y - shapeUV.x)));\r\n shape = smoothstep(0.02, 1., shape);\r\n\r\n } else if (u_shape < 3.5) {\r\n // Dots\r\n shapeUV *= .05;\r\n\r\n float stripeIdx = floor(2. * shapeUV.x / TWO_PI);\r\n float rand = hash11(stripeIdx * 10.);\r\n rand = sign(rand - .5) * pow(.1 + abs(rand), .4);\r\n shape = sin(shapeUV.x) * cos(shapeUV.y - 5. * rand * t);\r\n shape = pow(abs(shape), 6.);\r\n\r\n } else if (u_shape < 4.5) {\r\n // Sine wave\r\n shapeUV *= 4.;\r\n\r\n float wave = cos(.5 * shapeUV.x - 2. * t) * sin(1.5 * shapeUV.x + t) * (.75 + .25 * cos(3. * t));\r\n shape = 1. - smoothstep(-1., 1., shapeUV.y + wave);\r\n\r\n } else if (u_shape < 5.5) {\r\n // Ripple\r\n\r\n float dist = length(shapeUV);\r\n float waves = sin(pow(dist, 1.7) * 7. - 3. * t) * .5 + .5;\r\n shape = waves;\r\n\r\n } else if (u_shape < 6.5) {\r\n // Swirl\r\n\r\n float l = length(shapeUV);\r\n float angle = 6. * atan(shapeUV.y, shapeUV.x) + 4. * t;\r\n float twist = 1.2;\r\n float offset = 1. / pow(max(l, 1e-6), twist) + angle / TWO_PI;\r\n float mid = smoothstep(0., 1., pow(l, twist));\r\n shape = mix(0., fract(offset), mid);\r\n\r\n } else {\r\n // Sphere\r\n shapeUV *= 2.;\r\n\r\n float d = 1. - pow(length(shapeUV), 2.);\r\n vec3 pos = vec3(shapeUV, sqrt(max(0., d)));\r\n vec3 lightPos = normalize(vec3(cos(1.5 * t), .8, sin(1.25 * t)));\r\n shape = .5 + .5 * dot(lightPos, pos);\r\n shape *= step(0., d);\r\n }\r\n\r\n\r\n int type = int(floor(u_type));\r\n float dithering = 0.0;\r\n\r\n switch (type) {\r\n case 1: {\r\n dithering = step(hash21(ditheringNoiseUV), shape);\r\n } break;\r\n case 2:\r\n dithering = getBayerValue(pxSizeUV, 2);\r\n break;\r\n case 3:\r\n dithering = getBayerValue(pxSizeUV, 4);\r\n break;\r\n default :\r\n dithering = getBayerValue(pxSizeUV, 8);\r\n break;\r\n }\r\n\r\n dithering -= .5;\r\n float res = step(.5, shape + dithering);\r\n\r\n vec3 fgColor = u_colorFront.rgb * u_colorFront.a;\r\n float fgOpacity = u_colorFront.a;\r\n vec3 bgColor = u_colorBack.rgb * u_colorBack.a;\r\n float bgOpacity = u_colorBack.a;\r\n\r\n vec3 color = fgColor * res;\r\n float opacity = fgOpacity * res;\r\n\r\n color += bgColor * (1. - opacity);\r\n opacity += bgOpacity * (1. - opacity);\r\n\r\n fragColor = vec4(color, opacity);\r\n}\r\n`;\r\n\r\nexport interface DitheringUniforms extends ShaderSizingUniforms {\r\n u_colorBack: [number, number, number, number];\r\n u_colorFront: [number, number, number, number];\r\n u_shape: (typeof DitheringShapes)[DitheringShape];\r\n u_type: (typeof DitheringTypes)[DitheringType];\r\n u_pxSize: number;\r\n}\r\n\r\nexport interface DitheringParams extends ShaderSizingParams, ShaderMotionParams {\r\n colorBack?: string;\r\n colorFront?: string;\r\n shape?: DitheringShape;\r\n type?: DitheringType;\r\n size?: number;\r\n}\r\n\r\nexport const DitheringShapes = {\r\n simplex: 1,\r\n warp: 2,\r\n dots: 3,\r\n wave: 4,\r\n ripple: 5,\r\n swirl: 6,\r\n sphere: 7,\r\n} as const;\r\n\r\nexport type DitheringShape = keyof typeof DitheringShapes;\r\n\r\nexport const DitheringTypes = {\r\n 'random': 1,\r\n '2x2': 2,\r\n '4x4': 3,\r\n '8x8': 4,\r\n} as const;\r\n\r\nexport type DitheringType = keyof typeof DitheringTypes;\r\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
+ "names": []
7
+ }
@@ -0,0 +1,65 @@
1
+ import { type ShaderSizingParams, type ShaderSizingUniforms } from '../shader-sizing.js';
2
+ /**
3
+ * Static grid pattern made of circles, diamonds, squares or triangles.
4
+ *
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, needs strokeWidth > 0
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, needs colorStroke alpha > 0 (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)
32
+ *
33
+ */
34
+ export declare const dotGridFragmentShader: string;
35
+ export interface DotGridUniforms extends ShaderSizingUniforms {
36
+ u_colorBack: [number, number, number, number];
37
+ u_colorFill: [number, number, number, number];
38
+ u_colorStroke: [number, number, number, number];
39
+ u_dotSize: number;
40
+ u_gapX: number;
41
+ u_gapY: number;
42
+ u_strokeWidth: number;
43
+ u_sizeRange: number;
44
+ u_opacityRange: number;
45
+ u_shape: (typeof DotGridShapes)[DotGridShape];
46
+ }
47
+ export interface DotGridParams extends ShaderSizingParams {
48
+ colorBack?: string;
49
+ colorFill?: string;
50
+ colorStroke?: string;
51
+ size?: number;
52
+ gapX?: number;
53
+ gapY?: number;
54
+ strokeWidth?: number;
55
+ sizeRange?: number;
56
+ opacityRange?: number;
57
+ shape?: DotGridShape;
58
+ }
59
+ export declare const DotGridShapes: {
60
+ readonly circle: 0;
61
+ readonly diamond: 1;
62
+ readonly square: 2;
63
+ readonly triangle: 3;
64
+ };
65
+ export type DotGridShape = keyof typeof DotGridShapes;