@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.
- package/dist/index.d.ts +29 -18
- package/dist/index.js +6 -0
- package/dist/index.js.map +2 -2
- package/dist/shader-sizing.d.ts +0 -5
- package/dist/shader-sizing.js +1 -193
- package/dist/shader-sizing.js.map +2 -2
- package/dist/shaders/color-panels.d.ts +32 -12
- package/dist/shaders/color-panels.js +5 -5
- package/dist/shaders/color-panels.js.map +2 -2
- package/dist/shaders/dithering.d.ts +25 -19
- package/dist/shaders/dithering.js +114 -66
- package/dist/shaders/dithering.js.map +2 -2
- package/dist/shaders/dot-grid.d.ts +28 -14
- package/dist/shaders/dot-grid.js +2 -2
- package/dist/shaders/dot-grid.js.map +2 -2
- package/dist/shaders/dot-orbit.d.ts +27 -9
- package/dist/shaders/dot-orbit.js +8 -9
- package/dist/shaders/dot-orbit.js.map +2 -2
- package/dist/shaders/fluted-glass.d.ts +43 -18
- package/dist/shaders/fluted-glass.js +20 -51
- package/dist/shaders/fluted-glass.js.map +2 -2
- package/dist/shaders/god-rays.d.ts +32 -10
- package/dist/shaders/god-rays.js +2 -2
- package/dist/shaders/god-rays.js.map +2 -2
- package/dist/shaders/grain-gradient.d.ts +41 -17
- package/dist/shaders/grain-gradient.js +47 -33
- package/dist/shaders/grain-gradient.js.map +2 -2
- package/dist/shaders/halftone-cmyk.d.ts +105 -0
- package/dist/shaders/halftone-cmyk.js +290 -0
- package/dist/shaders/halftone-cmyk.js.map +7 -0
- package/dist/shaders/halftone-dots.d.ts +35 -6
- package/dist/shaders/halftone-dots.js +18 -55
- package/dist/shaders/halftone-dots.js.map +2 -2
- package/dist/shaders/heatmap.d.ts +36 -0
- package/dist/shaders/heatmap.js +98 -16
- package/dist/shaders/heatmap.js.map +2 -2
- package/dist/shaders/image-dithering.d.ts +29 -15
- package/dist/shaders/image-dithering.js +68 -37
- package/dist/shaders/image-dithering.js.map +2 -2
- package/dist/shaders/liquid-metal.d.ts +38 -14
- package/dist/shaders/liquid-metal.js +5 -2
- package/dist/shaders/liquid-metal.js.map +2 -2
- package/dist/shaders/mesh-gradient.d.ts +27 -8
- package/dist/shaders/mesh-gradient.js +1 -7
- package/dist/shaders/mesh-gradient.js.map +2 -2
- package/dist/shaders/metaballs.d.ts +24 -8
- package/dist/shaders/metaballs.js +2 -2
- package/dist/shaders/metaballs.js.map +2 -2
- package/dist/shaders/neuro-noise.d.ts +27 -5
- package/dist/shaders/neuro-noise.js +2 -3
- package/dist/shaders/neuro-noise.js.map +2 -2
- package/dist/shaders/paper-texture.d.ts +37 -12
- package/dist/shaders/paper-texture.js +20 -20
- package/dist/shaders/paper-texture.js.map +2 -2
- package/dist/shaders/perlin-noise.d.ts +27 -8
- package/dist/shaders/perlin-noise.js +13 -35
- package/dist/shaders/perlin-noise.js.map +2 -2
- package/dist/shaders/pulsing-border.d.ts +39 -13
- package/dist/shaders/pulsing-border.js +9 -7
- package/dist/shaders/pulsing-border.js.map +2 -2
- package/dist/shaders/simplex-noise.d.ts +25 -6
- package/dist/shaders/simplex-noise.js +21 -21
- package/dist/shaders/simplex-noise.js.map +2 -2
- package/dist/shaders/smoke-ring.d.ts +29 -7
- package/dist/shaders/smoke-ring.js +20 -17
- package/dist/shaders/smoke-ring.js.map +2 -2
- package/dist/shaders/spiral.d.ts +30 -10
- package/dist/shaders/spiral.js +4 -4
- package/dist/shaders/spiral.js.map +2 -2
- package/dist/shaders/static-mesh-gradient.d.ts +30 -9
- package/dist/shaders/static-mesh-gradient.js +9 -17
- package/dist/shaders/static-mesh-gradient.js.map +2 -2
- package/dist/shaders/static-radial-gradient.d.ts +33 -11
- package/dist/shaders/static-radial-gradient.js +18 -25
- package/dist/shaders/static-radial-gradient.js.map +2 -2
- package/dist/shaders/swirl.d.ts +29 -8
- package/dist/shaders/swirl.js +4 -4
- package/dist/shaders/swirl.js.map +2 -2
- package/dist/shaders/voronoi.d.ts +31 -10
- package/dist/shaders/voronoi.js +8 -8
- package/dist/shaders/voronoi.js.map +2 -2
- package/dist/shaders/warp.d.ts +31 -13
- package/dist/shaders/warp.js +3 -3
- package/dist/shaders/warp.js.map +2 -2
- package/dist/shaders/water.d.ts +30 -10
- package/dist/shaders/water.js +2 -2
- package/dist/shaders/water.js.map +2 -2
- package/dist/shaders/waves.d.ts +27 -12
- package/dist/shaders/waves.js +3 -3
- package/dist/shaders/waves.js.map +2 -2
- package/dist/vertex-shader.d.ts +1 -1
- package/dist/vertex-shader.js +2 -53
- package/dist/vertex-shader.js.map +2 -2
- package/package.json +1 -1
|
@@ -6,21 +6,47 @@ export declare const pulsingBorderMeta: {
|
|
|
6
6
|
readonly maxSpots: 4;
|
|
7
7
|
};
|
|
8
8
|
/**
|
|
9
|
-
*
|
|
9
|
+
* Luminous trails of color merging into a glowing gradient contour.
|
|
10
10
|
*
|
|
11
|
-
*
|
|
12
|
-
* -
|
|
13
|
-
* -
|
|
14
|
-
* -
|
|
15
|
-
* -
|
|
16
|
-
* -
|
|
17
|
-
* -
|
|
18
|
-
* -
|
|
19
|
-
* -
|
|
20
|
-
* -
|
|
21
|
-
* -
|
|
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 20)
|
|
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 (0 to 1)
|
|
31
|
+
* - u_noiseTexture (sampler2D): Pre-computed randomizer source texture
|
|
22
32
|
*
|
|
23
|
-
*
|
|
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)
|
|
24
50
|
*
|
|
25
51
|
*/
|
|
26
52
|
export declare const pulsingBorderFragmentShader: string;
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* https://github.com/paper-design/shaders *
|
|
4
4
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import {} from "../shader-sizing.js";
|
|
7
7
|
import { declarePI, textureRandomizerGB, colorBandingFix } from "../shader-utils.js";
|
|
8
8
|
const pulsingBorderMeta = {
|
|
9
9
|
maxColorCount: 5,
|
|
@@ -35,7 +35,9 @@ uniform float u_smokeSize;
|
|
|
35
35
|
|
|
36
36
|
uniform sampler2D u_noiseTexture;
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
in vec2 v_responsiveUV;
|
|
39
|
+
in vec2 v_responsiveBoxGivenSize;
|
|
40
|
+
in vec2 v_patternUV;
|
|
39
41
|
|
|
40
42
|
out vec4 fragColor;
|
|
41
43
|
|
|
@@ -126,8 +128,8 @@ void main() {
|
|
|
126
128
|
halfSize.y *= (1. - mY);
|
|
127
129
|
|
|
128
130
|
vec2 centerShift = vec2(
|
|
129
|
-
|
|
130
|
-
|
|
131
|
+
(mL - mR) * max(canvasRatio, 1.) * 0.5,
|
|
132
|
+
(mB - mT) / min(canvasRatio, 1.) * 0.5
|
|
131
133
|
);
|
|
132
134
|
|
|
133
135
|
borderUV -= centerShift;
|
|
@@ -185,9 +187,9 @@ void main() {
|
|
|
185
187
|
time *= mix(1., -1., step(.5, randVal.y));
|
|
186
188
|
|
|
187
189
|
float mask = .5 + .5 * mix(
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
190
|
+
sin(t + spotIdxF * (5. - 1.5 * colorIdxF)),
|
|
191
|
+
cos(t + spotIdxF * (3. + 1.3 * colorIdxF)),
|
|
192
|
+
step(mod(colorIdxF, 2.), .5)
|
|
191
193
|
);
|
|
192
194
|
|
|
193
195
|
float p = clamp(2. * u_pulse - randVal.x, 0., 1.);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/shaders/pulsing-border.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, textureRandomizerGB, colorBandingFix } from '../shader-utils.js';\n\nexport const pulsingBorderMeta = {\n maxColorCount: 5,\n maxSpots: 4,\n} as const;\n\n/**\n * Color spots traveling around rectangular stroke (border)\n *\n * Uniforms:\n * - u_colorBack (RGBA)\n * - u_colors (vec4[]), u_colorsCount (float used as integer)\n * - u_roundness, u_thickness, u_softness: border parameters\n * - u_aspectRatio\n * - u_intensity: thickness of individual spots\n * - u_bloom: normal / additive color blending\n * - u_spotSize: angular size of spots\n * - u_spots (float used as int): number of spots rendered per color\n * - u_pulse: optional pulsing animation\n * - u_smoke, u_smokeSize: optional noisy shapes around the border\n *\n * - u_noiseTexture (sampler2D): pre-computed randomizer source\n *\n */\n\n// language=GLSL\nexport const pulsingBorderFragmentShader: string = `#version 300 es\nprecision lowp float;\n\nuniform float u_time;\n\nuniform vec4 u_colorBack;\nuniform vec4 u_colors[${pulsingBorderMeta.maxColorCount}];\nuniform float u_colorsCount;\nuniform float u_roundness;\nuniform float u_thickness;\nuniform float u_marginLeft;\nuniform float u_marginRight;\nuniform float u_marginTop;\nuniform float u_marginBottom;\nuniform float u_aspectRatio;\nuniform float u_softness;\nuniform float u_intensity;\nuniform float u_bloom;\nuniform float u_spotSize;\nuniform float u_spots;\nuniform float u_pulse;\nuniform float u_smoke;\nuniform float u_smokeSize;\n\nuniform sampler2D u_noiseTexture;\n\n${sizingVariablesDeclaration}\n\nout vec4 fragColor;\n\n${declarePI}\n\nfloat beat(float time) {\n float first = pow(abs(sin(time * TWO_PI)), 10.);\n float second = pow(abs(sin((time - .15) * TWO_PI)), 10.);\n\n return clamp(first + 0.6 * second, 0.0, 1.0);\n}\n\nfloat sst(float edge0, float edge1, float x) {\n return smoothstep(edge0, edge1, x);\n}\n\nfloat roundedBox(vec2 uv, vec2 halfSize, float distance, float cornerDistance, float thickness, float softness) {\n float borderDistance = abs(distance);\n float aa = 2. * fwidth(distance);\n float border = 1. - sst(min(mix(thickness, -thickness, softness), thickness + aa), max(mix(thickness, -thickness, softness), thickness + aa), borderDistance);\n float cornerFadeCircles = 0.;\n cornerFadeCircles = mix(1., cornerFadeCircles, sst(0., 1., length((uv + halfSize) / thickness)));\n cornerFadeCircles = mix(1., cornerFadeCircles, sst(0., 1., length((uv - vec2(-halfSize.x, halfSize.y)) / thickness)));\n cornerFadeCircles = mix(1., cornerFadeCircles, sst(0., 1., length((uv - vec2(halfSize.x, -halfSize.y)) / thickness)));\n cornerFadeCircles = mix(1., cornerFadeCircles, sst(0., 1., length((uv - halfSize) / thickness)));\n aa = fwidth(cornerDistance);\n float cornerFade = sst(0., mix(aa, thickness, softness), cornerDistance);\n cornerFade *= cornerFadeCircles;\n border += cornerFade;\n return border;\n}\n\n${textureRandomizerGB}\n\nfloat randomG(vec2 p) {\n vec2 uv = floor(p) / 100. + .5;\n return texture(u_noiseTexture, fract(uv)).g;\n}\nfloat valueNoise(vec2 st) {\n vec2 i = floor(st);\n vec2 f = fract(st);\n float a = randomG(i);\n float b = randomG(i + vec2(1.0, 0.0));\n float c = randomG(i + vec2(0.0, 1.0));\n float d = randomG(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\nvoid main() {\n const float firstFrameOffset = 109.;\n float t = 1.2 * (u_time + firstFrameOffset);\n\n vec2 borderUV = v_responsiveUV;\n float pulse = u_pulse * beat(.18 * u_time);\n\n float canvasRatio = v_responsiveBoxGivenSize.x / v_responsiveBoxGivenSize.y;\n vec2 halfSize = vec2(.5);\n borderUV.x *= max(canvasRatio, 1.);\n borderUV.y /= min(canvasRatio, 1.);\n halfSize.x *= max(canvasRatio, 1.);\n halfSize.y /= min(canvasRatio, 1.);\n\n float mL = u_marginLeft;\n float mR = u_marginRight;\n float mT = u_marginTop;\n float mB = u_marginBottom;\n float mX = mL + mR;\n float mY = mT + mB;\n\n if (u_aspectRatio > 0.) {\n float shapeRatio = canvasRatio * (1. - mX) / max(1. - mY, 1e-6);\n float freeX = shapeRatio > 1. ? (1. - mX) * (1. - 1. / max(abs(shapeRatio), 1e-6)) : 0.;\n float freeY = shapeRatio < 1. ? (1. - mY) * (1. - shapeRatio) : 0.;\n mL += freeX * 0.5;\n mR += freeX * 0.5;\n mT += freeY * 0.5;\n mB += freeY * 0.5;\n mX = mL + mR;\n mY = mT + mB;\n }\n\n float thickness = .5 * u_thickness * min(halfSize.x, halfSize.y);\n\n halfSize.x *= (1. - mX);\n halfSize.y *= (1. - mY);\n\n vec2 centerShift = vec2(\n (mL - mR) * max(canvasRatio, 1.) * 0.5,\n (mB - mT) / min(canvasRatio, 1.) * 0.5\n );\n\n borderUV -= centerShift;\n halfSize -= mix(thickness, 0., u_softness);\n\n float radius = mix(0., min(halfSize.x, halfSize.y), u_roundness);\n vec2 d = abs(borderUV) - halfSize + radius;\n float outsideDistance = length(max(d, .0001)) - radius;\n float insideDistance = min(max(d.x, d.y), .0001);\n float cornerDistance = abs(min(max(d.x, d.y) - .45 * radius, .0));\n float distance = outsideDistance + insideDistance;\n\n float borderThickness = mix(thickness, 3. * thickness, u_softness);\n float border = roundedBox(borderUV, halfSize, distance, cornerDistance, borderThickness, u_softness);\n border = pow(border, 1. + u_softness);\n\n vec2 smokeUV = .3 * u_smokeSize * v_patternUV;\n float smoke = clamp(3. * valueNoise(2.7 * smokeUV + .5 * t), 0., 1.);\n smoke -= valueNoise(3.4 * smokeUV - .5 * t);\n float smokeThickness = thickness + .2;\n smokeThickness = min(.4, max(smokeThickness, .1));\n smoke *= roundedBox(borderUV, halfSize, distance, cornerDistance, smokeThickness, 1.);\n smoke = 30. * smoke * smoke;\n smoke *= mix(0., .5, pow(u_smoke, 2.));\n smoke *= mix(1., pulse, u_pulse);\n smoke = clamp(smoke, 0., 1.);\n border += smoke;\n\n border = clamp(border, 0., 1.);\n\n vec3 blendColor = vec3(0.);\n float blendAlpha = 0.;\n vec3 addColor = vec3(0.);\n float addAlpha = 0.;\n\n float bloom = 4. * u_bloom;\n float intensity = 1. + (1. + 4. * u_softness) * u_intensity;\n\n float angle = atan(borderUV.y, borderUV.x) / TWO_PI;\n\n for (int colorIdx = 0; colorIdx < ${pulsingBorderMeta.maxColorCount}; colorIdx++) {\n if (colorIdx >= int(u_colorsCount)) break;\n float colorIdxF = float(colorIdx);\n\n vec3 c = u_colors[colorIdx].rgb * u_colors[colorIdx].a;\n float a = u_colors[colorIdx].a;\n\n for (int spotIdx = 0; spotIdx < ${pulsingBorderMeta.maxSpots}; spotIdx++) {\n if (spotIdx >= int(u_spots)) break;\n float spotIdxF = float(spotIdx);\n\n vec2 randVal = randomGB(vec2(spotIdxF * 10. + 2., 40. + colorIdxF));\n\n float time = (.1 + .15 * abs(sin(spotIdxF * (2. + colorIdxF)) * cos(spotIdxF * (2. + 2.5 * colorIdxF)))) * t + randVal.x * 3.;\n time *= mix(1., -1., step(.5, randVal.y));\n\n float mask = .5 + .5 * mix(\n sin(t + spotIdxF * (5. - 1.5 * colorIdxF)),\n cos(t + spotIdxF * (3. + 1.3 * colorIdxF)),\n step(mod(colorIdxF, 2.), .5)\n );\n\n float p = clamp(2. * u_pulse - randVal.x, 0., 1.);\n mask = mix(mask, pulse, p);\n\n float atg1 = fract(angle + time);\n float spotSize = .05 + .6 * pow(u_spotSize, 2.) + .05 * randVal.x;\n spotSize = mix(spotSize, .1, p);\n float sector = sst(.5 - spotSize, .5, atg1) * (1. - sst(.5, .5 + spotSize, atg1));\n\n sector *= mask;\n sector *= border;\n sector *= intensity;\n sector = clamp(sector, 0., 1.);\n\n vec3 srcColor = c * sector;\n float srcAlpha = a * sector;\n\n blendColor += ((1. - blendAlpha) * srcColor);\n blendAlpha = blendAlpha + (1. - blendAlpha) * srcAlpha;\n addColor += srcColor;\n addAlpha += srcAlpha;\n }\n }\n\n vec3 accumColor = mix(blendColor, addColor, bloom);\n float accumAlpha = mix(blendAlpha, addAlpha, bloom);\n accumAlpha = clamp(accumAlpha, 0., 1.);\n\n vec3 bgColor = u_colorBack.rgb * u_colorBack.a;\n vec3 color = accumColor + (1. - accumAlpha) * bgColor;\n float opacity = accumAlpha + (1. - accumAlpha) * u_colorBack.a;\n\n ${colorBandingFix}\n\n fragColor = vec4(color, opacity);\n}`;\n\nexport interface PulsingBorderUniforms extends ShaderSizingUniforms {\n u_colorBack: [number, number, number, number];\n u_colors: vec4[];\n u_colorsCount: number;\n u_roundness: number;\n u_thickness: number;\n u_marginLeft: number;\n u_marginRight: number;\n u_marginTop: number;\n u_marginBottom: number;\n u_aspectRatio: (typeof PulsingBorderAspectRatios)[PulsingBorderAspectRatio];\n u_softness: number;\n u_intensity: number;\n u_bloom: number;\n u_spots: number;\n u_spotSize: number;\n u_pulse: number;\n u_smoke: number;\n u_smokeSize: number;\n u_noiseTexture?: HTMLImageElement;\n}\n\nexport interface PulsingBorderParams extends ShaderSizingParams, ShaderMotionParams {\n colorBack?: string;\n colors?: string[];\n roundness?: number;\n thickness?: number;\n margin?: number;\n marginLeft?: number;\n marginRight?: number;\n marginTop?: number;\n marginBottom?: number;\n aspectRatio?: PulsingBorderAspectRatio;\n softness?: number;\n intensity?: number;\n bloom?: number;\n spots?: number;\n spotSize?: number;\n pulse?: number;\n smoke?: number;\n smokeSize?: number;\n}\n\nexport const PulsingBorderAspectRatios = {\n auto: 0,\n square: 1,\n} as const;\n\nexport type PulsingBorderAspectRatio = keyof typeof PulsingBorderAspectRatios;\n"],
|
|
5
|
-
"mappings": ";;;;;AAEA,
|
|
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, textureRandomizerGB, colorBandingFix } from '../shader-utils.js';\n\nexport const pulsingBorderMeta = {\n maxColorCount: 5,\n maxSpots: 4,\n} as const;\n\n/**\n * Luminous trails of color merging into a glowing gradient contour.\n *\n * Fragment shader uniforms:\n * - u_time (float): Animation time\n * - u_colorBack (vec4): Background color in RGBA\n * - u_colors (vec4[]): Up to 5 spot colors in RGBA\n * - u_colorsCount (float): Number of active colors\n * - u_roundness (float): Border radius (0 to 1)\n * - u_thickness (float): Border base width (0 to 1)\n * - u_softness (float): Border edge sharpness, 0 = hard edge, 1 = smooth gradient (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_aspectRatio (float): Aspect ratio mode (0 = auto, 1 = square)\n * - u_intensity (float): Thickness of individual color spots (0 to 1)\n * - u_bloom (float): Power of glow, 0 = normal blending, 1 = additive blending (0 to 1)\n * - u_spots (float): Number of spots added for each color (1 to 20)\n * - u_spotSize (float): Angular size of spots (0 to 1)\n * - u_pulse (float): Optional pulsing animation intensity (0 to 1)\n * - u_smoke (float): Optional noisy shape extending the border (0 to 1)\n * - u_smokeSize (float): Size of the smoke effect (0 to 1)\n * - u_noiseTexture (sampler2D): Pre-computed randomizer source texture\n *\n * Vertex shader outputs (used in fragment shader):\n * - v_responsiveUV (vec2): Responsive UV coordinates that adapt to canvas aspect ratio\n * - v_responsiveBoxGivenSize (vec2): Given size of the responsive bounding box\n * - v_patternUV (vec2): UV coordinates for pattern with global sizing (rotation, scale, offset, etc) applied (used for smoke calculation)\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 pulsingBorderFragmentShader: string = `#version 300 es\nprecision lowp float;\n\nuniform float u_time;\n\nuniform vec4 u_colorBack;\nuniform vec4 u_colors[${ pulsingBorderMeta.maxColorCount }];\nuniform float u_colorsCount;\nuniform float u_roundness;\nuniform float u_thickness;\nuniform float u_marginLeft;\nuniform float u_marginRight;\nuniform float u_marginTop;\nuniform float u_marginBottom;\nuniform float u_aspectRatio;\nuniform float u_softness;\nuniform float u_intensity;\nuniform float u_bloom;\nuniform float u_spotSize;\nuniform float u_spots;\nuniform float u_pulse;\nuniform float u_smoke;\nuniform float u_smokeSize;\n\nuniform sampler2D u_noiseTexture;\n\nin vec2 v_responsiveUV;\nin vec2 v_responsiveBoxGivenSize;\nin vec2 v_patternUV;\n\nout vec4 fragColor;\n\n${ declarePI }\n\nfloat beat(float time) {\n float first = pow(abs(sin(time * TWO_PI)), 10.);\n float second = pow(abs(sin((time - .15) * TWO_PI)), 10.);\n\n return clamp(first + 0.6 * second, 0.0, 1.0);\n}\n\nfloat sst(float edge0, float edge1, float x) {\n return smoothstep(edge0, edge1, x);\n}\n\nfloat roundedBox(vec2 uv, vec2 halfSize, float distance, float cornerDistance, float thickness, float softness) {\n float borderDistance = abs(distance);\n float aa = 2. * fwidth(distance);\n float border = 1. - sst(min(mix(thickness, -thickness, softness), thickness + aa), max(mix(thickness, -thickness, softness), thickness + aa), borderDistance);\n float cornerFadeCircles = 0.;\n cornerFadeCircles = mix(1., cornerFadeCircles, sst(0., 1., length((uv + halfSize) / thickness)));\n cornerFadeCircles = mix(1., cornerFadeCircles, sst(0., 1., length((uv - vec2(-halfSize.x, halfSize.y)) / thickness)));\n cornerFadeCircles = mix(1., cornerFadeCircles, sst(0., 1., length((uv - vec2(halfSize.x, -halfSize.y)) / thickness)));\n cornerFadeCircles = mix(1., cornerFadeCircles, sst(0., 1., length((uv - halfSize) / thickness)));\n aa = fwidth(cornerDistance);\n float cornerFade = sst(0., mix(aa, thickness, softness), cornerDistance);\n cornerFade *= cornerFadeCircles;\n border += cornerFade;\n return border;\n}\n\n${ textureRandomizerGB }\n\nfloat randomG(vec2 p) {\n vec2 uv = floor(p) / 100. + .5;\n return texture(u_noiseTexture, fract(uv)).g;\n}\nfloat valueNoise(vec2 st) {\n vec2 i = floor(st);\n vec2 f = fract(st);\n float a = randomG(i);\n float b = randomG(i + vec2(1.0, 0.0));\n float c = randomG(i + vec2(0.0, 1.0));\n float d = randomG(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\nvoid main() {\n const float firstFrameOffset = 109.;\n float t = 1.2 * (u_time + firstFrameOffset);\n\n vec2 borderUV = v_responsiveUV;\n float pulse = u_pulse * beat(.18 * u_time);\n\n float canvasRatio = v_responsiveBoxGivenSize.x / v_responsiveBoxGivenSize.y;\n vec2 halfSize = vec2(.5);\n borderUV.x *= max(canvasRatio, 1.);\n borderUV.y /= min(canvasRatio, 1.);\n halfSize.x *= max(canvasRatio, 1.);\n halfSize.y /= min(canvasRatio, 1.);\n\n float mL = u_marginLeft;\n float mR = u_marginRight;\n float mT = u_marginTop;\n float mB = u_marginBottom;\n float mX = mL + mR;\n float mY = mT + mB;\n\n if (u_aspectRatio > 0.) {\n float shapeRatio = canvasRatio * (1. - mX) / max(1. - mY, 1e-6);\n float freeX = shapeRatio > 1. ? (1. - mX) * (1. - 1. / max(abs(shapeRatio), 1e-6)) : 0.;\n float freeY = shapeRatio < 1. ? (1. - mY) * (1. - shapeRatio) : 0.;\n mL += freeX * 0.5;\n mR += freeX * 0.5;\n mT += freeY * 0.5;\n mB += freeY * 0.5;\n mX = mL + mR;\n mY = mT + mB;\n }\n\n float thickness = .5 * u_thickness * min(halfSize.x, halfSize.y);\n\n halfSize.x *= (1. - mX);\n halfSize.y *= (1. - mY);\n\n vec2 centerShift = vec2(\n (mL - mR) * max(canvasRatio, 1.) * 0.5,\n (mB - mT) / min(canvasRatio, 1.) * 0.5\n );\n\n borderUV -= centerShift;\n halfSize -= mix(thickness, 0., u_softness);\n\n float radius = mix(0., min(halfSize.x, halfSize.y), u_roundness);\n vec2 d = abs(borderUV) - halfSize + radius;\n float outsideDistance = length(max(d, .0001)) - radius;\n float insideDistance = min(max(d.x, d.y), .0001);\n float cornerDistance = abs(min(max(d.x, d.y) - .45 * radius, .0));\n float distance = outsideDistance + insideDistance;\n\n float borderThickness = mix(thickness, 3. * thickness, u_softness);\n float border = roundedBox(borderUV, halfSize, distance, cornerDistance, borderThickness, u_softness);\n border = pow(border, 1. + u_softness);\n\n vec2 smokeUV = .3 * u_smokeSize * v_patternUV;\n float smoke = clamp(3. * valueNoise(2.7 * smokeUV + .5 * t), 0., 1.);\n smoke -= valueNoise(3.4 * smokeUV - .5 * t);\n float smokeThickness = thickness + .2;\n smokeThickness = min(.4, max(smokeThickness, .1));\n smoke *= roundedBox(borderUV, halfSize, distance, cornerDistance, smokeThickness, 1.);\n smoke = 30. * smoke * smoke;\n smoke *= mix(0., .5, pow(u_smoke, 2.));\n smoke *= mix(1., pulse, u_pulse);\n smoke = clamp(smoke, 0., 1.);\n border += smoke;\n\n border = clamp(border, 0., 1.);\n\n vec3 blendColor = vec3(0.);\n float blendAlpha = 0.;\n vec3 addColor = vec3(0.);\n float addAlpha = 0.;\n\n float bloom = 4. * u_bloom;\n float intensity = 1. + (1. + 4. * u_softness) * u_intensity;\n\n float angle = atan(borderUV.y, borderUV.x) / TWO_PI;\n\n for (int colorIdx = 0; colorIdx < ${ pulsingBorderMeta.maxColorCount }; colorIdx++) {\n if (colorIdx >= int(u_colorsCount)) break;\n float colorIdxF = float(colorIdx);\n\n vec3 c = u_colors[colorIdx].rgb * u_colors[colorIdx].a;\n float a = u_colors[colorIdx].a;\n\n for (int spotIdx = 0; spotIdx < ${ pulsingBorderMeta.maxSpots }; spotIdx++) {\n if (spotIdx >= int(u_spots)) break;\n float spotIdxF = float(spotIdx);\n\n vec2 randVal = randomGB(vec2(spotIdxF * 10. + 2., 40. + colorIdxF));\n\n float time = (.1 + .15 * abs(sin(spotIdxF * (2. + colorIdxF)) * cos(spotIdxF * (2. + 2.5 * colorIdxF)))) * t + randVal.x * 3.;\n time *= mix(1., -1., step(.5, randVal.y));\n\n float mask = .5 + .5 * mix(\n sin(t + spotIdxF * (5. - 1.5 * colorIdxF)),\n cos(t + spotIdxF * (3. + 1.3 * colorIdxF)),\n step(mod(colorIdxF, 2.), .5)\n );\n\n float p = clamp(2. * u_pulse - randVal.x, 0., 1.);\n mask = mix(mask, pulse, p);\n\n float atg1 = fract(angle + time);\n float spotSize = .05 + .6 * pow(u_spotSize, 2.) + .05 * randVal.x;\n spotSize = mix(spotSize, .1, p);\n float sector = sst(.5 - spotSize, .5, atg1) * (1. - sst(.5, .5 + spotSize, atg1));\n\n sector *= mask;\n sector *= border;\n sector *= intensity;\n sector = clamp(sector, 0., 1.);\n\n vec3 srcColor = c * sector;\n float srcAlpha = a * sector;\n\n blendColor += ((1. - blendAlpha) * srcColor);\n blendAlpha = blendAlpha + (1. - blendAlpha) * srcAlpha;\n addColor += srcColor;\n addAlpha += srcAlpha;\n }\n }\n\n vec3 accumColor = mix(blendColor, addColor, bloom);\n float accumAlpha = mix(blendAlpha, addAlpha, bloom);\n accumAlpha = clamp(accumAlpha, 0., 1.);\n\n vec3 bgColor = u_colorBack.rgb * u_colorBack.a;\n vec3 color = accumColor + (1. - accumAlpha) * bgColor;\n float opacity = accumAlpha + (1. - accumAlpha) * u_colorBack.a;\n\n ${ colorBandingFix }\n\n fragColor = vec4(color, opacity);\n}`;\n\nexport interface PulsingBorderUniforms extends ShaderSizingUniforms {\n u_colorBack: [number, number, number, number];\n u_colors: vec4[];\n u_colorsCount: number;\n u_roundness: number;\n u_thickness: number;\n u_marginLeft: number;\n u_marginRight: number;\n u_marginTop: number;\n u_marginBottom: number;\n u_aspectRatio: (typeof PulsingBorderAspectRatios)[PulsingBorderAspectRatio];\n u_softness: number;\n u_intensity: number;\n u_bloom: number;\n u_spots: number;\n u_spotSize: number;\n u_pulse: number;\n u_smoke: number;\n u_smokeSize: number;\n u_noiseTexture?: HTMLImageElement;\n}\n\nexport interface PulsingBorderParams extends ShaderSizingParams, ShaderMotionParams {\n colorBack?: string;\n colors?: string[];\n roundness?: number;\n thickness?: number;\n margin?: number;\n marginLeft?: number;\n marginRight?: number;\n marginTop?: number;\n marginBottom?: number;\n aspectRatio?: PulsingBorderAspectRatio;\n softness?: number;\n intensity?: number;\n bloom?: number;\n spots?: number;\n spotSize?: number;\n pulse?: number;\n smoke?: number;\n smokeSize?: number;\n}\n\nexport const PulsingBorderAspectRatios = {\n auto: 0,\n square: 1,\n} as const;\n\nexport type PulsingBorderAspectRatio = keyof typeof PulsingBorderAspectRatios;\n"],
|
|
5
|
+
"mappings": ";;;;;AAEA,eAAmE;AACnE,SAAS,WAAW,qBAAqB,uBAAuB;AAEzD,MAAM,oBAAoB;AAAA,EAC/B,eAAe;AAAA,EACf,UAAU;AACZ;AAgDO,MAAM,8BAAsC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAM1B,kBAAkB,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,EA0BtD,SAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA6BV,mBAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,sCAoGgB,kBAAkB,aAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,sCAOhC,kBAAkB,QAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IA8C7D,eAAgB;AAAA;AAAA;AAAA;AAgDd,MAAM,4BAA4B;AAAA,EACvC,MAAM;AAAA,EACN,QAAQ;AACV;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -5,14 +5,33 @@ export declare const simplexNoiseMeta: {
|
|
|
5
5
|
readonly maxColorCount: 10;
|
|
6
6
|
};
|
|
7
7
|
/**
|
|
8
|
-
*
|
|
8
|
+
* A multi-color gradient mapped into smooth, animated curves built as a combination of 2 Simplex noises.
|
|
9
9
|
*
|
|
10
|
-
*
|
|
11
|
-
* -
|
|
12
|
-
* -
|
|
13
|
-
* -
|
|
10
|
+
* Fragment shader uniforms:
|
|
11
|
+
* - u_time (float): Animation time
|
|
12
|
+
* - u_scale (float): Overall zoom level, used for anti-aliasing calculations
|
|
13
|
+
* - u_colors (vec4[]): Up to 10 base colors in RGBA
|
|
14
|
+
* - u_colorsCount (float): Number of active colors
|
|
15
|
+
* - u_stepsPerColor (float): Number of extra colors between base colors, 1 = N colors, 2 = 2×N, etc. (1 to 10)
|
|
16
|
+
* - u_softness (float): Color transition sharpness, 0 = hard edge, 1 = smooth gradient (0 to 1)
|
|
14
17
|
*
|
|
15
|
-
*
|
|
18
|
+
* Vertex shader outputs (used in fragment shader):
|
|
19
|
+
* - v_patternUV (vec2): UV coordinates for pattern with global sizing (rotation, scale, offset, etc) applied
|
|
20
|
+
*
|
|
21
|
+
* Vertex shader uniforms:
|
|
22
|
+
* - u_resolution (vec2): Canvas resolution in pixels
|
|
23
|
+
* - u_pixelRatio (float): Device pixel ratio
|
|
24
|
+
* - u_originX (float): Reference point for positioning world width in the canvas (0 to 1)
|
|
25
|
+
* - u_originY (float): Reference point for positioning world height in the canvas (0 to 1)
|
|
26
|
+
* - u_worldWidth (float): Virtual width of the graphic before it's scaled to fit the canvas
|
|
27
|
+
* - u_worldHeight (float): Virtual height of the graphic before it's scaled to fit the canvas
|
|
28
|
+
* - u_fit (float): How to fit the rendered shader into the canvas dimensions (0 = none, 1 = contain, 2 = cover)
|
|
29
|
+
* - u_scale (float): Overall zoom level of the graphics (0.01 to 4)
|
|
30
|
+
* - u_rotation (float): Overall rotation angle of the graphics in degrees (0 to 360)
|
|
31
|
+
* - u_offsetX (float): Horizontal offset of the graphics center (-1 to 1)
|
|
32
|
+
* - u_offsetY (float): Vertical offset of the graphics center (-1 to 1)
|
|
33
|
+
*
|
|
34
|
+
*/
|
|
16
35
|
export declare const simplexNoiseFragmentShader: string;
|
|
17
36
|
export interface SimplexNoiseUniforms extends ShaderSizingUniforms {
|
|
18
37
|
u_colors: vec4[];
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* https://github.com/paper-design/shaders *
|
|
4
4
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import {} from "../shader-sizing.js";
|
|
7
7
|
import { simplexNoise, colorBandingFix } from "../shader-utils.js";
|
|
8
8
|
const simplexNoiseMeta = {
|
|
9
9
|
maxColorCount: 10
|
|
@@ -19,7 +19,7 @@ uniform float u_colorsCount;
|
|
|
19
19
|
uniform float u_stepsPerColor;
|
|
20
20
|
uniform float u_softness;
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
in vec2 v_patternUV;
|
|
23
23
|
|
|
24
24
|
out vec4 fragColor;
|
|
25
25
|
|
|
@@ -32,7 +32,7 @@ float getNoise(vec2 uv, float t) {
|
|
|
32
32
|
return noise;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
float steppedSmooth(float m, float steps, float softness) {
|
|
35
|
+
float steppedSmooth(float m, float steps, float softness) {
|
|
36
36
|
float stepT = floor(m * steps) / steps;
|
|
37
37
|
float f = m * steps - floor(m * steps);
|
|
38
38
|
float fw = steps * fwidth(m);
|
|
@@ -60,29 +60,29 @@ void main() {
|
|
|
60
60
|
vec4 gradient = u_colors[0];
|
|
61
61
|
gradient.rgb *= gradient.a;
|
|
62
62
|
for (int i = 1; i < ${simplexNoiseMeta.maxColorCount}; i++) {
|
|
63
|
-
|
|
63
|
+
if (i >= int(u_colorsCount)) break;
|
|
64
64
|
|
|
65
|
-
|
|
66
|
-
|
|
65
|
+
float localM = clamp(mixer - float(i - 1), 0., 1.);
|
|
66
|
+
localM = steppedSmooth(localM, steps, .5 * u_softness);
|
|
67
67
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
68
|
+
vec4 c = u_colors[i];
|
|
69
|
+
c.rgb *= c.a;
|
|
70
|
+
gradient = mix(gradient, c, localM);
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
if (u_extraSides == true) {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
74
|
+
if ((mixer < 0.) || (mixer > (u_colorsCount - 1.))) {
|
|
75
|
+
float localM = mixer + 1.;
|
|
76
|
+
if (mixer > (u_colorsCount - 1.)) {
|
|
77
|
+
localM = mixer - (u_colorsCount - 1.);
|
|
78
|
+
}
|
|
79
|
+
localM = steppedSmooth(localM, steps, .5 * u_softness);
|
|
80
|
+
vec4 cFst = u_colors[0];
|
|
81
|
+
cFst.rgb *= cFst.a;
|
|
82
|
+
vec4 cLast = u_colors[int(u_colorsCount - 1.)];
|
|
83
|
+
cLast.rgb *= cLast.a;
|
|
84
|
+
gradient = mix(cLast, cFst, localM);
|
|
85
|
+
}
|
|
86
86
|
}
|
|
87
87
|
|
|
88
88
|
vec3 color = gradient.rgb;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/shaders/simplex-noise.ts"],
|
|
4
|
-
"sourcesContent": ["import type { vec4 } from '../types.js';\nimport type { ShaderMotionParams } from '../shader-mount.js';\nimport {
|
|
5
|
-
"mappings": ";;;;;AAEA,
|
|
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 { simplexNoise, colorBandingFix } from '../shader-utils.js';\n\nexport const simplexNoiseMeta = {\n maxColorCount: 10,\n} as const;\n\n/**\n * A multi-color gradient mapped into smooth, animated curves built as a combination of 2 Simplex noises.\n *\n * Fragment shader uniforms:\n * - u_time (float): Animation time\n * - u_scale (float): Overall zoom level, used for anti-aliasing calculations\n * - u_colors (vec4[]): Up to 10 base colors in RGBA\n * - u_colorsCount (float): Number of active colors\n * - u_stepsPerColor (float): Number of extra colors between base colors, 1 = N colors, 2 = 2\u00D7N, etc. (1 to 10)\n * - u_softness (float): Color transition sharpness, 0 = hard edge, 1 = smooth gradient (0 to 1)\n *\n * Vertex shader outputs (used in fragment shader):\n * - v_patternUV (vec2): UV coordinates for pattern 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_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 simplexNoiseFragmentShader: string = `#version 300 es\nprecision mediump float;\n\nuniform float u_time;\nuniform float u_scale;\n\nuniform vec4 u_colors[${ simplexNoiseMeta.maxColorCount }];\nuniform float u_colorsCount;\nuniform float u_stepsPerColor;\nuniform float u_softness;\n\nin vec2 v_patternUV;\n\nout vec4 fragColor;\n\n${ simplexNoise }\n\nfloat getNoise(vec2 uv, float t) {\n float noise = .5 * snoise(uv - vec2(0., .3 * t));\n noise += .5 * snoise(2. * uv + vec2(0., .32 * t));\n\n return noise;\n}\n\nfloat steppedSmooth(float m, float steps, float softness) {\n float stepT = floor(m * steps) / steps;\n float f = m * steps - floor(m * steps);\n float fw = steps * fwidth(m);\n float smoothed = smoothstep(.5 - softness, min(1., .5 + softness + fw), f);\n return stepT + smoothed / steps;\n}\n\nvoid main() {\n vec2 shape_uv = v_patternUV;\n shape_uv *= .1;\n\n float t = .2 * u_time;\n\n float shape = .5 + .5 * getNoise(shape_uv, t);\n\n bool u_extraSides = true;\n\n float mixer = shape * (u_colorsCount - 1.);\n if (u_extraSides == true) {\n mixer = (shape - .5 / u_colorsCount) * u_colorsCount;\n }\n\n float steps = max(1., u_stepsPerColor);\n\n vec4 gradient = u_colors[0];\n gradient.rgb *= gradient.a;\n for (int i = 1; i < ${ simplexNoiseMeta.maxColorCount }; i++) {\n if (i >= int(u_colorsCount)) break;\n\n float localM = clamp(mixer - float(i - 1), 0., 1.);\n localM = steppedSmooth(localM, steps, .5 * u_softness);\n\n vec4 c = u_colors[i];\n c.rgb *= c.a;\n gradient = mix(gradient, c, localM);\n }\n\n if (u_extraSides == true) {\n if ((mixer < 0.) || (mixer > (u_colorsCount - 1.))) {\n float localM = mixer + 1.;\n if (mixer > (u_colorsCount - 1.)) {\n localM = mixer - (u_colorsCount - 1.);\n }\n localM = steppedSmooth(localM, steps, .5 * u_softness);\n vec4 cFst = u_colors[0];\n cFst.rgb *= cFst.a;\n vec4 cLast = u_colors[int(u_colorsCount - 1.)];\n cLast.rgb *= cLast.a;\n gradient = mix(cLast, cFst, localM);\n }\n }\n\n vec3 color = gradient.rgb;\n float opacity = gradient.a;\n\n ${ colorBandingFix }\n\n fragColor = vec4(color, opacity);\n}\n`;\n\nexport interface SimplexNoiseUniforms extends ShaderSizingUniforms {\n u_colors: vec4[];\n u_colorsCount: number;\n u_stepsPerColor: number;\n u_softness: number;\n}\n\nexport interface SimplexNoiseParams extends ShaderSizingParams, ShaderMotionParams {\n colors?: string[];\n stepsPerColor?: number;\n softness?: number;\n}\n"],
|
|
5
|
+
"mappings": ";;;;;AAEA,eAAmE;AACnE,SAAS,cAAc,uBAAuB;AAEvC,MAAM,mBAAmB;AAAA,EAC9B,eAAe;AACjB;AAgCO,MAAM,6BAAqC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAMzB,iBAAiB,aAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASrD,YAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAoCS,iBAAiB,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,IA6BnD,eAAgB;AAAA;AAAA;AAAA;AAAA;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -6,15 +6,37 @@ export declare const smokeRingMeta: {
|
|
|
6
6
|
readonly maxNoiseIterations: 8;
|
|
7
7
|
};
|
|
8
8
|
/**
|
|
9
|
-
* Radial gradient with layered
|
|
9
|
+
* Radial multi-colored gradient shaped with layered noise for a natural, smoky aesthetic.
|
|
10
10
|
*
|
|
11
|
-
* Uniforms:
|
|
12
|
-
* - u_colorBack (RGBA)
|
|
13
|
-
* - u_colors (vec4[]), u_colorsCount (float used as integer)
|
|
14
|
-
* - u_thickness, u_radius, u_innerShape: ring mask settings
|
|
15
|
-
* - u_noiseIterations, u_noiseScale: how detailed is the noise (number of fbm layers & noise frequency)
|
|
16
11
|
*
|
|
17
|
-
*
|
|
12
|
+
* Fragment shader uniforms:
|
|
13
|
+
* - u_time (float): Animation time
|
|
14
|
+
* - u_colorBack (vec4): Background color in RGBA
|
|
15
|
+
* - u_colors (vec4[]): Up to 10 gradient colors in RGBA
|
|
16
|
+
* - u_colorsCount (float): Number of active colors
|
|
17
|
+
* - u_thickness (float): Thickness of the ring shape (0.01 to 1)
|
|
18
|
+
* - u_radius (float): Radius of the ring shape (0 to 1)
|
|
19
|
+
* - u_innerShape (float): Ring inner fill amount (0 to 4)
|
|
20
|
+
* - u_noiseIterations (float): Number of noise layers, more layers gives more details (1 to 8)
|
|
21
|
+
* - u_noiseScale (float): Noise frequency (0.01 to 5)
|
|
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
|
+
* Vertex shader uniforms:
|
|
28
|
+
* - u_resolution (vec2): Canvas resolution in pixels
|
|
29
|
+
* - u_pixelRatio (float): Device pixel ratio
|
|
30
|
+
* - u_originX (float): Reference point for positioning world width in the canvas (0 to 1)
|
|
31
|
+
* - u_originY (float): Reference point for positioning world height in the canvas (0 to 1)
|
|
32
|
+
* - u_worldWidth (float): Virtual width of the graphic before it's scaled to fit the canvas
|
|
33
|
+
* - u_worldHeight (float): Virtual height of the graphic before it's scaled to fit the canvas
|
|
34
|
+
* - u_fit (float): How to fit the rendered shader into the canvas dimensions (0 = none, 1 = contain, 2 = cover)
|
|
35
|
+
* - u_scale (float): Overall zoom level of the graphics (0.01 to 4)
|
|
36
|
+
* - u_rotation (float): Overall rotation angle of the graphics in degrees (0 to 360)
|
|
37
|
+
* - u_offsetX (float): Horizontal offset of the graphics center (-1 to 1)
|
|
38
|
+
* - u_offsetY (float): Vertical offset of the graphics center (-1 to 1)
|
|
39
|
+
*
|
|
18
40
|
*/
|
|
19
41
|
export declare const smokeRingFragmentShader: string;
|
|
20
42
|
export interface SmokeRingUniforms extends ShaderSizingUniforms {
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* https://github.com/paper-design/shaders *
|
|
4
4
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import {} from "../shader-sizing.js";
|
|
7
7
|
import { declarePI, textureRandomizerR, colorBandingFix } from "../shader-utils.js";
|
|
8
8
|
const smokeRingMeta = {
|
|
9
9
|
maxColorCount: 10,
|
|
@@ -26,7 +26,7 @@ uniform float u_innerShape;
|
|
|
26
26
|
uniform float u_noiseScale;
|
|
27
27
|
uniform float u_noiseIterations;
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
in vec2 v_objectUV;
|
|
30
30
|
|
|
31
31
|
out vec4 fragColor;
|
|
32
32
|
|
|
@@ -44,23 +44,26 @@ float valueNoise(vec2 st) {
|
|
|
44
44
|
float x2 = mix(c, d, u.x);
|
|
45
45
|
return mix(x1, x2, u.y);
|
|
46
46
|
}
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
vec2 fbm(vec2 n0, vec2 n1) {
|
|
48
|
+
vec2 total = vec2(0.0);
|
|
49
|
+
float amplitude = .4;
|
|
49
50
|
for (int i = 0; i < ${smokeRingMeta.maxNoiseIterations}; i++) {
|
|
50
51
|
if (i >= int(u_noiseIterations)) break;
|
|
51
|
-
total += valueNoise(
|
|
52
|
-
|
|
52
|
+
total.x += valueNoise(n0) * amplitude;
|
|
53
|
+
total.y += valueNoise(n1) * amplitude;
|
|
54
|
+
n0 *= 1.99;
|
|
55
|
+
n1 *= 1.99;
|
|
53
56
|
amplitude *= 0.65;
|
|
54
57
|
}
|
|
55
58
|
return total;
|
|
56
59
|
}
|
|
57
60
|
|
|
58
61
|
float getNoise(vec2 uv, vec2 pUv, float t) {
|
|
59
|
-
|
|
62
|
+
vec2 pUvLeft = pUv + .03 * t;
|
|
60
63
|
float period = max(abs(u_noiseScale * TWO_PI), 1e-6);
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
return mix(
|
|
64
|
+
vec2 pUvRight = vec2(fract(pUv.x / period) * period, pUv.y) + .03 * t;
|
|
65
|
+
vec2 noise = fbm(pUvLeft, pUvRight);
|
|
66
|
+
return mix(noise.y, noise.x, smoothstep(-.25, .25, uv.x));
|
|
64
67
|
}
|
|
65
68
|
|
|
66
69
|
float getRingShape(vec2 uv) {
|
|
@@ -87,12 +90,11 @@ void main() {
|
|
|
87
90
|
|
|
88
91
|
float atg = atan(shape_uv.y, shape_uv.x) + .001;
|
|
89
92
|
float l = length(shape_uv);
|
|
90
|
-
|
|
91
|
-
polar_uv1
|
|
93
|
+
float radialOffset = .5 * l - inversesqrt(max(1e-4, l));
|
|
94
|
+
vec2 polar_uv1 = vec2(atg, localTime1 - radialOffset) * u_noiseScale;
|
|
95
|
+
vec2 polar_uv2 = vec2(atg, localTime2 - radialOffset) * u_noiseScale;
|
|
96
|
+
|
|
92
97
|
float noise1 = getNoise(shape_uv, polar_uv1, t);
|
|
93
|
-
|
|
94
|
-
vec2 polar_uv2 = vec2(atg, localTime2 - (.5 * l) + 1. / pow(max(1e-4, l), .5));
|
|
95
|
-
polar_uv2 *= u_noiseScale;
|
|
96
98
|
float noise2 = getNoise(shape_uv, polar_uv2, t);
|
|
97
99
|
|
|
98
100
|
float noise = mix(noise1, noise2, timeBlend);
|
|
@@ -102,10 +104,11 @@ void main() {
|
|
|
102
104
|
float ringShape = getRingShape(shape_uv);
|
|
103
105
|
|
|
104
106
|
float mixer = ringShape * ringShape * (u_colorsCount - 1.);
|
|
105
|
-
|
|
107
|
+
int idxLast = int(u_colorsCount) - 1;
|
|
108
|
+
vec4 gradient = u_colors[idxLast];
|
|
106
109
|
gradient.rgb *= gradient.a;
|
|
107
110
|
for (int i = ${smokeRingMeta.maxColorCount} - 2; i >= 0; i--) {
|
|
108
|
-
float localT = clamp(mixer - float(
|
|
111
|
+
float localT = clamp(mixer - float(idxLast - i - 1), 0., 1.);
|
|
109
112
|
vec4 c = u_colors[i];
|
|
110
113
|
c.rgb *= c.a;
|
|
111
114
|
gradient = mix(gradient, c, localT);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/shaders/smoke-ring.ts"],
|
|
4
|
-
"sourcesContent": ["import type { vec4 } from '../types.js';\nimport type { ShaderMotionParams } from '../shader-mount.js';\nimport {
|
|
5
|
-
"mappings": ";;;;;AAEA,
|
|
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, textureRandomizerR, colorBandingFix } from '../shader-utils.js';\n\nexport const smokeRingMeta = {\n maxColorCount: 10,\n maxNoiseIterations: 8,\n} as const;\n\n/**\n * Radial multi-colored gradient shaped with layered noise for a natural, smoky aesthetic.\n *\n *\n * Fragment shader uniforms:\n * - u_time (float): Animation time\n * - u_colorBack (vec4): Background color in RGBA\n * - u_colors (vec4[]): Up to 10 gradient colors in RGBA\n * - u_colorsCount (float): Number of active colors\n * - u_thickness (float): Thickness of the ring shape (0.01 to 1)\n * - u_radius (float): Radius of the ring shape (0 to 1)\n * - u_innerShape (float): Ring inner fill amount (0 to 4)\n * - u_noiseIterations (float): Number of noise layers, more layers gives more details (1 to 8)\n * - u_noiseScale (float): Noise frequency (0.01 to 5)\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 * 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 smokeRingFragmentShader: string = `#version 300 es\nprecision mediump float;\n\nuniform float u_time;\n\nuniform sampler2D u_noiseTexture;\n\nuniform vec4 u_colorBack;\nuniform vec4 u_colors[${ smokeRingMeta.maxColorCount }];\nuniform float u_colorsCount;\n\nuniform float u_thickness;\nuniform float u_radius;\nuniform float u_innerShape;\nuniform float u_noiseScale;\nuniform float u_noiseIterations;\n\nin vec2 v_objectUV;\n\nout vec4 fragColor;\n\n${ declarePI }\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}\nvec2 fbm(vec2 n0, vec2 n1) {\n vec2 total = vec2(0.0);\n float amplitude = .4;\n for (int i = 0; i < ${ smokeRingMeta.maxNoiseIterations }; i++) {\n if (i >= int(u_noiseIterations)) break;\n total.x += valueNoise(n0) * amplitude;\n total.y += valueNoise(n1) * amplitude;\n n0 *= 1.99;\n n1 *= 1.99;\n amplitude *= 0.65;\n }\n return total;\n}\n\nfloat getNoise(vec2 uv, vec2 pUv, float t) {\n vec2 pUvLeft = pUv + .03 * t;\n float period = max(abs(u_noiseScale * TWO_PI), 1e-6);\n vec2 pUvRight = vec2(fract(pUv.x / period) * period, pUv.y) + .03 * t;\n vec2 noise = fbm(pUvLeft, pUvRight);\n return mix(noise.y, noise.x, smoothstep(-.25, .25, uv.x));\n}\n\nfloat getRingShape(vec2 uv) {\n float radius = u_radius;\n float thickness = u_thickness;\n\n float distance = length(uv);\n float ringValue = 1. - smoothstep(radius, radius + thickness, distance);\n ringValue *= smoothstep(radius - pow(u_innerShape, 3.) * thickness, radius, distance);\n\n return ringValue;\n}\n\nvoid main() {\n vec2 shape_uv = v_objectUV;\n\n float t = u_time;\n\n float cycleDuration = 3.;\n float period2 = 2.0 * cycleDuration;\n float localTime1 = fract((0.1 * t + cycleDuration) / period2) * period2;\n float localTime2 = fract((0.1 * t) / period2) * period2;\n float timeBlend = .5 + .5 * sin(.1 * t * PI / cycleDuration - .5 * PI);\n\n float atg = atan(shape_uv.y, shape_uv.x) + .001;\n float l = length(shape_uv);\n float radialOffset = .5 * l - inversesqrt(max(1e-4, l));\n vec2 polar_uv1 = vec2(atg, localTime1 - radialOffset) * u_noiseScale;\n vec2 polar_uv2 = vec2(atg, localTime2 - radialOffset) * u_noiseScale;\n \n float noise1 = getNoise(shape_uv, polar_uv1, t);\n float noise2 = getNoise(shape_uv, polar_uv2, t);\n\n float noise = mix(noise1, noise2, timeBlend);\n\n shape_uv *= (.8 + 1.2 * noise);\n\n float ringShape = getRingShape(shape_uv);\n\n float mixer = ringShape * ringShape * (u_colorsCount - 1.);\n int idxLast = int(u_colorsCount) - 1;\n vec4 gradient = u_colors[idxLast];\n gradient.rgb *= gradient.a;\n for (int i = ${ smokeRingMeta.maxColorCount } - 2; i >= 0; i--) {\n float localT = clamp(mixer - float(idxLast - i - 1), 0., 1.);\n vec4 c = u_colors[i];\n c.rgb *= c.a;\n gradient = mix(gradient, c, localT);\n }\n\n vec3 color = gradient.rgb * ringShape;\n float opacity = gradient.a * ringShape;\n\n vec3 bgColor = u_colorBack.rgb * u_colorBack.a;\n color = color + bgColor * (1. - opacity);\n opacity = opacity + u_colorBack.a * (1. - opacity);\n\n ${ colorBandingFix }\n\n fragColor = vec4(color, opacity);\n}\n`;\n\nexport interface SmokeRingUniforms extends ShaderSizingUniforms {\n u_colorBack: [number, number, number, number];\n u_colors: vec4[];\n u_colorsCount: number;\n u_noiseScale: number;\n u_thickness: number;\n u_radius: number;\n u_innerShape: number;\n u_noiseIterations: number;\n u_noiseTexture?: HTMLImageElement;\n}\n\nexport interface SmokeRingParams extends ShaderSizingParams, ShaderMotionParams {\n colorBack?: string;\n colors?: string[];\n noiseScale?: number;\n thickness?: number;\n radius?: number;\n innerShape?: number;\n noiseIterations?: number;\n}\n"],
|
|
5
|
+
"mappings": ";;;;;AAEA,eAAmE;AACnE,SAAS,WAAW,oBAAoB,uBAAuB;AAExD,MAAM,gBAAgB;AAAA,EAC3B,eAAe;AAAA,EACf,oBAAoB;AACtB;AAqCO,MAAM,0BAAkC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAQtB,cAAc,aAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAalD,SAAU;AAAA,EACV,kBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAgBG,cAAc,kBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iBA4DxC,cAAc,aAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAczC,eAAgB;AAAA;AAAA;AAAA;AAAA;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/shaders/spiral.d.ts
CHANGED
|
@@ -1,17 +1,37 @@
|
|
|
1
1
|
import type { ShaderMotionParams } from '../shader-mount.js';
|
|
2
2
|
import { type ShaderSizingParams, type ShaderSizingUniforms } from '../shader-sizing.js';
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
4
|
+
* A single-colored animated spiral that morphs across a wide range of shapes -
|
|
5
|
+
* from crisp, thin-lined geometry to flowing whirlpool forms and wavy, abstract rings.
|
|
5
6
|
*
|
|
6
|
-
*
|
|
7
|
-
* -
|
|
8
|
-
* -
|
|
9
|
-
* -
|
|
10
|
-
* -
|
|
11
|
-
* -
|
|
12
|
-
* -
|
|
13
|
-
* -
|
|
14
|
-
* -
|
|
7
|
+
* Vertex shader uniforms:
|
|
8
|
+
* - u_resolution (vec2): Canvas resolution in pixels
|
|
9
|
+
* - u_pixelRatio (float): Device pixel ratio
|
|
10
|
+
* - u_originX (float): Reference point for positioning world width in the canvas (0 to 1)
|
|
11
|
+
* - u_originY (float): Reference point for positioning world height in the canvas (0 to 1)
|
|
12
|
+
* - u_worldWidth (float): Virtual width of the graphic before it's scaled to fit the canvas
|
|
13
|
+
* - u_worldHeight (float): Virtual height of the graphic before it's scaled to fit the canvas
|
|
14
|
+
* - u_fit (float): How to fit the rendered shader into the canvas dimensions (0 = none, 1 = contain, 2 = cover)
|
|
15
|
+
* - u_scale (float): Overall zoom level of the graphics (0.01 to 4)
|
|
16
|
+
* - u_rotation (float): Overall rotation angle of the graphics in degrees (0 to 360)
|
|
17
|
+
* - u_offsetX (float): Horizontal offset of the graphics center (-1 to 1)
|
|
18
|
+
* - u_offsetY (float): Vertical offset of the graphics center (-1 to 1)
|
|
19
|
+
*
|
|
20
|
+
* Vertex shader outputs (used in fragment shader):
|
|
21
|
+
* - v_patternUV (vec2): UV coordinates in pixels (scaled by 0.01 for precision), with rotation and offset applied
|
|
22
|
+
*
|
|
23
|
+
* Fragment shader uniforms:
|
|
24
|
+
* - u_time (float): Animation time
|
|
25
|
+
* - u_colorBack (vec4): Background color in RGBA
|
|
26
|
+
* - u_colorFront (vec4): Foreground (ink) color in RGBA
|
|
27
|
+
* - u_density (float): Spacing falloff simulating perspective, 0 = flat spiral (0 to 1)
|
|
28
|
+
* - u_distortion (float): Power of shape distortion applied along the spiral (0 to 1)
|
|
29
|
+
* - u_strokeWidth (float): Thickness of spiral curve (0 to 1)
|
|
30
|
+
* - u_strokeTaper (float): How much stroke loses width away from center, 0 = full visibility (0 to 1)
|
|
31
|
+
* - u_strokeCap (float): Extra stroke width at the center, no effect with strokeWidth = 0.5 (0 to 1)
|
|
32
|
+
* - u_noise (float): Noise distortion applied over the canvas, no effect with noiseFrequency = 0 (0 to 1)
|
|
33
|
+
* - u_noiseFrequency (float): Noise frequency, no effect with noise = 0 (0 to 1)
|
|
34
|
+
* - u_softness (float): Color transition sharpness, 0 = hard edge, 1 = smooth gradient (0 to 1)
|
|
15
35
|
*
|
|
16
36
|
*/
|
|
17
37
|
export declare const spiralFragmentShader: string;
|
package/dist/shaders/spiral.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* https://github.com/paper-design/shaders *
|
|
4
4
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import {} from "../shader-sizing.js";
|
|
7
7
|
import { simplexNoise, declarePI, colorBandingFix } from "../shader-utils.js";
|
|
8
8
|
const spiralFragmentShader = `#version 300 es
|
|
9
9
|
precision mediump float;
|
|
@@ -21,7 +21,7 @@ uniform float u_noise;
|
|
|
21
21
|
uniform float u_noiseFrequency;
|
|
22
22
|
uniform float u_softness;
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
in vec2 v_patternUV;
|
|
25
25
|
|
|
26
26
|
out vec4 fragColor;
|
|
27
27
|
|
|
@@ -30,7 +30,7 @@ ${simplexNoise}
|
|
|
30
30
|
|
|
31
31
|
void main() {
|
|
32
32
|
vec2 uv = 2. * v_patternUV;
|
|
33
|
-
|
|
33
|
+
|
|
34
34
|
float t = u_time;
|
|
35
35
|
float l = length(uv);
|
|
36
36
|
float density = clamp(u_density, 0., 1.);
|
|
@@ -43,7 +43,7 @@ void main() {
|
|
|
43
43
|
float offset = l + angleNormalised;
|
|
44
44
|
offset -= u_distortion * (sin(4. * l - .5 * t) * cos(PI + l + .5 * t));
|
|
45
45
|
float stripe = fract(offset);
|
|
46
|
-
|
|
46
|
+
|
|
47
47
|
float shape = 2. * abs(stripe - .5);
|
|
48
48
|
float width = 1. - clamp(u_strokeWidth, .005 * u_strokeTaper, 1.);
|
|
49
49
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/shaders/spiral.ts"],
|
|
4
|
-
"sourcesContent": ["import type { ShaderMotionParams } from '../shader-mount.js';\nimport {
|
|
5
|
-
"mappings": ";;;;;AACA,
|
|
4
|
+
"sourcesContent": ["import type { ShaderMotionParams } from '../shader-mount.js';\nimport { type ShaderSizingParams, type ShaderSizingUniforms } from '../shader-sizing.js';\nimport { simplexNoise, declarePI, colorBandingFix } from '../shader-utils.js';\n\n/**\n * A single-colored animated spiral that morphs across a wide range of shapes -\n * from crisp, thin-lined geometry to flowing whirlpool forms and wavy, abstract rings.\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 * Vertex shader outputs (used in fragment shader):\n * - v_patternUV (vec2): UV coordinates in pixels (scaled by 0.01 for precision), with rotation and offset applied\n *\n * Fragment shader uniforms:\n * - u_time (float): Animation time\n * - u_colorBack (vec4): Background color in RGBA\n * - u_colorFront (vec4): Foreground (ink) color in RGBA\n * - u_density (float): Spacing falloff simulating perspective, 0 = flat spiral (0 to 1)\n * - u_distortion (float): Power of shape distortion applied along the spiral (0 to 1)\n * - u_strokeWidth (float): Thickness of spiral curve (0 to 1)\n * - u_strokeTaper (float): How much stroke loses width away from center, 0 = full visibility (0 to 1)\n * - u_strokeCap (float): Extra stroke width at the center, no effect with strokeWidth = 0.5 (0 to 1)\n * - u_noise (float): Noise distortion applied over the canvas, no effect with noiseFrequency = 0 (0 to 1)\n * - u_noiseFrequency (float): Noise frequency, no effect with noise = 0 (0 to 1)\n * - u_softness (float): Color transition sharpness, 0 = hard edge, 1 = smooth gradient (0 to 1)\n *\n */\n\n// language=GLSL\nexport const spiralFragmentShader: string = `#version 300 es\nprecision mediump float;\n\nuniform float u_time;\n\nuniform vec4 u_colorBack;\nuniform vec4 u_colorFront;\nuniform float u_density;\nuniform float u_distortion;\nuniform float u_strokeWidth;\nuniform float u_strokeCap;\nuniform float u_strokeTaper;\nuniform float u_noise;\nuniform float u_noiseFrequency;\nuniform float u_softness;\n\nin vec2 v_patternUV;\n\nout vec4 fragColor;\n\n${ declarePI }\n${ simplexNoise }\n\nvoid main() {\n vec2 uv = 2. * v_patternUV;\n\n float t = u_time;\n float l = length(uv);\n float density = clamp(u_density, 0., 1.);\n l = pow(max(l, 1e-6), density);\n float angle = atan(uv.y, uv.x) - t;\n float angleNormalised = angle / TWO_PI;\n\n angleNormalised += .125 * u_noise * snoise(16. * pow(u_noiseFrequency, 3.) * uv);\n\n float offset = l + angleNormalised;\n offset -= u_distortion * (sin(4. * l - .5 * t) * cos(PI + l + .5 * t));\n float stripe = fract(offset);\n\n float shape = 2. * abs(stripe - .5);\n float width = 1. - clamp(u_strokeWidth, .005 * u_strokeTaper, 1.);\n\n\n float wCap = mix(width, (1. - stripe) * (1. - step(.5, stripe)), (1. - clamp(l, 0., 1.)));\n width = mix(width, wCap, u_strokeCap);\n width *= (1. - clamp(u_strokeTaper, 0., 1.) * l);\n\n float fw = fwidth(offset);\n float fwMult = 4. - 3. * (smoothstep(.05, .4, 2. * u_strokeWidth) * smoothstep(.05, .4, 2. * (1. - u_strokeWidth)));\n float pixelSize = mix(fwMult * fw, fwidth(shape), clamp(fw, 0., 1.));\n pixelSize = mix(pixelSize, .002, u_strokeCap * (1. - clamp(l, 0., 1.)));\n\n float res = smoothstep(width - pixelSize - u_softness, width + pixelSize + u_softness, shape);\n\n vec3 fgColor = u_colorFront.rgb * u_colorFront.a;\n float fgOpacity = u_colorFront.a;\n vec3 bgColor = u_colorBack.rgb * u_colorBack.a;\n float bgOpacity = u_colorBack.a;\n\n vec3 color = fgColor * res;\n float opacity = fgOpacity * res;\n\n color += bgColor * (1. - opacity);\n opacity += bgOpacity * (1. - opacity);\n\n ${ colorBandingFix }\n\n fragColor = vec4(color, opacity);\n}\n`;\n\nexport interface SpiralUniforms extends ShaderSizingUniforms {\n u_colorBack: [number, number, number, number];\n u_colorFront: [number, number, number, number];\n u_density: number;\n u_distortion: number;\n u_strokeWidth: number;\n u_strokeTaper: number;\n u_strokeCap: number;\n u_noise: number;\n u_noiseFrequency: number;\n u_softness: number;\n}\n\nexport interface SpiralParams extends ShaderSizingParams, ShaderMotionParams {\n colorBack?: string;\n colorFront?: string;\n density?: number;\n distortion?: number;\n strokeWidth?: number;\n strokeTaper?: number;\n strokeCap?: number;\n noise?: number;\n noiseFrequency?: number;\n softness?: number;\n}\n"],
|
|
5
|
+
"mappings": ";;;;;AACA,eAAmE;AACnE,SAAS,cAAc,WAAW,uBAAuB;AAsClD,MAAM,uBAA+B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAoBzC,SAAU;AAAA,EACV,YAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IA4CX,eAAgB;AAAA;AAAA;AAAA;AAAA;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|