@paper-design/shaders 0.0.67 → 0.0.69

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/dist/index.d.ts +29 -18
  2. package/dist/index.js +6 -0
  3. package/dist/index.js.map +2 -2
  4. package/dist/shader-sizing.d.ts +0 -5
  5. package/dist/shader-sizing.js +1 -193
  6. package/dist/shader-sizing.js.map +2 -2
  7. package/dist/shaders/color-panels.d.ts +32 -12
  8. package/dist/shaders/color-panels.js +5 -5
  9. package/dist/shaders/color-panels.js.map +2 -2
  10. package/dist/shaders/dithering.d.ts +25 -19
  11. package/dist/shaders/dithering.js +114 -66
  12. package/dist/shaders/dithering.js.map +2 -2
  13. package/dist/shaders/dot-grid.d.ts +28 -14
  14. package/dist/shaders/dot-grid.js +2 -2
  15. package/dist/shaders/dot-grid.js.map +2 -2
  16. package/dist/shaders/dot-orbit.d.ts +27 -9
  17. package/dist/shaders/dot-orbit.js +8 -9
  18. package/dist/shaders/dot-orbit.js.map +2 -2
  19. package/dist/shaders/fluted-glass.d.ts +43 -18
  20. package/dist/shaders/fluted-glass.js +20 -51
  21. package/dist/shaders/fluted-glass.js.map +2 -2
  22. package/dist/shaders/god-rays.d.ts +32 -10
  23. package/dist/shaders/god-rays.js +2 -2
  24. package/dist/shaders/god-rays.js.map +2 -2
  25. package/dist/shaders/grain-gradient.d.ts +41 -17
  26. package/dist/shaders/grain-gradient.js +47 -33
  27. package/dist/shaders/grain-gradient.js.map +2 -2
  28. package/dist/shaders/halftone-cmyk.d.ts +105 -0
  29. package/dist/shaders/halftone-cmyk.js +290 -0
  30. package/dist/shaders/halftone-cmyk.js.map +7 -0
  31. package/dist/shaders/halftone-dots.d.ts +35 -6
  32. package/dist/shaders/halftone-dots.js +18 -55
  33. package/dist/shaders/halftone-dots.js.map +2 -2
  34. package/dist/shaders/heatmap.d.ts +36 -0
  35. package/dist/shaders/heatmap.js +98 -16
  36. package/dist/shaders/heatmap.js.map +2 -2
  37. package/dist/shaders/image-dithering.d.ts +29 -15
  38. package/dist/shaders/image-dithering.js +68 -37
  39. package/dist/shaders/image-dithering.js.map +2 -2
  40. package/dist/shaders/liquid-metal.d.ts +38 -14
  41. package/dist/shaders/liquid-metal.js +5 -2
  42. package/dist/shaders/liquid-metal.js.map +2 -2
  43. package/dist/shaders/mesh-gradient.d.ts +27 -8
  44. package/dist/shaders/mesh-gradient.js +1 -7
  45. package/dist/shaders/mesh-gradient.js.map +2 -2
  46. package/dist/shaders/metaballs.d.ts +24 -8
  47. package/dist/shaders/metaballs.js +2 -2
  48. package/dist/shaders/metaballs.js.map +2 -2
  49. package/dist/shaders/neuro-noise.d.ts +27 -5
  50. package/dist/shaders/neuro-noise.js +2 -3
  51. package/dist/shaders/neuro-noise.js.map +2 -2
  52. package/dist/shaders/paper-texture.d.ts +37 -12
  53. package/dist/shaders/paper-texture.js +20 -20
  54. package/dist/shaders/paper-texture.js.map +2 -2
  55. package/dist/shaders/perlin-noise.d.ts +27 -8
  56. package/dist/shaders/perlin-noise.js +13 -35
  57. package/dist/shaders/perlin-noise.js.map +2 -2
  58. package/dist/shaders/pulsing-border.d.ts +39 -13
  59. package/dist/shaders/pulsing-border.js +9 -7
  60. package/dist/shaders/pulsing-border.js.map +2 -2
  61. package/dist/shaders/simplex-noise.d.ts +25 -6
  62. package/dist/shaders/simplex-noise.js +21 -21
  63. package/dist/shaders/simplex-noise.js.map +2 -2
  64. package/dist/shaders/smoke-ring.d.ts +29 -7
  65. package/dist/shaders/smoke-ring.js +20 -17
  66. package/dist/shaders/smoke-ring.js.map +2 -2
  67. package/dist/shaders/spiral.d.ts +30 -10
  68. package/dist/shaders/spiral.js +4 -4
  69. package/dist/shaders/spiral.js.map +2 -2
  70. package/dist/shaders/static-mesh-gradient.d.ts +30 -9
  71. package/dist/shaders/static-mesh-gradient.js +9 -17
  72. package/dist/shaders/static-mesh-gradient.js.map +2 -2
  73. package/dist/shaders/static-radial-gradient.d.ts +33 -11
  74. package/dist/shaders/static-radial-gradient.js +18 -25
  75. package/dist/shaders/static-radial-gradient.js.map +2 -2
  76. package/dist/shaders/swirl.d.ts +29 -8
  77. package/dist/shaders/swirl.js +4 -4
  78. package/dist/shaders/swirl.js.map +2 -2
  79. package/dist/shaders/voronoi.d.ts +31 -10
  80. package/dist/shaders/voronoi.js +8 -8
  81. package/dist/shaders/voronoi.js.map +2 -2
  82. package/dist/shaders/warp.d.ts +31 -13
  83. package/dist/shaders/warp.js +3 -3
  84. package/dist/shaders/warp.js.map +2 -2
  85. package/dist/shaders/water.d.ts +30 -10
  86. package/dist/shaders/water.js +2 -2
  87. package/dist/shaders/water.js.map +2 -2
  88. package/dist/shaders/waves.d.ts +27 -12
  89. package/dist/shaders/waves.js +3 -3
  90. package/dist/shaders/waves.js.map +2 -2
  91. package/dist/vertex-shader.d.ts +1 -1
  92. package/dist/vertex-shader.js +2 -53
  93. package/dist/vertex-shader.js.map +2 -2
  94. package/package.json +1 -1
@@ -1,25 +1,50 @@
1
1
  import type { ShaderMotionParams } from '../shader-mount.js';
2
2
  import { type ShaderSizingParams, type ShaderSizingUniforms } from '../shader-sizing.js';
3
3
  /**
4
- * Mimicking glass surface distortion over the image by distorting the texture
5
- * coordinates within line patterns
4
+ * Fluted glass image filter that transforms an image into streaked, ribbed distortions,
5
+ * giving a mix of clarity and obscurity.
6
6
  *
7
- * Uniforms:
8
- * - u_size, u_angle - size and direction of grid relative to the image
9
- * - u_shape (float used as integer):
10
- * ---- 1: uniformly spaced stripes
11
- * ---- 2: randomly spaced stripes
12
- * ---- 3: sine wave stripes
13
- * ---- 4: zigzag stripes
14
- * ---- 5: wave-based pattern
15
- * - u_distortion - the power of distortion applied along within each stripe
16
- * - u_distortionShape (float used as integer):
17
- * ---- 5 shapes available
18
- * - u_shift - texture shift in direction opposite to the grid
19
- * - u_blur - one-directional blur applied over the main distortion
20
- * - u_edges -
21
- * - u_marginLeft, u_marginRight, u_marginTop, u_marginBottom - paddings
22
- * within picture to be shown without any distortion
7
+ * Fragment shader uniforms:
8
+ * - u_resolution (vec2): Canvas resolution in pixels
9
+ * - u_pixelRatio (float): Device pixel ratio
10
+ * - u_rotation (float): Overall rotation angle of the graphics in degrees (0 to 360)
11
+ * - u_image (sampler2D): Source image texture
12
+ * - u_imageAspectRatio (float): Aspect ratio of the source image
13
+ * - u_colorBack (vec4): Background color in RGBA
14
+ * - u_colorShadow (vec4): Shadows color in RGBA
15
+ * - u_colorHighlight (vec4): Highlights color in RGBA
16
+ * - u_shadows (float): Color gradient added over image and background, following distortion shape (0 to 1)
17
+ * - u_highlights (float): Thin strokes along distortion shape, useful for antialiasing on small grid (0 to 1)
18
+ * - u_size (float): Size of the distortion shape grid (0 to 1)
19
+ * - u_shape (float): Grid shape (1 = lines, 2 = linesIrregular, 3 = wave, 4 = zigzag, 5 = pattern)
20
+ * - u_angle (float): Direction of the grid relative to the image in degrees (0 to 180)
21
+ * - u_distortionShape (float): Shape of distortion (1 = prism, 2 = lens, 3 = contour, 4 = cascade, 5 = flat)
22
+ * - u_distortion (float): Power of distortion applied within each stripe (0 to 1)
23
+ * - u_shift (float): Texture shift in direction opposite to the grid (-1 to 1)
24
+ * - u_stretch (float): Extra distortion along the grid lines (0 to 1)
25
+ * - u_blur (float): One-directional blur over the image and extra blur around edges (0 to 1)
26
+ * - u_edges (float): Glass distortion and softness on the image edges (0 to 1)
27
+ * - u_marginLeft (float): Distance from the left edge to the effect (0 to 1)
28
+ * - u_marginRight (float): Distance from the right edge to the effect (0 to 1)
29
+ * - u_marginTop (float): Distance from the top edge to the effect (0 to 1)
30
+ * - u_marginBottom (float): Distance from the bottom edge to the effect (0 to 1)
31
+ * - u_grainMixer (float): Strength of grain distortion applied to shape edges (0 to 1)
32
+ * - u_grainOverlay (float): Post-processing black/white grain overlay (0 to 1)
33
+ *
34
+ * Vertex shader outputs (used in fragment shader):
35
+ * - v_imageUV (vec2): Image UV coordinates with global sizing (rotation, scale, offset, etc) applied
36
+ *
37
+ * Vertex shader uniforms:
38
+ * - u_resolution (vec2): Canvas resolution in pixels
39
+ * - u_pixelRatio (float): Device pixel ratio
40
+ * - u_originX (float): Reference point for positioning world width in the canvas (0 to 1)
41
+ * - u_originY (float): Reference point for positioning world height in the canvas (0 to 1)
42
+ * - u_fit (float): How to fit the rendered shader into the canvas dimensions (0 = none, 1 = contain, 2 = cover)
43
+ * - u_scale (float): Overall zoom level of the graphics (0.01 to 4)
44
+ * - u_rotation (float): Overall rotation angle of the graphics in degrees (0 to 360)
45
+ * - u_offsetX (float): Horizontal offset of the graphics center (-1 to 1)
46
+ * - u_offsetY (float): Vertical offset of the graphics center (-1 to 1)
47
+ * - u_imageAspectRatio (float): Aspect ratio of the source image
23
48
  *
24
49
  */
25
50
  export declare const flutedGlassFragmentShader: string;
@@ -3,14 +3,14 @@
3
3
  * https://github.com/paper-design/shaders *
4
4
  * * * * * * * * * * * * * * * * * * * * * * * * * * * */
5
5
 
6
- import { sizingUniformsDeclaration } from "../shader-sizing.js";
6
+ import {} from "../shader-sizing.js";
7
7
  import { declarePI, rotation2, proceduralHash21 } from "../shader-utils.js";
8
8
  const flutedGlassFragmentShader = `#version 300 es
9
9
  precision mediump float;
10
10
 
11
11
  uniform vec2 u_resolution;
12
12
  uniform float u_pixelRatio;
13
- ${sizingUniformsDeclaration}
13
+ uniform float u_rotation;
14
14
 
15
15
  uniform vec4 u_colorBack;
16
16
  uniform vec4 u_colorShadow;
@@ -37,6 +37,8 @@ uniform float u_marginBottom;
37
37
  uniform float u_grainMixer;
38
38
  uniform float u_grainOverlay;
39
39
 
40
+ in vec2 v_imageUV;
41
+
40
42
  out vec4 fragColor;
41
43
 
42
44
  ${declarePI}
@@ -56,38 +58,6 @@ float valueNoise(vec2 st) {
56
58
  return mix(x1, x2, u.y);
57
59
  }
58
60
 
59
-
60
- vec2 getImageUV(vec2 uv, vec2 extraScale) {
61
- vec2 boxOrigin = vec2(.5 - u_originX, u_originY - .5);
62
- float r = u_rotation * PI / 180.;
63
- mat2 graphicRotation = mat2(cos(r), sin(r), -sin(r), cos(r));
64
- vec2 graphicOffset = vec2(-u_offsetX, u_offsetY);
65
-
66
- vec2 imageBoxSize;
67
- if (u_fit == 1.) {
68
- imageBoxSize.x = min(u_resolution.x / u_imageAspectRatio, u_resolution.y) * u_imageAspectRatio;
69
- } else {
70
- imageBoxSize.x = max(u_resolution.x / u_imageAspectRatio, u_resolution.y) * u_imageAspectRatio;
71
- }
72
- imageBoxSize.y = imageBoxSize.x / u_imageAspectRatio;
73
- vec2 imageBoxScale = u_resolution.xy / imageBoxSize;
74
-
75
- vec2 imageUV = uv;
76
- imageUV *= imageBoxScale;
77
- imageUV += boxOrigin * (imageBoxScale - 1.);
78
- imageUV += graphicOffset;
79
- imageUV /= u_scale;
80
- imageUV *= extraScale;
81
- imageUV.x *= u_imageAspectRatio;
82
- imageUV = graphicRotation * imageUV;
83
- imageUV.x /= u_imageAspectRatio;
84
-
85
- imageUV += .5;
86
- imageUV.y = 1. - imageUV.y;
87
-
88
- return imageUV;
89
- }
90
-
91
61
  float getUvFrame(vec2 uv, float softness) {
92
62
  float aax = 2. * fwidth(uv.x);
93
63
  float aay = 2. * fwidth(uv.y);
@@ -132,7 +102,7 @@ vec4 getBlur(sampler2D tex, vec2 uv, vec2 texelSize, vec2 dir, float sigma) {
132
102
  if (result.a > 0.) {
133
103
  result.rgb /= result.a;
134
104
  }
135
-
105
+
136
106
  return result;
137
107
  }
138
108
 
@@ -155,22 +125,19 @@ float smoothFract(float x) {
155
125
 
156
126
  void main() {
157
127
 
158
- vec2 uvNormalised = (gl_FragCoord.xy - .5 * u_resolution) / u_resolution.xy;
159
- vec2 uvOriginal = getImageUV(uvNormalised, vec2(1.));
160
-
161
128
  float patternRotation = -u_angle * PI / 180.;
162
129
  float patternSize = mix(200., 5., u_size);
163
130
 
164
- vec2 uv = uvOriginal;
131
+ vec2 uv = v_imageUV;
165
132
 
166
133
  vec2 uvMask = gl_FragCoord.xy / u_resolution.xy;
167
134
  vec2 sw = vec2(.005);
168
135
  vec4 margins = vec4(u_marginLeft, u_marginTop, u_marginRight, u_marginBottom);
169
136
  float mask =
170
- smoothstep(margins[0], margins[0] + sw.x, uvMask.x + sw.x) *
171
- smoothstep(margins[2], margins[2] + sw.x, 1.0 - uvMask.x + sw.x) *
172
- smoothstep(margins[1], margins[1] + sw.y, uvMask.y + sw.y) *
173
- smoothstep(margins[3], margins[3] + sw.y, 1.0 - uvMask.y + sw.y);
137
+ smoothstep(margins[0], margins[0] + sw.x, uvMask.x + sw.x) *
138
+ smoothstep(margins[2], margins[2] + sw.x, 1.0 - uvMask.x + sw.x) *
139
+ smoothstep(margins[1], margins[1] + sw.y, uvMask.y + sw.y) *
140
+ smoothstep(margins[3], margins[3] + sw.y, 1.0 - uvMask.y + sw.y);
174
141
  float maskOuter =
175
142
  smoothstep(margins[0] - sw.x, margins[0], uvMask.x + sw.x) *
176
143
  smoothstep(margins[2] - sw.x, margins[2], 1.0 - uvMask.x + sw.x) *
@@ -178,10 +145,10 @@ void main() {
178
145
  smoothstep(margins[3] - sw.y, margins[3], 1.0 - uvMask.y + sw.y);
179
146
  float maskStroke = maskOuter - mask;
180
147
  float maskInner =
181
- smoothstep(margins[0] - 2. * sw.x, margins[0], uvMask.x) *
182
- smoothstep(margins[2] - 2. * sw.x, margins[2], 1.0 - uvMask.x) *
183
- smoothstep(margins[1] - 2. * sw.y, margins[1], uvMask.y) *
184
- smoothstep(margins[3] - 2. * sw.y, margins[3], 1.0 - uvMask.y);
148
+ smoothstep(margins[0] - 2. * sw.x, margins[0], uvMask.x) *
149
+ smoothstep(margins[2] - 2. * sw.x, margins[2], 1.0 - uvMask.x) *
150
+ smoothstep(margins[1] - 2. * sw.y, margins[1], uvMask.y) *
151
+ smoothstep(margins[3] - 2. * sw.y, margins[3], 1.0 - uvMask.y);
185
152
  float maskStrokeInner = maskInner - mask;
186
153
 
187
154
  uv -= .5;
@@ -284,9 +251,11 @@ void main() {
284
251
  distortion *= fadeX;
285
252
  }
286
253
 
287
- vec2 dudx = dFdx(uvOriginal);
288
- vec2 dudy = dFdy(uvOriginal);
289
- vec2 grainUV = getImageUV(uvNormalised, .8 / vec2(length(dudx), length(dudy)));
254
+ vec2 dudx = dFdx(v_imageUV);
255
+ vec2 dudy = dFdy(v_imageUV);
256
+ vec2 grainUV = v_imageUV - .5;
257
+ grainUV *= (.8 / vec2(length(dudx), length(dudy)));
258
+ grainUV += .5;
290
259
  float grain = valueNoise(grainUV);
291
260
  grain = smoothstep(.4, .7, grain);
292
261
  grain *= u_grainMixer;
@@ -311,7 +280,7 @@ void main() {
311
280
 
312
281
  uv += vec2(.5);
313
282
 
314
- uv = mix(uvOriginal, uv, smoothstep(0., .7, mask));
283
+ uv = mix(v_imageUV, uv, smoothstep(0., .7, mask));
315
284
  float blur = mix(0., 50., u_blur);
316
285
  blur = mix(0., blur, smoothstep(.5, 1., mask));
317
286
 
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/shaders/fluted-glass.ts"],
4
- "sourcesContent": ["import type { ShaderMotionParams } from '../shader-mount.js';\nimport { sizingUniformsDeclaration, type ShaderSizingParams, type ShaderSizingUniforms } from '../shader-sizing.js';\nimport { declarePI, rotation2, proceduralHash21 } 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_size, u_angle - size 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_edges -\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 vec2 u_resolution;\nuniform float u_pixelRatio;\n${sizingUniformsDeclaration}\n\nuniform vec4 u_colorBack;\nuniform vec4 u_colorShadow;\nuniform vec4 u_colorHighlight;\n\nuniform sampler2D u_image;\nuniform float u_imageAspectRatio;\n\nuniform float u_size;\nuniform float u_shadows;\nuniform float u_angle;\nuniform float u_stretch;\nuniform float u_shape;\nuniform float u_distortion;\nuniform float u_highlights;\nuniform float u_distortionShape;\nuniform float u_shift;\nuniform float u_blur;\nuniform float u_edges;\nuniform float u_marginLeft;\nuniform float u_marginRight;\nuniform float u_marginTop;\nuniform float u_marginBottom;\nuniform float u_grainMixer;\nuniform float u_grainOverlay;\n\nout vec4 fragColor;\n\n${declarePI}\n${rotation2}\n${proceduralHash21}\n\nfloat valueNoise(vec2 st) {\n vec2 i = floor(st);\n vec2 f = fract(st);\n float a = hash21(i);\n float b = hash21(i + vec2(1.0, 0.0));\n float c = hash21(i + vec2(0.0, 1.0));\n float d = hash21(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\nvec2 getImageUV(vec2 uv, vec2 extraScale) {\n vec2 boxOrigin = vec2(.5 - u_originX, u_originY - .5);\n float r = u_rotation * PI / 180.;\n mat2 graphicRotation = mat2(cos(r), sin(r), -sin(r), cos(r));\n vec2 graphicOffset = vec2(-u_offsetX, u_offsetY);\n\n vec2 imageBoxSize;\n if (u_fit == 1.) {\n imageBoxSize.x = min(u_resolution.x / u_imageAspectRatio, u_resolution.y) * u_imageAspectRatio;\n } else {\n imageBoxSize.x = max(u_resolution.x / u_imageAspectRatio, u_resolution.y) * u_imageAspectRatio;\n }\n imageBoxSize.y = imageBoxSize.x / u_imageAspectRatio;\n vec2 imageBoxScale = u_resolution.xy / imageBoxSize;\n\n vec2 imageUV = uv;\n imageUV *= imageBoxScale;\n imageUV += boxOrigin * (imageBoxScale - 1.);\n imageUV += graphicOffset;\n imageUV /= u_scale;\n imageUV *= extraScale;\n imageUV.x *= u_imageAspectRatio;\n imageUV = graphicRotation * imageUV;\n imageUV.x /= u_imageAspectRatio;\n\n imageUV += .5;\n imageUV.y = 1. - imageUV.y;\n\n return imageUV;\n}\n\nfloat getUvFrame(vec2 uv, float softness) {\n float aax = 2. * fwidth(uv.x);\n float aay = 2. * fwidth(uv.y);\n float left = smoothstep(0., aax + softness, uv.x);\n float right = 1. - smoothstep(1. - softness - aax, 1., uv.x);\n float bottom = smoothstep(0., aay + softness, uv.y);\n float top = 1. - smoothstep(1. - softness - aay, 1., uv.y);\n return left * right * bottom * top;\n}\n\nconst int MAX_RADIUS = 50;\nvec4 samplePremultiplied(sampler2D tex, vec2 uv) {\n vec4 c = texture(tex, uv);\n c.rgb *= c.a;\n return c;\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 = samplePremultiplied(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 = samplePremultiplied(tex, uv + offset);\n vec4 s2 = samplePremultiplied(tex, uv - offset);\n\n sum += (s1 + s2) * w;\n weightSum += 2.0 * w;\n }\n\n vec4 result = sum / weightSum;\n if (result.a > 0.) {\n result.rgb /= result.a;\n }\n \n return result;\n}\n\nvec2 rotateAspect(vec2 p, float a, float aspect) {\n p.x *= aspect;\n p = rotate(p, a);\n p.x /= aspect;\n return p;\n}\n\nfloat smoothFract(float x) {\n float f = fract(x);\n float w = fwidth(x);\n\n float edge = abs(f - 0.5) - 0.5;\n float band = smoothstep(-w, w, edge);\n\n return mix(f, 1.0 - f, band);\n}\n\nvoid main() {\n\n vec2 uvNormalised = (gl_FragCoord.xy - .5 * u_resolution) / u_resolution.xy;\n vec2 uvOriginal = getImageUV(uvNormalised, vec2(1.));\n\n float patternRotation = -u_angle * PI / 180.;\n float patternSize = mix(200., 5., u_size);\n\n vec2 uv = uvOriginal;\n\n vec2 uvMask = gl_FragCoord.xy / u_resolution.xy;\n vec2 sw = vec2(.005);\n vec4 margins = vec4(u_marginLeft, u_marginTop, u_marginRight, u_marginBottom);\n float mask =\n smoothstep(margins[0], margins[0] + sw.x, uvMask.x + sw.x) *\n smoothstep(margins[2], margins[2] + sw.x, 1.0 - uvMask.x + sw.x) *\n smoothstep(margins[1], margins[1] + sw.y, uvMask.y + sw.y) *\n smoothstep(margins[3], margins[3] + sw.y, 1.0 - uvMask.y + sw.y);\n float maskOuter =\n smoothstep(margins[0] - sw.x, margins[0], uvMask.x + sw.x) *\n smoothstep(margins[2] - sw.x, margins[2], 1.0 - uvMask.x + sw.x) *\n smoothstep(margins[1] - sw.y, margins[1], uvMask.y + sw.y) *\n smoothstep(margins[3] - sw.y, margins[3], 1.0 - uvMask.y + sw.y);\n float maskStroke = maskOuter - mask;\n float maskInner =\n smoothstep(margins[0] - 2. * sw.x, margins[0], uvMask.x) *\n smoothstep(margins[2] - 2. * sw.x, margins[2], 1.0 - uvMask.x) *\n smoothstep(margins[1] - 2. * sw.y, margins[1], uvMask.y) *\n smoothstep(margins[3] - 2. * sw.y, margins[3], 1.0 - uvMask.y);\n float maskStrokeInner = maskInner - mask;\n\n uv -= .5;\n uv *= patternSize;\n uv = rotateAspect(uv, patternRotation, u_imageAspectRatio);\n\n float curve = 0.;\n float patternY = uv.y / u_imageAspectRatio;\n if (u_shape > 4.5) {\n // pattern\n curve = .5 + .5 * sin(.5 * PI * uv.x) * cos(.5 * PI * patternY);\n } else if (u_shape > 3.5) {\n // zigzag\n curve = 10. * abs(fract(.1 * patternY) - .5);\n } else if (u_shape > 2.5) {\n // wave\n curve = 4. * sin(.23 * patternY);\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 }\n\n vec2 UvToFract = uv + curve;\n vec2 fractOrigUV = fract(uv);\n vec2 floorOrigUV = floor(uv);\n\n float x = smoothFract(UvToFract.x);\n float xNonSmooth = fract(UvToFract.x) + .0001;\n\n float highlightsWidth = 2. * max(.001, fwidth(UvToFract.x));\n highlightsWidth += 2. * maskStrokeInner;\n float highlights = smoothstep(0., highlightsWidth, xNonSmooth);\n highlights *= smoothstep(1., 1. - highlightsWidth, xNonSmooth);\n highlights = 1. - highlights;\n highlights *= u_highlights;\n highlights = clamp(highlights, 0., 1.);\n highlights *= mask;\n\n float shadows = pow(x, 1.3);\n float distortion = 0.;\n float fadeX = 1.;\n float frameFade = 0.;\n\n float aa = fwidth(xNonSmooth);\n aa = max(aa, fwidth(uv.x));\n aa = max(aa, fwidth(UvToFract.x));\n aa = max(aa, .0001);\n\n if (u_distortionShape == 1.) {\n distortion = -pow(1.5 * x, 3.);\n distortion += (.5 - u_shift);\n\n frameFade = pow(1.5 * x, 3.);\n aa = max(.2, aa);\n aa += mix(.2, 0., u_size);\n fadeX = smoothstep(0., aa, xNonSmooth) * smoothstep(1., 1. - aa, xNonSmooth);\n distortion = mix(.5, distortion, fadeX);\n } else if (u_distortionShape == 2.) {\n distortion = 2. * pow(x, 2.);\n distortion -= (.5 + u_shift);\n\n frameFade = pow(abs(x - .5), 4.);\n aa = max(.2, aa);\n aa += mix(.2, 0., u_size);\n fadeX = smoothstep(0., aa, xNonSmooth) * smoothstep(1., 1. - aa, xNonSmooth);\n distortion = mix(.5, distortion, fadeX);\n frameFade = mix(1., frameFade, .5 * fadeX);\n } else if (u_distortionShape == 3.) {\n distortion = pow(2. * (xNonSmooth - .5), 6.);\n distortion -= .25;\n distortion -= u_shift;\n\n frameFade = 1. - 2. * pow(abs(x - .4), 2.);\n aa = .15;\n aa += mix(.1, 0., u_size);\n fadeX = smoothstep(0., aa, xNonSmooth) * smoothstep(1., 1. - aa, xNonSmooth);\n frameFade = mix(1., frameFade, fadeX);\n\n } else if (u_distortionShape == 4.) {\n x = xNonSmooth;\n distortion = sin((x + .25) * TWO_PI);\n shadows = .5 + .5 * asin(distortion) / (.5 * PI);\n distortion *= .5;\n distortion -= u_shift;\n frameFade = .5 + .5 * sin(x * TWO_PI);\n } else if (u_distortionShape == 5.) {\n distortion -= pow(abs(x), .2) * x;\n distortion += .33;\n distortion -= 3. * u_shift;\n distortion *= .33;\n\n frameFade = .3 * (smoothstep(.0, 1., x));\n shadows = pow(x, 2.5);\n\n aa = max(.1, aa);\n aa += mix(.1, 0., u_size);\n fadeX = smoothstep(0., aa, xNonSmooth) * smoothstep(1., 1. - aa, xNonSmooth);\n distortion *= fadeX;\n }\n\n vec2 dudx = dFdx(uvOriginal);\n vec2 dudy = dFdy(uvOriginal);\n vec2 grainUV = getImageUV(uvNormalised, .8 / vec2(length(dudx), length(dudy)));\n float grain = valueNoise(grainUV);\n grain = smoothstep(.4, .7, grain);\n grain *= u_grainMixer;\n distortion = mix(distortion, 0., grain);\n\n shadows = min(shadows, 1.);\n shadows += maskStrokeInner;\n shadows *= mask;\n shadows = min(shadows, 1.);\n shadows *= pow(u_shadows, 2.);\n shadows = clamp(shadows, 0., 1.);\n\n distortion *= 3. * u_distortion;\n frameFade *= u_distortion;\n\n fractOrigUV.x += distortion;\n floorOrigUV = rotateAspect(floorOrigUV, -patternRotation, u_imageAspectRatio);\n fractOrigUV = rotateAspect(fractOrigUV, -patternRotation, u_imageAspectRatio);\n\n uv = (floorOrigUV + fractOrigUV) / patternSize;\n uv += pow(maskStroke, 4.);\n\n uv += vec2(.5);\n\n uv = mix(uvOriginal, uv, smoothstep(0., .7, mask));\n float blur = mix(0., 50., u_blur);\n blur = mix(0., blur, smoothstep(.5, 1., mask));\n\n float edgeDistortion = mix(.0, .04, u_edges);\n edgeDistortion += .06 * frameFade * u_edges;\n edgeDistortion *= mask;\n float frame = getUvFrame(uv, edgeDistortion);\n\n float stretch = 1. - smoothstep(0., .5, xNonSmooth) * smoothstep(1., 1. - .5, xNonSmooth);\n stretch = pow(stretch, 2.);\n stretch *= mask;\n stretch *= getUvFrame(uv, .1 + .05 * mask * frameFade);\n uv.y = mix(uv.y, .5, u_stretch * stretch);\n\n vec4 image = getBlur(u_image, uv, 1. / u_resolution / u_pixelRatio, vec2(0., 1.), blur);\n image.rgb *= image.a;\n vec4 backColor = u_colorBack;\n backColor.rgb *= backColor.a;\n vec4 highlightColor = u_colorHighlight;\n highlightColor.rgb *= highlightColor.a;\n vec4 shadowColor = u_colorShadow;\n\n vec3 color = highlightColor.rgb * highlights;\n float opacity = highlightColor.a * highlights;\n\n shadows = mix(shadows * shadowColor.a, 0., highlights);\n color = mix(color, shadowColor.rgb * shadowColor.a, .5 * shadows);\n color += .5 * pow(shadows, .5) * shadowColor.rgb;\n opacity += shadows;\n color = clamp(color, vec3(0.), vec3(1.));\n opacity = clamp(opacity, 0., 1.);\n\n color += image.rgb * (1. - opacity) * frame;\n opacity += image.a * (1. - opacity) * frame;\n\n color += backColor.rgb * (1. - opacity);\n opacity += backColor.a * (1. - opacity);\n\n float grainOverlay = valueNoise(rotate(grainUV, 1.) + vec2(3.));\n grainOverlay = mix(grainOverlay, valueNoise(rotate(grainUV, 2.) + vec2(-1.)), .5);\n grainOverlay = pow(grainOverlay, 1.3);\n\n float grainOverlayV = grainOverlay * 2. - 1.;\n vec3 grainOverlayColor = vec3(step(0., grainOverlayV));\n float grainOverlayStrength = u_grainOverlay * abs(grainOverlayV);\n grainOverlayStrength = pow(grainOverlayStrength, .8);\n grainOverlayStrength *= mask;\n color = mix(color, grainOverlayColor, .35 * grainOverlayStrength);\n\n opacity += .5 * grainOverlayStrength;\n opacity = clamp(opacity, 0., 1.);\n\n fragColor = vec4(color, opacity);\n}\n`;\n\nexport interface FlutedGlassUniforms extends ShaderSizingUniforms {\n u_image: HTMLImageElement | string | undefined;\n u_colorBack: [number, number, number, number];\n u_colorShadow: [number, number, number, number];\n u_colorHighlight: [number, number, number, number];\n u_shadows: number;\n u_size: number;\n u_angle: number;\n u_distortion: number;\n u_shift: number;\n u_blur: number;\n u_edges: number;\n u_marginLeft: number;\n u_marginRight: number;\n u_marginTop: number;\n u_marginBottom: number;\n u_stretch: number;\n u_distortionShape: (typeof GlassDistortionShapes)[GlassDistortionShape];\n u_highlights: number;\n u_shape: (typeof GlassGridShapes)[GlassGridShape];\n u_grainMixer: number;\n u_grainOverlay: number;\n u_noiseTexture?: HTMLImageElement;\n}\n\nexport interface FlutedGlassParams extends ShaderSizingParams, ShaderMotionParams {\n image?: HTMLImageElement | string;\n colorBack?: string;\n colorShadow?: string;\n colorHighlight?: string;\n shadows?: number;\n size?: number;\n angle?: number;\n distortion?: number;\n shift?: number;\n blur?: number;\n edges?: number;\n margin?: number;\n marginLeft?: number;\n marginRight?: number;\n marginTop?: number;\n marginBottom?: number;\n stretch?: number;\n distortionShape?: GlassDistortionShape;\n highlights?: number;\n shape?: GlassGridShape;\n grainMixer?: number;\n grainOverlay?: number;\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 contour: 3,\n cascade: 4,\n flat: 5,\n} as const;\n\nexport type GlassDistortionShape = keyof typeof GlassDistortionShapes;\nexport type GlassGridShape = keyof typeof GlassGridShapes;\n"],
5
- "mappings": ";;;;;AACA,SAAS,iCAAqF;AAC9F,SAAS,WAAW,WAAW,wBAAwB;AA0BhD,MAAM,4BAAoC;AAAA;AAAA;AAAA;AAAA;AAAA,EAK/C,yBAAyB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA6BzB,SAAS;AAAA,EACT,SAAS;AAAA,EACT,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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAyXX,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,SAAS;AAAA,EACT,SAAS;AAAA,EACT,MAAM;AACR;",
4
+ "sourcesContent": ["import type { ShaderMotionParams } from '../shader-mount.js';\nimport { type ShaderSizingParams, type ShaderSizingUniforms } from '../shader-sizing.js';\nimport { declarePI, rotation2, proceduralHash21 } from '../shader-utils.js';\n\n/**\n * Fluted glass image filter that transforms an image into streaked, ribbed distortions,\n * giving a mix of clarity and obscurity.\n *\n * Fragment shader uniforms:\n * - u_resolution (vec2): Canvas resolution in pixels\n * - u_pixelRatio (float): Device pixel ratio\n * - u_rotation (float): Overall rotation angle of the graphics in degrees (0 to 360)\n * - u_image (sampler2D): Source image texture\n * - u_imageAspectRatio (float): Aspect ratio of the source image\n * - u_colorBack (vec4): Background color in RGBA\n * - u_colorShadow (vec4): Shadows color in RGBA\n * - u_colorHighlight (vec4): Highlights color in RGBA\n * - u_shadows (float): Color gradient added over image and background, following distortion shape (0 to 1)\n * - u_highlights (float): Thin strokes along distortion shape, useful for antialiasing on small grid (0 to 1)\n * - u_size (float): Size of the distortion shape grid (0 to 1)\n * - u_shape (float): Grid shape (1 = lines, 2 = linesIrregular, 3 = wave, 4 = zigzag, 5 = pattern)\n * - u_angle (float): Direction of the grid relative to the image in degrees (0 to 180)\n * - u_distortionShape (float): Shape of distortion (1 = prism, 2 = lens, 3 = contour, 4 = cascade, 5 = flat)\n * - u_distortion (float): Power of distortion applied within each stripe (0 to 1)\n * - u_shift (float): Texture shift in direction opposite to the grid (-1 to 1)\n * - u_stretch (float): Extra distortion along the grid lines (0 to 1)\n * - u_blur (float): One-directional blur over the image and extra blur around edges (0 to 1)\n * - u_edges (float): Glass distortion and softness on the image edges (0 to 1)\n * - u_marginLeft (float): Distance from the left edge to the effect (0 to 1)\n * - u_marginRight (float): Distance from the right edge to the effect (0 to 1)\n * - u_marginTop (float): Distance from the top edge to the effect (0 to 1)\n * - u_marginBottom (float): Distance from the bottom edge to the effect (0 to 1)\n * - u_grainMixer (float): Strength of grain distortion applied to shape edges (0 to 1)\n * - u_grainOverlay (float): Post-processing black/white grain overlay (0 to 1)\n *\n * Vertex shader outputs (used in fragment shader):\n * - v_imageUV (vec2): Image UV coordinates with global sizing (rotation, scale, offset, etc) applied\n *\n * Vertex shader uniforms:\n * - u_resolution (vec2): Canvas resolution in pixels\n * - u_pixelRatio (float): Device pixel ratio\n * - u_originX (float): Reference point for positioning world width in the canvas (0 to 1)\n * - u_originY (float): Reference point for positioning world height in the canvas (0 to 1)\n * - u_fit (float): How to fit the rendered shader into the canvas dimensions (0 = none, 1 = contain, 2 = cover)\n * - u_scale (float): Overall zoom level of the graphics (0.01 to 4)\n * - u_rotation (float): Overall rotation angle of the graphics in degrees (0 to 360)\n * - u_offsetX (float): Horizontal offset of the graphics center (-1 to 1)\n * - u_offsetY (float): Vertical offset of the graphics center (-1 to 1)\n * - u_imageAspectRatio (float): Aspect ratio of the source image\n *\n */\n\n// language=GLSL\nexport const flutedGlassFragmentShader: string = `#version 300 es\nprecision mediump float;\n\nuniform vec2 u_resolution;\nuniform float u_pixelRatio;\nuniform float u_rotation;\n\nuniform vec4 u_colorBack;\nuniform vec4 u_colorShadow;\nuniform vec4 u_colorHighlight;\n\nuniform sampler2D u_image;\nuniform float u_imageAspectRatio;\n\nuniform float u_size;\nuniform float u_shadows;\nuniform float u_angle;\nuniform float u_stretch;\nuniform float u_shape;\nuniform float u_distortion;\nuniform float u_highlights;\nuniform float u_distortionShape;\nuniform float u_shift;\nuniform float u_blur;\nuniform float u_edges;\nuniform float u_marginLeft;\nuniform float u_marginRight;\nuniform float u_marginTop;\nuniform float u_marginBottom;\nuniform float u_grainMixer;\nuniform float u_grainOverlay;\n\nin vec2 v_imageUV;\n\nout vec4 fragColor;\n\n${ declarePI }\n${ rotation2 }\n${ proceduralHash21 }\n\nfloat valueNoise(vec2 st) {\n vec2 i = floor(st);\n vec2 f = fract(st);\n float a = hash21(i);\n float b = hash21(i + vec2(1.0, 0.0));\n float c = hash21(i + vec2(0.0, 1.0));\n float d = hash21(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\nfloat getUvFrame(vec2 uv, float softness) {\n float aax = 2. * fwidth(uv.x);\n float aay = 2. * fwidth(uv.y);\n float left = smoothstep(0., aax + softness, uv.x);\n float right = 1. - smoothstep(1. - softness - aax, 1., uv.x);\n float bottom = smoothstep(0., aay + softness, uv.y);\n float top = 1. - smoothstep(1. - softness - aay, 1., uv.y);\n return left * right * bottom * top;\n}\n\nconst int MAX_RADIUS = 50;\nvec4 samplePremultiplied(sampler2D tex, vec2 uv) {\n vec4 c = texture(tex, uv);\n c.rgb *= c.a;\n return c;\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 = samplePremultiplied(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 = samplePremultiplied(tex, uv + offset);\n vec4 s2 = samplePremultiplied(tex, uv - offset);\n\n sum += (s1 + s2) * w;\n weightSum += 2.0 * w;\n }\n\n vec4 result = sum / weightSum;\n if (result.a > 0.) {\n result.rgb /= result.a;\n }\n\n return result;\n}\n\nvec2 rotateAspect(vec2 p, float a, float aspect) {\n p.x *= aspect;\n p = rotate(p, a);\n p.x /= aspect;\n return p;\n}\n\nfloat smoothFract(float x) {\n float f = fract(x);\n float w = fwidth(x);\n\n float edge = abs(f - 0.5) - 0.5;\n float band = smoothstep(-w, w, edge);\n\n return mix(f, 1.0 - f, band);\n}\n\nvoid main() {\n\n float patternRotation = -u_angle * PI / 180.;\n float patternSize = mix(200., 5., u_size);\n\n vec2 uv = v_imageUV;\n\n vec2 uvMask = gl_FragCoord.xy / u_resolution.xy;\n vec2 sw = vec2(.005);\n vec4 margins = vec4(u_marginLeft, u_marginTop, u_marginRight, u_marginBottom);\n float mask =\n smoothstep(margins[0], margins[0] + sw.x, uvMask.x + sw.x) *\n smoothstep(margins[2], margins[2] + sw.x, 1.0 - uvMask.x + sw.x) *\n smoothstep(margins[1], margins[1] + sw.y, uvMask.y + sw.y) *\n smoothstep(margins[3], margins[3] + sw.y, 1.0 - uvMask.y + sw.y);\n float maskOuter =\n smoothstep(margins[0] - sw.x, margins[0], uvMask.x + sw.x) *\n smoothstep(margins[2] - sw.x, margins[2], 1.0 - uvMask.x + sw.x) *\n smoothstep(margins[1] - sw.y, margins[1], uvMask.y + sw.y) *\n smoothstep(margins[3] - sw.y, margins[3], 1.0 - uvMask.y + sw.y);\n float maskStroke = maskOuter - mask;\n float maskInner =\n smoothstep(margins[0] - 2. * sw.x, margins[0], uvMask.x) *\n smoothstep(margins[2] - 2. * sw.x, margins[2], 1.0 - uvMask.x) *\n smoothstep(margins[1] - 2. * sw.y, margins[1], uvMask.y) *\n smoothstep(margins[3] - 2. * sw.y, margins[3], 1.0 - uvMask.y);\n float maskStrokeInner = maskInner - mask;\n\n uv -= .5;\n uv *= patternSize;\n uv = rotateAspect(uv, patternRotation, u_imageAspectRatio);\n\n float curve = 0.;\n float patternY = uv.y / u_imageAspectRatio;\n if (u_shape > 4.5) {\n // pattern\n curve = .5 + .5 * sin(.5 * PI * uv.x) * cos(.5 * PI * patternY);\n } else if (u_shape > 3.5) {\n // zigzag\n curve = 10. * abs(fract(.1 * patternY) - .5);\n } else if (u_shape > 2.5) {\n // wave\n curve = 4. * sin(.23 * patternY);\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 }\n\n vec2 UvToFract = uv + curve;\n vec2 fractOrigUV = fract(uv);\n vec2 floorOrigUV = floor(uv);\n\n float x = smoothFract(UvToFract.x);\n float xNonSmooth = fract(UvToFract.x) + .0001;\n\n float highlightsWidth = 2. * max(.001, fwidth(UvToFract.x));\n highlightsWidth += 2. * maskStrokeInner;\n float highlights = smoothstep(0., highlightsWidth, xNonSmooth);\n highlights *= smoothstep(1., 1. - highlightsWidth, xNonSmooth);\n highlights = 1. - highlights;\n highlights *= u_highlights;\n highlights = clamp(highlights, 0., 1.);\n highlights *= mask;\n\n float shadows = pow(x, 1.3);\n float distortion = 0.;\n float fadeX = 1.;\n float frameFade = 0.;\n\n float aa = fwidth(xNonSmooth);\n aa = max(aa, fwidth(uv.x));\n aa = max(aa, fwidth(UvToFract.x));\n aa = max(aa, .0001);\n\n if (u_distortionShape == 1.) {\n distortion = -pow(1.5 * x, 3.);\n distortion += (.5 - u_shift);\n\n frameFade = pow(1.5 * x, 3.);\n aa = max(.2, aa);\n aa += mix(.2, 0., u_size);\n fadeX = smoothstep(0., aa, xNonSmooth) * smoothstep(1., 1. - aa, xNonSmooth);\n distortion = mix(.5, distortion, fadeX);\n } else if (u_distortionShape == 2.) {\n distortion = 2. * pow(x, 2.);\n distortion -= (.5 + u_shift);\n\n frameFade = pow(abs(x - .5), 4.);\n aa = max(.2, aa);\n aa += mix(.2, 0., u_size);\n fadeX = smoothstep(0., aa, xNonSmooth) * smoothstep(1., 1. - aa, xNonSmooth);\n distortion = mix(.5, distortion, fadeX);\n frameFade = mix(1., frameFade, .5 * fadeX);\n } else if (u_distortionShape == 3.) {\n distortion = pow(2. * (xNonSmooth - .5), 6.);\n distortion -= .25;\n distortion -= u_shift;\n\n frameFade = 1. - 2. * pow(abs(x - .4), 2.);\n aa = .15;\n aa += mix(.1, 0., u_size);\n fadeX = smoothstep(0., aa, xNonSmooth) * smoothstep(1., 1. - aa, xNonSmooth);\n frameFade = mix(1., frameFade, fadeX);\n\n } else if (u_distortionShape == 4.) {\n x = xNonSmooth;\n distortion = sin((x + .25) * TWO_PI);\n shadows = .5 + .5 * asin(distortion) / (.5 * PI);\n distortion *= .5;\n distortion -= u_shift;\n frameFade = .5 + .5 * sin(x * TWO_PI);\n } else if (u_distortionShape == 5.) {\n distortion -= pow(abs(x), .2) * x;\n distortion += .33;\n distortion -= 3. * u_shift;\n distortion *= .33;\n\n frameFade = .3 * (smoothstep(.0, 1., x));\n shadows = pow(x, 2.5);\n\n aa = max(.1, aa);\n aa += mix(.1, 0., u_size);\n fadeX = smoothstep(0., aa, xNonSmooth) * smoothstep(1., 1. - aa, xNonSmooth);\n distortion *= fadeX;\n }\n\n vec2 dudx = dFdx(v_imageUV);\n vec2 dudy = dFdy(v_imageUV);\n vec2 grainUV = v_imageUV - .5;\n grainUV *= (.8 / vec2(length(dudx), length(dudy)));\n grainUV += .5;\n float grain = valueNoise(grainUV);\n grain = smoothstep(.4, .7, grain);\n grain *= u_grainMixer;\n distortion = mix(distortion, 0., grain);\n\n shadows = min(shadows, 1.);\n shadows += maskStrokeInner;\n shadows *= mask;\n shadows = min(shadows, 1.);\n shadows *= pow(u_shadows, 2.);\n shadows = clamp(shadows, 0., 1.);\n\n distortion *= 3. * u_distortion;\n frameFade *= u_distortion;\n\n fractOrigUV.x += distortion;\n floorOrigUV = rotateAspect(floorOrigUV, -patternRotation, u_imageAspectRatio);\n fractOrigUV = rotateAspect(fractOrigUV, -patternRotation, u_imageAspectRatio);\n\n uv = (floorOrigUV + fractOrigUV) / patternSize;\n uv += pow(maskStroke, 4.);\n\n uv += vec2(.5);\n\n uv = mix(v_imageUV, uv, smoothstep(0., .7, mask));\n float blur = mix(0., 50., u_blur);\n blur = mix(0., blur, smoothstep(.5, 1., mask));\n\n float edgeDistortion = mix(.0, .04, u_edges);\n edgeDistortion += .06 * frameFade * u_edges;\n edgeDistortion *= mask;\n float frame = getUvFrame(uv, edgeDistortion);\n\n float stretch = 1. - smoothstep(0., .5, xNonSmooth) * smoothstep(1., 1. - .5, xNonSmooth);\n stretch = pow(stretch, 2.);\n stretch *= mask;\n stretch *= getUvFrame(uv, .1 + .05 * mask * frameFade);\n uv.y = mix(uv.y, .5, u_stretch * stretch);\n\n vec4 image = getBlur(u_image, uv, 1. / u_resolution / u_pixelRatio, vec2(0., 1.), blur);\n image.rgb *= image.a;\n vec4 backColor = u_colorBack;\n backColor.rgb *= backColor.a;\n vec4 highlightColor = u_colorHighlight;\n highlightColor.rgb *= highlightColor.a;\n vec4 shadowColor = u_colorShadow;\n\n vec3 color = highlightColor.rgb * highlights;\n float opacity = highlightColor.a * highlights;\n\n shadows = mix(shadows * shadowColor.a, 0., highlights);\n color = mix(color, shadowColor.rgb * shadowColor.a, .5 * shadows);\n color += .5 * pow(shadows, .5) * shadowColor.rgb;\n opacity += shadows;\n color = clamp(color, vec3(0.), vec3(1.));\n opacity = clamp(opacity, 0., 1.);\n\n color += image.rgb * (1. - opacity) * frame;\n opacity += image.a * (1. - opacity) * frame;\n\n color += backColor.rgb * (1. - opacity);\n opacity += backColor.a * (1. - opacity);\n\n float grainOverlay = valueNoise(rotate(grainUV, 1.) + vec2(3.));\n grainOverlay = mix(grainOverlay, valueNoise(rotate(grainUV, 2.) + vec2(-1.)), .5);\n grainOverlay = pow(grainOverlay, 1.3);\n\n float grainOverlayV = grainOverlay * 2. - 1.;\n vec3 grainOverlayColor = vec3(step(0., grainOverlayV));\n float grainOverlayStrength = u_grainOverlay * abs(grainOverlayV);\n grainOverlayStrength = pow(grainOverlayStrength, .8);\n grainOverlayStrength *= mask;\n color = mix(color, grainOverlayColor, .35 * grainOverlayStrength);\n\n opacity += .5 * grainOverlayStrength;\n opacity = clamp(opacity, 0., 1.);\n\n fragColor = vec4(color, opacity);\n}\n`;\n\nexport interface FlutedGlassUniforms extends ShaderSizingUniforms {\n u_image: HTMLImageElement | string | undefined;\n u_colorBack: [number, number, number, number];\n u_colorShadow: [number, number, number, number];\n u_colorHighlight: [number, number, number, number];\n u_shadows: number;\n u_size: number;\n u_angle: number;\n u_distortion: number;\n u_shift: number;\n u_blur: number;\n u_edges: number;\n u_marginLeft: number;\n u_marginRight: number;\n u_marginTop: number;\n u_marginBottom: number;\n u_stretch: number;\n u_distortionShape: (typeof GlassDistortionShapes)[GlassDistortionShape];\n u_highlights: number;\n u_shape: (typeof GlassGridShapes)[GlassGridShape];\n u_grainMixer: number;\n u_grainOverlay: number;\n u_noiseTexture?: HTMLImageElement;\n}\n\nexport interface FlutedGlassParams extends ShaderSizingParams, ShaderMotionParams {\n image?: HTMLImageElement | string;\n colorBack?: string;\n colorShadow?: string;\n colorHighlight?: string;\n shadows?: number;\n size?: number;\n angle?: number;\n distortion?: number;\n shift?: number;\n blur?: number;\n edges?: number;\n margin?: number;\n marginLeft?: number;\n marginRight?: number;\n marginTop?: number;\n marginBottom?: number;\n stretch?: number;\n distortionShape?: GlassDistortionShape;\n highlights?: number;\n shape?: GlassGridShape;\n grainMixer?: number;\n grainOverlay?: number;\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 contour: 3,\n cascade: 4,\n flat: 5,\n} as const;\n\nexport type GlassDistortionShape = keyof typeof GlassDistortionShapes;\nexport type GlassGridShape = keyof typeof GlassGridShapes;\n"],
5
+ "mappings": ";;;;;AACA,eAAmE;AACnE,SAAS,WAAW,WAAW,wBAAwB;AAmDhD,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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAoC9C,SAAU;AAAA,EACV,SAAU;AAAA,EACV,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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAwVb,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,SAAS;AAAA,EACT,SAAS;AAAA,EACT,MAAM;AACR;",
6
6
  "names": []
7
7
  }
@@ -5,18 +5,40 @@ export declare const godRaysMeta: {
5
5
  readonly maxColorCount: 5;
6
6
  };
7
7
  /**
8
- * Radial rays animated from center
8
+ * Animated rays of light radiating from the center, blended with up to 5 colors.
9
9
  *
10
- * Uniforms:
11
- * - u_colorBack, u_colorBloom (RGBA)
12
- * - u_colors (vec4[]), u_colorsCount (float used as integer)
13
- * - u_density: frequency of sector shapes
14
- * - u_intensity: rays visibility within sectors
15
- * - u_spotty: density of spots on the ray (higher = more spots)
16
- * - u_midSize, u_midIntensity: central shape over the rays
17
- * - u_bloom (0..1): normal to additive blending mix
10
+ * Fragment shader uniforms:
11
+ * - u_time (float): Animation time
12
+ * - u_colorBack (vec4): Background color in RGBA
13
+ * - u_colorBloom (vec4): Color overlay blended with the rays in RGBA
14
+ * - u_colors (vec4[]): Up to 5 ray colors in RGBA
15
+ * - u_colorsCount (float): Number of active colors
16
+ * - u_bloom (float): Strength of the bloom/overlay effect, 0 = alpha blend, 1 = additive blend (0 to 1)
17
+ * - u_intensity (float): Visibility/strength of the rays (0 to 1)
18
+ * - u_density (float): The number of rays (0 to 1)
19
+ * - u_spotty (float): The length of the rays, higher = more spots/shorter rays (0 to 1)
20
+ * - u_midSize (float): Size of the circular glow shape in the center (0 to 1)
21
+ * - u_midIntensity (float): Brightness/intensity of the central glow (0 to 1)
22
+ * - u_noiseTexture (sampler2D): Pre-computed randomizer source texture
23
+ *
24
+ * Vertex shader outputs (used in fragment shader):
25
+ * - v_objectUV (vec2): Object box UV coordinates with global sizing (scale, rotation, offsets, etc) applied
26
+ *
27
+ * The rays are adjustable by size, density, brightness and center glow.
28
+ *
29
+ * Vertex shader uniforms:
30
+ * - u_resolution (vec2): Canvas resolution in pixels
31
+ * - u_pixelRatio (float): Device pixel ratio
32
+ * - u_originX (float): Reference point for positioning world width in the canvas (0 to 1)
33
+ * - u_originY (float): Reference point for positioning world height in the canvas (0 to 1)
34
+ * - u_worldWidth (float): Virtual width of the graphic before it's scaled to fit the canvas
35
+ * - u_worldHeight (float): Virtual height of the graphic before it's scaled to fit the canvas
36
+ * - u_fit (float): How to fit the rendered shader into the canvas dimensions (0 = none, 1 = contain, 2 = cover)
37
+ * - u_scale (float): Overall zoom level of the graphics (0.01 to 4)
38
+ * - u_rotation (float): Overall rotation angle of the graphics in degrees (0 to 360)
39
+ * - u_offsetX (float): Horizontal offset of the graphics center (-1 to 1)
40
+ * - u_offsetY (float): Vertical offset of the graphics center (-1 to 1)
18
41
  *
19
- * - u_noiseTexture (sampler2D): pre-computed randomizer source
20
42
  */
21
43
  export declare const godRaysFragmentShader: string;
22
44
  export interface GodRaysUniforms extends ShaderSizingUniforms {
@@ -3,7 +3,7 @@
3
3
  * https://github.com/paper-design/shaders *
4
4
  * * * * * * * * * * * * * * * * * * * * * * * * * * * */
5
5
 
6
- import { sizingVariablesDeclaration } from "../shader-sizing.js";
6
+ import {} from "../shader-sizing.js";
7
7
  import { declarePI, rotation2, textureRandomizerR, colorBandingFix, proceduralHash11 } from "../shader-utils.js";
8
8
  const godRaysMeta = {
9
9
  maxColorCount: 5
@@ -27,7 +27,7 @@ uniform float u_midIntensity;
27
27
  uniform float u_intensity;
28
28
  uniform float u_bloom;
29
29
 
30
- ${sizingVariablesDeclaration}
30
+ in vec2 v_objectUV;
31
31
 
32
32
  out vec4 fragColor;
33
33
 
@@ -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, 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(fract(a / TWO_PI) * 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 ms_lo = 0.02 * midSize;\n float ms_hi = max(midSize, 1e-6);\n float middleShape = pow(u_midIntensity, 0.3) * (1. - smoothstep(ms_lo, ms_hi, 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;AAAA;AAAA,wBAiCM,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 { 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 * Animated rays of light radiating from the center, blended with up to 5 colors.\n *\n * Fragment shader uniforms:\n * - u_time (float): Animation time\n * - u_colorBack (vec4): Background color in RGBA\n * - u_colorBloom (vec4): Color overlay blended with the rays in RGBA\n * - u_colors (vec4[]): Up to 5 ray colors in RGBA\n * - u_colorsCount (float): Number of active colors\n * - u_bloom (float): Strength of the bloom/overlay effect, 0 = alpha blend, 1 = additive blend (0 to 1)\n * - u_intensity (float): Visibility/strength of the rays (0 to 1)\n * - u_density (float): The number of rays (0 to 1)\n * - u_spotty (float): The length of the rays, higher = more spots/shorter rays (0 to 1)\n * - u_midSize (float): Size of the circular glow shape in the center (0 to 1)\n * - u_midIntensity (float): Brightness/intensity of the central glow (0 to 1)\n * - u_noiseTexture (sampler2D): Pre-computed randomizer source texture\n *\n * Vertex shader outputs (used in fragment shader):\n * - v_objectUV (vec2): Object box UV coordinates with global sizing (scale, rotation, offsets, etc) applied\n *\n * The rays are adjustable by size, density, brightness and center glow.\n *\n * Vertex shader uniforms:\n * - u_resolution (vec2): Canvas resolution in pixels\n * - u_pixelRatio (float): Device pixel ratio\n * - u_originX (float): Reference point for positioning world width in the canvas (0 to 1)\n * - u_originY (float): Reference point for positioning world height in the canvas (0 to 1)\n * - u_worldWidth (float): Virtual width of the graphic before it's scaled to fit the canvas\n * - u_worldHeight (float): Virtual height of the graphic before it's scaled to fit the canvas\n * - u_fit (float): How to fit the rendered shader into the canvas dimensions (0 = none, 1 = contain, 2 = cover)\n * - u_scale (float): Overall zoom level of the graphics (0.01 to 4)\n * - u_rotation (float): Overall rotation angle of the graphics in degrees (0 to 360)\n * - u_offsetX (float): Horizontal offset of the graphics center (-1 to 1)\n * - u_offsetY (float): Vertical offset of the graphics center (-1 to 1)\n *\n */\n\n// language=GLSL\nexport const 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\nin vec2 v_objectUV;\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(fract(a / TWO_PI) * 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 ms_lo = 0.02 * midSize;\n float ms_hi = max(midSize, 1e-6);\n float middleShape = pow(u_midIntensity, 0.3) * (1. - smoothstep(ms_lo, ms_hi, 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,eAAmE;AACnE,SAAS,WAAW,WAAW,oBAAoB,iBAAiB,wBAAwB;AAErF,MAAM,cAAc;AAAA,EACzB,eAAe;AACjB;AAwCO,MAAM,wBAAgC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBASpB,YAAY,aAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAchD,SAAU;AAAA,EACV,SAAU;AAAA,EACV,kBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcnB,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,wBAiCK,YAAY,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,IAyC9C,eAAgB;AAAA;AAAA;AAAA;AAAA;",
6
6
  "names": []
7
7
  }
@@ -5,26 +5,50 @@ export declare const grainGradientMeta: {
5
5
  readonly maxColorCount: 7;
6
6
  };
7
7
  /**
8
- * Multi-color gradient with noise & grain over animated abstract shapes
8
+ * Multi-color gradients with grainy, noise-textured distortion available in 7 animated abstract forms.
9
9
  *
10
- * Uniforms:
11
- * - u_colorBack (RGBA)
12
- * - u_colors (vec4[]), u_colorsCount (float used as integer)
13
- * - u_softness (0..1): blur between color bands
14
- * - u_intensity (0..1): distortion between color bands
15
- * - u_noise (0..1): grainy noise independent of softness
16
- * - u_shape (float used as integer):
17
- * ---- 1: single sine wave
18
- * ---- 2: dots pattern
19
- * ---- 3: truchet pattern
20
- * ---- 4: corners (2 rounded rectangles)
21
- * ---- 5: ripple
22
- * ---- 6: blob (metaballs)
23
- * ---- 7: circle imitating 3d look
10
+ * Note: grains are calculated using gl_FragCoord & u_resolution, meaning grains don't react to scaling and fit
24
11
  *
25
- * - u_noiseTexture (sampler2D): pre-computed randomizer source
12
+ * Fragment shader uniforms:
13
+ * - u_time (float): Animation time
14
+ * - u_resolution (vec2): Canvas resolution in pixels
15
+ * - u_pixelRatio (float): Device pixel ratio
16
+ * - u_originX (float): Reference point for positioning (0 to 1)
17
+ * - u_originY (float): Reference point for positioning (0 to 1)
18
+ * - u_worldWidth (float): Virtual width of the graphic
19
+ * - u_worldHeight (float): Virtual height of the graphic
20
+ * - u_fit (float): Fit mode (0 = none, 1 = contain, 2 = cover)
21
+ * - u_scale (float): Overall zoom level (0.01 to 4)
22
+ * - u_rotation (float): Rotation angle in degrees (0 to 360)
23
+ * - u_offsetX (float): Horizontal offset (-1 to 1)
24
+ * - u_offsetY (float): Vertical offset (-1 to 1)
25
+ * - u_colorBack (vec4): Background color in RGBA
26
+ * - u_colors (vec4[]): Up to 7 gradient colors in RGBA
27
+ * - u_colorsCount (float): Number of active colors
28
+ * - u_softness (float): Color transition sharpness, 0 = hard edge, 1 = smooth gradient (0 to 1)
29
+ * - u_intensity (float): Distortion between color bands (0 to 1)
30
+ * - u_noise (float): Grainy noise overlay (0 to 1)
31
+ * - u_shape (float): Shape type (1 = wave, 2 = dots, 3 = truchet, 4 = corners, 5 = ripple, 6 = blob, 7 = sphere)
32
+ * - u_noiseTexture (sampler2D): Pre-computed randomizer source texture
26
33
  *
27
- * Note: grains are calculated using gl_FragCoord & u_resolution, meaning grains don't react to scaling and fit
34
+ * Vertex shader outputs (used in fragment shader):
35
+ * - v_objectUV (vec2): Object box UV coordinates with global sizing (scale, rotation, offsets, etc) applied (used for shapes 4-7)
36
+ * - v_objectBoxSize (vec2): Size of the object bounding box in pixels
37
+ * - v_patternUV (vec2): UV coordinates for pattern with global sizing (rotation, scale, offset, etc) applied (used for shapes 1-3)
38
+ * - v_patternBoxSize (vec2): Size of the pattern bounding box in pixels
39
+ *
40
+ * Vertex shader uniforms:
41
+ * - u_resolution (vec2): Canvas resolution in pixels
42
+ * - u_pixelRatio (float): Device pixel ratio
43
+ * - u_originX (float): Reference point for positioning world width in the canvas (0 to 1)
44
+ * - u_originY (float): Reference point for positioning world height in the canvas (0 to 1)
45
+ * - u_worldWidth (float): Virtual width of the graphic before it's scaled to fit the canvas
46
+ * - u_worldHeight (float): Virtual height of the graphic before it's scaled to fit the canvas
47
+ * - u_fit (float): How to fit the rendered shader into the canvas dimensions (0 = none, 1 = contain, 2 = cover)
48
+ * - u_scale (float): Overall zoom level of the graphics (0.01 to 4)
49
+ * - u_rotation (float): Overall rotation angle of the graphics in degrees (0 to 360)
50
+ * - u_offsetX (float): Horizontal offset of the graphics center (-1 to 1)
51
+ * - u_offsetY (float): Vertical offset of the graphics center (-1 to 1)
28
52
  *
29
53
  */
30
54
  export declare const grainGradientFragmentShader: string;
@@ -4,15 +4,12 @@
4
4
  * * * * * * * * * * * * * * * * * * * * * * * * * * * */
5
5
 
6
6
  import {
7
- sizingVariablesDeclaration,
8
- sizingDebugVariablesDeclaration
9
7
  } from "../shader-sizing.js";
10
8
  import {
11
9
  simplexNoise,
12
10
  declarePI,
13
11
  rotation2,
14
12
  textureRandomizerR,
15
- proceduralHash21,
16
13
  proceduralHash11
17
14
  } from "../shader-utils.js";
18
15
  const grainGradientMeta = {
@@ -46,15 +43,16 @@ uniform mediump float u_rotation;
46
43
  uniform mediump float u_offsetX;
47
44
  uniform mediump float u_offsetY;
48
45
 
49
- ${sizingVariablesDeclaration}
50
- ${sizingDebugVariablesDeclaration}
46
+ in vec2 v_objectUV;
47
+ in vec2 v_patternUV;
48
+ in vec2 v_objectBoxSize;
49
+ in vec2 v_patternBoxSize;
51
50
 
52
51
  out vec4 fragColor;
53
52
 
54
53
  ${declarePI}
55
54
  ${simplexNoise}
56
55
  ${rotation2}
57
- ${proceduralHash21}
58
56
  ${textureRandomizerR}
59
57
 
60
58
  float valueNoiseR(vec2 st) {
@@ -69,13 +67,22 @@ float valueNoiseR(vec2 st) {
69
67
  float x2 = mix(c, d, u.x);
70
68
  return mix(x1, x2, u.y);
71
69
  }
72
- float fbmR(vec2 n) {
73
- float total = 0.;
74
- float amplitude = .2;
70
+ vec4 fbmR(vec2 n0, vec2 n1, vec2 n2, vec2 n3) {
71
+ float amplitude = 0.2;
72
+ vec4 total = vec4(0.);
75
73
  for (int i = 0; i < 3; i++) {
76
- n = rotate(n, .3);
77
- total += valueNoiseR(n) * amplitude;
78
- n *= 1.99;
74
+ n0 = rotate(n0, 0.3);
75
+ n1 = rotate(n1, 0.3);
76
+ n2 = rotate(n2, 0.3);
77
+ n3 = rotate(n3, 0.3);
78
+ total.x += valueNoiseR(n0) * amplitude;
79
+ total.y += valueNoiseR(n1) * amplitude;
80
+ total.z += valueNoiseR(n2) * amplitude;
81
+ total.z += valueNoiseR(n3) * amplitude;
82
+ n0 *= 1.99;
83
+ n1 *= 1.99;
84
+ n2 *= 1.99;
85
+ n3 *= 1.99;
79
86
  amplitude *= 0.6;
80
87
  }
81
88
  return total;
@@ -84,15 +91,15 @@ float fbmR(vec2 n) {
84
91
  ${proceduralHash11}
85
92
 
86
93
  vec2 truchet(vec2 uv, float idx){
87
- idx = fract(((idx - .5) * 2.));
88
- if (idx > 0.75) {
89
- uv = vec2(1.0) - uv;
90
- } else if (idx > 0.5) {
91
- uv = vec2(1.0 - uv.x, uv.y);
92
- } else if (idx > 0.25) {
93
- uv = 1.0 - vec2(1.0 - uv.x, uv.y);
94
- }
95
- return uv;
94
+ idx = fract(((idx - .5) * 2.));
95
+ if (idx > 0.75) {
96
+ uv = vec2(1.0) - uv;
97
+ } else if (idx > 0.5) {
98
+ uv = vec2(1.0 - uv.x, uv.y);
99
+ } else if (idx > 0.25) {
100
+ uv = 1.0 - vec2(1.0 - uv.x, uv.y);
101
+ }
102
+ return uv;
96
103
  }
97
104
 
98
105
  void main() {
@@ -103,14 +110,17 @@ void main() {
103
110
  vec2 shape_uv = vec2(0.);
104
111
  vec2 grain_uv = vec2(0.);
105
112
 
113
+ float r = u_rotation * PI / 180.;
114
+ float cr = cos(r);
115
+ float sr = sin(r);
116
+ mat2 graphicRotation = mat2(cr, sr, -sr, cr);
117
+ vec2 graphicOffset = vec2(-u_offsetX, u_offsetY);
118
+
106
119
  if (u_shape > 3.5) {
107
120
  shape_uv = v_objectUV;
108
121
  grain_uv = shape_uv;
109
122
 
110
123
  // apply inverse transform to grain_uv so it respects the originXY
111
- float r = u_rotation * 3.14159265358979323846 / 180.;
112
- mat2 graphicRotation = mat2(cos(r), sin(r), -sin(r), cos(r));
113
- vec2 graphicOffset = vec2(-u_offsetX, u_offsetY);
114
124
  grain_uv = transpose(graphicRotation) * grain_uv;
115
125
  grain_uv *= u_scale;
116
126
  grain_uv -= graphicOffset;
@@ -121,9 +131,6 @@ void main() {
121
131
  grain_uv = 100. * v_patternUV;
122
132
 
123
133
  // apply inverse transform to grain_uv so it respects the originXY
124
- float r = u_rotation * 3.14159265358979323846 / 180.;
125
- mat2 graphicRotation = mat2(cos(r), sin(r), -sin(r), cos(r));
126
- vec2 graphicOffset = vec2(-u_offsetX, u_offsetY);
127
134
  grain_uv = transpose(graphicRotation) * grain_uv;
128
135
  grain_uv *= u_scale;
129
136
  if (u_fit > 0.) {
@@ -131,8 +138,8 @@ void main() {
131
138
  givenBoxSize = max(givenBoxSize, vec2(1.)) * u_pixelRatio;
132
139
  float patternBoxRatio = givenBoxSize.x / givenBoxSize.y;
133
140
  vec2 patternBoxGivenSize = vec2(
134
- (u_worldWidth == 0.) ? u_resolution.x : givenBoxSize.x,
135
- (u_worldHeight == 0.) ? u_resolution.y : givenBoxSize.y
141
+ (u_worldWidth == 0.) ? u_resolution.x : givenBoxSize.x,
142
+ (u_worldHeight == 0.) ? u_resolution.y : givenBoxSize.y
136
143
  );
137
144
  patternBoxRatio = patternBoxGivenSize.x / patternBoxGivenSize.y;
138
145
  float patternBoxNoFitBoxWidth = patternBoxRatio * min(patternBoxGivenSize.x / patternBoxRatio, patternBoxGivenSize.y);
@@ -235,9 +242,15 @@ void main() {
235
242
  shape *= step(0., d);
236
243
  }
237
244
 
238
- float simplex = snoise(grain_uv * .5);
239
- float grainDist = simplex * snoise(grain_uv * .2) - fbmR(.002 * grain_uv + 10.) - fbmR(.003 * grain_uv);
240
- float rawNoise = .75 * simplex - fbmR(rotate(.4 * grain_uv, 2.)) - fbmR(.001 * grain_uv);
245
+ float baseNoise = snoise(grain_uv * .5);
246
+ vec4 fbmVals = fbmR(
247
+ .002 * grain_uv + 10.,
248
+ .003 * grain_uv,
249
+ .001 * grain_uv,
250
+ rotate(.4 * grain_uv, 2.)
251
+ );
252
+ float grainDist = baseNoise * snoise(grain_uv * .2) - fbmVals.x - fbmVals.y;
253
+ float rawNoise = .75 * baseNoise - fbmVals.w - fbmVals.z;
241
254
  float noise = clamp(rawNoise, 0., 1.);
242
255
 
243
256
  shape += u_intensity * 2. / u_colorsCount * (grainDist + .5);
@@ -249,10 +262,11 @@ void main() {
249
262
  float totalShape = smoothstep(0., u_softness + 2. * aa, clamp(shape * u_colorsCount, 0., 1.));
250
263
  float mixer = shape * (u_colorsCount - 1.);
251
264
 
265
+ int cntStop = int(u_colorsCount) - 1;
252
266
  vec4 gradient = u_colors[0];
253
267
  gradient.rgb *= gradient.a;
254
268
  for (int i = 1; i < ${grainGradientMeta.maxColorCount}; i++) {
255
- if (i > int(u_colorsCount) - 1) break;
269
+ if (i > cntStop) break;
256
270
 
257
271
  float localT = clamp(mixer - float(i - 1), 0., 1.);
258
272
  localT = smoothstep(.5 - .5 * u_softness - aa, .5 + .5 * u_softness + aa, localT);