shaders-oneshot 0.0.81-shared.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. package/LICENSE +201 -0
  2. package/NOTICE +5 -0
  3. package/README.md +7 -0
  4. package/dist/empty-pixel.d.ts +1 -0
  5. package/dist/empty-pixel.js +10 -0
  6. package/dist/empty-pixel.js.map +7 -0
  7. package/dist/get-shader-color-from-string.d.ts +3 -0
  8. package/dist/get-shader-color-from-string.js +101 -0
  9. package/dist/get-shader-color-from-string.js.map +7 -0
  10. package/dist/get-shader-color-from-string.test.d.ts +1 -0
  11. package/dist/get-shader-color-from-string.test.js +69 -0
  12. package/dist/get-shader-noise-texture.d.ts +1 -0
  13. package/dist/get-shader-noise-texture.js +18 -0
  14. package/dist/get-shader-noise-texture.js.map +7 -0
  15. package/dist/index.d.ts +68 -0
  16. package/dist/index.js +194 -0
  17. package/dist/index.js.map +7 -0
  18. package/dist/shader-color-spaces.d.ts +6 -0
  19. package/dist/shader-color-spaces.js +96 -0
  20. package/dist/shader-color-spaces.js.map +7 -0
  21. package/dist/shader-mount.d.ts +199 -0
  22. package/dist/shader-mount.js +735 -0
  23. package/dist/shader-mount.js.map +7 -0
  24. package/dist/shader-sizing.d.ts +30 -0
  25. package/dist/shader-sizing.js +38 -0
  26. package/dist/shader-sizing.js.map +7 -0
  27. package/dist/shader-utils.d.ts +10 -0
  28. package/dist/shader-utils.js +131 -0
  29. package/dist/shader-utils.js.map +7 -0
  30. package/dist/shaders/color-panels.d.ts +70 -0
  31. package/dist/shaders/color-panels.js +224 -0
  32. package/dist/shaders/color-panels.js.map +7 -0
  33. package/dist/shaders/dithering.d.ts +62 -0
  34. package/dist/shaders/dithering.js +271 -0
  35. package/dist/shaders/dithering.js.map +7 -0
  36. package/dist/shaders/dot-grid.d.ts +65 -0
  37. package/dist/shaders/dot-grid.js +110 -0
  38. package/dist/shaders/dot-grid.js.map +7 -0
  39. package/dist/shaders/dot-orbit.d.ts +57 -0
  40. package/dist/shaders/dot-orbit.js +123 -0
  41. package/dist/shaders/dot-orbit.js.map +7 -0
  42. package/dist/shaders/fluted-glass.d.ts +112 -0
  43. package/dist/shaders/fluted-glass.js +361 -0
  44. package/dist/shaders/fluted-glass.js.map +7 -0
  45. package/dist/shaders/gem-smoke.d.ts +96 -0
  46. package/dist/shaders/gem-smoke.js +573 -0
  47. package/dist/shaders/gem-smoke.js.map +7 -0
  48. package/dist/shaders/god-rays.d.ts +67 -0
  49. package/dist/shaders/god-rays.js +133 -0
  50. package/dist/shaders/god-rays.js.map +7 -0
  51. package/dist/shaders/grain-gradient.d.ts +80 -0
  52. package/dist/shaders/grain-gradient.js +301 -0
  53. package/dist/shaders/grain-gradient.js.map +7 -0
  54. package/dist/shaders/halftone-cmyk.d.ts +104 -0
  55. package/dist/shaders/halftone-cmyk.js +295 -0
  56. package/dist/shaders/halftone-cmyk.js.map +7 -0
  57. package/dist/shaders/halftone-dots.d.ts +80 -0
  58. package/dist/shaders/halftone-dots.js +321 -0
  59. package/dist/shaders/halftone-dots.js.map +7 -0
  60. package/dist/shaders/heatmap.d.ts +66 -0
  61. package/dist/shaders/heatmap.js +384 -0
  62. package/dist/shaders/heatmap.js.map +7 -0
  63. package/dist/shaders/image-dithering.d.ts +64 -0
  64. package/dist/shaders/image-dithering.js +199 -0
  65. package/dist/shaders/image-dithering.js.map +7 -0
  66. package/dist/shaders/lens-distortion.d.ts +97 -0
  67. package/dist/shaders/lens-distortion.js +276 -0
  68. package/dist/shaders/lens-distortion.js.map +7 -0
  69. package/dist/shaders/liquid-metal.d.ts +89 -0
  70. package/dist/shaders/liquid-metal.js +633 -0
  71. package/dist/shaders/liquid-metal.js.map +7 -0
  72. package/dist/shaders/mesh-gradient.d.ts +52 -0
  73. package/dist/shaders/mesh-gradient.js +131 -0
  74. package/dist/shaders/mesh-gradient.js.map +7 -0
  75. package/dist/shaders/metaballs.d.ts +51 -0
  76. package/dist/shaders/metaballs.js +111 -0
  77. package/dist/shaders/metaballs.js.map +7 -0
  78. package/dist/shaders/neuro-noise.d.ts +47 -0
  79. package/dist/shaders/neuro-noise.js +77 -0
  80. package/dist/shaders/neuro-noise.js.map +7 -0
  81. package/dist/shaders/paper-texture.d.ts +109 -0
  82. package/dist/shaders/paper-texture.js +527 -0
  83. package/dist/shaders/paper-texture.js.map +7 -0
  84. package/dist/shaders/perlin-noise.d.ts +52 -0
  85. package/dist/shaders/perlin-noise.js +167 -0
  86. package/dist/shaders/perlin-noise.js.map +7 -0
  87. package/dist/shaders/pulsing-border.d.ts +98 -0
  88. package/dist/shaders/pulsing-border.js +239 -0
  89. package/dist/shaders/pulsing-border.js.map +7 -0
  90. package/dist/shaders/simplex-noise.d.ts +45 -0
  91. package/dist/shaders/simplex-noise.js +92 -0
  92. package/dist/shaders/simplex-noise.js.map +7 -0
  93. package/dist/shaders/smoke-ring.d.ts +61 -0
  94. package/dist/shaders/smoke-ring.js +133 -0
  95. package/dist/shaders/smoke-ring.js.map +7 -0
  96. package/dist/shaders/spiral.d.ts +61 -0
  97. package/dist/shaders/spiral.js +83 -0
  98. package/dist/shaders/spiral.js.map +7 -0
  99. package/dist/shaders/static-mesh-gradient.d.ts +63 -0
  100. package/dist/shaders/static-mesh-gradient.js +131 -0
  101. package/dist/shaders/static-mesh-gradient.js.map +7 -0
  102. package/dist/shaders/static-radial-gradient.d.ts +72 -0
  103. package/dist/shaders/static-radial-gradient.js +188 -0
  104. package/dist/shaders/static-radial-gradient.js.map +7 -0
  105. package/dist/shaders/swirl.d.ts +63 -0
  106. package/dist/shaders/swirl.js +104 -0
  107. package/dist/shaders/swirl.js.map +7 -0
  108. package/dist/shaders/voronoi.d.ts +65 -0
  109. package/dist/shaders/voronoi.js +139 -0
  110. package/dist/shaders/voronoi.js.map +7 -0
  111. package/dist/shaders/warp.d.ts +70 -0
  112. package/dist/shaders/warp.js +130 -0
  113. package/dist/shaders/warp.js.map +7 -0
  114. package/dist/shaders/water.d.ts +59 -0
  115. package/dist/shaders/water.js +122 -0
  116. package/dist/shaders/water.js.map +7 -0
  117. package/dist/shaders/waves.d.ts +53 -0
  118. package/dist/shaders/waves.js +66 -0
  119. package/dist/shaders/waves.js.map +7 -0
  120. package/dist/shared-webgl-renderer.d.ts +63 -0
  121. package/dist/shared-webgl-renderer.js +262 -0
  122. package/dist/shared-webgl-renderer.js.map +7 -0
  123. package/dist/types.d.ts +3 -0
  124. package/dist/types.js +6 -0
  125. package/dist/types.js.map +7 -0
  126. package/dist/vertex-shader.d.ts +2 -0
  127. package/dist/vertex-shader.js +160 -0
  128. package/dist/vertex-shader.js.map +7 -0
  129. package/package.json +29 -0
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/shaders/paper-texture.ts"],
4
+ "sourcesContent": ["import type { ShaderMotionParams } from '../shader-mount.js';\r\nimport { type ShaderSizingParams, type ShaderSizingUniforms } from '../shader-sizing.js';\r\nimport { declarePI, proceduralHash21, proceduralHash22 } from '../shader-utils.js';\r\n\r\nexport const paperTextureMeta = {\r\n maxCrumpleCount: 15,\r\n} as const;\r\n\r\n/**\r\n * Static paper-like texture built from a combination of grain, noise and multiple fold patterns.\r\n * Works as an image filter or as a standalone texture.\r\n *\r\n * Fragment shader uniforms:\r\n * - u_image (sampler2D): Optional source image texture\r\n * - u_isImage (bool): Whether a source image was provided\r\n * - u_imageAspectRatio (float): Aspect ratio of the source image\r\n * - u_colorBack (vec4): Color behind the paper sheet in RGBA\r\n * - u_colorPaper (vec4): Color of the paper sheet in RGBA\r\n * - u_colorShadow (vec4): Color of the patterns over the paper sheet in RGBA\r\n * - u_blending (float): Amount of image-to-paper blending, needs image (0 to 1)\r\n * - u_distortion (float): How much the image bends with the paper surface, needs image (-1 to 1)\r\n * - u_clip (bool): Cuts the paper sheet to the image frame, needs image\r\n * - u_angle (float): Direction the surface is lit from in degrees, also the roughness rows direction, needs crumples, wrinkles, folds, roughnessRows or drops > 0 (0 to 360)\r\n * - u_seed (float): Seed applied to every pattern (0 to 1000)\r\n * - u_roughness (float): Fine grain covering the surface evenly (0 to 1)\r\n * - u_roughnessSize (float): Scale of the roughness grain, needs roughness > 0 (0 to 1)\r\n * - u_roughnessRows (float): Lines the roughness up into stripes, 0 = even scatter, 1 = laid-paper rows, needs roughness > 0 (0 to 1)\r\n * - u_fiber (float): Curly thread-like noise covering the surface evenly (0 to 1)\r\n * - u_fiberSize (float): Scale of the fiber noise, needs fiber > 0 (0 to 1)\r\n * - u_folds (float): Straight vertical and horizontal fold lines producing ridges and valleys (0 to 1)\r\n * - u_foldSizeX (float): Size of the vertical folds, needs folds > 0 (0 to 1)\r\n * - u_foldSizeY (float): Size of the horizontal folds, needs folds > 0 (0 to 1)\r\n * - u_foldOffsetX (float): Shifts the vertical folds across the surface, needs folds > 0 (0 to 1)\r\n * - u_foldOffsetY (float): Shifts the horizontal folds across the surface, needs folds > 0 (0 to 1)\r\n * - u_wrinkles (float): Crumple-like facets repeating across the surface (0 to 1)\r\n * - u_wrinkleSize (float): Scale of the wrinkle facets, needs wrinkles > 0 (0 to 1)\r\n * - u_crumples (float): A set of irregular folding lines (0 to 1)\r\n * - u_crumpleCount (float): Number of facets in the crumple field, needs crumples > 0 (2 to 15)\r\n * - u_drops (float): Visibility of the speckle pattern, darkens the image instead of coloring it (0 to 1)\r\n * - u_noiseTexture (sampler2D): Pre-computed randomizer source texture\r\n *\r\n * Vertex shader outputs (used in fragment shader):\r\n * - v_imageUV (vec2): UV coordinates for sampling the source image, with fit, scale, rotation, and offset applied\r\n *\r\n * Vertex shader uniforms:\r\n * - u_resolution (vec2): Canvas resolution in pixels\r\n * - u_pixelRatio (float): Device pixel ratio\r\n * - u_originX (float): Reference point for positioning world width in the canvas (0 to 1)\r\n * - u_originY (float): Reference point for positioning world height in the canvas (0 to 1)\r\n * - u_fit (float): How to fit the rendered shader into the canvas dimensions (0 = none, 1 = contain, 2 = cover)\r\n * - u_scale (float): Overall zoom level of the graphics (0.01 to 4)\r\n * - u_rotation (float): Overall rotation angle of the graphics in degrees (0 to 360)\r\n * - u_offsetX (float): Horizontal offset of the graphics center (-1 to 1)\r\n * - u_offsetY (float): Vertical offset of the graphics center (-1 to 1)\r\n * - u_imageAspectRatio (float): Aspect ratio of the source image\r\n *\r\n */\r\n\r\n// language=GLSL\r\nexport const paperTextureFragmentShader: string = `#version 300 es\r\nprecision mediump float;\r\n\r\nuniform sampler2D u_image;\r\nuniform bool u_isImage;\r\nuniform float u_imageAspectRatio;\r\n\r\nuniform vec4 u_colorBack;\r\nuniform vec4 u_colorPaper;\r\nuniform vec4 u_colorShadow;\r\n\r\nuniform float u_blending;\r\nuniform float u_distortion;\r\nuniform bool u_clip;\r\nuniform float u_angle;\r\nuniform float u_seed;\r\n\r\nuniform float u_roughness;\r\nuniform float u_roughnessSize;\r\nuniform float u_roughnessRows;\r\nuniform float u_fiber;\r\nuniform float u_fiberSize;\r\nuniform float u_folds;\r\nuniform float u_foldSizeX;\r\nuniform float u_foldSizeY;\r\nuniform float u_foldOffsetX;\r\nuniform float u_foldOffsetY;\r\nuniform float u_wrinkles;\r\nuniform float u_wrinkleSize;\r\nuniform float u_crumples;\r\nuniform float u_crumpleCount;\r\nuniform float u_drops;\r\n\r\nuniform sampler2D u_noiseTexture;\r\n\r\nin vec2 v_imageUV;\r\nout vec4 fragColor;\r\n\r\nfloat getUvFrame(vec2 uv) {\r\n vec2 invAA = .5 / clamp(fwidth(uv), 1e-5, .02);\r\n vec2 lo = clamp(uv * invAA + .5, 0., 1.);\r\n vec2 hi = clamp((1. - uv) * invAA + .5, 0., 1.);\r\n return lo.x * hi.x * lo.y * hi.y;\r\n}\r\n\r\nfloat lst(float edge0, float edge1, float x) {\r\n return clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0);\r\n}\r\n\r\n${declarePI}\r\n${proceduralHash21}\r\n${proceduralHash22}\r\n\r\nfloat getRoughness(vec2 p, vec2 lightDir, vec2 seedShift, float basePixel) {\r\n vec2 u = p / vec2(2, 4);\r\n float w = 100. * basePixel;\r\n float eps = 4. * w;\r\n\r\n float size = mix(3.2, .8, u_roughnessSize);\r\n float logLac = log2(2.1);\r\n float level = -log2(w + 1e-8) / logLac;\r\n float baseLevel = floor(level) - 2.;\r\n float fade = fract(level);\r\n\r\n vec2 px = (u.x + vec2(eps, -eps)) * .1;\r\n float py = u.y * .1;\r\n\r\n vec2 sum = vec2(0.);\r\n float norm = 0., amp = .5;\r\n float freq = exp2(baseLevel * logLac);\r\n for (int i = 0; i < 4; i++) {\r\n float absIdx = baseLevel + float(i);\r\n vec2 qx = size * px * freq;\r\n float qy = size * py * freq;\r\n\r\n float wi = 1.;\r\n if (i == 0) wi = 1. - fade;\r\n if (i == 3) wi = fade;\r\n\r\n vec2 fx = fract(qx);\r\n float fy = fract(qy);\r\n vec2 shift = .5 + absIdx * .3 + seedShift;\r\n float uvY = floor(qy) / 50. + shift.y;\r\n vec2 s0a = textureLod(u_noiseTexture, fract(vec2(floor(qx.x) / 50. + shift.x, uvY)), 0.).rg;\r\n vec2 s1a = textureLod(u_noiseTexture, fract(vec2( ceil(qx.x) / 50. + shift.x, uvY)), 0.).rg;\r\n vec2 s0b = textureLod(u_noiseTexture, fract(vec2(floor(qx.y) / 50. + shift.x, uvY)), 0.).rg;\r\n vec2 s1b = textureLod(u_noiseTexture, fract(vec2( ceil(qx.y) / 50. + shift.x, uvY)), 0.).rg;\r\n vec2 ny0 = mix(vec2(s0a.r, s0b.r), vec2(s0a.g, s0b.g), fy);\r\n vec2 ny1 = mix(vec2(s1a.r, s1b.r), vec2(s1a.g, s1b.g), fy);\r\n vec2 n = mix(ny0, ny1, fx);\r\n\r\n sum += amp * wi * n;\r\n norm += amp * wi;\r\n amp *= .8;\r\n freq *= 2.1;\r\n }\r\n\r\n vec2 r = sum / norm;\r\n float dx = .5 + r.x - r.y;\r\n float grain = 3. * dx * dx - .7;\r\n\r\n float rowBand = fract(dot(p, lightDir) * .05 * size);\r\n return grain + .6 * u_roughnessRows * (rowBand - .5);\r\n}\r\n\r\nfloat getFiber(vec2 p, vec2 seedShift, float basePixel) {\r\n float size = mix(4., 1., u_fiberSize);\r\n float w = 50. * basePixel;\r\n float level = -log2(w + 1e-8);\r\n float baseLevel = floor(level) - 3.;\r\n float fade = fract(level);\r\n\r\n vec2 grad = vec2(0.);\r\n float scale = 1.;\r\n float amp = 1.;\r\n float freq = pow(1.7, baseLevel);\r\n for (int i = 0; i < 5; i++) {\r\n float absIdx = baseLevel + float(i);\r\n vec2 q = size * p * freq;\r\n\r\n float an = absIdx * .8;\r\n float rc = cos(an), rs = sin(an);\r\n q = vec2(rc * q.x - rs * q.y, rs * q.x + rc * q.y);\r\n\r\n float wi = 1.;\r\n if (i == 0) wi = 1. - fade;\r\n if (i == 4) wi = fade;\r\n\r\n vec2 iq = floor(q);\r\n vec2 fq = fract(q);\r\n float shift = absIdx * .3;\r\n vec4 uv = fract(vec4(iq, iq + 1.) / 50. + .5 + shift + seedShift.xyxy);\r\n float aF = textureLod(u_noiseTexture, uv.xy, 0.).b;\r\n float bF = textureLod(u_noiseTexture, uv.zy, 0.).b;\r\n float cF = textureLod(u_noiseTexture, uv.xw, 0.).b;\r\n float dF = textureLod(u_noiseTexture, uv.zw, 0.).b;\r\n vec2 u = fq * fq * (3. - 2. * fq);\r\n vec2 du = 8. * fq * (1. - fq);\r\n float dx = du.x * mix(bF - aF, dF - cF, u.y);\r\n float dy = du.y * mix(cF - aF, dF - bF, u.x);\r\n grad += wi * amp * scale * vec2(rc * dx + rs * dy, -rs * dx + rc * dy);\r\n scale *= 1.7;\r\n amp *= .5;\r\n freq *= 1.7;\r\n }\r\n\r\n return clamp(.333 * length(grad), 0., 1.);\r\n}\r\n\r\nvec2 smoothNoise(vec2 p) {\r\n vec2 t = p * 50. - .5;\r\n vec2 i = floor(t);\r\n vec2 f = fract(t);\r\n f = f * f * (3. - 2. * f);\r\n return textureLod(u_noiseTexture, fract((i + f + .5) / vec2(50.)), 0.).rg;\r\n}\r\n\r\nfloat getDrops(vec2 uv, vec2 seedShift) {\r\n vec2 iDropsUV = floor(uv);\r\n vec2 fDropsUV = fract(uv);\r\n float dropsMinDist = 1.;\r\n for (int y = -1; y < 2; y += 1) {\r\n for (int x = -1; x < 2; x += 1) {\r\n vec2 neighbor = vec2(float(y), float(x));\r\n vec2 offset = hash22(iDropsUV + neighbor + 50. * seedShift);\r\n vec2 pos = neighbor + offset - fDropsUV;\r\n dropsMinDist *= min(1., dot(pos, pos));\r\n }\r\n }\r\n return .5 * lst(.09, .08, sqrt(sqrt(dropsMinDist)));\r\n}\r\n\r\nvec2 getCellTilt(float idx, float radius) {\r\n vec2 rand = hash22(vec2(idx + 31., idx * u_seed + 17.));\r\n float an = rand.x * TWO_PI;\r\n return vec2(cos(an), sin(an)) * mix(.3, 1.7, rand.y * rand.y) * mix(.7, 1., radius);\r\n}\r\n\r\nvec2 getCrumpleDetail(vec2 uv, float freq, float shift, float basePixel, out float depth) {\r\n depth = 0.;\r\n vec2 v = uv * freq;\r\n float pixel = .9 * freq * basePixel;\r\n vec2 base = floor(v);\r\n float n1 = 9., n2 = 9.;\r\n vec2 s1 = vec2(0.), s2 = vec2(0.), q1 = vec2(0.), q2 = vec2(0.);\r\n\r\n for (int y = -1; y <= 1; y++) {\r\n for (int x = -1; x <= 1; x++) {\r\n vec2 cell = base + vec2(float(x), float(y));\r\n vec2 q = hash22(vec2(cell.y * 1.9 + 3.1 + shift, cell.x * 1.3 + .11 * u_seed));\r\n float keep = .8;\r\n if (q.y > keep) continue;\r\n\r\n vec2 r = hash22(vec2(cell.x + .37 * u_seed + shift + 11.1, cell.y - .21 * u_seed + 5.7));\r\n vec2 s = cell + .06 + .88 * r;\r\n\r\n vec2 d = v - s;\r\n float dsq = dot(d, d);\r\n if (dsq < n1) {\r\n n2 = n1;\r\n s2 = s1;\r\n q2 = q1;\r\n n1 = dsq;\r\n s1 = s;\r\n q1 = q;\r\n } else if (dsq < n2) {\r\n n2 = dsq;\r\n s2 = s;\r\n q2 = q;\r\n }\r\n }\r\n }\r\n\r\n if (n1 > 8.) return vec2(0.);\r\n\r\n float an1 = q1.x * TWO_PI, mag1 = q1.y / .8;\r\n vec2 t1 = vec2(cos(an1), sin(an1)) * mix(.3, 1.7, mag1 * mag1);\r\n float an2 = q2.x * TWO_PI, mag2 = q2.y / .8;\r\n vec2 t2 = vec2(cos(an2), sin(an2)) * mix(.3, 1.7, mag2 * mag2);\r\n\r\n vec2 span = s1 - s2;\r\n float spanLen = max(length(span), 1e-4);\r\n float toEdge = (n2 - n1) / (2. * spanLen);\r\n\r\n float pair = hash21(s1 + s2 + 1.7 * abs(s1 - s2));\r\n float pairSoft = .05 + .1 * step(pair, .4);\r\n float b = clamp(toEdge / max(1.5 * pixel, .5 * pairSoft), 0., 1.);\r\n b = b * b * (3. - 2. * b);\r\n float d1 = max(sqrt(n1), 1e-4);\r\n depth = .2 * d1;\r\n float shoulderAmt = max(0., 1. - toEdge / .42) * b;\r\n vec2 shoulder = vec2(0.);\r\n if (shoulderAmt > 0.) {\r\n float d2 = max(sqrt(n2), 1e-4);\r\n shoulder = shoulderAmt * ((v - s2) / d2 - (v - s1) / d1);\r\n }\r\n\r\n vec2 mid = .5 * (t1 + t2);\r\n return mid + (t1 - mid) * b + .9 * shoulder;\r\n}\r\n\r\nvec4 getCrumples(vec2 uv) {\r\n float crumpleN = max(2., floor(u_crumpleCount + .5));\r\n float near = 60000., nearB = 60000.;\r\n float idx = 0., rad = 0.;\r\n vec2 nearP = vec2(0.), nearPb = vec2(0.);\r\n vec4 seeds[${paperTextureMeta.maxCrumpleCount}];\r\n for (int i = 0; i < ${paperTextureMeta.maxCrumpleCount}; i++) {\r\n if (float(i) >= crumpleN) break;\r\n vec2 rand = hash22(vec2(float(i), float(i) * u_seed));\r\n float an = rand.x * TWO_PI;\r\n vec2 p = vec2(cos(an), sin(an)) * rand.y;\r\n seeds[i] = vec4(p, rand);\r\n\r\n vec2 d = uv - p;\r\n float dsq = dot(d, d);\r\n if (dsq < near) {\r\n nearB = near;\r\n nearPb = nearP;\r\n near = dsq;\r\n idx = float(i);\r\n rad = rand.y;\r\n nearP = p;\r\n } else if (dsq < nearB) {\r\n nearB = dsq;\r\n nearPb = p;\r\n }\r\n }\r\n float l = sqrt(near), lb = sqrt(nearB);\r\n vec2 dir = (uv - nearP) / max(l, 1e-4);\r\n float edge = lst(0., .5, lb - l);\r\n\r\n float shoulderLimit = l + .5;\r\n\r\n vec2 tilt = getCellTilt(idx, rad);\r\n float tiltSum = 1.;\r\n vec2 wide = vec2(0.);\r\n float wideSum = 0.;\r\n float toEdge = 9., edgeSoft = 0.;\r\n\r\n for (int i = 0; i < ${paperTextureMeta.maxCrumpleCount}; i++) {\r\n if (float(i) >= crumpleN) break;\r\n if (float(i) == idx) continue;\r\n vec4 seed = seeds[i];\r\n vec2 p = seed.xy;\r\n vec2 rand = seed.zw;\r\n\r\n vec2 d = uv - p;\r\n float dsq = dot(d, d);\r\n\r\n if (dsq < shoulderLimit * shoulderLimit) {\r\n float di = sqrt(dsq);\r\n float shoulder = lst(.5, 0., di - l);\r\n wide += shoulder * (d / max(di, 1e-4) - dir);\r\n wideSum += shoulder;\r\n }\r\n\r\n float pairSoft = .01 + .05 * step(.2, rand.x) + .3 * rand.y;\r\n float toBisector = (dsq - near) / (.2 * max(length(p - nearP), 1e-4));\r\n if (toBisector < toEdge) {\r\n toEdge = toBisector;\r\n edgeSoft = pairSoft;\r\n }\r\n\r\n float w = 1. - toBisector / pairSoft;\r\n if (w > 0.) {\r\n w *= w;\r\n tilt += w * getCellTilt(float(i), rand.y);\r\n tiltSum += w;\r\n }\r\n }\r\n\r\n float blend = clamp(toEdge / edgeSoft, 0., 1.);\r\n vec2 sharp = (1. - edge) * ((uv - nearPb) / max(lb, 1e-4) - dir);\r\n vec2 rounding = mix(sharp, wide / max(wideSum, 1.), min(2. * edgeSoft, 1.));\r\n float radial = l / max(l + toEdge, 1e-4);\r\n\r\n return vec4(tilt / tiltSum + rounding * blend * radial, .2 * l, edge);\r\n}\r\n\r\nvoid getFolds(vec2 coord, vec2 offset, vec2 count, vec2 noise, vec2 baseFwidth, out vec2 slope, out vec2 dark, out vec2 lift) {\r\n vec2 g = coord * count + .5 * offset + noise;\r\n vec2 dx = fract(g) - .5;\r\n vec2 adx = abs(dx);\r\n float foldRadius = .3;\r\n vec2 t = clamp(adx / foldRadius, 0., 1.);\r\n dark = t * t * (3. - 2. * t);\r\n lift = 1. - t;\r\n lift *= lift;\r\n\r\n vec2 crease = clamp(dx / max(count * baseFwidth, 1e-5), -1., 1.);\r\n slope = crease * (1. - dark);\r\n\r\n vec2 lineWidth = .02 * count * mix(vec2(2.5), vec2(.8), dark.yx) + .1 * noise;\r\n slope -= 1. - smoothstep(vec2(0.), lineWidth, adx);\r\n}\r\n\r\nvoid main() {\r\n\r\n vec2 patternUV = (v_imageUV - .5) * vec2(u_imageAspectRatio, 1.);\r\n float basePixel = max(length(dFdx(patternUV)), length(dFdy(patternUV)));\r\n vec2 baseFwidth = fwidth(patternUV);\r\n\r\n float pattern = 0.;\r\n\r\n float crumpleDepth = 0.;\r\n float wrinkleDepth = 0.;\r\n float foldDepth = 0.;\r\n float roughness = 0.;\r\n float fiber = 0.;\r\n float drops = 0.;\r\n\r\n float grazing = 0.7;\r\n float lightRad = radians(u_angle);\r\n vec2 lightDir = vec2(sin(lightRad), -cos(lightRad));\r\n float foldAngleInSector = mod(u_angle, 90.);\r\n float foldLightRad = radians(u_angle - foldAngleInSector + mix(12., 78., foldAngleInSector / 90.));\r\n vec2 foldLightDir = vec2(sin(foldLightRad), -cos(foldLightRad));\r\n vec2 relief = vec2(0.);\r\n vec2 foldSlope = vec2(0.);\r\n float reliefAmount = 0.;\r\n float foldInk = 1.;\r\n vec2 crumpleFlow = vec2(0.);\r\n\r\n vec2 warpNoise = vec2(0.);\r\n if (u_crumples > 0. || u_folds > 0. || u_wrinkles > 0.) {\r\n warpNoise = smoothNoise(patternUV * .1 + .2 + .6 * fract(.017 * u_seed)) - .5;\r\n }\r\n vec2 crumplesUV = (patternUV * .9) + .012 * warpNoise;\r\n\r\n if (u_crumples > 0.) {\r\n vec4 crumples = getCrumples(crumplesUV);\r\n\r\n vec2 crumpleTilt = .5 * u_crumples * crumples.xy;\r\n crumpleTilt -= .1 * max(dot(crumpleTilt, lightDir), 0.) * lightDir;\r\n relief += crumpleTilt;\r\n reliefAmount += .6 * u_crumples;\r\n crumpleFlow = crumples.w * crumpleTilt;\r\n\r\n crumpleDepth = clamp(5. * crumples.z, 0., 1.);\r\n }\r\n\r\n if (u_wrinkles > 0.) {\r\n float detailFreq = mix(10., 1., u_wrinkleSize);\r\n float detailAmp = .2;\r\n vec2 detailGrad = vec2(0.);\r\n float detailDepth = 0., depthSum = 0.;\r\n for (int i = 0; i < 3; i++) {\r\n float layerDepth;\r\n detailGrad += detailAmp * getCrumpleDetail(crumplesUV, detailFreq, 31. * float(i), basePixel, layerDepth);\r\n detailDepth += detailAmp * layerDepth;\r\n depthSum += detailAmp;\r\n detailAmp *= (.5 + .2 * detailGrad.x);\r\n detailFreq *= 2.1;\r\n }\r\n\r\n vec2 detailTilt = 1.5 * u_wrinkles * detailGrad;\r\n detailTilt -= .65 * max(dot(detailTilt, lightDir), 0.) * lightDir;\r\n relief += detailTilt;\r\n reliefAmount += .6 * u_wrinkles;\r\n\r\n wrinkleDepth = clamp(5. * detailDepth / max(depthSum, 1e-4), 0., 1.);\r\n }\r\n\r\n if (u_folds > 0.) {\r\n vec2 foldOffset = vec2(1. - 2. * u_foldOffsetX, 1. - 2. * u_foldOffsetY);\r\n vec2 foldCount = vec2(mix(3., .5, u_foldSizeX), mix(3., .5, u_foldSizeY));\r\n vec2 foldNoise = .005 * warpNoise * foldCount;\r\n vec2 uv = patternUV + .03 * crumpleFlow;\r\n\r\n vec2 slope, dark, lift;\r\n getFolds(uv, foldOffset, foldCount, foldNoise, baseFwidth, slope, dark, lift);\r\n\r\n foldSlope = u_folds * slope;\r\n reliefAmount += 1. * u_folds;\r\n vec2 ink = mix(vec2(.96), vec2(1.), dark);\r\n float flatness = dark.x * dark.y;\r\n foldInk *= mix(1., ink.x * ink.y * mix(.5, .3, flatness), u_folds);\r\n\r\n foldDepth = u_folds * (lift.y * foldLightDir.y - lift.x * foldLightDir.x);\r\n }\r\n\r\n float unlit = cos(grazing);\r\n float lit = unlit;\r\n\r\n if (reliefAmount > 0.) {\r\n float lightFalloff = clamp(.5 + dot(v_imageUV - .5, lightDir), 0., 1.);\r\n float lightPower = mix(.5, 1., lightFalloff);\r\n float slope = clamp(dot(relief, lightDir) + dot(foldSlope, foldLightDir), -1.2, 1.2);\r\n lit = max(cos(slope + grazing), 0.);\r\n\r\n pattern += (clamp(reliefAmount, 0., 1.) * unlit + (lit - unlit)) * foldInk * lightPower;\r\n }\r\n\r\n patternUV += .04 * crumpleFlow;\r\n\r\n vec2 seedShift = floor(fract(u_seed * vec2(.7548776662, .5698402909)) * 50.) / 50.;\r\n\r\n if (u_roughness > 0.) {\r\n roughness = u_roughness * getRoughness(1000. * patternUV, lightDir, seedShift, basePixel);\r\n pattern += roughness;\r\n }\r\n\r\n if (u_fiber > 0.) {\r\n fiber = u_fiber * getFiber(50. * patternUV, seedShift, basePixel);\r\n pattern += fiber;\r\n }\r\n\r\n if (u_drops > 0.) {\r\n drops = u_drops * getDrops(patternUV * 10., seedShift);\r\n }\r\n\r\n pattern = clamp(pattern, 0., 1.);\r\n\r\n vec3 backColor = u_colorBack.rgb * u_colorBack.a;\r\n float backOpacity = u_colorBack.a;\r\n vec3 baseColor = u_colorPaper.rgb * u_colorPaper.a;\r\n float baseOpacity = u_colorPaper.a;\r\n vec3 shadowColor = u_colorShadow.rgb * u_colorShadow.a;\r\n float shadowOpacity = u_colorShadow.a;\r\n\r\n float notClipped = u_clip ? .1 : 1.;\r\n vec2 imageCenteredUV = v_imageUV - .5;\r\n float edgeDist = 2. * max(abs(imageCenteredUV.x), abs(imageCenteredUV.y));\r\n float wrinkleDistortion = mix(.38, .0175, smoothstep(0., 1., edgeDist));\r\n float scaleDistortion = .15 * u_crumples * (crumpleDepth - .5) + wrinkleDistortion * u_wrinkles * (wrinkleDepth - .5) + .05 * foldDepth;\r\n vec2 linearDistortion = notClipped * .002 * lightDir * drops;\r\n float radialDistortion = notClipped * .02 * (roughness + fiber);\r\n vec2 centeredUV = imageCenteredUV * (1. - u_distortion * scaleDistortion);\r\n centeredUV -= u_distortion * linearDistortion;\r\n vec2 imageUV = .5 + centeredUV * (1. - abs(u_distortion) * radialDistortion * dot(centeredUV, centeredUV));\r\n\r\n vec3 color = shadowColor * pattern;\r\n float opacity = shadowOpacity * pattern;\r\n color += baseColor * (1. - opacity);\r\n opacity += baseOpacity * (1. - opacity);\r\n\r\n if (u_isImage) {\r\n float frame = getUvFrame(imageUV);\r\n vec4 image = texture(u_image, imageUV);\r\n frame *= image.a;\r\n\r\n float maxC = max(max(image.r, image.g), image.b);\r\n float minC = min(min(image.r, image.g), image.b);\r\n float sat = maxC > 0. ? (maxC - minC) / maxC : 0.;\r\n float midC = image.r + image.g + image.b - maxC - minC;\r\n float secondaryness = maxC > minC ? (midC - minC) / (maxC - minC) : 0.;\r\n float satDampen = sat * (1. - .5 * secondaryness);\r\n float darkDampen = 1. - dot(vec3(.2126, .7152, .0722), image.rgb);\r\n float dampen = mix(0., .7, u_blending) * max(satDampen, darkDampen);\r\n\r\n vec3 paper = vec3(1.) - opacity + color;\r\n vec3 pic = image.rgb * paper * u_blending + image.rgb * (1. - u_blending);\r\n pic = mix(pic, vec3(1.), .6 * pow(dampen, 2. + 3. * pattern));\r\n\r\n color = mix(color, pic, frame);\r\n opacity = frame + opacity * (1. - frame);\r\n\r\n if (u_clip) {\r\n color *= frame;\r\n opacity *= frame;\r\n }\r\n }\r\n\r\n color *= mix(vec3(1.), .5 * u_colorShadow.rgb, drops * shadowOpacity);\r\n\r\n color += backColor * (1. - opacity);\r\n opacity += backOpacity * (1. - opacity);\r\n\r\n fragColor = vec4(color, opacity);\r\n}\r\n`;\r\n\r\nexport interface PaperTextureUniforms extends ShaderSizingUniforms {\r\n u_image: HTMLImageElement | string | undefined;\r\n u_isImage: boolean;\r\n u_colorBack: [number, number, number, number];\r\n u_colorPaper: [number, number, number, number];\r\n u_colorShadow: [number, number, number, number];\r\n u_blending: number;\r\n u_distortion: number;\r\n u_clip: boolean;\r\n u_angle: number;\r\n u_seed: number;\r\n u_roughness: number;\r\n u_roughnessSize: number;\r\n u_roughnessRows: number;\r\n u_fiber: number;\r\n u_fiberSize: number;\r\n u_folds: number;\r\n u_foldSizeX: number;\r\n u_foldSizeY: number;\r\n u_foldOffsetX: number;\r\n u_foldOffsetY: number;\r\n u_wrinkles: number;\r\n u_wrinkleSize: number;\r\n u_crumples: number;\r\n u_crumpleCount: number;\r\n u_drops: number;\r\n u_noiseTexture?: HTMLImageElement;\r\n}\r\nexport interface PaperTextureParams extends ShaderSizingParams, ShaderMotionParams {\r\n image?: HTMLImageElement | string;\r\n colorBack?: string;\r\n colorPaper?: string;\r\n colorShadow?: string;\r\n blending?: number;\r\n distortion?: number;\r\n clip?: boolean;\r\n angle?: number;\r\n seed?: number;\r\n roughness?: number;\r\n roughnessSize?: number;\r\n roughnessRows?: number;\r\n fiber?: number;\r\n fiberSize?: number;\r\n folds?: number;\r\n foldSizeX?: number;\r\n foldSizeY?: number;\r\n foldOffsetX?: number;\r\n foldOffsetY?: number;\r\n wrinkles?: number;\r\n wrinkleSize?: number;\r\n crumples?: number;\r\n crumpleCount?: number;\r\n drops?: number;\r\n}\r\n"],
5
+ "mappings": ";;;;;AACA,eAAmE;AACnE,SAAS,WAAW,kBAAkB,wBAAwB;AAEvD,MAAM,mBAAmB;AAAA,EAC9B,iBAAiB;AACnB;AAqDO,MAAM,6BAAqC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiDhD,SAAS;AAAA,EACT,gBAAgB;AAAA,EAChB,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,eAmMH,iBAAiB,eAAe;AAAA,wBACvB,iBAAiB,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAiChC,iBAAiB,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;",
6
+ "names": []
7
+ }
@@ -0,0 +1,52 @@
1
+ import type { ShaderMotionParams } from '../shader-mount.js';
2
+ import { type ShaderSizingParams, type ShaderSizingUniforms } from '../shader-sizing.js';
3
+ /**
4
+ * Classic animated 3D Perlin noise with exposed controls.
5
+ * Original algorithm: https://www.shadertoy.com/view/NlSGDz
6
+ *
7
+ * Fragment shader uniforms:
8
+ * - u_time (float): Animation time
9
+ * - u_colorFront (vec4): Foreground color in RGBA
10
+ * - u_colorBack (vec4): Background color in RGBA
11
+ * - u_proportion (float): Blend point between two colors, 0.5 = equal distribution (0 to 1)
12
+ * - u_softness (float): Color transition sharpness, 0 = hard edge, 1 = smooth gradient (0 to 1)
13
+ * - u_octaveCount (float): Perlin noise octaves number, more octaves for more detailed patterns (1 to 8)
14
+ * - u_persistence (float): Roughness, falloff between octaves, needs octaveCount > 1 (0.3 to 1)
15
+ * - u_lacunarity (float): Frequency step, defines how compressed the pattern is, needs octaveCount > 1 (1.5 to 10)
16
+ *
17
+ * Vertex shader outputs (used in fragment shader):
18
+ * - v_patternUV (vec2): UV coordinates for pattern with global sizing (rotation, scale, offset, etc) applied
19
+ *
20
+ * Vertex shader uniforms:
21
+ * - u_resolution (vec2): Canvas resolution in pixels
22
+ * - u_pixelRatio (float): Device pixel ratio
23
+ * - u_originX (float): Reference point for positioning world width in the canvas (0 to 1)
24
+ * - u_originY (float): Reference point for positioning world height in the canvas (0 to 1)
25
+ * - u_worldWidth (float): Virtual width of the graphic before it's scaled to fit the canvas
26
+ * - u_worldHeight (float): Virtual height of the graphic before it's scaled to fit the canvas
27
+ * - u_fit (float): How to fit the rendered shader into the canvas dimensions (0 = none, 1 = contain, 2 = cover)
28
+ * - u_scale (float): Overall zoom level of the graphics (0.01 to 4)
29
+ * - u_rotation (float): Overall rotation angle of the graphics in degrees (0 to 360)
30
+ * - u_offsetX (float): Horizontal offset of the graphics center (-1 to 1)
31
+ * - u_offsetY (float): Vertical offset of the graphics center (-1 to 1)
32
+ *
33
+ */
34
+ export declare const perlinNoiseFragmentShader: string;
35
+ export interface PerlinNoiseUniforms extends ShaderSizingUniforms {
36
+ u_colorFront: [number, number, number, number];
37
+ u_colorBack: [number, number, number, number];
38
+ u_proportion: number;
39
+ u_softness: number;
40
+ u_octaveCount: number;
41
+ u_persistence: number;
42
+ u_lacunarity: number;
43
+ }
44
+ export interface PerlinNoiseParams extends ShaderSizingParams, ShaderMotionParams {
45
+ colorFront?: string;
46
+ colorBack?: string;
47
+ proportion?: number;
48
+ softness?: number;
49
+ octaveCount?: number;
50
+ persistence?: number;
51
+ lacunarity?: number;
52
+ }
@@ -0,0 +1,167 @@
1
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * *
2
+ * Paper Shaders *
3
+ * https://github.com/paper-design/shaders *
4
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * */
5
+
6
+ import {} from "../shader-sizing.js";
7
+ import { declarePI, colorBandingFix, proceduralHash11, proceduralHash21 } from "../shader-utils.js";
8
+ const perlinNoiseFragmentShader = `#version 300 es
9
+ precision mediump float;
10
+
11
+ uniform float u_time;
12
+
13
+ uniform vec4 u_colorFront;
14
+ uniform vec4 u_colorBack;
15
+ uniform float u_proportion;
16
+ uniform float u_softness;
17
+ uniform float u_octaveCount;
18
+ uniform float u_persistence;
19
+ uniform float u_lacunarity;
20
+
21
+ in vec2 v_patternUV;
22
+
23
+ out vec4 fragColor;
24
+
25
+ ${declarePI}
26
+ ${proceduralHash11}
27
+ ${proceduralHash21}
28
+
29
+ float hash31(vec3 p) {
30
+ p = fract(p * 0.3183099) + 0.1;
31
+ p += dot(p, p.yzx + 19.19);
32
+ return fract(p.x * (p.y + p.z));
33
+ }
34
+
35
+ vec3 gradientPredefined(float hash) {
36
+ int idx = int(hash * 12.0) % 12;
37
+
38
+ if (idx == 0) return vec3(1, 1, 0);
39
+ if (idx == 1) return vec3(-1, 1, 0);
40
+ if (idx == 2) return vec3(1, -1, 0);
41
+ if (idx == 3) return vec3(-1, -1, 0);
42
+ if (idx == 4) return vec3(1, 0, 1);
43
+ if (idx == 5) return vec3(-1, 0, 1);
44
+ if (idx == 6) return vec3(1, 0, -1);
45
+ if (idx == 7) return vec3(-1, 0, -1);
46
+ if (idx == 8) return vec3(0, 1, 1);
47
+ if (idx == 9) return vec3(0, -1, 1);
48
+ if (idx == 10) return vec3(0, 1, -1);
49
+ return vec3(0, -1, -1);// idx == 11
50
+ }
51
+
52
+ float interpolateSafe(float v000, float v001, float v010, float v011,
53
+ float v100, float v101, float v110, float v111, vec3 t) {
54
+ t = clamp(t, 0.0, 1.0);
55
+
56
+ float v00 = mix(v000, v100, t.x);
57
+ float v01 = mix(v001, v101, t.x);
58
+ float v10 = mix(v010, v110, t.x);
59
+ float v11 = mix(v011, v111, t.x);
60
+
61
+ float v0 = mix(v00, v10, t.y);
62
+ float v1 = mix(v01, v11, t.y);
63
+
64
+ return mix(v0, v1, t.z);
65
+ }
66
+
67
+ vec3 fade(vec3 t) {
68
+ return t * t * t * (t * (t * 6.0 - 15.0) + 10.0);
69
+ }
70
+
71
+ float perlinNoise(vec3 position, float seed) {
72
+ position += vec3(seed * 127.1, seed * 311.7, seed * 74.7);
73
+
74
+ vec3 i = floor(position);
75
+ vec3 f = fract(position);
76
+ float h000 = hash31(i);
77
+ float h001 = hash31(i + vec3(0, 0, 1));
78
+ float h010 = hash31(i + vec3(0, 1, 0));
79
+ float h011 = hash31(i + vec3(0, 1, 1));
80
+ float h100 = hash31(i + vec3(1, 0, 0));
81
+ float h101 = hash31(i + vec3(1, 0, 1));
82
+ float h110 = hash31(i + vec3(1, 1, 0));
83
+ float h111 = hash31(i + vec3(1, 1, 1));
84
+ vec3 g000 = gradientPredefined(h000);
85
+ vec3 g001 = gradientPredefined(h001);
86
+ vec3 g010 = gradientPredefined(h010);
87
+ vec3 g011 = gradientPredefined(h011);
88
+ vec3 g100 = gradientPredefined(h100);
89
+ vec3 g101 = gradientPredefined(h101);
90
+ vec3 g110 = gradientPredefined(h110);
91
+ vec3 g111 = gradientPredefined(h111);
92
+ float v000 = dot(g000, f - vec3(0, 0, 0));
93
+ float v001 = dot(g001, f - vec3(0, 0, 1));
94
+ float v010 = dot(g010, f - vec3(0, 1, 0));
95
+ float v011 = dot(g011, f - vec3(0, 1, 1));
96
+ float v100 = dot(g100, f - vec3(1, 0, 0));
97
+ float v101 = dot(g101, f - vec3(1, 0, 1));
98
+ float v110 = dot(g110, f - vec3(1, 1, 0));
99
+ float v111 = dot(g111, f - vec3(1, 1, 1));
100
+
101
+ vec3 u = fade(f);
102
+ return interpolateSafe(v000, v001, v010, v011, v100, v101, v110, v111, u);
103
+ }
104
+
105
+ float p_noise(vec3 position, int octaveCount, float persistence, float lacunarity) {
106
+ float value = 0.0;
107
+ float amplitude = 1.0;
108
+ float frequency = 10.0;
109
+ octaveCount = clamp(octaveCount, 1, 8);
110
+
111
+ for (int i = 0; i < octaveCount; i++) {
112
+ float seed = float(i) * 0.7319;
113
+ value += perlinNoise(position * frequency, seed) * amplitude;
114
+ amplitude *= persistence;
115
+ frequency *= lacunarity;
116
+ }
117
+ return value;
118
+ }
119
+
120
+ float get_max_amp(float persistence, float octaveCount) {
121
+ persistence = clamp(persistence * 0.999, 0.0, 0.999);
122
+ octaveCount = clamp(octaveCount, 1.0, 8.0);
123
+
124
+ return (1.0 - pow(persistence, octaveCount)) / max(1e-4, (1.0 - persistence));
125
+ }
126
+
127
+ void main() {
128
+ vec2 uv = v_patternUV;
129
+ uv *= .5;
130
+
131
+ float t = .2 * u_time;
132
+
133
+ vec3 p = vec3(uv, t);
134
+
135
+ float octCount = floor(u_octaveCount);
136
+ float noise = p_noise(p, int(octCount), u_persistence, u_lacunarity);
137
+
138
+ float max_amp = get_max_amp(u_persistence, octCount);
139
+ float noise_normalized = clamp((noise + max_amp) / max(1e-4, (2. * max_amp)) + (u_proportion - .5), 0.0, 1.0);
140
+ float sharpness = clamp(u_softness, 0., 1.);
141
+ float smooth_w = 0.5 * max(fwidth(noise_normalized), 0.001);
142
+ float res = smoothstep(
143
+ .5 - .5 * sharpness - smooth_w,
144
+ .5 + .5 * sharpness + smooth_w,
145
+ noise_normalized
146
+ );
147
+
148
+ vec3 fgColor = u_colorFront.rgb * u_colorFront.a;
149
+ float fgOpacity = u_colorFront.a;
150
+ vec3 bgColor = u_colorBack.rgb * u_colorBack.a;
151
+ float bgOpacity = u_colorBack.a;
152
+
153
+ vec3 color = fgColor * res;
154
+ float opacity = fgOpacity * res;
155
+
156
+ color += bgColor * (1. - opacity);
157
+ opacity += bgOpacity * (1. - opacity);
158
+
159
+ ${colorBandingFix}
160
+
161
+ fragColor = vec4(color, opacity);
162
+ }
163
+ `;
164
+ export {
165
+ perlinNoiseFragmentShader
166
+ };
167
+ //# sourceMappingURL=perlin-noise.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/shaders/perlin-noise.ts"],
4
+ "sourcesContent": ["import type { ShaderMotionParams } from '../shader-mount.js';\r\nimport { type ShaderSizingParams, type ShaderSizingUniforms } from '../shader-sizing.js';\r\nimport { declarePI, colorBandingFix, proceduralHash11, proceduralHash21 } from '../shader-utils.js';\r\n\r\n/**\r\n * Classic animated 3D Perlin noise with exposed controls.\r\n * Original algorithm: https://www.shadertoy.com/view/NlSGDz\r\n *\r\n * Fragment shader uniforms:\r\n * - u_time (float): Animation time\r\n * - u_colorFront (vec4): Foreground color in RGBA\r\n * - u_colorBack (vec4): Background color in RGBA\r\n * - u_proportion (float): Blend point between two colors, 0.5 = equal distribution (0 to 1)\r\n * - u_softness (float): Color transition sharpness, 0 = hard edge, 1 = smooth gradient (0 to 1)\r\n * - u_octaveCount (float): Perlin noise octaves number, more octaves for more detailed patterns (1 to 8)\r\n * - u_persistence (float): Roughness, falloff between octaves, needs octaveCount > 1 (0.3 to 1)\r\n * - u_lacunarity (float): Frequency step, defines how compressed the pattern is, needs octaveCount > 1 (1.5 to 10)\r\n *\r\n * Vertex shader outputs (used in fragment shader):\r\n * - v_patternUV (vec2): UV coordinates for pattern with global sizing (rotation, scale, offset, etc) applied\r\n *\r\n * Vertex shader uniforms:\r\n * - u_resolution (vec2): Canvas resolution in pixels\r\n * - u_pixelRatio (float): Device pixel ratio\r\n * - u_originX (float): Reference point for positioning world width in the canvas (0 to 1)\r\n * - u_originY (float): Reference point for positioning world height in the canvas (0 to 1)\r\n * - u_worldWidth (float): Virtual width of the graphic before it's scaled to fit the canvas\r\n * - u_worldHeight (float): Virtual height of the graphic before it's scaled to fit the canvas\r\n * - u_fit (float): How to fit the rendered shader into the canvas dimensions (0 = none, 1 = contain, 2 = cover)\r\n * - u_scale (float): Overall zoom level of the graphics (0.01 to 4)\r\n * - u_rotation (float): Overall rotation angle of the graphics in degrees (0 to 360)\r\n * - u_offsetX (float): Horizontal offset of the graphics center (-1 to 1)\r\n * - u_offsetY (float): Vertical offset of the graphics center (-1 to 1)\r\n *\r\n */\r\n\r\n// language=GLSL\r\nexport const perlinNoiseFragmentShader: string = `#version 300 es\r\nprecision mediump float;\r\n\r\nuniform float u_time;\r\n\r\nuniform vec4 u_colorFront;\r\nuniform vec4 u_colorBack;\r\nuniform float u_proportion;\r\nuniform float u_softness;\r\nuniform float u_octaveCount;\r\nuniform float u_persistence;\r\nuniform float u_lacunarity;\r\n\r\nin vec2 v_patternUV;\r\n\r\nout vec4 fragColor;\r\n\r\n${ declarePI }\r\n${ proceduralHash11 }\r\n${ proceduralHash21 }\r\n\r\nfloat hash31(vec3 p) {\r\n p = fract(p * 0.3183099) + 0.1;\r\n p += dot(p, p.yzx + 19.19);\r\n return fract(p.x * (p.y + p.z));\r\n}\r\n\r\nvec3 gradientPredefined(float hash) {\r\n int idx = int(hash * 12.0) % 12;\r\n\r\n if (idx == 0) return vec3(1, 1, 0);\r\n if (idx == 1) return vec3(-1, 1, 0);\r\n if (idx == 2) return vec3(1, -1, 0);\r\n if (idx == 3) return vec3(-1, -1, 0);\r\n if (idx == 4) return vec3(1, 0, 1);\r\n if (idx == 5) return vec3(-1, 0, 1);\r\n if (idx == 6) return vec3(1, 0, -1);\r\n if (idx == 7) return vec3(-1, 0, -1);\r\n if (idx == 8) return vec3(0, 1, 1);\r\n if (idx == 9) return vec3(0, -1, 1);\r\n if (idx == 10) return vec3(0, 1, -1);\r\n return vec3(0, -1, -1);// idx == 11\r\n}\r\n\r\nfloat interpolateSafe(float v000, float v001, float v010, float v011,\r\nfloat v100, float v101, float v110, float v111, vec3 t) {\r\n t = clamp(t, 0.0, 1.0);\r\n\r\n float v00 = mix(v000, v100, t.x);\r\n float v01 = mix(v001, v101, t.x);\r\n float v10 = mix(v010, v110, t.x);\r\n float v11 = mix(v011, v111, t.x);\r\n\r\n float v0 = mix(v00, v10, t.y);\r\n float v1 = mix(v01, v11, t.y);\r\n\r\n return mix(v0, v1, t.z);\r\n}\r\n\r\nvec3 fade(vec3 t) {\r\n return t * t * t * (t * (t * 6.0 - 15.0) + 10.0);\r\n}\r\n\r\nfloat perlinNoise(vec3 position, float seed) {\r\n position += vec3(seed * 127.1, seed * 311.7, seed * 74.7);\r\n\r\n vec3 i = floor(position);\r\n vec3 f = fract(position);\r\n float h000 = hash31(i);\r\n float h001 = hash31(i + vec3(0, 0, 1));\r\n float h010 = hash31(i + vec3(0, 1, 0));\r\n float h011 = hash31(i + vec3(0, 1, 1));\r\n float h100 = hash31(i + vec3(1, 0, 0));\r\n float h101 = hash31(i + vec3(1, 0, 1));\r\n float h110 = hash31(i + vec3(1, 1, 0));\r\n float h111 = hash31(i + vec3(1, 1, 1));\r\n vec3 g000 = gradientPredefined(h000);\r\n vec3 g001 = gradientPredefined(h001);\r\n vec3 g010 = gradientPredefined(h010);\r\n vec3 g011 = gradientPredefined(h011);\r\n vec3 g100 = gradientPredefined(h100);\r\n vec3 g101 = gradientPredefined(h101);\r\n vec3 g110 = gradientPredefined(h110);\r\n vec3 g111 = gradientPredefined(h111);\r\n float v000 = dot(g000, f - vec3(0, 0, 0));\r\n float v001 = dot(g001, f - vec3(0, 0, 1));\r\n float v010 = dot(g010, f - vec3(0, 1, 0));\r\n float v011 = dot(g011, f - vec3(0, 1, 1));\r\n float v100 = dot(g100, f - vec3(1, 0, 0));\r\n float v101 = dot(g101, f - vec3(1, 0, 1));\r\n float v110 = dot(g110, f - vec3(1, 1, 0));\r\n float v111 = dot(g111, f - vec3(1, 1, 1));\r\n\r\n vec3 u = fade(f);\r\n return interpolateSafe(v000, v001, v010, v011, v100, v101, v110, v111, u);\r\n}\r\n\r\nfloat p_noise(vec3 position, int octaveCount, float persistence, float lacunarity) {\r\n float value = 0.0;\r\n float amplitude = 1.0;\r\n float frequency = 10.0;\r\n octaveCount = clamp(octaveCount, 1, 8);\r\n\r\n for (int i = 0; i < octaveCount; i++) {\r\n float seed = float(i) * 0.7319;\r\n value += perlinNoise(position * frequency, seed) * amplitude;\r\n amplitude *= persistence;\r\n frequency *= lacunarity;\r\n }\r\n return value;\r\n}\r\n\r\nfloat get_max_amp(float persistence, float octaveCount) {\r\n persistence = clamp(persistence * 0.999, 0.0, 0.999);\r\n octaveCount = clamp(octaveCount, 1.0, 8.0);\r\n\r\n return (1.0 - pow(persistence, octaveCount)) / max(1e-4, (1.0 - persistence));\r\n}\r\n\r\nvoid main() {\r\n vec2 uv = v_patternUV;\r\n uv *= .5;\r\n\r\n float t = .2 * u_time;\r\n\r\n vec3 p = vec3(uv, t);\r\n\r\n float octCount = floor(u_octaveCount);\r\n float noise = p_noise(p, int(octCount), u_persistence, u_lacunarity);\r\n\r\n float max_amp = get_max_amp(u_persistence, octCount);\r\n float noise_normalized = clamp((noise + max_amp) / max(1e-4, (2. * max_amp)) + (u_proportion - .5), 0.0, 1.0);\r\n float sharpness = clamp(u_softness, 0., 1.);\r\n float smooth_w = 0.5 * max(fwidth(noise_normalized), 0.001);\r\n float res = smoothstep(\r\n .5 - .5 * sharpness - smooth_w,\r\n .5 + .5 * sharpness + smooth_w,\r\n noise_normalized\r\n );\r\n\r\n vec3 fgColor = u_colorFront.rgb * u_colorFront.a;\r\n float fgOpacity = u_colorFront.a;\r\n vec3 bgColor = u_colorBack.rgb * u_colorBack.a;\r\n float bgOpacity = u_colorBack.a;\r\n\r\n vec3 color = fgColor * res;\r\n float opacity = fgOpacity * res;\r\n\r\n color += bgColor * (1. - opacity);\r\n opacity += bgOpacity * (1. - opacity);\r\n\r\n ${ colorBandingFix }\r\n\r\n fragColor = vec4(color, opacity);\r\n}\r\n`;\r\n\r\nexport interface PerlinNoiseUniforms extends ShaderSizingUniforms {\r\n u_colorFront: [number, number, number, number];\r\n u_colorBack: [number, number, number, number];\r\n u_proportion: number;\r\n u_softness: number;\r\n u_octaveCount: number;\r\n u_persistence: number;\r\n u_lacunarity: number;\r\n}\r\n\r\nexport interface PerlinNoiseParams extends ShaderSizingParams, ShaderMotionParams {\r\n colorFront?: string;\r\n colorBack?: string;\r\n proportion?: number;\r\n softness?: number;\r\n octaveCount?: number;\r\n persistence?: number;\r\n lacunarity?: number;\r\n}\r\n"],
5
+ "mappings": ";;;;;AACA,eAAmE;AACnE,SAAS,WAAW,iBAAiB,kBAAkB,wBAAwB;AAmCxE,MAAM,4BAAoC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiB9C,SAAU;AAAA,EACV,gBAAiB;AAAA,EACjB,gBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAoIf,eAAgB;AAAA;AAAA;AAAA;AAAA;",
6
+ "names": []
7
+ }
@@ -0,0 +1,98 @@
1
+ import type { vec4 } from '../types.js';
2
+ import type { ShaderMotionParams } from '../shader-mount.js';
3
+ import { type ShaderSizingParams, type ShaderSizingUniforms } from '../shader-sizing.js';
4
+ export declare const pulsingBorderMeta: {
5
+ readonly maxColorCount: 5;
6
+ readonly maxSpots: 4;
7
+ };
8
+ /**
9
+ * Luminous trails of color merging into a glowing gradient contour.
10
+ *
11
+ * Fragment shader uniforms:
12
+ * - u_time (float): Animation time
13
+ * - u_colorBack (vec4): Background color in RGBA
14
+ * - u_colors (vec4[]): Up to 5 spot colors in RGBA
15
+ * - u_colorsCount (float): Number of active colors
16
+ * - u_roundness (float): Border radius (0 to 1)
17
+ * - u_thickness (float): Border base width (0 to 1)
18
+ * - u_softness (float): Border edge sharpness, 0 = hard edge, 1 = smooth gradient (0 to 1)
19
+ * - u_marginLeft (float): Distance from the left edge to the effect (0 to 1)
20
+ * - u_marginRight (float): Distance from the right edge to the effect (0 to 1)
21
+ * - u_marginTop (float): Distance from the top edge to the effect (0 to 1)
22
+ * - u_marginBottom (float): Distance from the bottom edge to the effect (0 to 1)
23
+ * - u_aspectRatio (float): Aspect ratio mode (0 = auto, 1 = square)
24
+ * - u_intensity (float): Thickness of individual color spots (0 to 1)
25
+ * - u_bloom (float): Power of glow, 0 = normal blending, 1 = additive blending (0 to 1)
26
+ * - u_spots (float): Number of spots added for each color (1 to 4)
27
+ * - u_spotSize (float): Angular size of spots (0 to 1)
28
+ * - u_pulse (float): Optional pulsing animation intensity (0 to 1)
29
+ * - u_smoke (float): Optional noisy shape extending the border (0 to 1)
30
+ * - u_smokeSize (float): Size of the smoke effect, needs smoke > 0 (0 to 1)
31
+ * - u_noiseTexture (sampler2D): Pre-computed randomizer source texture
32
+ *
33
+ * Vertex shader outputs (used in fragment shader):
34
+ * - v_responsiveUV (vec2): Responsive UV coordinates that adapt to canvas aspect ratio
35
+ * - v_responsiveBoxGivenSize (vec2): Given size of the responsive bounding box
36
+ * - v_patternUV (vec2): UV coordinates for pattern with global sizing (rotation, scale, offset, etc) applied (used for smoke calculation)
37
+ *
38
+ * Vertex shader uniforms:
39
+ * - u_resolution (vec2): Canvas resolution in pixels
40
+ * - u_pixelRatio (float): Device pixel ratio
41
+ * - u_originX (float): Reference point for positioning world width in the canvas (0 to 1)
42
+ * - u_originY (float): Reference point for positioning world height in the canvas (0 to 1)
43
+ * - u_worldWidth (float): Virtual width of the graphic before it's scaled to fit the canvas
44
+ * - u_worldHeight (float): Virtual height of the graphic before it's scaled to fit the canvas
45
+ * - u_fit (float): How to fit the rendered shader into the canvas dimensions (0 = none, 1 = contain, 2 = cover)
46
+ * - u_scale (float): Overall zoom level of the graphics (0.01 to 4)
47
+ * - u_rotation (float): Overall rotation angle of the graphics in degrees (0 to 360)
48
+ * - u_offsetX (float): Horizontal offset of the graphics center (-1 to 1)
49
+ * - u_offsetY (float): Vertical offset of the graphics center (-1 to 1)
50
+ *
51
+ */
52
+ export declare const pulsingBorderFragmentShader: string;
53
+ export interface PulsingBorderUniforms extends ShaderSizingUniforms {
54
+ u_colorBack: [number, number, number, number];
55
+ u_colors: vec4[];
56
+ u_colorsCount: number;
57
+ u_roundness: number;
58
+ u_thickness: number;
59
+ u_marginLeft: number;
60
+ u_marginRight: number;
61
+ u_marginTop: number;
62
+ u_marginBottom: number;
63
+ u_aspectRatio: (typeof PulsingBorderAspectRatios)[PulsingBorderAspectRatio];
64
+ u_softness: number;
65
+ u_intensity: number;
66
+ u_bloom: number;
67
+ u_spots: number;
68
+ u_spotSize: number;
69
+ u_pulse: number;
70
+ u_smoke: number;
71
+ u_smokeSize: number;
72
+ u_noiseTexture?: HTMLImageElement;
73
+ }
74
+ export interface PulsingBorderParams extends ShaderSizingParams, ShaderMotionParams {
75
+ colorBack?: string;
76
+ colors?: string[];
77
+ roundness?: number;
78
+ thickness?: number;
79
+ margin?: number;
80
+ marginLeft?: number;
81
+ marginRight?: number;
82
+ marginTop?: number;
83
+ marginBottom?: number;
84
+ aspectRatio?: PulsingBorderAspectRatio;
85
+ softness?: number;
86
+ intensity?: number;
87
+ bloom?: number;
88
+ spots?: number;
89
+ spotSize?: number;
90
+ pulse?: number;
91
+ smoke?: number;
92
+ smokeSize?: number;
93
+ }
94
+ export declare const PulsingBorderAspectRatios: {
95
+ readonly auto: 0;
96
+ readonly square: 1;
97
+ };
98
+ export type PulsingBorderAspectRatio = keyof typeof PulsingBorderAspectRatios;
@@ -0,0 +1,239 @@
1
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * *
2
+ * Paper Shaders *
3
+ * https://github.com/paper-design/shaders *
4
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * */
5
+
6
+ import {} from "../shader-sizing.js";
7
+ import { declarePI, textureRandomizerGB, colorBandingFix } from "../shader-utils.js";
8
+ const pulsingBorderMeta = {
9
+ maxColorCount: 5,
10
+ maxSpots: 4
11
+ };
12
+ const pulsingBorderFragmentShader = `#version 300 es
13
+ precision lowp float;
14
+
15
+ uniform float u_time;
16
+
17
+ uniform vec4 u_colorBack;
18
+ uniform vec4 u_colors[${pulsingBorderMeta.maxColorCount}];
19
+ uniform float u_colorsCount;
20
+ uniform float u_roundness;
21
+ uniform float u_thickness;
22
+ uniform float u_marginLeft;
23
+ uniform float u_marginRight;
24
+ uniform float u_marginTop;
25
+ uniform float u_marginBottom;
26
+ uniform float u_aspectRatio;
27
+ uniform float u_softness;
28
+ uniform float u_intensity;
29
+ uniform float u_bloom;
30
+ uniform float u_spotSize;
31
+ uniform float u_spots;
32
+ uniform float u_pulse;
33
+ uniform float u_smoke;
34
+ uniform float u_smokeSize;
35
+
36
+ uniform sampler2D u_noiseTexture;
37
+
38
+ in vec2 v_responsiveUV;
39
+ in vec2 v_responsiveBoxGivenSize;
40
+ in vec2 v_patternUV;
41
+
42
+ out vec4 fragColor;
43
+
44
+ ${declarePI}
45
+
46
+ float beat(float time) {
47
+ float first = pow(abs(sin(time * TWO_PI)), 10.);
48
+ float second = pow(abs(sin((time - .15) * TWO_PI)), 10.);
49
+
50
+ return clamp(first + 0.6 * second, 0.0, 1.0);
51
+ }
52
+
53
+ float sst(float edge0, float edge1, float x) {
54
+ return smoothstep(edge0, edge1, x);
55
+ }
56
+
57
+ float roundedBox(vec2 uv, vec2 halfSize, float distance, float cornerDistance, float thickness, float softness) {
58
+ float borderDistance = abs(distance);
59
+ float aa = 2. * fwidth(distance);
60
+ float border = 1. - sst(min(mix(thickness, -thickness, softness), thickness + aa), max(mix(thickness, -thickness, softness), thickness + aa), borderDistance);
61
+ float cornerFadeCircles = 0.;
62
+ cornerFadeCircles = mix(1., cornerFadeCircles, sst(0., 1., length((uv + halfSize) / thickness)));
63
+ cornerFadeCircles = mix(1., cornerFadeCircles, sst(0., 1., length((uv - vec2(-halfSize.x, halfSize.y)) / thickness)));
64
+ cornerFadeCircles = mix(1., cornerFadeCircles, sst(0., 1., length((uv - vec2(halfSize.x, -halfSize.y)) / thickness)));
65
+ cornerFadeCircles = mix(1., cornerFadeCircles, sst(0., 1., length((uv - halfSize) / thickness)));
66
+ aa = fwidth(cornerDistance);
67
+ float cornerFade = sst(0., mix(aa, thickness, softness), cornerDistance);
68
+ cornerFade *= cornerFadeCircles;
69
+ border += cornerFade;
70
+ return border;
71
+ }
72
+
73
+ ${textureRandomizerGB}
74
+
75
+ float randomG(vec2 p) {
76
+ vec2 uv = floor(p) / 100. + .5;
77
+ return texture(u_noiseTexture, fract(uv)).g;
78
+ }
79
+ float valueNoise(vec2 st) {
80
+ vec2 i = floor(st);
81
+ vec2 f = fract(st);
82
+ float a = randomG(i);
83
+ float b = randomG(i + vec2(1.0, 0.0));
84
+ float c = randomG(i + vec2(0.0, 1.0));
85
+ float d = randomG(i + vec2(1.0, 1.0));
86
+ vec2 u = f * f * (3.0 - 2.0 * f);
87
+ float x1 = mix(a, b, u.x);
88
+ float x2 = mix(c, d, u.x);
89
+ return mix(x1, x2, u.y);
90
+ }
91
+
92
+ void main() {
93
+ const float firstFrameOffset = 109.;
94
+ float t = 1.2 * (u_time + firstFrameOffset);
95
+
96
+ vec2 borderUV = v_responsiveUV;
97
+ float pulse = u_pulse * beat(.18 * u_time);
98
+
99
+ float canvasRatio = v_responsiveBoxGivenSize.x / v_responsiveBoxGivenSize.y;
100
+ vec2 halfSize = vec2(.5);
101
+ borderUV.x *= max(canvasRatio, 1.);
102
+ borderUV.y /= min(canvasRatio, 1.);
103
+ halfSize.x *= max(canvasRatio, 1.);
104
+ halfSize.y /= min(canvasRatio, 1.);
105
+
106
+ float mL = u_marginLeft;
107
+ float mR = u_marginRight;
108
+ float mT = u_marginTop;
109
+ float mB = u_marginBottom;
110
+ float mX = mL + mR;
111
+ float mY = mT + mB;
112
+
113
+ if (u_aspectRatio > 0.) {
114
+ float shapeRatio = canvasRatio * (1. - mX) / max(1. - mY, 1e-6);
115
+ float freeX = shapeRatio > 1. ? (1. - mX) * (1. - 1. / max(abs(shapeRatio), 1e-6)) : 0.;
116
+ float freeY = shapeRatio < 1. ? (1. - mY) * (1. - shapeRatio) : 0.;
117
+ mL += freeX * 0.5;
118
+ mR += freeX * 0.5;
119
+ mT += freeY * 0.5;
120
+ mB += freeY * 0.5;
121
+ mX = mL + mR;
122
+ mY = mT + mB;
123
+ }
124
+
125
+ float thickness = .5 * u_thickness * min(halfSize.x, halfSize.y);
126
+
127
+ halfSize.x *= (1. - mX);
128
+ halfSize.y *= (1. - mY);
129
+
130
+ vec2 centerShift = vec2(
131
+ (mL - mR) * max(canvasRatio, 1.) * 0.5,
132
+ (mB - mT) / min(canvasRatio, 1.) * 0.5
133
+ );
134
+
135
+ borderUV -= centerShift;
136
+ halfSize -= mix(thickness, 0., u_softness);
137
+
138
+ float radius = mix(0., min(halfSize.x, halfSize.y), u_roundness);
139
+ vec2 d = abs(borderUV) - halfSize + radius;
140
+ float outsideDistance = length(max(d, .0001)) - radius;
141
+ float insideDistance = min(max(d.x, d.y), .0001);
142
+ float cornerDistance = abs(min(max(d.x, d.y) - .45 * radius, .0));
143
+ float distance = outsideDistance + insideDistance;
144
+
145
+ float borderThickness = mix(thickness, 3. * thickness, u_softness);
146
+ float border = roundedBox(borderUV, halfSize, distance, cornerDistance, borderThickness, u_softness);
147
+ border = pow(border, 1. + u_softness);
148
+
149
+ vec2 smokeUV = .3 * u_smokeSize * v_patternUV;
150
+ float smoke = clamp(3. * valueNoise(2.7 * smokeUV + .5 * t), 0., 1.);
151
+ smoke -= valueNoise(3.4 * smokeUV - .5 * t);
152
+ float smokeThickness = thickness + .2;
153
+ smokeThickness = min(.4, max(smokeThickness, .1));
154
+ smoke *= roundedBox(borderUV, halfSize, distance, cornerDistance, smokeThickness, 1.);
155
+ smoke = 30. * smoke * smoke;
156
+ smoke *= mix(0., .5, pow(u_smoke, 2.));
157
+ smoke *= mix(1., pulse, u_pulse);
158
+ smoke = clamp(smoke, 0., 1.);
159
+ border += smoke;
160
+
161
+ border = clamp(border, 0., 1.);
162
+
163
+ vec3 blendColor = vec3(0.);
164
+ float blendAlpha = 0.;
165
+ vec3 addColor = vec3(0.);
166
+ float addAlpha = 0.;
167
+
168
+ float bloom = 4. * u_bloom;
169
+ float intensity = 1. + (1. + 4. * u_softness) * u_intensity;
170
+
171
+ float angle = atan(borderUV.y, borderUV.x) / TWO_PI;
172
+
173
+ for (int colorIdx = 0; colorIdx < ${pulsingBorderMeta.maxColorCount}; colorIdx++) {
174
+ if (colorIdx >= int(u_colorsCount)) break;
175
+ float colorIdxF = float(colorIdx);
176
+
177
+ vec3 c = u_colors[colorIdx].rgb * u_colors[colorIdx].a;
178
+ float a = u_colors[colorIdx].a;
179
+
180
+ for (int spotIdx = 0; spotIdx < ${pulsingBorderMeta.maxSpots}; spotIdx++) {
181
+ if (spotIdx >= int(u_spots)) break;
182
+ float spotIdxF = float(spotIdx);
183
+
184
+ vec2 randVal = randomGB(vec2(spotIdxF * 10. + 2., 40. + colorIdxF));
185
+
186
+ float time = (.1 + .15 * abs(sin(spotIdxF * (2. + colorIdxF)) * cos(spotIdxF * (2. + 2.5 * colorIdxF)))) * t + randVal.x * 3.;
187
+ time *= mix(1., -1., step(.5, randVal.y));
188
+
189
+ float mask = .5 + .5 * mix(
190
+ sin(t + spotIdxF * (5. - 1.5 * colorIdxF)),
191
+ cos(t + spotIdxF * (3. + 1.3 * colorIdxF)),
192
+ step(mod(colorIdxF, 2.), .5)
193
+ );
194
+
195
+ float p = clamp(2. * u_pulse - randVal.x, 0., 1.);
196
+ mask = mix(mask, pulse, p);
197
+
198
+ float atg1 = fract(angle + time);
199
+ float spotSize = .05 + .6 * pow(u_spotSize, 2.) + .05 * randVal.x;
200
+ spotSize = mix(spotSize, .1, p);
201
+ float sector = sst(.5 - spotSize, .5, atg1) * (1. - sst(.5, .5 + spotSize, atg1));
202
+
203
+ sector *= mask;
204
+ sector *= border;
205
+ sector *= intensity;
206
+ sector = clamp(sector, 0., 1.);
207
+
208
+ vec3 srcColor = c * sector;
209
+ float srcAlpha = a * sector;
210
+
211
+ blendColor += ((1. - blendAlpha) * srcColor);
212
+ blendAlpha = blendAlpha + (1. - blendAlpha) * srcAlpha;
213
+ addColor += srcColor;
214
+ addAlpha += srcAlpha;
215
+ }
216
+ }
217
+
218
+ vec3 accumColor = mix(blendColor, addColor, bloom);
219
+ float accumAlpha = mix(blendAlpha, addAlpha, bloom);
220
+ accumAlpha = clamp(accumAlpha, 0., 1.);
221
+
222
+ vec3 bgColor = u_colorBack.rgb * u_colorBack.a;
223
+ vec3 color = accumColor + (1. - accumAlpha) * bgColor;
224
+ float opacity = accumAlpha + (1. - accumAlpha) * u_colorBack.a;
225
+
226
+ ${colorBandingFix}
227
+
228
+ fragColor = vec4(color, opacity);
229
+ }`;
230
+ const PulsingBorderAspectRatios = {
231
+ auto: 0,
232
+ square: 1
233
+ };
234
+ export {
235
+ PulsingBorderAspectRatios,
236
+ pulsingBorderFragmentShader,
237
+ pulsingBorderMeta
238
+ };
239
+ //# sourceMappingURL=pulsing-border.js.map