@paper-design/shaders 0.0.40 → 0.0.46

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 (78) hide show
  1. package/README.md +2 -1
  2. package/dist/get-shader-noise-texture.d.ts +1 -1
  3. package/dist/get-shader-noise-texture.js +5 -9
  4. package/dist/get-shader-noise-texture.js.map +2 -2
  5. package/dist/index.d.ts +4 -0
  6. package/dist/index.js +18 -0
  7. package/dist/index.js.map +2 -2
  8. package/dist/shader-mount.d.ts +8 -2
  9. package/dist/shader-mount.js +12 -177
  10. package/dist/shader-mount.js.map +2 -2
  11. package/dist/shader-sizing.d.ts +2 -2
  12. package/dist/shader-sizing.js +39 -1
  13. package/dist/shader-sizing.js.map +2 -2
  14. package/dist/shader-utils.d.ts +8 -5
  15. package/dist/shader-utils.js +70 -51
  16. package/dist/shader-utils.js.map +2 -2
  17. package/dist/shaders/dithering.js +13 -11
  18. package/dist/shaders/dithering.js.map +2 -2
  19. package/dist/shaders/dot-grid.js +2 -2
  20. package/dist/shaders/dot-grid.js.map +2 -2
  21. package/dist/shaders/dot-orbit.d.ts +3 -0
  22. package/dist/shaders/dot-orbit.js +9 -9
  23. package/dist/shaders/dot-orbit.js.map +2 -2
  24. package/dist/shaders/fluted-glass.d.ts +72 -0
  25. package/dist/shaders/fluted-glass.js +188 -0
  26. package/dist/shaders/fluted-glass.js.map +7 -0
  27. package/dist/shaders/god-rays.d.ts +2 -0
  28. package/dist/shaders/god-rays.js +20 -9
  29. package/dist/shaders/god-rays.js.map +2 -2
  30. package/dist/shaders/grain-gradient.d.ts +1 -0
  31. package/dist/shaders/grain-gradient.js +65 -42
  32. package/dist/shaders/grain-gradient.js.map +2 -2
  33. package/dist/shaders/image-dithering.d.ts +49 -0
  34. package/dist/shaders/image-dithering.js +164 -0
  35. package/dist/shaders/image-dithering.js.map +7 -0
  36. package/dist/shaders/liquid-metal.js +4 -4
  37. package/dist/shaders/liquid-metal.js.map +2 -2
  38. package/dist/shaders/mesh-gradient.js +2 -2
  39. package/dist/shaders/mesh-gradient.js.map +2 -2
  40. package/dist/shaders/metaballs.d.ts +3 -0
  41. package/dist/shaders/metaballs.js +8 -7
  42. package/dist/shaders/metaballs.js.map +2 -2
  43. package/dist/shaders/neuro-noise.js +2 -2
  44. package/dist/shaders/neuro-noise.js.map +2 -2
  45. package/dist/shaders/paper-texture.d.ts +53 -0
  46. package/dist/shaders/paper-texture.js +236 -0
  47. package/dist/shaders/paper-texture.js.map +7 -0
  48. package/dist/shaders/perlin-noise.js +111 -117
  49. package/dist/shaders/perlin-noise.js.map +2 -2
  50. package/dist/shaders/pulsing-border.d.ts +1 -0
  51. package/dist/shaders/pulsing-border.js +23 -15
  52. package/dist/shaders/pulsing-border.js.map +2 -2
  53. package/dist/shaders/simplex-noise.js +2 -2
  54. package/dist/shaders/simplex-noise.js.map +2 -2
  55. package/dist/shaders/smoke-ring.js +13 -8
  56. package/dist/shaders/smoke-ring.js.map +2 -2
  57. package/dist/shaders/spiral.js +3 -3
  58. package/dist/shaders/spiral.js.map +2 -2
  59. package/dist/shaders/static-mesh-gradient.d.ts +2 -0
  60. package/dist/shaders/static-mesh-gradient.js +15 -14
  61. package/dist/shaders/static-mesh-gradient.js.map +2 -2
  62. package/dist/shaders/static-radial-gradient.d.ts +2 -0
  63. package/dist/shaders/static-radial-gradient.js +15 -13
  64. package/dist/shaders/static-radial-gradient.js.map +2 -2
  65. package/dist/shaders/swirl.js +3 -3
  66. package/dist/shaders/swirl.js.map +2 -2
  67. package/dist/shaders/voronoi.js +6 -10
  68. package/dist/shaders/voronoi.js.map +2 -2
  69. package/dist/shaders/warp.d.ts +3 -0
  70. package/dist/shaders/warp.js +20 -4
  71. package/dist/shaders/warp.js.map +2 -2
  72. package/dist/shaders/water.d.ts +39 -0
  73. package/dist/shaders/water.js +119 -0
  74. package/dist/shaders/water.js.map +7 -0
  75. package/dist/vertex-shader.d.ts +2 -0
  76. package/dist/vertex-shader.js +212 -0
  77. package/dist/vertex-shader.js.map +7 -0
  78. package/package.json +1 -1
@@ -0,0 +1,188 @@
1
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * *
2
+ * Paper Shaders *
3
+ * https://github.com/paper-design/shaders *
4
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * */
5
+
6
+ import { sizingVariablesDeclaration } from "../shader-sizing.js";
7
+ import { declarePI, rotation2 } from "../shader-utils.js";
8
+ const flutedGlassFragmentShader = `#version 300 es
9
+ precision mediump float;
10
+
11
+ uniform float u_time;
12
+ uniform vec2 u_resolution;
13
+ uniform float u_pixelRatio;
14
+
15
+ uniform sampler2D u_image;
16
+ uniform float u_imageAspectRatio;
17
+
18
+ uniform float u_count;
19
+ uniform float u_angle;
20
+ uniform float u_highlights;
21
+ uniform float u_shape;
22
+ uniform float u_distortion;
23
+ uniform float u_distortionShape;
24
+ uniform float u_shift;
25
+ uniform float u_blur;
26
+ uniform float u_marginLeft;
27
+ uniform float u_marginRight;
28
+ uniform float u_marginTop;
29
+ uniform float u_marginBottom;
30
+
31
+ ${sizingVariablesDeclaration}
32
+
33
+ out vec4 fragColor;
34
+
35
+ ${declarePI}
36
+ ${rotation2}
37
+
38
+ float getUvFrame(vec2 uv) {
39
+ float aax = 2. * fwidth(uv.x);
40
+ float aay = 2. * fwidth(uv.y);
41
+
42
+ float left = smoothstep(0., aax, uv.x);
43
+ float right = smoothstep(1., 1. - aax, uv.x);
44
+ float bottom = smoothstep(0., aay, uv.y);
45
+ float top = smoothstep(1., 1. - aay, uv.y);
46
+
47
+ return left * right * bottom * top;
48
+ }
49
+
50
+ const int MAX_RADIUS = 50;
51
+
52
+ vec4 getBlur(sampler2D tex, vec2 uv, vec2 texelSize, vec2 dir, float sigma) {
53
+ if (sigma <= .5) return texture(tex, uv);
54
+ int radius = int(min(float(MAX_RADIUS), ceil(3.0 * sigma)));
55
+
56
+ float twoSigma2 = 2.0 * sigma * sigma;
57
+ float gaussianNorm = 1.0 / sqrt(TWO_PI * sigma * sigma);
58
+
59
+ vec4 sum = texture(tex, uv) * gaussianNorm;
60
+ float weightSum = gaussianNorm;
61
+
62
+ for (int i = 1; i <= MAX_RADIUS; i++) {
63
+ if (i > radius) break;
64
+
65
+ float x = float(i);
66
+ float w = exp(-(x * x) / twoSigma2) * gaussianNorm;
67
+
68
+ vec2 offset = dir * texelSize * x;
69
+ vec4 s1 = texture(tex, uv + offset);
70
+ vec4 s2 = texture(tex, uv - offset);
71
+
72
+ sum += (s1 + s2) * w;
73
+ weightSum += 2.0 * w;
74
+ }
75
+
76
+ return sum / weightSum;
77
+ }
78
+
79
+ void main() {
80
+ vec2 imageUV = v_imageUV;
81
+
82
+ vec2 uv = imageUV;
83
+ float frame = getUvFrame(imageUV);
84
+ if (frame < .05) discard;
85
+
86
+ float gridNumber = u_count * u_imageAspectRatio;
87
+
88
+ vec2 sw = vec2(.005 * u_distortion) * vec2(1., u_imageAspectRatio);
89
+ float maskOuter =
90
+ smoothstep(u_marginLeft - sw.x, u_marginLeft, imageUV.x + sw.x) *
91
+ smoothstep(u_marginRight - sw.x, u_marginRight, 1.0 - imageUV.x + sw.x) *
92
+ smoothstep(u_marginTop - sw.y, u_marginTop, imageUV.y + sw.y) *
93
+ smoothstep(u_marginBottom - sw.y, u_marginBottom, 1.0 - imageUV.y + sw.y);
94
+ float mask =
95
+ smoothstep(u_marginLeft, u_marginLeft + sw.x, imageUV.x + sw.x) *
96
+ smoothstep(u_marginRight, u_marginRight + sw.x, 1.0 - imageUV.x + sw.x) *
97
+ smoothstep(u_marginTop, u_marginTop + sw.y, imageUV.y + sw.y) *
98
+ smoothstep(u_marginBottom, u_marginBottom + sw.y, 1.0 - imageUV.y + sw.y);
99
+ float stroke = (1. - mask) * maskOuter;
100
+
101
+ float patternRotation = u_angle * PI / 180.;
102
+ uv = rotate(uv - vec2(.5), patternRotation);
103
+ uv *= gridNumber;
104
+
105
+ float curve = 0.;
106
+ if (u_shape > 4.5) {
107
+ // pattern
108
+ curve = .5 + .5 * sin(1.5 * uv.x) * cos(1.5 * uv.y);
109
+ } else if (u_shape > 3.5) {
110
+ // zigzag
111
+ curve = 10. * abs(fract(.1 * uv.y) - .5);
112
+ } else if (u_shape > 2.5) {
113
+ // wave
114
+ curve = 4. * sin(.23 * uv.y);
115
+ } else if (u_shape > 1.5) {
116
+ // lines irregular
117
+ curve = .5 + .5 * sin(.5 * uv.x) * sin(1.7 * uv.x);
118
+ } else {
119
+ // lines
120
+ curve = .2 * gridNumber / u_imageAspectRatio;
121
+ }
122
+
123
+ vec2 uvOrig = uv;
124
+ uv += curve;
125
+
126
+ vec2 fractUV = fract(uv);
127
+ vec2 floorUV = floor(uv);
128
+
129
+ vec2 fractOrigUV = fract(uvOrig);
130
+ vec2 floorOrigUV = floor(uvOrig);
131
+
132
+ float highlights = smoothstep(.85, .95, fractUV.x);
133
+ highlights *= mask;
134
+
135
+ float xDistortion = 0.;
136
+ if (u_distortionShape == 1.) {
137
+ xDistortion = -pow(1.5 * fractUV.x, 3.) + (.5 + u_shift);
138
+ } else if (u_distortionShape == 2.) {
139
+ xDistortion = 2. * pow(fractUV.x, 2.) - (.5 + u_shift);
140
+ } else if (u_distortionShape == 3.) {
141
+ xDistortion = pow(2. * (fractUV.x - .5), 6.) + .5 - .5 + u_shift;
142
+ } else if (u_distortionShape == 4.) {
143
+ xDistortion = sin((fractUV.x + .25 + u_shift) * TWO_PI);
144
+ xDistortion *= .5;
145
+ } else if (u_distortionShape == 5.) {
146
+ xDistortion += (.5 + u_shift);
147
+ xDistortion -= pow(abs(fractUV.x), .2) * fractUV.x;
148
+ xDistortion *= .33;
149
+ }
150
+
151
+ xDistortion *= 3. * u_distortion;
152
+
153
+ uv = (floorOrigUV + fractOrigUV) / gridNumber;
154
+ uv.x += xDistortion / gridNumber;
155
+ uv += pow(stroke, 4.);
156
+ uv.y = mix(uv.y, .0, .4 * u_highlights * highlights);
157
+
158
+ uv = rotate(uv, -patternRotation) + vec2(.5);
159
+
160
+ uv = mix(imageUV, uv, mask);
161
+ float blur = mix(0., u_blur, mask);
162
+
163
+ vec4 color = getBlur(u_image, uv, 1. / u_resolution / u_pixelRatio, vec2(0., 1.), blur);
164
+
165
+ float opacity = color.a;
166
+ fragColor = vec4(color.rgb, opacity);
167
+ }
168
+ `;
169
+ const GlassGridShapes = {
170
+ lines: 1,
171
+ linesIrregular: 2,
172
+ wave: 3,
173
+ zigzag: 4,
174
+ pattern: 5
175
+ };
176
+ const GlassDistortionShapes = {
177
+ prism: 1,
178
+ lens: 2,
179
+ \u0441ontour: 3,
180
+ \u0441ascade: 4,
181
+ facete: 5
182
+ };
183
+ export {
184
+ GlassDistortionShapes,
185
+ GlassGridShapes,
186
+ flutedGlassFragmentShader
187
+ };
188
+ //# sourceMappingURL=fluted-glass.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/shaders/fluted-glass.ts"],
4
+ "sourcesContent": ["import type { ShaderMotionParams } from '../shader-mount.js';\nimport { sizingVariablesDeclaration, type ShaderSizingParams, type ShaderSizingUniforms } from '../shader-sizing.js';\nimport { declarePI, rotation2 } from '../shader-utils.js';\n\n/**\n * Mimicking glass surface distortion over the image by distorting the texture\n * coordinates within line patterns\n *\n * Uniforms:\n * - u_count, u_angle - number and direction of grid relative to the image\n * - u_shape (float used as integer):\n * ---- 1: uniformly spaced stripes\n * ---- 2: randomly spaced stripes\n * ---- 3: sine wave stripes\n * ---- 4: zigzag stripes\n * ---- 5: wave-based pattern\n * - u_distortion - the power of distortion applied along within each stripe\n * - u_distortionShape (float used as integer):\n * ---- 5 shapes available\n * - u_shift - texture shift in direction opposite to the grid\n * - u_blur - one-directional blur applied over the main distortion\n * - u_highlights - thin color lines along the grid (independent from distortion)\n * - u_marginLeft, u_marginRight, u_marginTop, u_marginBottom - paddings\n * within picture to be shown without any distortion\n *\n */\n\n// language=GLSL\nexport const flutedGlassFragmentShader: string = `#version 300 es\nprecision mediump float;\n\nuniform float u_time;\nuniform vec2 u_resolution;\nuniform float u_pixelRatio;\n\nuniform sampler2D u_image;\nuniform float u_imageAspectRatio;\n\nuniform float u_count;\nuniform float u_angle;\nuniform float u_highlights;\nuniform float u_shape;\nuniform float u_distortion;\nuniform float u_distortionShape;\nuniform float u_shift;\nuniform float u_blur;\nuniform float u_marginLeft;\nuniform float u_marginRight;\nuniform float u_marginTop;\nuniform float u_marginBottom;\n\n${sizingVariablesDeclaration}\n\nout vec4 fragColor;\n\n${declarePI}\n${rotation2}\n\nfloat getUvFrame(vec2 uv) {\n float aax = 2. * fwidth(uv.x);\n float aay = 2. * fwidth(uv.y);\n\n float left = smoothstep(0., aax, uv.x);\n float right = smoothstep(1., 1. - aax, uv.x);\n float bottom = smoothstep(0., aay, uv.y);\n float top = smoothstep(1., 1. - aay, uv.y);\n\n return left * right * bottom * top;\n}\n\nconst int MAX_RADIUS = 50;\n\nvec4 getBlur(sampler2D tex, vec2 uv, vec2 texelSize, vec2 dir, float sigma) {\n if (sigma <= .5) return texture(tex, uv);\n int radius = int(min(float(MAX_RADIUS), ceil(3.0 * sigma)));\n\n float twoSigma2 = 2.0 * sigma * sigma;\n float gaussianNorm = 1.0 / sqrt(TWO_PI * sigma * sigma);\n\n vec4 sum = texture(tex, uv) * gaussianNorm;\n float weightSum = gaussianNorm;\n\n for (int i = 1; i <= MAX_RADIUS; i++) {\n if (i > radius) break;\n\n float x = float(i);\n float w = exp(-(x * x) / twoSigma2) * gaussianNorm;\n\n vec2 offset = dir * texelSize * x;\n vec4 s1 = texture(tex, uv + offset);\n vec4 s2 = texture(tex, uv - offset);\n\n sum += (s1 + s2) * w;\n weightSum += 2.0 * w;\n }\n\n return sum / weightSum;\n}\n\nvoid main() {\n vec2 imageUV = v_imageUV;\n \n vec2 uv = imageUV;\n float frame = getUvFrame(imageUV);\n if (frame < .05) discard;\n\n float gridNumber = u_count * u_imageAspectRatio;\n\n vec2 sw = vec2(.005 * u_distortion) * vec2(1., u_imageAspectRatio);\n float maskOuter =\n smoothstep(u_marginLeft - sw.x, u_marginLeft, imageUV.x + sw.x) *\n smoothstep(u_marginRight - sw.x, u_marginRight, 1.0 - imageUV.x + sw.x) *\n smoothstep(u_marginTop - sw.y, u_marginTop, imageUV.y + sw.y) *\n smoothstep(u_marginBottom - sw.y, u_marginBottom, 1.0 - imageUV.y + sw.y);\n float mask =\n smoothstep(u_marginLeft, u_marginLeft + sw.x, imageUV.x + sw.x) *\n smoothstep(u_marginRight, u_marginRight + sw.x, 1.0 - imageUV.x + sw.x) *\n smoothstep(u_marginTop, u_marginTop + sw.y, imageUV.y + sw.y) *\n smoothstep(u_marginBottom, u_marginBottom + sw.y, 1.0 - imageUV.y + sw.y);\n float stroke = (1. - mask) * maskOuter;\n\n float patternRotation = u_angle * PI / 180.;\n uv = rotate(uv - vec2(.5), patternRotation);\n uv *= gridNumber;\n \n float curve = 0.;\n if (u_shape > 4.5) {\n // pattern\n curve = .5 + .5 * sin(1.5 * uv.x) * cos(1.5 * uv.y);\n } else if (u_shape > 3.5) {\n // zigzag\n curve = 10. * abs(fract(.1 * uv.y) - .5);\n } else if (u_shape > 2.5) {\n // wave\n curve = 4. * sin(.23 * uv.y);\n } else if (u_shape > 1.5) {\n // lines irregular\n curve = .5 + .5 * sin(.5 * uv.x) * sin(1.7 * uv.x);\n } else {\n // lines\n curve = .2 * gridNumber / u_imageAspectRatio;\n }\n\n vec2 uvOrig = uv;\n uv += curve;\n\n vec2 fractUV = fract(uv);\n vec2 floorUV = floor(uv);\n\n vec2 fractOrigUV = fract(uvOrig);\n vec2 floorOrigUV = floor(uvOrig);\n\n float highlights = smoothstep(.85, .95, fractUV.x);\n highlights *= mask;\n\n float xDistortion = 0.;\n if (u_distortionShape == 1.) {\n xDistortion = -pow(1.5 * fractUV.x, 3.) + (.5 + u_shift);\n } else if (u_distortionShape == 2.) {\n xDistortion = 2. * pow(fractUV.x, 2.) - (.5 + u_shift);\n } else if (u_distortionShape == 3.) {\n xDistortion = pow(2. * (fractUV.x - .5), 6.) + .5 - .5 + u_shift;\n } else if (u_distortionShape == 4.) {\n xDistortion = sin((fractUV.x + .25 + u_shift) * TWO_PI);\n xDistortion *= .5;\n } else if (u_distortionShape == 5.) {\n xDistortion += (.5 + u_shift);\n xDistortion -= pow(abs(fractUV.x), .2) * fractUV.x;\n xDistortion *= .33;\n }\n\n xDistortion *= 3. * u_distortion;\n\n uv = (floorOrigUV + fractOrigUV) / gridNumber;\n uv.x += xDistortion / gridNumber;\n uv += pow(stroke, 4.);\n uv.y = mix(uv.y, .0, .4 * u_highlights * highlights);\n \n uv = rotate(uv, -patternRotation) + vec2(.5);\n\n uv = mix(imageUV, uv, mask);\n float blur = mix(0., u_blur, mask);\n \n vec4 color = getBlur(u_image, uv, 1. / u_resolution / u_pixelRatio, vec2(0., 1.), blur);\n\n float opacity = color.a;\n fragColor = vec4(color.rgb, opacity);\n}\n`;\n\nexport interface FlutedGlassUniforms extends ShaderSizingUniforms {\n u_image: HTMLImageElement | string | undefined;\n u_count: number;\n u_angle: number;\n u_distortion: number;\n u_shift: number;\n u_blur: number;\n u_marginLeft: number;\n u_marginRight: number;\n u_marginTop: number;\n u_marginBottom: number;\n u_highlights: number;\n u_distortionShape: (typeof GlassDistortionShapes)[GlassDistortionShape];\n u_shape: (typeof GlassGridShapes)[GlassGridShape];\n u_noiseTexture?: HTMLImageElement;\n}\n\nexport interface FlutedGlassParams extends ShaderSizingParams, ShaderMotionParams {\n image?: HTMLImageElement | string | undefined;\n count?: number;\n angle?: number;\n distortion?: number;\n shift?: number;\n blur?: number;\n marginLeft?: number;\n marginRight?: number;\n marginTop?: number;\n marginBottom?: number;\n highlights?: number;\n distortionShape?: GlassDistortionShape;\n shape?: GlassGridShape;\n}\n\nexport const GlassGridShapes = {\n lines: 1,\n linesIrregular: 2,\n wave: 3,\n zigzag: 4,\n pattern: 5,\n} as const;\n\nexport const GlassDistortionShapes = {\n prism: 1,\n lens: 2,\n \u0441ontour: 3,\n \u0441ascade: 4,\n facete: 5,\n} as const;\n\nexport type GlassDistortionShape = keyof typeof GlassDistortionShapes;\nexport type GlassGridShape = keyof typeof GlassGridShapes;\n"],
5
+ "mappings": ";;;;;AACA,SAAS,kCAAsF;AAC/F,SAAS,WAAW,iBAAiB;AA0B9B,MAAM,4BAAoC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAuB/C,0BAA0B;AAAA;AAAA;AAAA;AAAA,EAI1B,SAAS;AAAA,EACT,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAuKJ,MAAM,kBAAkB;AAAA,EAC7B,OAAO;AAAA,EACP,gBAAgB;AAAA,EAChB,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,SAAS;AACX;AAEO,MAAM,wBAAwB;AAAA,EACnC,OAAO;AAAA,EACP,MAAM;AAAA,EACN,cAAS;AAAA,EACT,cAAS;AAAA,EACT,QAAQ;AACV;",
6
+ "names": []
7
+ }
@@ -16,6 +16,7 @@ export declare const godRaysMeta: {
16
16
  * - u_midSize, u_midIntensity: central shape over the rays
17
17
  * - u_bloom (0..1): normal to additive blending mix
18
18
  *
19
+ * - u_noiseTexture (sampler2D): pre-computed randomizer source
19
20
  */
20
21
  export declare const godRaysFragmentShader: string;
21
22
  export interface GodRaysUniforms extends ShaderSizingUniforms {
@@ -29,6 +30,7 @@ export interface GodRaysUniforms extends ShaderSizingUniforms {
29
30
  u_density: number;
30
31
  u_intensity: number;
31
32
  u_bloom: number;
33
+ u_noiseTexture?: HTMLImageElement;
32
34
  }
33
35
  export interface GodRaysParams extends ShaderSizingParams, ShaderMotionParams {
34
36
  colorBack?: string;
@@ -4,7 +4,7 @@
4
4
  * * * * * * * * * * * * * * * * * * * * * * * * * * * */
5
5
 
6
6
  import { sizingVariablesDeclaration } from "../shader-sizing.js";
7
- import { declarePI, declareRandom, declareRotate, declareValueNoise, colorBandingFix } from "../shader-utils.js";
7
+ import { declarePI, rotation2, textureRandomizerR, colorBandingFix, proceduralHash11 } from "../shader-utils.js";
8
8
  const godRaysMeta = {
9
9
  maxColorCount: 5
10
10
  };
@@ -13,6 +13,8 @@ precision mediump float;
13
13
 
14
14
  uniform float u_time;
15
15
 
16
+ uniform sampler2D u_noiseTexture;
17
+
16
18
  uniform vec4 u_colorBack;
17
19
  uniform vec4 u_colorBloom;
18
20
  uniform vec4 u_colors[${godRaysMeta.maxColorCount}];
@@ -30,14 +32,23 @@ ${sizingVariablesDeclaration}
30
32
  out vec4 fragColor;
31
33
 
32
34
  ${declarePI}
33
- ${declareRandom}
34
- ${declareRotate}
35
- ${declareValueNoise}
36
-
37
- float hash(float n) {
38
- return fract(sin(n * 43758.5453123) * 43758.5453123);
35
+ ${rotation2}
36
+ ${textureRandomizerR}
37
+ float valueNoise(vec2 st) {
38
+ vec2 i = floor(st);
39
+ vec2 f = fract(st);
40
+ float a = randomR(i);
41
+ float b = randomR(i + vec2(1.0, 0.0));
42
+ float c = randomR(i + vec2(0.0, 1.0));
43
+ float d = randomR(i + vec2(1.0, 1.0));
44
+ vec2 u = f * f * (3.0 - 2.0 * f);
45
+ float x1 = mix(a, b, u.x);
46
+ float x2 = mix(c, d, u.x);
47
+ return mix(x1, x2, u.y);
39
48
  }
40
49
 
50
+ ${proceduralHash11}
51
+
41
52
  float raysShape(vec2 uv, float r, float freq, float intensity, float radius) {
42
53
  float a = atan(uv.y, uv.x);
43
54
  vec2 left = vec2(a * freq, r);
@@ -54,7 +65,7 @@ void main() {
54
65
  float t = .2 * u_time;
55
66
 
56
67
  float radius = length(shape_uv);
57
- float spots = 5. * abs(u_spotty);
68
+ float spots = 6.5 * abs(u_spotty);
58
69
 
59
70
  float intensity = 4. - 3. * clamp(u_intensity, 0., 1.);
60
71
 
@@ -75,7 +86,7 @@ void main() {
75
86
  float r1 = radius * (1.0 + 0.4 * float(i)) - 3.0 * t;
76
87
  float r2 = 0.5 * radius * (1.0 + spots) - 2.0 * t;
77
88
  float density = 6. * u_density + step(.5, u_density) * pow(4.5 * (u_density - .5), 4.);
78
- float f = mix(1.0, 3.0 + 0.5 * float(i), hash(float(i) + 10.0)) * density;
89
+ float f = mix(1.0, 3.0 + 0.5 * float(i), hash11(float(i) * 15.)) * density;
79
90
 
80
91
  float ray = raysShape(rotatedUV, r1, 5.0 * f, intensity, radius);
81
92
  ray *= raysShape(rotatedUV, r2, 4.0 * f, intensity, radius);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/shaders/god-rays.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, declareRandom, declareRotate, declareValueNoise, colorBandingFix } from '../shader-utils.js';\n\nexport const godRaysMeta = {\n maxColorCount: 5,\n} as const;\n\n/**\n * Radial rays animated from center\n *\n * Uniforms:\n * - u_colorBack, u_colorBloom (RGBA)\n * - u_colors (vec4[]), u_colorsCount (float used as integer)\n * - u_density: frequency of sector shapes\n * - u_intensity: rays visibility within sectors\n * - u_spotty: density of spots on the ray (higher = more spots)\n * - u_midSize, u_midIntensity: central shape over the rays\n * - u_bloom (0..1): normal to additive blending mix\n *\n */\n\n// language=GLSL\nexport const godRaysFragmentShader: string = `#version 300 es\nprecision mediump float;\n\nuniform float u_time;\n\nuniform vec4 u_colorBack;\nuniform vec4 u_colorBloom;\nuniform vec4 u_colors[${godRaysMeta.maxColorCount}];\nuniform float u_colorsCount;\n\nuniform float u_density;\nuniform float u_spotty;\nuniform float u_midSize;\nuniform float u_midIntensity;\nuniform float u_intensity;\nuniform float u_bloom;\n\n${sizingVariablesDeclaration}\n\nout vec4 fragColor;\n\n${declarePI}\n${declareRandom}\n${declareRotate}\n${declareValueNoise}\n\nfloat hash(float n) {\n return fract(sin(n * 43758.5453123) * 43758.5453123);\n}\n\nfloat raysShape(vec2 uv, float r, float freq, float intensity, float radius) {\n float a = atan(uv.y, uv.x);\n vec2 left = vec2(a * freq, r);\n vec2 right = vec2(mod(a, TWO_PI) * freq, r);\n float n_left = pow(valueNoise(left), intensity);\n float n_right = pow(valueNoise(right), intensity);\n float shape = mix(n_right, n_left, smoothstep(-.15, .15, uv.x));\n return shape;\n}\n\nvoid main() {\n vec2 shape_uv = v_objectUV;\n\n float t = .2 * u_time;\n\n float radius = length(shape_uv);\n float spots = 5. * abs(u_spotty);\n\n float intensity = 4. - 3. * clamp(u_intensity, 0., 1.);\n\n float delta = 1. - smoothstep(0., 1., radius);\n\n float midSize = 10. * abs(u_midSize);\n float middleShape = pow(u_midIntensity, .3) * smoothstep(midSize, 0.02 * midSize, 3.0 * radius);\n middleShape = pow(middleShape, 5.0);\n\n vec3 accumColor = vec3(0.0);\n float accumAlpha = 0.0;\n\n for (int i = 0; i < ${godRaysMeta.maxColorCount}; i++) {\n if (i >= int(u_colorsCount)) break;\n\n vec2 rotatedUV = rotate(shape_uv, float(i) + 1.0);\n\n float r1 = radius * (1.0 + 0.4 * float(i)) - 3.0 * t;\n float r2 = 0.5 * radius * (1.0 + spots) - 2.0 * t;\n float density = 6. * u_density + step(.5, u_density) * pow(4.5 * (u_density - .5), 4.);\n float f = mix(1.0, 3.0 + 0.5 * float(i), hash(float(i) + 10.0)) * density;\n\n float ray = raysShape(rotatedUV, r1, 5.0 * f, intensity, radius);\n ray *= raysShape(rotatedUV, r2, 4.0 * f, intensity, radius);\n ray += (1. + 4. * ray) * middleShape;\n ray = clamp(ray, 0.0, 1.0);\n\n float srcAlpha = u_colors[i].a * ray;\n vec3 srcColor = u_colors[i].rgb * srcAlpha;\n\n vec3 alphaBlendColor = accumColor + (1.0 - accumAlpha) * srcColor;\n float alphaBlendAlpha = accumAlpha + (1.0 - accumAlpha) * srcAlpha;\n\n vec3 addBlendColor = accumColor + srcColor;\n float addBlendAlpha = accumAlpha + srcAlpha;\n\n accumColor = mix(alphaBlendColor, addBlendColor, u_bloom);\n accumAlpha = mix(alphaBlendAlpha, addBlendAlpha, u_bloom);\n }\n\n float overlayAlpha = u_colorBloom.a;\n vec3 overlayColor = u_colorBloom.rgb * overlayAlpha;\n\n vec3 colorWithOverlay = accumColor + accumAlpha * overlayColor;\n accumColor = mix(accumColor, colorWithOverlay, u_bloom);\n\n vec3 bgColor = u_colorBack.rgb * u_colorBack.a;\n\n vec3 color = accumColor + (1. - accumAlpha) * bgColor;\n float opacity = accumAlpha + (1. - accumAlpha) * u_colorBack.a;\n color = clamp(color, 0., 1.);\n opacity = clamp(opacity, 0., 1.);\n\n ${colorBandingFix}\n\n fragColor = vec4(color, opacity);\n}\n`;\n\nexport interface GodRaysUniforms extends ShaderSizingUniforms {\n u_colorBack: [number, number, number, number];\n u_colorBloom: [number, number, number, number];\n u_colors: vec4[];\n u_colorsCount: number;\n u_spotty: number;\n u_midSize: number;\n u_midIntensity: number;\n u_density: number;\n u_intensity: number;\n u_bloom: number;\n}\n\nexport interface GodRaysParams extends ShaderSizingParams, ShaderMotionParams {\n colorBack?: string;\n colorBloom?: string;\n colors?: string[];\n spotty?: number;\n midSize?: number;\n midIntensity?: number;\n density?: number;\n intensity?: number;\n bloom?: number;\n}\n"],
5
- "mappings": ";;;;;AAEA,SAAS,kCAAsF;AAC/F,SAAS,WAAW,eAAe,eAAe,mBAAmB,uBAAuB;AAErF,MAAM,cAAc;AAAA,EACzB,eAAe;AACjB;AAiBO,MAAM,wBAAgC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAOrB,YAAY,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAU/C,0BAA0B;AAAA;AAAA;AAAA;AAAA,EAI1B,SAAS;AAAA,EACT,aAAa;AAAA,EACb,aAAa;AAAA,EACb,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAmCK,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,IAyC7C,eAAe;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, colorBandingFix, proceduralHash11 } from '../shader-utils.js';\n\nexport const godRaysMeta = {\n maxColorCount: 5,\n} as const;\n\n/**\n * Radial rays animated from center\n *\n * Uniforms:\n * - u_colorBack, u_colorBloom (RGBA)\n * - u_colors (vec4[]), u_colorsCount (float used as integer)\n * - u_density: frequency of sector shapes\n * - u_intensity: rays visibility within sectors\n * - u_spotty: density of spots on the ray (higher = more spots)\n * - u_midSize, u_midIntensity: central shape over the rays\n * - u_bloom (0..1): normal to additive blending mix\n *\n * - u_noiseTexture (sampler2D): pre-computed randomizer source\n */\n\n// language=GLSL\nexport const godRaysFragmentShader: 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_colorBloom;\nuniform vec4 u_colors[${godRaysMeta.maxColorCount}];\nuniform float u_colorsCount;\n\nuniform float u_density;\nuniform float u_spotty;\nuniform float u_midSize;\nuniform float u_midIntensity;\nuniform float u_intensity;\nuniform float u_bloom;\n\n${sizingVariablesDeclaration}\n\nout vec4 fragColor;\n\n${declarePI}\n${rotation2}\n${textureRandomizerR}\nfloat valueNoise(vec2 st) {\n vec2 i = floor(st);\n vec2 f = fract(st);\n float a = randomR(i);\n float b = randomR(i + vec2(1.0, 0.0));\n float c = randomR(i + vec2(0.0, 1.0));\n float d = randomR(i + vec2(1.0, 1.0));\n vec2 u = f * f * (3.0 - 2.0 * f);\n float x1 = mix(a, b, u.x);\n float x2 = mix(c, d, u.x);\n return mix(x1, x2, u.y);\n}\n\n${proceduralHash11}\n\nfloat raysShape(vec2 uv, float r, float freq, float intensity, float radius) {\n float a = atan(uv.y, uv.x);\n vec2 left = vec2(a * freq, r);\n vec2 right = vec2(mod(a, TWO_PI) * freq, r);\n float n_left = pow(valueNoise(left), intensity);\n float n_right = pow(valueNoise(right), intensity);\n float shape = mix(n_right, n_left, smoothstep(-.15, .15, uv.x));\n return shape;\n}\n\nvoid main() {\n vec2 shape_uv = v_objectUV;\n\n float t = .2 * u_time;\n\n float radius = length(shape_uv);\n float spots = 6.5 * abs(u_spotty);\n\n float intensity = 4. - 3. * clamp(u_intensity, 0., 1.);\n\n float delta = 1. - smoothstep(0., 1., radius);\n\n float midSize = 10. * abs(u_midSize);\n float middleShape = pow(u_midIntensity, .3) * smoothstep(midSize, 0.02 * midSize, 3.0 * radius);\n middleShape = pow(middleShape, 5.0);\n\n vec3 accumColor = vec3(0.0);\n float accumAlpha = 0.0;\n\n for (int i = 0; i < ${godRaysMeta.maxColorCount}; i++) {\n if (i >= int(u_colorsCount)) break;\n\n vec2 rotatedUV = rotate(shape_uv, float(i) + 1.0);\n\n float r1 = radius * (1.0 + 0.4 * float(i)) - 3.0 * t;\n float r2 = 0.5 * radius * (1.0 + spots) - 2.0 * t;\n float density = 6. * u_density + step(.5, u_density) * pow(4.5 * (u_density - .5), 4.);\n float f = mix(1.0, 3.0 + 0.5 * float(i), hash11(float(i) * 15.)) * density;\n\n float ray = raysShape(rotatedUV, r1, 5.0 * f, intensity, radius);\n ray *= raysShape(rotatedUV, r2, 4.0 * f, intensity, radius);\n ray += (1. + 4. * ray) * middleShape;\n ray = clamp(ray, 0.0, 1.0);\n\n float srcAlpha = u_colors[i].a * ray;\n vec3 srcColor = u_colors[i].rgb * srcAlpha;\n\n vec3 alphaBlendColor = accumColor + (1.0 - accumAlpha) * srcColor;\n float alphaBlendAlpha = accumAlpha + (1.0 - accumAlpha) * srcAlpha;\n\n vec3 addBlendColor = accumColor + srcColor;\n float addBlendAlpha = accumAlpha + srcAlpha;\n\n accumColor = mix(alphaBlendColor, addBlendColor, u_bloom);\n accumAlpha = mix(alphaBlendAlpha, addBlendAlpha, u_bloom);\n }\n\n float overlayAlpha = u_colorBloom.a;\n vec3 overlayColor = u_colorBloom.rgb * overlayAlpha;\n\n vec3 colorWithOverlay = accumColor + accumAlpha * overlayColor;\n accumColor = mix(accumColor, colorWithOverlay, u_bloom);\n\n vec3 bgColor = u_colorBack.rgb * u_colorBack.a;\n\n vec3 color = accumColor + (1. - accumAlpha) * bgColor;\n float opacity = accumAlpha + (1. - accumAlpha) * u_colorBack.a;\n color = clamp(color, 0., 1.);\n opacity = clamp(opacity, 0., 1.);\n\n ${colorBandingFix}\n\n fragColor = vec4(color, opacity);\n}\n`;\n\nexport interface GodRaysUniforms extends ShaderSizingUniforms {\n u_colorBack: [number, number, number, number];\n u_colorBloom: [number, number, number, number];\n u_colors: vec4[];\n u_colorsCount: number;\n u_spotty: number;\n u_midSize: number;\n u_midIntensity: number;\n u_density: number;\n u_intensity: number;\n u_bloom: number;\n u_noiseTexture?: HTMLImageElement;\n}\n\nexport interface GodRaysParams extends ShaderSizingParams, ShaderMotionParams {\n colorBack?: string;\n colorBloom?: string;\n colors?: string[];\n spotty?: number;\n midSize?: number;\n midIntensity?: number;\n density?: number;\n intensity?: number;\n bloom?: number;\n}\n"],
5
+ "mappings": ";;;;;AAEA,SAAS,kCAAsF;AAC/F,SAAS,WAAW,WAAW,oBAAoB,iBAAiB,wBAAwB;AAErF,MAAM,cAAc;AAAA,EACzB,eAAe;AACjB;AAkBO,MAAM,wBAAgC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBASrB,YAAY,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAU/C,0BAA0B;AAAA;AAAA;AAAA;AAAA,EAI1B,SAAS;AAAA,EACT,SAAS;AAAA,EACT,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAclB,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,wBA+BM,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,IAyC7C,eAAe;AAAA;AAAA;AAAA;AAAA;",
6
6
  "names": []
7
7
  }
@@ -36,6 +36,7 @@ export interface GrainGradientUniforms extends ShaderSizingUniforms {
36
36
  u_intensity: number;
37
37
  u_noise: number;
38
38
  u_shape: (typeof GrainGradientShapes)[GrainGradientShape];
39
+ u_noiseTexture?: HTMLImageElement;
39
40
  }
40
41
  export interface GrainGradientParams extends ShaderSizingParams, ShaderMotionParams {
41
42
  colorBack?: string;
@@ -5,19 +5,25 @@
5
5
 
6
6
  import {
7
7
  sizingVariablesDeclaration,
8
- sizingDebugVariablesDeclaration,
9
- sizingUniformsDeclaration
8
+ sizingDebugVariablesDeclaration
10
9
  } from "../shader-sizing.js";
11
- import { declareSimplexNoise, declarePI, declareValueNoise, declareRotate } from "../shader-utils.js";
10
+ import {
11
+ simplexNoise,
12
+ declarePI,
13
+ rotation2,
14
+ textureRandomizerR,
15
+ proceduralHash21,
16
+ proceduralHash11
17
+ } from "../shader-utils.js";
12
18
  const grainGradientMeta = {
13
19
  maxColorCount: 7
14
20
  };
15
21
  const grainGradientFragmentShader = `#version 300 es
16
- precision mediump float;
22
+ precision lowp float;
17
23
 
18
- uniform float u_time;
19
- uniform vec2 u_resolution;
20
- uniform float u_pixelRatio;
24
+ uniform mediump float u_time;
25
+ uniform mediump vec2 u_resolution;
26
+ uniform mediump float u_pixelRatio;
21
27
 
22
28
  uniform sampler2D u_noiseTexture;
23
29
 
@@ -29,34 +35,53 @@ uniform float u_intensity;
29
35
  uniform float u_noise;
30
36
  uniform float u_shape;
31
37
 
38
+ uniform mediump float u_originX;
39
+ uniform mediump float u_originY;
40
+ uniform mediump float u_worldWidth;
41
+ uniform mediump float u_worldHeight;
42
+ uniform mediump float u_fit;
43
+
44
+ uniform mediump float u_scale;
45
+ uniform mediump float u_rotation;
46
+ uniform mediump float u_offsetX;
47
+ uniform mediump float u_offsetY;
48
+
32
49
  ${sizingVariablesDeclaration}
33
50
  ${sizingDebugVariablesDeclaration}
34
- ${sizingUniformsDeclaration}
35
51
 
36
52
  out vec4 fragColor;
37
53
 
38
54
  ${declarePI}
39
- ${declareSimplexNoise}
40
- ${declareRotate}
41
-
42
- float randomGeneric(vec2 st) {
43
- return fract(sin(dot(st.xy, vec2(12.9898, 78.233))) * 43758.5453123);
44
- }
45
- float random(vec2 p) {
46
- vec2 uv = floor(p) / 100. + .5;
47
- return texture(u_noiseTexture, uv).r;
55
+ ${simplexNoise}
56
+ ${rotation2}
57
+ ${proceduralHash21}
58
+ ${textureRandomizerR}
59
+
60
+ float valueNoiseR(vec2 st) {
61
+ vec2 i = floor(st);
62
+ vec2 f = fract(st);
63
+ float a = randomR(i);
64
+ float b = randomR(i + vec2(1.0, 0.0));
65
+ float c = randomR(i + vec2(0.0, 1.0));
66
+ float d = randomR(i + vec2(1.0, 1.0));
67
+ vec2 u = f * f * (3.0 - 2.0 * f);
68
+ float x1 = mix(a, b, u.x);
69
+ float x2 = mix(c, d, u.x);
70
+ return mix(x1, x2, u.y);
48
71
  }
49
- ${declareValueNoise}
50
- float fbm(in vec2 n) {
51
- float total = 0.0, amplitude = .2;
72
+ float fbmR(vec2 n) {
73
+ float total = 0.;
74
+ float amplitude = .2;
52
75
  for (int i = 0; i < 3; i++) {
53
- total += valueNoise(n) * amplitude;
54
- n += n;
76
+ n = rotate(n, .3);
77
+ total += valueNoiseR(n) * amplitude;
78
+ n *= 1.99;
55
79
  amplitude *= 0.6;
56
80
  }
57
81
  return total;
58
82
  }
59
83
 
84
+ ${proceduralHash11}
60
85
 
61
86
  vec2 truchet(vec2 uv, float idx){
62
87
  idx = fract(((idx - .5) * 2.));
@@ -73,7 +98,7 @@ vec2 truchet(vec2 uv, float idx){
73
98
  void main() {
74
99
 
75
100
  float t = .1 * u_time;
76
-
101
+
77
102
  vec2 shape_uv = vec2(0.);
78
103
  vec2 grain_uv = vec2(0.);
79
104
 
@@ -84,7 +109,7 @@ void main() {
84
109
  // apply inverse transform to grain_uv so it respects the originXY
85
110
  float r = u_rotation * 3.14159265358979323846 / 180.;
86
111
  mat2 graphicRotation = mat2(cos(r), sin(r), -sin(r), cos(r));
87
- vec2 graphicOffset = vec2(-u_offsetX, u_offsetY);
112
+ vec2 graphicOffset = vec2(-u_offsetX, u_offsetY);
88
113
  grain_uv = transpose(graphicRotation) * grain_uv;
89
114
  grain_uv *= u_scale;
90
115
  grain_uv -= graphicOffset;
@@ -93,11 +118,11 @@ void main() {
93
118
  } else {
94
119
  shape_uv = .5 * v_patternUV;
95
120
  grain_uv = 100. * v_patternUV;
96
-
121
+
97
122
  // apply inverse transform to grain_uv so it respects the originXY
98
123
  float r = u_rotation * 3.14159265358979323846 / 180.;
99
124
  mat2 graphicRotation = mat2(cos(r), sin(r), -sin(r), cos(r));
100
- vec2 graphicOffset = vec2(-u_offsetX, u_offsetY);
125
+ vec2 graphicOffset = vec2(-u_offsetX, u_offsetY);
101
126
  grain_uv = transpose(graphicRotation) * grain_uv;
102
127
  grain_uv *= u_scale;
103
128
  if (u_fit > 0.) {
@@ -130,20 +155,19 @@ void main() {
130
155
  // Grid (dots)
131
156
 
132
157
  float stripeIdx = floor(2. * shape_uv.x / TWO_PI);
133
- float rand = fract(sin(stripeIdx * 12.9898) * 43758.5453);
134
-
135
- float speed = sign(rand - .5) * ceil(2. + rand);
136
- shape = sin(shape_uv.x) * cos(shape_uv.y + speed * t);
158
+ float rand = hash11(stripeIdx + 2.);
159
+ rand = sign(rand - .5) * pow(.2 + abs(rand), .3);
160
+ shape = sin(shape_uv.x) * cos(shape_uv.y - 5. * rand * t);
137
161
  shape = pow(shape, 4.);
138
162
 
139
163
  } else if (u_shape < 3.5) {
140
164
  // Truchet pattern
141
-
142
- float n2 = valueNoise(shape_uv * .4 - 3.75 * t);
165
+
166
+ float n2 = valueNoiseR(shape_uv * .4 - 3.75 * t);
143
167
  shape_uv.x += 10.;
144
168
  shape_uv *= .6;
145
169
 
146
- vec2 tile = truchet(fract(shape_uv), randomGeneric(floor(shape_uv)));
170
+ vec2 tile = truchet(fract(shape_uv), randomR(floor(shape_uv)));
147
171
 
148
172
  float distance1 = length(tile);
149
173
  float distance2 = length(tile - vec2(1.));
@@ -203,18 +227,17 @@ void main() {
203
227
  // Sphere
204
228
 
205
229
  shape_uv *= 2.;
206
- float d = length(shape_uv);
207
- float z = sqrt(1.0 - clamp(pow(d, 2.0), 0.0, 1.0));
208
- vec3 pos = vec3(shape_uv, z);
209
- vec3 lightPos = normalize(vec3(cos(4.5 * t), 0.8, sin(3.75 * t)));
210
- float lighting = dot(lightPos, pos);
211
- float edge = smoothstep(1., .97, d);
212
- shape = mix(.1, .5 + .5 * lighting, edge);
230
+ float d = 1. - pow(length(shape_uv), 2.);
231
+ vec3 pos = vec3(shape_uv, sqrt(d));
232
+ vec3 lightPos = normalize(vec3(cos(1.5 * t), .8, sin(1.25 * t)));
233
+ shape = .5 + .5 * dot(lightPos, pos);
234
+ shape *= step(0., d);
213
235
  }
214
236
 
215
237
  float simplex = snoise(grain_uv * .5);
216
- float grainDist = simplex * snoise(grain_uv * .2) - fbm(.002 * grain_uv + 10.) - fbm(.003 * grain_uv);
217
- float noise = clamp(.65 * simplex - fbm(rotate(.4 * grain_uv, 2.)) - fbm(.001 * grain_uv), 0., 1.);
238
+ float grainDist = simplex * snoise(grain_uv * .2) - fbmR(.002 * grain_uv + 10.) - fbmR(.003 * grain_uv);
239
+ float rawNoise = .6 * simplex - fbmR(rotate(.4 * grain_uv, 2.)) - fbmR(.001 * grain_uv);
240
+ float noise = clamp(rawNoise, 0., 1.);
218
241
 
219
242
  shape += u_intensity * 2. / u_colorsCount * (grainDist + .5);
220
243
  shape += u_noise * 10. / u_colorsCount * noise;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/shaders/grain-gradient.ts"],
4
- "sourcesContent": ["import type { vec4 } from '../types.js';\nimport type { ShaderMotionParams } from '../shader-mount.js';\nimport {\n sizingVariablesDeclaration,\n type ShaderSizingParams,\n type ShaderSizingUniforms,\n sizingDebugVariablesDeclaration,\n sizingUniformsDeclaration,\n} from '../shader-sizing.js';\nimport { declareSimplexNoise, declarePI, declareValueNoise, declareRotate } from '../shader-utils.js';\n\nexport const grainGradientMeta = {\n maxColorCount: 7,\n} as const;\n\n/**\n * Multi-color gradient with noise & grain over animated abstract shapes\n *\n * Uniforms:\n * - u_colorBack (RGBA)\n * - u_colors (vec4[]), u_colorsCount (float used as integer)\n * - u_softness (0..1): blur between color bands\n * - u_intensity (0..1): distortion between color bands\n * - u_noise (0..1): grainy noise independent of softness\n * - u_shape (float used as integer):\n * ---- 1: single sine wave\n * ---- 2: dots pattern\n * ---- 3: truchet pattern\n * ---- 4: corners (2 rounded rectangles)\n * ---- 5: ripple\n * ---- 6: blob (metaballs)\n * ---- 7: circle imitating 3d look\n *\n * - u_noiseTexture (sampler2D): pre-computed randomizer source\n *\n * Note: grains are calculated using gl_FragCoord & u_resolution, meaning grains don't react to scaling and fit\n *\n */\n\n// language=GLSL\nexport const grainGradientFragmentShader: string = `#version 300 es\nprecision mediump float;\n\nuniform float u_time;\nuniform vec2 u_resolution;\nuniform float u_pixelRatio;\n\nuniform sampler2D u_noiseTexture;\n\nuniform vec4 u_colorBack;\nuniform vec4 u_colors[${grainGradientMeta.maxColorCount}];\nuniform float u_colorsCount;\nuniform float u_softness;\nuniform float u_intensity;\nuniform float u_noise;\nuniform float u_shape;\n\n${sizingVariablesDeclaration}\n${sizingDebugVariablesDeclaration}\n${sizingUniformsDeclaration}\n\nout vec4 fragColor;\n\n${declarePI}\n${declareSimplexNoise}\n${declareRotate}\n\nfloat randomGeneric(vec2 st) {\n return fract(sin(dot(st.xy, vec2(12.9898, 78.233))) * 43758.5453123);\n}\nfloat random(vec2 p) {\n vec2 uv = floor(p) / 100. + .5;\n return texture(u_noiseTexture, uv).r;\n}\n${declareValueNoise}\nfloat fbm(in vec2 n) {\n float total = 0.0, amplitude = .2;\n for (int i = 0; i < 3; i++) {\n total += valueNoise(n) * amplitude;\n n += n;\n amplitude *= 0.6;\n }\n return total;\n}\n\n\nvec2 truchet(vec2 uv, float idx){\n idx = fract(((idx - .5) * 2.));\n if (idx > 0.75) {\n uv = vec2(1.0) - uv;\n } else if (idx > 0.5) {\n uv = vec2(1.0 - uv.x, uv.y);\n } else if (idx > 0.25) {\n uv = 1.0 - vec2(1.0 - uv.x, uv.y);\n }\n return uv;\n}\n\nvoid main() {\n\n float t = .1 * u_time;\n \n vec2 shape_uv = vec2(0.);\n vec2 grain_uv = vec2(0.);\n\n if (u_shape > 3.5) {\n shape_uv = v_objectUV;\n grain_uv = shape_uv;\n\n // apply inverse transform to grain_uv so it respects the originXY\n float r = u_rotation * 3.14159265358979323846 / 180.;\n mat2 graphicRotation = mat2(cos(r), sin(r), -sin(r), cos(r));\n vec2 graphicOffset = vec2(-u_offsetX, u_offsetY); \n grain_uv = transpose(graphicRotation) * grain_uv;\n grain_uv *= u_scale;\n grain_uv -= graphicOffset;\n grain_uv *= v_objectBoxSize;\n grain_uv *= .7;\n } else {\n shape_uv = .5 * v_patternUV;\n grain_uv = 100. * v_patternUV;\n \n // apply inverse transform to grain_uv so it respects the originXY\n float r = u_rotation * 3.14159265358979323846 / 180.;\n mat2 graphicRotation = mat2(cos(r), sin(r), -sin(r), cos(r));\n vec2 graphicOffset = vec2(-u_offsetX, u_offsetY); \n grain_uv = transpose(graphicRotation) * grain_uv;\n grain_uv *= u_scale;\n if (u_fit > 0.) {\n vec2 givenBoxSize = vec2(u_worldWidth, u_worldHeight);\n givenBoxSize = max(givenBoxSize, vec2(1.)) * u_pixelRatio;\n float patternBoxRatio = givenBoxSize.x / givenBoxSize.y;\n vec2 patternBoxGivenSize = vec2(\n (u_worldWidth == 0.) ? u_resolution.x : givenBoxSize.x,\n (u_worldHeight == 0.) ? u_resolution.y : givenBoxSize.y\n );\n patternBoxRatio = patternBoxGivenSize.x / patternBoxGivenSize.y;\n float patternBoxNoFitBoxWidth = patternBoxRatio * min(patternBoxGivenSize.x / patternBoxRatio, patternBoxGivenSize.y);\n grain_uv /= (patternBoxNoFitBoxWidth / v_patternBoxSize.x);\n }\n vec2 patternBoxScale = u_resolution.xy / v_patternBoxSize;\n grain_uv -= graphicOffset / patternBoxScale;\n grain_uv *= 1.6;\n }\n\n\n float shape = 0.;\n\n if (u_shape < 1.5) {\n // Sine wave\n\n float wave = cos(.5 * shape_uv.x - 4. * t) * sin(1.5 * shape_uv.x + 2. * t) * (.75 + .25 * cos(6. * t));\n shape = 1. - smoothstep(-1., 1., shape_uv.y + wave);\n\n } else if (u_shape < 2.5) {\n // Grid (dots)\n\n float stripeIdx = floor(2. * shape_uv.x / TWO_PI);\n float rand = fract(sin(stripeIdx * 12.9898) * 43758.5453);\n\n float speed = sign(rand - .5) * ceil(2. + rand);\n shape = sin(shape_uv.x) * cos(shape_uv.y + speed * t);\n shape = pow(shape, 4.);\n\n } else if (u_shape < 3.5) {\n // Truchet pattern\n \n float n2 = valueNoise(shape_uv * .4 - 3.75 * t);\n shape_uv.x += 10.;\n shape_uv *= .6;\n\n vec2 tile = truchet(fract(shape_uv), randomGeneric(floor(shape_uv)));\n\n float distance1 = length(tile);\n float distance2 = length(tile - vec2(1.));\n\n n2 -= .5;\n n2 *= .1;\n shape = smoothstep(.2, .55, distance1 + n2) * smoothstep(.8, .45, distance1 - n2);\n shape += smoothstep(.2, .55, distance2 + n2) * smoothstep(.8, .45, distance2 - n2);\n\n shape = pow(shape, 1.5);\n\n } else if (u_shape < 4.5) {\n // Corners\n\n shape_uv *= .6;\n vec2 outer = vec2(.5);\n\n vec2 bl = smoothstep(vec2(0.), outer, shape_uv + vec2(.1 + .1 * sin(3. * t), .2 - .1 * sin(5.25 * t)));\n vec2 tr = smoothstep(vec2(0.), outer, 1. - shape_uv);\n shape = 1. - bl.x * bl.y * tr.x * tr.y;\n\n shape_uv = -shape_uv;\n bl = smoothstep(vec2(0.), outer, shape_uv + vec2(.1 + .1 * sin(3. * t), .2 - .1 * cos(5.25 * t)));\n tr = smoothstep(vec2(0.), outer, 1. - shape_uv);\n shape -= bl.x * bl.y * tr.x * tr.y;\n\n shape = 1. - smoothstep(0., 1., shape);\n\n } else if (u_shape < 5.5) {\n // Ripple\n\n shape_uv *= 2.;\n float dist = length(.4 * shape_uv);\n float waves = sin(pow(dist, 1.2) * 5. - 3. * t) * .5 + .5;\n shape = waves;\n\n } else if (u_shape < 6.5) {\n // Blob\n\n t *= 2.;\n\n vec2 f1_traj = .25 * vec2(1.3 * sin(t), .2 + 1.3 * cos(.6 * t + 4.));\n vec2 f2_traj = .2 * vec2(1.2 * sin(-t), 1.3 * sin(1.6 * t));\n vec2 f3_traj = .25 * vec2(1.7 * cos(-.6 * t), cos(-1.6 * t));\n vec2 f4_traj = .3 * vec2(1.4 * cos(.8 * t), 1.2 * sin(-.6 * t - 3.));\n\n shape = .5 * pow(1. - clamp(0., 1., length(shape_uv + f1_traj)), 5.);\n shape += .5 * pow(1. - clamp(0., 1., length(shape_uv + f2_traj)), 5.);\n shape += .5 * pow(1. - clamp(0., 1., length(shape_uv + f3_traj)), 5.);\n shape += .5 * pow(1. - clamp(0., 1., length(shape_uv + f4_traj)), 5.);\n\n shape = smoothstep(.0, .9, shape);\n float edge = smoothstep(.25, .3, shape);\n shape = mix(.0, shape, edge);\n\n } else {\n // Sphere\n\n shape_uv *= 2.;\n float d = length(shape_uv);\n float z = sqrt(1.0 - clamp(pow(d, 2.0), 0.0, 1.0));\n vec3 pos = vec3(shape_uv, z);\n vec3 lightPos = normalize(vec3(cos(4.5 * t), 0.8, sin(3.75 * t)));\n float lighting = dot(lightPos, pos);\n float edge = smoothstep(1., .97, d);\n shape = mix(.1, .5 + .5 * lighting, edge);\n }\n\n float simplex = snoise(grain_uv * .5);\n float grainDist = simplex * snoise(grain_uv * .2) - fbm(.002 * grain_uv + 10.) - fbm(.003 * grain_uv);\n float noise = clamp(.65 * simplex - fbm(rotate(.4 * grain_uv, 2.)) - fbm(.001 * grain_uv), 0., 1.);\n\n shape += u_intensity * 2. / u_colorsCount * (grainDist + .5);\n shape += u_noise * 10. / u_colorsCount * noise;\n\n float aa = fwidth(shape);\n\n shape = clamp(shape - .5 / u_colorsCount, 0., 1.);\n float totalShape = smoothstep(0., u_softness + 2. * aa, clamp(shape * u_colorsCount, 0., 1.));\n float mixer = shape * (u_colorsCount - 1.);\n\n vec4 gradient = u_colors[0];\n gradient.rgb *= gradient.a;\n for (int i = 1; i < ${grainGradientMeta.maxColorCount}; i++) {\n if (i > int(u_colorsCount) - 1) break;\n\n float localT = clamp(mixer - float(i - 1), 0., 1.);\n localT = smoothstep(.5 - .5 * u_softness - aa, .5 + .5 * u_softness + aa, localT);\n\n vec4 c = u_colors[i];\n c.rgb *= c.a;\n gradient = mix(gradient, c, localT);\n }\n\n vec3 color = gradient.rgb * totalShape;\n float opacity = gradient.a * totalShape;\n\n vec3 bgColor = u_colorBack.rgb * u_colorBack.a;\n color = color + bgColor * (1.0 - opacity);\n opacity = opacity + u_colorBack.a * (1.0 - opacity);\n\n fragColor = vec4(color, opacity);\n}\n`;\n\nexport interface GrainGradientUniforms extends ShaderSizingUniforms {\n u_colorBack: [number, number, number, number];\n u_colors: vec4[];\n u_colorsCount: number;\n u_softness: number;\n u_intensity: number;\n u_noise: number;\n u_shape: (typeof GrainGradientShapes)[GrainGradientShape];\n}\n\nexport interface GrainGradientParams extends ShaderSizingParams, ShaderMotionParams {\n colorBack?: string;\n colors?: string[];\n softness?: number;\n intensity?: number;\n noise?: number;\n shape?: GrainGradientShape;\n}\n\nexport const GrainGradientShapes = {\n wave: 1,\n dots: 2,\n truchet: 3,\n corners: 4,\n ripple: 5,\n blob: 6,\n sphere: 7,\n};\n\nexport type GrainGradientShape = keyof typeof GrainGradientShapes;\n"],
5
- "mappings": ";;;;;AAEA;AAAA,EACE;AAAA,EAGA;AAAA,EACA;AAAA,OACK;AACP,SAAS,qBAAqB,WAAW,mBAAmB,qBAAqB;AAE1E,MAAM,oBAAoB;AAAA,EAC/B,eAAe;AACjB;AA2BO,MAAM,8BAAsC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAU3B,kBAAkB,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOrD,0BAA0B;AAAA,EAC1B,+BAA+B;AAAA,EAC/B,yBAAyB;AAAA;AAAA;AAAA;AAAA,EAIzB,SAAS;AAAA,EACT,mBAAmB;AAAA,EACnB,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASb,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAqLK,kBAAkB,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAyChD,MAAM,sBAAsB;AAAA,EACjC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,SAAS;AAAA,EACT,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,QAAQ;AACV;",
4
+ "sourcesContent": ["import type { vec4 } from '../types.js';\nimport type { ShaderMotionParams } from '../shader-mount.js';\nimport {\n sizingVariablesDeclaration,\n type ShaderSizingParams,\n type ShaderSizingUniforms,\n sizingDebugVariablesDeclaration,\n} from '../shader-sizing.js';\nimport {\n simplexNoise,\n declarePI,\n rotation2,\n textureRandomizerR,\n proceduralHash21,\n proceduralHash11,\n} from '../shader-utils.js';\n\nexport const grainGradientMeta = {\n maxColorCount: 7,\n} as const;\n\n/**\n * Multi-color gradient with noise & grain over animated abstract shapes\n *\n * Uniforms:\n * - u_colorBack (RGBA)\n * - u_colors (vec4[]), u_colorsCount (float used as integer)\n * - u_softness (0..1): blur between color bands\n * - u_intensity (0..1): distortion between color bands\n * - u_noise (0..1): grainy noise independent of softness\n * - u_shape (float used as integer):\n * ---- 1: single sine wave\n * ---- 2: dots pattern\n * ---- 3: truchet pattern\n * ---- 4: corners (2 rounded rectangles)\n * ---- 5: ripple\n * ---- 6: blob (metaballs)\n * ---- 7: circle imitating 3d look\n *\n * - u_noiseTexture (sampler2D): pre-computed randomizer source\n *\n * Note: grains are calculated using gl_FragCoord & u_resolution, meaning grains don't react to scaling and fit\n *\n */\n\n// language=GLSL\nexport const grainGradientFragmentShader: string = `#version 300 es\nprecision lowp float;\n\nuniform mediump float u_time;\nuniform mediump vec2 u_resolution;\nuniform mediump float u_pixelRatio;\n\nuniform sampler2D u_noiseTexture;\n\nuniform vec4 u_colorBack;\nuniform vec4 u_colors[${grainGradientMeta.maxColorCount}];\nuniform float u_colorsCount;\nuniform float u_softness;\nuniform float u_intensity;\nuniform float u_noise;\nuniform float u_shape;\n\nuniform mediump float u_originX;\nuniform mediump float u_originY;\nuniform mediump float u_worldWidth;\nuniform mediump float u_worldHeight;\nuniform mediump float u_fit;\n\nuniform mediump float u_scale;\nuniform mediump float u_rotation;\nuniform mediump float u_offsetX;\nuniform mediump float u_offsetY;\n\n${sizingVariablesDeclaration}\n${ sizingDebugVariablesDeclaration }\n\nout vec4 fragColor;\n\n${declarePI}\n${simplexNoise}\n${rotation2}\n${proceduralHash21}\n${textureRandomizerR}\n\nfloat valueNoiseR(vec2 st) {\n vec2 i = floor(st);\n vec2 f = fract(st);\n float a = randomR(i);\n float b = randomR(i + vec2(1.0, 0.0));\n float c = randomR(i + vec2(0.0, 1.0));\n float d = randomR(i + vec2(1.0, 1.0));\n vec2 u = f * f * (3.0 - 2.0 * f);\n float x1 = mix(a, b, u.x);\n float x2 = mix(c, d, u.x);\n return mix(x1, x2, u.y);\n}\nfloat fbmR(vec2 n) {\n float total = 0.;\n float amplitude = .2;\n for (int i = 0; i < 3; i++) {\n n = rotate(n, .3);\n total += valueNoiseR(n) * amplitude;\n n *= 1.99;\n amplitude *= 0.6;\n }\n return total;\n}\n\n${proceduralHash11}\n\nvec2 truchet(vec2 uv, float idx){\n idx = fract(((idx - .5) * 2.));\n if (idx > 0.75) {\n uv = vec2(1.0) - uv;\n } else if (idx > 0.5) {\n uv = vec2(1.0 - uv.x, uv.y);\n } else if (idx > 0.25) {\n uv = 1.0 - vec2(1.0 - uv.x, uv.y);\n }\n return uv;\n}\n\nvoid main() {\n\n float t = .1 * u_time;\n\n vec2 shape_uv = vec2(0.);\n vec2 grain_uv = vec2(0.);\n\n if (u_shape > 3.5) {\n shape_uv = v_objectUV;\n grain_uv = shape_uv;\n\n // apply inverse transform to grain_uv so it respects the originXY\n float r = u_rotation * 3.14159265358979323846 / 180.;\n mat2 graphicRotation = mat2(cos(r), sin(r), -sin(r), cos(r));\n vec2 graphicOffset = vec2(-u_offsetX, u_offsetY);\n grain_uv = transpose(graphicRotation) * grain_uv;\n grain_uv *= u_scale;\n grain_uv -= graphicOffset;\n grain_uv *= v_objectBoxSize;\n grain_uv *= .7;\n } else {\n shape_uv = .5 * v_patternUV;\n grain_uv = 100. * v_patternUV;\n\n // apply inverse transform to grain_uv so it respects the originXY\n float r = u_rotation * 3.14159265358979323846 / 180.;\n mat2 graphicRotation = mat2(cos(r), sin(r), -sin(r), cos(r));\n vec2 graphicOffset = vec2(-u_offsetX, u_offsetY);\n grain_uv = transpose(graphicRotation) * grain_uv;\n grain_uv *= u_scale;\n if (u_fit > 0.) {\n vec2 givenBoxSize = vec2(u_worldWidth, u_worldHeight);\n givenBoxSize = max(givenBoxSize, vec2(1.)) * u_pixelRatio;\n float patternBoxRatio = givenBoxSize.x / givenBoxSize.y;\n vec2 patternBoxGivenSize = vec2(\n (u_worldWidth == 0.) ? u_resolution.x : givenBoxSize.x,\n (u_worldHeight == 0.) ? u_resolution.y : givenBoxSize.y\n );\n patternBoxRatio = patternBoxGivenSize.x / patternBoxGivenSize.y;\n float patternBoxNoFitBoxWidth = patternBoxRatio * min(patternBoxGivenSize.x / patternBoxRatio, patternBoxGivenSize.y);\n grain_uv /= (patternBoxNoFitBoxWidth / v_patternBoxSize.x);\n }\n vec2 patternBoxScale = u_resolution.xy / v_patternBoxSize;\n grain_uv -= graphicOffset / patternBoxScale;\n grain_uv *= 1.6;\n }\n\n\n float shape = 0.;\n\n if (u_shape < 1.5) {\n // Sine wave\n\n float wave = cos(.5 * shape_uv.x - 4. * t) * sin(1.5 * shape_uv.x + 2. * t) * (.75 + .25 * cos(6. * t));\n shape = 1. - smoothstep(-1., 1., shape_uv.y + wave);\n\n } else if (u_shape < 2.5) {\n // Grid (dots)\n\n float stripeIdx = floor(2. * shape_uv.x / TWO_PI);\n float rand = hash11(stripeIdx + 2.);\n rand = sign(rand - .5) * pow(.2 + abs(rand), .3);\n shape = sin(shape_uv.x) * cos(shape_uv.y - 5. * rand * t);\n shape = pow(shape, 4.);\n\n } else if (u_shape < 3.5) {\n // Truchet pattern\n\n float n2 = valueNoiseR(shape_uv * .4 - 3.75 * t);\n shape_uv.x += 10.;\n shape_uv *= .6;\n\n vec2 tile = truchet(fract(shape_uv), randomR(floor(shape_uv)));\n\n float distance1 = length(tile);\n float distance2 = length(tile - vec2(1.));\n\n n2 -= .5;\n n2 *= .1;\n shape = smoothstep(.2, .55, distance1 + n2) * smoothstep(.8, .45, distance1 - n2);\n shape += smoothstep(.2, .55, distance2 + n2) * smoothstep(.8, .45, distance2 - n2);\n\n shape = pow(shape, 1.5);\n\n } else if (u_shape < 4.5) {\n // Corners\n\n shape_uv *= .6;\n vec2 outer = vec2(.5);\n\n vec2 bl = smoothstep(vec2(0.), outer, shape_uv + vec2(.1 + .1 * sin(3. * t), .2 - .1 * sin(5.25 * t)));\n vec2 tr = smoothstep(vec2(0.), outer, 1. - shape_uv);\n shape = 1. - bl.x * bl.y * tr.x * tr.y;\n\n shape_uv = -shape_uv;\n bl = smoothstep(vec2(0.), outer, shape_uv + vec2(.1 + .1 * sin(3. * t), .2 - .1 * cos(5.25 * t)));\n tr = smoothstep(vec2(0.), outer, 1. - shape_uv);\n shape -= bl.x * bl.y * tr.x * tr.y;\n\n shape = 1. - smoothstep(0., 1., shape);\n\n } else if (u_shape < 5.5) {\n // Ripple\n\n shape_uv *= 2.;\n float dist = length(.4 * shape_uv);\n float waves = sin(pow(dist, 1.2) * 5. - 3. * t) * .5 + .5;\n shape = waves;\n\n } else if (u_shape < 6.5) {\n // Blob\n\n t *= 2.;\n\n vec2 f1_traj = .25 * vec2(1.3 * sin(t), .2 + 1.3 * cos(.6 * t + 4.));\n vec2 f2_traj = .2 * vec2(1.2 * sin(-t), 1.3 * sin(1.6 * t));\n vec2 f3_traj = .25 * vec2(1.7 * cos(-.6 * t), cos(-1.6 * t));\n vec2 f4_traj = .3 * vec2(1.4 * cos(.8 * t), 1.2 * sin(-.6 * t - 3.));\n\n shape = .5 * pow(1. - clamp(0., 1., length(shape_uv + f1_traj)), 5.);\n shape += .5 * pow(1. - clamp(0., 1., length(shape_uv + f2_traj)), 5.);\n shape += .5 * pow(1. - clamp(0., 1., length(shape_uv + f3_traj)), 5.);\n shape += .5 * pow(1. - clamp(0., 1., length(shape_uv + f4_traj)), 5.);\n\n shape = smoothstep(.0, .9, shape);\n float edge = smoothstep(.25, .3, shape);\n shape = mix(.0, shape, edge);\n\n } else {\n // Sphere\n\n shape_uv *= 2.;\n float d = 1. - pow(length(shape_uv), 2.);\n vec3 pos = vec3(shape_uv, sqrt(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 float simplex = snoise(grain_uv * .5);\n float grainDist = simplex * snoise(grain_uv * .2) - fbmR(.002 * grain_uv + 10.) - fbmR(.003 * grain_uv);\n float rawNoise = .6 * simplex - fbmR(rotate(.4 * grain_uv, 2.)) - fbmR(.001 * grain_uv);\n float noise = clamp(rawNoise, 0., 1.);\n\n shape += u_intensity * 2. / u_colorsCount * (grainDist + .5);\n shape += u_noise * 10. / u_colorsCount * noise;\n\n float aa = fwidth(shape);\n\n shape = clamp(shape - .5 / u_colorsCount, 0., 1.);\n float totalShape = smoothstep(0., u_softness + 2. * aa, clamp(shape * u_colorsCount, 0., 1.));\n float mixer = shape * (u_colorsCount - 1.);\n\n vec4 gradient = u_colors[0];\n gradient.rgb *= gradient.a;\n for (int i = 1; i < ${grainGradientMeta.maxColorCount}; i++) {\n if (i > int(u_colorsCount) - 1) break;\n\n float localT = clamp(mixer - float(i - 1), 0., 1.);\n localT = smoothstep(.5 - .5 * u_softness - aa, .5 + .5 * u_softness + aa, localT);\n\n vec4 c = u_colors[i];\n c.rgb *= c.a;\n gradient = mix(gradient, c, localT);\n }\n\n vec3 color = gradient.rgb * totalShape;\n float opacity = gradient.a * totalShape;\n\n vec3 bgColor = u_colorBack.rgb * u_colorBack.a;\n color = color + bgColor * (1.0 - opacity);\n opacity = opacity + u_colorBack.a * (1.0 - opacity);\n\n fragColor = vec4(color, opacity);\n}\n`;\n\nexport interface GrainGradientUniforms extends ShaderSizingUniforms {\n u_colorBack: [number, number, number, number];\n u_colors: vec4[];\n u_colorsCount: number;\n u_softness: number;\n u_intensity: number;\n u_noise: number;\n u_shape: (typeof GrainGradientShapes)[GrainGradientShape];\n u_noiseTexture?: HTMLImageElement;\n}\n\nexport interface GrainGradientParams extends ShaderSizingParams, ShaderMotionParams {\n colorBack?: string;\n colors?: string[];\n softness?: number;\n intensity?: number;\n noise?: number;\n shape?: GrainGradientShape;\n}\n\nexport const GrainGradientShapes = {\n wave: 1,\n dots: 2,\n truchet: 3,\n corners: 4,\n ripple: 5,\n blob: 6,\n sphere: 7,\n};\n\nexport type GrainGradientShape = keyof typeof GrainGradientShapes;\n"],
5
+ "mappings": ";;;;;AAEA;AAAA,EACE;AAAA,EAGA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEA,MAAM,oBAAoB;AAAA,EAC/B,eAAe;AACjB;AA2BO,MAAM,8BAAsC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAU3B,kBAAkB,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBrD,0BAA0B;AAAA,EACzB,+BAAgC;AAAA;AAAA;AAAA;AAAA,EAIjC,SAAS;AAAA,EACT,YAAY;AAAA,EACZ,SAAS;AAAA,EACT,gBAAgB;AAAA,EAChB,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA0BlB,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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAyKM,kBAAkB,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA0ChD,MAAM,sBAAsB;AAAA,EACjC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,SAAS;AAAA,EACT,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,QAAQ;AACV;",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,49 @@
1
+ import type { ShaderMotionParams } from '../shader-mount.js';
2
+ import { type ShaderSizingParams, type ShaderSizingUniforms } from '../shader-sizing.js';
3
+ /**
4
+ * Dithering effect over user texture using 3-color palette
5
+ * or colors sampled from original image
6
+ *
7
+ * Uniforms:
8
+ * - u_colorBack, u_colorFront, u_colorHighlight (RGBA)
9
+ * (u_colorHighlight to be the lightest parts of u_colorFront pixels)
10
+ * - pxSize: px size set relative to canvas resolution
11
+ * - u_type (float used as integer)
12
+ * ---- 1: random dithering
13
+ * ---- 2: 2x2 Bayer matrix
14
+ * ---- 3: 4x4 Bayer matrix
15
+ * ---- 4: 8x8 Bayer matrix
16
+ * - u_originalColors - switching between 3 colors palette and original image colors
17
+ * - u_colorSteps - number of colors to use (applies to both color modes)
18
+ *
19
+ * Note: pixelization is applied to the shapes BEFORE dithering,
20
+ * meaning pixels don't react to scaling and fit
21
+ */
22
+ export declare const imageDitheringFragmentShader: string;
23
+ export interface ImageDitheringUniforms extends ShaderSizingUniforms {
24
+ u_image: HTMLImageElement | string | undefined;
25
+ u_colorFront: [number, number, number, number];
26
+ u_colorBack: [number, number, number, number];
27
+ u_colorHighlight: [number, number, number, number];
28
+ u_type: (typeof DitheringTypes)[DitheringType];
29
+ u_pxSize: number;
30
+ u_colorSteps: number;
31
+ u_originalColors: boolean;
32
+ }
33
+ export interface ImageDitheringParams extends ShaderSizingParams, ShaderMotionParams {
34
+ image?: HTMLImageElement | string | undefined;
35
+ colorFront?: string;
36
+ colorBack?: string;
37
+ colorHighlight?: string;
38
+ type?: DitheringType;
39
+ pxSize?: number;
40
+ colorSteps?: number;
41
+ originalColors?: boolean;
42
+ }
43
+ export declare const DitheringTypes: {
44
+ readonly random: 1;
45
+ readonly '2x2': 2;
46
+ readonly '4x4': 3;
47
+ readonly '8x8': 4;
48
+ };
49
+ export type DitheringType = keyof typeof DitheringTypes;