@paper-design/shaders 0.0.0-canary.156ab35
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/LICENSE +21 -0
- package/README.md +7 -0
- package/dist/get-empty-pixel.d.ts +1 -0
- package/dist/get-empty-pixel.js +19 -0
- package/dist/get-empty-pixel.js.map +7 -0
- package/dist/get-shader-color-from-string.d.ts +3 -0
- package/dist/get-shader-color-from-string.js +93 -0
- package/dist/get-shader-color-from-string.js.map +7 -0
- package/dist/get-shader-noise-texture.d.ts +1 -0
- package/dist/get-shader-noise-texture.js +19 -0
- package/dist/get-shader-noise-texture.js.map +7 -0
- package/dist/index.d.ts +53 -0
- package/dist/index.js +168 -0
- package/dist/index.js.map +7 -0
- package/dist/shader-color-spaces.d.ts +6 -0
- package/dist/shader-color-spaces.js +96 -0
- package/dist/shader-color-spaces.js.map +7 -0
- package/dist/shader-mount.d.ts +130 -0
- package/dist/shader-mount.js +483 -0
- package/dist/shader-mount.js.map +7 -0
- package/dist/shader-sizing.d.ts +35 -0
- package/dist/shader-sizing.js +230 -0
- package/dist/shader-sizing.js.map +7 -0
- package/dist/shader-utils.d.ts +10 -0
- package/dist/shader-utils.js +131 -0
- package/dist/shader-utils.js.map +7 -0
- package/dist/shaders/color-panels.d.ts +50 -0
- package/dist/shaders/color-panels.js +224 -0
- package/dist/shaders/color-panels.js.map +7 -0
- package/dist/shaders/dithering.d.ts +56 -0
- package/dist/shaders/dithering.js +223 -0
- package/dist/shaders/dithering.js.map +7 -0
- package/dist/shaders/dot-grid.d.ts +51 -0
- package/dist/shaders/dot-grid.js +110 -0
- package/dist/shaders/dot-grid.js.map +7 -0
- package/dist/shaders/dot-orbit.d.ts +39 -0
- package/dist/shaders/dot-orbit.js +124 -0
- package/dist/shaders/dot-orbit.js.map +7 -0
- package/dist/shaders/fluted-glass.d.ts +73 -0
- package/dist/shaders/fluted-glass.js +187 -0
- package/dist/shaders/fluted-glass.js.map +7 -0
- package/dist/shaders/god-rays.d.ts +45 -0
- package/dist/shaders/god-rays.js +133 -0
- package/dist/shaders/god-rays.js.map +7 -0
- package/dist/shaders/grain-gradient.d.ts +58 -0
- package/dist/shaders/grain-gradient.js +289 -0
- package/dist/shaders/grain-gradient.js.map +7 -0
- package/dist/shaders/heatmap.d.ts +31 -0
- package/dist/shaders/heatmap.js +303 -0
- package/dist/shaders/heatmap.js.map +7 -0
- package/dist/shaders/image-dithering.d.ts +49 -0
- package/dist/shaders/image-dithering.js +163 -0
- package/dist/shaders/image-dithering.js.map +7 -0
- package/dist/shaders/image-halftone-dots.d.ts +46 -0
- package/dist/shaders/image-halftone-dots.js +337 -0
- package/dist/shaders/image-halftone-dots.js.map +7 -0
- package/dist/shaders/liquid-metal.d.ts +66 -0
- package/dist/shaders/liquid-metal.js +627 -0
- package/dist/shaders/liquid-metal.js.map +7 -0
- package/dist/shaders/mesh-gradient.d.ts +33 -0
- package/dist/shaders/mesh-gradient.js +136 -0
- package/dist/shaders/mesh-gradient.js.map +7 -0
- package/dist/shaders/metaballs.d.ts +35 -0
- package/dist/shaders/metaballs.js +112 -0
- package/dist/shaders/metaballs.js.map +7 -0
- package/dist/shaders/neuro-noise.d.ts +27 -0
- package/dist/shaders/neuro-noise.js +80 -0
- package/dist/shaders/neuro-noise.js.map +7 -0
- package/dist/shaders/paper-texture.d.ts +53 -0
- package/dist/shaders/paper-texture.js +248 -0
- package/dist/shaders/paper-texture.js.map +7 -0
- package/dist/shaders/perlin-noise.d.ts +33 -0
- package/dist/shaders/perlin-noise.js +195 -0
- package/dist/shaders/perlin-noise.js.map +7 -0
- package/dist/shaders/pulsing-border.d.ts +72 -0
- package/dist/shaders/pulsing-border.js +237 -0
- package/dist/shaders/pulsing-border.js.map +7 -0
- package/dist/shaders/simplex-noise.d.ts +27 -0
- package/dist/shaders/simplex-noise.js +100 -0
- package/dist/shaders/simplex-noise.js.map +7 -0
- package/dist/shaders/smoke-ring.d.ts +39 -0
- package/dist/shaders/smoke-ring.js +130 -0
- package/dist/shaders/smoke-ring.js.map +7 -0
- package/dist/shaders/spiral.d.ts +41 -0
- package/dist/shaders/spiral.js +81 -0
- package/dist/shaders/spiral.js.map +7 -0
- package/dist/shaders/static-mesh-gradient.d.ts +42 -0
- package/dist/shaders/static-mesh-gradient.js +139 -0
- package/dist/shaders/static-mesh-gradient.js.map +7 -0
- package/dist/shaders/static-radial-gradient.d.ts +50 -0
- package/dist/shaders/static-radial-gradient.js +195 -0
- package/dist/shaders/static-radial-gradient.js.map +7 -0
- package/dist/shaders/swirl.d.ts +42 -0
- package/dist/shaders/swirl.js +102 -0
- package/dist/shaders/swirl.js.map +7 -0
- package/dist/shaders/voronoi.d.ts +44 -0
- package/dist/shaders/voronoi.js +139 -0
- package/dist/shaders/voronoi.js.map +7 -0
- package/dist/shaders/warp.d.ts +54 -0
- package/dist/shaders/warp.js +132 -0
- package/dist/shaders/warp.js.map +7 -0
- package/dist/shaders/water.d.ts +39 -0
- package/dist/shaders/water.js +120 -0
- package/dist/shaders/water.js.map +7 -0
- package/dist/shaders/waves.d.ts +38 -0
- package/dist/shaders/waves.js +66 -0
- package/dist/shaders/waves.js.map +7 -0
- package/dist/types.d.ts +3 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +7 -0
- package/dist/vertex-shader.d.ts +2 -0
- package/dist/vertex-shader.js +211 -0
- package/dist/vertex-shader.js.map +7 -0
- package/package.json +27 -0
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
/* * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
2
|
+
* Paper Shaders *
|
|
3
|
+
* https://github.com/paper-design/shaders *
|
|
4
|
+
* * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
5
|
+
|
|
6
|
+
import { sizingVariablesDeclaration } 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
|
+
${sizingVariablesDeclaration}
|
|
39
|
+
|
|
40
|
+
out vec4 fragColor;
|
|
41
|
+
|
|
42
|
+
${declarePI}
|
|
43
|
+
|
|
44
|
+
float beat(float time) {
|
|
45
|
+
float first = pow(abs(sin(time * TWO_PI)), 10.);
|
|
46
|
+
float second = pow(abs(sin((time - .15) * TWO_PI)), 10.);
|
|
47
|
+
|
|
48
|
+
return clamp(first + 0.6 * second, 0.0, 1.0);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
float sst(float edge0, float edge1, float x) {
|
|
52
|
+
return smoothstep(edge0, edge1, x);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
float roundedBox(vec2 uv, vec2 halfSize, float distance, float cornerDistance, float thickness, float softness) {
|
|
56
|
+
float borderDistance = abs(distance);
|
|
57
|
+
float aa = 2. * fwidth(distance);
|
|
58
|
+
float border = 1. - sst(min(mix(thickness, -thickness, softness), thickness + aa), max(mix(thickness, -thickness, softness), thickness + aa), borderDistance);
|
|
59
|
+
float cornerFadeCircles = 0.;
|
|
60
|
+
cornerFadeCircles = mix(1., cornerFadeCircles, sst(0., 1., length((uv + halfSize) / thickness)));
|
|
61
|
+
cornerFadeCircles = mix(1., cornerFadeCircles, sst(0., 1., length((uv - vec2(-halfSize.x, halfSize.y)) / thickness)));
|
|
62
|
+
cornerFadeCircles = mix(1., cornerFadeCircles, sst(0., 1., length((uv - vec2(halfSize.x, -halfSize.y)) / thickness)));
|
|
63
|
+
cornerFadeCircles = mix(1., cornerFadeCircles, sst(0., 1., length((uv - halfSize) / thickness)));
|
|
64
|
+
aa = fwidth(cornerDistance);
|
|
65
|
+
float cornerFade = sst(0., mix(aa, thickness, softness), cornerDistance);
|
|
66
|
+
cornerFade *= cornerFadeCircles;
|
|
67
|
+
border += cornerFade;
|
|
68
|
+
return border;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
${textureRandomizerGB}
|
|
72
|
+
|
|
73
|
+
float randomG(vec2 p) {
|
|
74
|
+
vec2 uv = floor(p) / 100. + .5;
|
|
75
|
+
return texture(u_noiseTexture, fract(uv)).g;
|
|
76
|
+
}
|
|
77
|
+
float valueNoise(vec2 st) {
|
|
78
|
+
vec2 i = floor(st);
|
|
79
|
+
vec2 f = fract(st);
|
|
80
|
+
float a = randomG(i);
|
|
81
|
+
float b = randomG(i + vec2(1.0, 0.0));
|
|
82
|
+
float c = randomG(i + vec2(0.0, 1.0));
|
|
83
|
+
float d = randomG(i + vec2(1.0, 1.0));
|
|
84
|
+
vec2 u = f * f * (3.0 - 2.0 * f);
|
|
85
|
+
float x1 = mix(a, b, u.x);
|
|
86
|
+
float x2 = mix(c, d, u.x);
|
|
87
|
+
return mix(x1, x2, u.y);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
void main() {
|
|
91
|
+
const float firstFrameOffset = 109.;
|
|
92
|
+
float t = 1.2 * (u_time + firstFrameOffset);
|
|
93
|
+
|
|
94
|
+
vec2 borderUV = v_responsiveUV;
|
|
95
|
+
float pulse = u_pulse * beat(.18 * u_time);
|
|
96
|
+
|
|
97
|
+
float canvasRatio = v_responsiveBoxGivenSize.x / v_responsiveBoxGivenSize.y;
|
|
98
|
+
vec2 halfSize = vec2(.5);
|
|
99
|
+
borderUV.x *= max(canvasRatio, 1.);
|
|
100
|
+
borderUV.y /= min(canvasRatio, 1.);
|
|
101
|
+
halfSize.x *= max(canvasRatio, 1.);
|
|
102
|
+
halfSize.y /= min(canvasRatio, 1.);
|
|
103
|
+
|
|
104
|
+
float mL = u_marginLeft;
|
|
105
|
+
float mR = u_marginRight;
|
|
106
|
+
float mT = u_marginTop;
|
|
107
|
+
float mB = u_marginBottom;
|
|
108
|
+
float mX = mL + mR;
|
|
109
|
+
float mY = mT + mB;
|
|
110
|
+
|
|
111
|
+
if (u_aspectRatio > 0.) {
|
|
112
|
+
float shapeRatio = canvasRatio * (1. - mX) / max(1. - mY, 1e-6);
|
|
113
|
+
float freeX = shapeRatio > 1. ? (1. - mX) * (1. - 1. / max(abs(shapeRatio), 1e-6)) : 0.;
|
|
114
|
+
float freeY = shapeRatio < 1. ? (1. - mY) * (1. - shapeRatio) : 0.;
|
|
115
|
+
mL += freeX * 0.5;
|
|
116
|
+
mR += freeX * 0.5;
|
|
117
|
+
mT += freeY * 0.5;
|
|
118
|
+
mB += freeY * 0.5;
|
|
119
|
+
mX = mL + mR;
|
|
120
|
+
mY = mT + mB;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
float thickness = .5 * u_thickness * min(halfSize.x, halfSize.y);
|
|
124
|
+
|
|
125
|
+
halfSize.x *= (1. - mX);
|
|
126
|
+
halfSize.y *= (1. - mY);
|
|
127
|
+
|
|
128
|
+
vec2 centerShift = vec2(
|
|
129
|
+
(mL - mR) * max(canvasRatio, 1.) * 0.5,
|
|
130
|
+
(mB - mT) / min(canvasRatio, 1.) * 0.5
|
|
131
|
+
);
|
|
132
|
+
|
|
133
|
+
borderUV -= centerShift;
|
|
134
|
+
halfSize -= mix(thickness, 0., u_softness);
|
|
135
|
+
|
|
136
|
+
float radius = mix(0., min(halfSize.x, halfSize.y), u_roundness);
|
|
137
|
+
vec2 d = abs(borderUV) - halfSize + radius;
|
|
138
|
+
float outsideDistance = length(max(d, .0001)) - radius;
|
|
139
|
+
float insideDistance = min(max(d.x, d.y), .0001);
|
|
140
|
+
float cornerDistance = abs(min(max(d.x, d.y) - .45 * radius, .0));
|
|
141
|
+
float distance = outsideDistance + insideDistance;
|
|
142
|
+
|
|
143
|
+
float borderThickness = mix(thickness, 3. * thickness, u_softness);
|
|
144
|
+
float border = roundedBox(borderUV, halfSize, distance, cornerDistance, borderThickness, u_softness);
|
|
145
|
+
border = pow(border, 1. + u_softness);
|
|
146
|
+
|
|
147
|
+
vec2 smokeUV = .3 * u_smokeSize * v_patternUV;
|
|
148
|
+
float smoke = clamp(3. * valueNoise(2.7 * smokeUV + .5 * t), 0., 1.);
|
|
149
|
+
smoke -= valueNoise(3.4 * smokeUV - .5 * t);
|
|
150
|
+
float smokeThickness = thickness + .2;
|
|
151
|
+
smokeThickness = min(.4, max(smokeThickness, .1));
|
|
152
|
+
smoke *= roundedBox(borderUV, halfSize, distance, cornerDistance, smokeThickness, 1.);
|
|
153
|
+
smoke = 30. * smoke * smoke;
|
|
154
|
+
smoke *= mix(0., .5, pow(u_smoke, 2.));
|
|
155
|
+
smoke *= mix(1., pulse, u_pulse);
|
|
156
|
+
smoke = clamp(smoke, 0., 1.);
|
|
157
|
+
border += smoke;
|
|
158
|
+
|
|
159
|
+
border = clamp(border, 0., 1.);
|
|
160
|
+
|
|
161
|
+
vec3 blendColor = vec3(0.);
|
|
162
|
+
float blendAlpha = 0.;
|
|
163
|
+
vec3 addColor = vec3(0.);
|
|
164
|
+
float addAlpha = 0.;
|
|
165
|
+
|
|
166
|
+
float bloom = 4. * u_bloom;
|
|
167
|
+
float intensity = 1. + (1. + 4. * u_softness) * u_intensity;
|
|
168
|
+
|
|
169
|
+
float angle = atan(borderUV.y, borderUV.x) / TWO_PI;
|
|
170
|
+
|
|
171
|
+
for (int colorIdx = 0; colorIdx < ${pulsingBorderMeta.maxColorCount}; colorIdx++) {
|
|
172
|
+
if (colorIdx >= int(u_colorsCount)) break;
|
|
173
|
+
float colorIdxF = float(colorIdx);
|
|
174
|
+
|
|
175
|
+
vec3 c = u_colors[colorIdx].rgb * u_colors[colorIdx].a;
|
|
176
|
+
float a = u_colors[colorIdx].a;
|
|
177
|
+
|
|
178
|
+
for (int spotIdx = 0; spotIdx < ${pulsingBorderMeta.maxSpots}; spotIdx++) {
|
|
179
|
+
if (spotIdx >= int(u_spots)) break;
|
|
180
|
+
float spotIdxF = float(spotIdx);
|
|
181
|
+
|
|
182
|
+
vec2 randVal = randomGB(vec2(spotIdxF * 10. + 2., 40. + colorIdxF));
|
|
183
|
+
|
|
184
|
+
float time = (.1 + .15 * abs(sin(spotIdxF * (2. + colorIdxF)) * cos(spotIdxF * (2. + 2.5 * colorIdxF)))) * t + randVal.x * 3.;
|
|
185
|
+
time *= mix(1., -1., step(.5, randVal.y));
|
|
186
|
+
|
|
187
|
+
float mask = .5 + .5 * mix(
|
|
188
|
+
sin(t + spotIdxF * (5. - 1.5 * colorIdxF)),
|
|
189
|
+
cos(t + spotIdxF * (3. + 1.3 * colorIdxF)),
|
|
190
|
+
step(mod(colorIdxF, 2.), .5)
|
|
191
|
+
);
|
|
192
|
+
|
|
193
|
+
float p = clamp(2. * u_pulse - randVal.x, 0., 1.);
|
|
194
|
+
mask = mix(mask, pulse, p);
|
|
195
|
+
|
|
196
|
+
float atg1 = fract(angle + time);
|
|
197
|
+
float spotSize = .05 + .6 * pow(u_spotSize, 2.) + .05 * randVal.x;
|
|
198
|
+
spotSize = mix(spotSize, .1, p);
|
|
199
|
+
float sector = sst(.5 - spotSize, .5, atg1) * (1. - sst(.5, .5 + spotSize, atg1));
|
|
200
|
+
|
|
201
|
+
sector *= mask;
|
|
202
|
+
sector *= border;
|
|
203
|
+
sector *= intensity;
|
|
204
|
+
sector = clamp(sector, 0., 1.);
|
|
205
|
+
|
|
206
|
+
vec3 srcColor = c * sector;
|
|
207
|
+
float srcAlpha = a * sector;
|
|
208
|
+
|
|
209
|
+
blendColor += ((1. - blendAlpha) * srcColor);
|
|
210
|
+
blendAlpha = blendAlpha + (1. - blendAlpha) * srcAlpha;
|
|
211
|
+
addColor += srcColor;
|
|
212
|
+
addAlpha += srcAlpha;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
vec3 accumColor = mix(blendColor, addColor, bloom);
|
|
217
|
+
float accumAlpha = mix(blendAlpha, addAlpha, bloom);
|
|
218
|
+
accumAlpha = clamp(accumAlpha, 0., 1.);
|
|
219
|
+
|
|
220
|
+
vec3 bgColor = u_colorBack.rgb * u_colorBack.a;
|
|
221
|
+
vec3 color = accumColor + (1. - accumAlpha) * bgColor;
|
|
222
|
+
float opacity = accumAlpha + (1. - accumAlpha) * u_colorBack.a;
|
|
223
|
+
|
|
224
|
+
${colorBandingFix}
|
|
225
|
+
|
|
226
|
+
fragColor = vec4(color, opacity);
|
|
227
|
+
}`;
|
|
228
|
+
const PulsingBorderAspectRatios = {
|
|
229
|
+
auto: 0,
|
|
230
|
+
square: 1
|
|
231
|
+
};
|
|
232
|
+
export {
|
|
233
|
+
PulsingBorderAspectRatios,
|
|
234
|
+
pulsingBorderFragmentShader,
|
|
235
|
+
pulsingBorderMeta
|
|
236
|
+
};
|
|
237
|
+
//# sourceMappingURL=pulsing-border.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 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,SAAS,kCAAsF;AAC/F,SAAS,WAAW,qBAAqB,uBAAuB;AAEzD,MAAM,oBAAoB;AAAA,EAC/B,eAAe;AAAA,EACf,UAAU;AACZ;AAsBO,MAAM,8BAAsC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAM3B,kBAAkB,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAoBrD,0BAA0B;AAAA;AAAA;AAAA;AAAA,EAI1B,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA6BT,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,sCAoGiB,kBAAkB,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,sCAO/B,kBAAkB,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IA8C5D,eAAe;AAAA;AAAA;AAAA;AAgDZ,MAAM,4BAA4B;AAAA,EACvC,MAAM;AAAA,EACN,QAAQ;AACV;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
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 simplexNoiseMeta: {
|
|
5
|
+
readonly maxColorCount: 10;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* Color Gradient mapped over a combination of 2 Simplex noises
|
|
9
|
+
*
|
|
10
|
+
* Uniforms:
|
|
11
|
+
* - u_colors (vec4[]), u_colorsCount (float used as integer)
|
|
12
|
+
* - u_stepsPerColor (float, used as int): discrete color steps between u_colors
|
|
13
|
+
* - u_softness: color transition sharpness (0 = hard edge, 1 = smooth fade)
|
|
14
|
+
*
|
|
15
|
+
* */
|
|
16
|
+
export declare const simplexNoiseFragmentShader: string;
|
|
17
|
+
export interface SimplexNoiseUniforms extends ShaderSizingUniforms {
|
|
18
|
+
u_colors: vec4[];
|
|
19
|
+
u_colorsCount: number;
|
|
20
|
+
u_stepsPerColor: number;
|
|
21
|
+
u_softness: number;
|
|
22
|
+
}
|
|
23
|
+
export interface SimplexNoiseParams extends ShaderSizingParams, ShaderMotionParams {
|
|
24
|
+
colors?: string[];
|
|
25
|
+
stepsPerColor?: number;
|
|
26
|
+
softness?: number;
|
|
27
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/* * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
2
|
+
* Paper Shaders *
|
|
3
|
+
* https://github.com/paper-design/shaders *
|
|
4
|
+
* * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
5
|
+
|
|
6
|
+
import { sizingVariablesDeclaration } from "../shader-sizing.js";
|
|
7
|
+
import { simplexNoise, colorBandingFix } from "../shader-utils.js";
|
|
8
|
+
const simplexNoiseMeta = {
|
|
9
|
+
maxColorCount: 10
|
|
10
|
+
};
|
|
11
|
+
const simplexNoiseFragmentShader = `#version 300 es
|
|
12
|
+
precision mediump float;
|
|
13
|
+
|
|
14
|
+
uniform float u_time;
|
|
15
|
+
uniform float u_scale;
|
|
16
|
+
|
|
17
|
+
uniform vec4 u_colors[${simplexNoiseMeta.maxColorCount}];
|
|
18
|
+
uniform float u_colorsCount;
|
|
19
|
+
uniform float u_stepsPerColor;
|
|
20
|
+
uniform float u_softness;
|
|
21
|
+
|
|
22
|
+
${sizingVariablesDeclaration}
|
|
23
|
+
|
|
24
|
+
out vec4 fragColor;
|
|
25
|
+
|
|
26
|
+
${simplexNoise}
|
|
27
|
+
|
|
28
|
+
float getNoise(vec2 uv, float t) {
|
|
29
|
+
float noise = .5 * snoise(uv - vec2(0., .3 * t));
|
|
30
|
+
noise += .5 * snoise(2. * uv + vec2(0., .32 * t));
|
|
31
|
+
|
|
32
|
+
return noise;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
float steppedSmooth(float m, float steps, float softness) {
|
|
36
|
+
float stepT = floor(m * steps) / steps;
|
|
37
|
+
float f = m * steps - floor(m * steps);
|
|
38
|
+
float fw = steps * fwidth(m);
|
|
39
|
+
float smoothed = smoothstep(.5 - softness, min(1., .5 + softness + fw), f);
|
|
40
|
+
return stepT + smoothed / steps;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
void main() {
|
|
44
|
+
vec2 shape_uv = v_patternUV;
|
|
45
|
+
shape_uv *= .1;
|
|
46
|
+
|
|
47
|
+
float t = .2 * u_time;
|
|
48
|
+
|
|
49
|
+
float shape = .5 + .5 * getNoise(shape_uv, t);
|
|
50
|
+
|
|
51
|
+
bool u_extraSides = true;
|
|
52
|
+
|
|
53
|
+
float mixer = shape * (u_colorsCount - 1.);
|
|
54
|
+
if (u_extraSides == true) {
|
|
55
|
+
mixer = (shape - .5 / u_colorsCount) * u_colorsCount;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
float steps = max(1., u_stepsPerColor);
|
|
59
|
+
|
|
60
|
+
vec4 gradient = u_colors[0];
|
|
61
|
+
gradient.rgb *= gradient.a;
|
|
62
|
+
for (int i = 1; i < ${simplexNoiseMeta.maxColorCount}; i++) {
|
|
63
|
+
if (i >= int(u_colorsCount)) break;
|
|
64
|
+
|
|
65
|
+
float localM = clamp(mixer - float(i - 1), 0., 1.);
|
|
66
|
+
localM = steppedSmooth(localM, steps, .5 * u_softness);
|
|
67
|
+
|
|
68
|
+
vec4 c = u_colors[i];
|
|
69
|
+
c.rgb *= c.a;
|
|
70
|
+
gradient = mix(gradient, c, localM);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (u_extraSides == true) {
|
|
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
|
+
}
|
|
87
|
+
|
|
88
|
+
vec3 color = gradient.rgb;
|
|
89
|
+
float opacity = gradient.a;
|
|
90
|
+
|
|
91
|
+
${colorBandingFix}
|
|
92
|
+
|
|
93
|
+
fragColor = vec4(color, opacity);
|
|
94
|
+
}
|
|
95
|
+
`;
|
|
96
|
+
export {
|
|
97
|
+
simplexNoiseFragmentShader,
|
|
98
|
+
simplexNoiseMeta
|
|
99
|
+
};
|
|
100
|
+
//# sourceMappingURL=simplex-noise.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/shaders/simplex-noise.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 { simplexNoise, colorBandingFix } from '../shader-utils.js';\n\nexport const simplexNoiseMeta = {\n maxColorCount: 10,\n} as const;\n\n/**\n * Color Gradient mapped over a combination of 2 Simplex noises\n *\n * Uniforms:\n * - u_colors (vec4[]), u_colorsCount (float used as integer)\n * - u_stepsPerColor (float, used as int): discrete color steps between u_colors\n * - u_softness: color transition sharpness (0 = hard edge, 1 = smooth fade)\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\n${sizingVariablesDeclaration}\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,SAAS,kCAAsF;AAC/F,SAAS,cAAc,uBAAuB;AAEvC,MAAM,mBAAmB;AAAA,EAC9B,eAAe;AACjB;AAaO,MAAM,6BAAqC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAM1B,iBAAiB,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA,EAKpD,0BAA0B;AAAA;AAAA;AAAA;AAAA,EAI1B,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAoCU,iBAAiB,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IA6BlD,eAAe;AAAA;AAAA;AAAA;AAAA;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
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 smokeRingMeta: {
|
|
5
|
+
readonly maxColorCount: 10;
|
|
6
|
+
readonly maxNoiseIterations: 8;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* Radial gradient with layered FBM displacement, masked with ring shape
|
|
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
|
+
*
|
|
17
|
+
* - u_noiseTexture (sampler2D): pre-computed randomizer source
|
|
18
|
+
*/
|
|
19
|
+
export declare const smokeRingFragmentShader: string;
|
|
20
|
+
export interface SmokeRingUniforms extends ShaderSizingUniforms {
|
|
21
|
+
u_colorBack: [number, number, number, number];
|
|
22
|
+
u_colors: vec4[];
|
|
23
|
+
u_colorsCount: number;
|
|
24
|
+
u_noiseScale: number;
|
|
25
|
+
u_thickness: number;
|
|
26
|
+
u_radius: number;
|
|
27
|
+
u_innerShape: number;
|
|
28
|
+
u_noiseIterations: number;
|
|
29
|
+
u_noiseTexture?: HTMLImageElement;
|
|
30
|
+
}
|
|
31
|
+
export interface SmokeRingParams extends ShaderSizingParams, ShaderMotionParams {
|
|
32
|
+
colorBack?: string;
|
|
33
|
+
colors?: string[];
|
|
34
|
+
noiseScale?: number;
|
|
35
|
+
thickness?: number;
|
|
36
|
+
radius?: number;
|
|
37
|
+
innerShape?: number;
|
|
38
|
+
noiseIterations?: number;
|
|
39
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/* * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
2
|
+
* Paper Shaders *
|
|
3
|
+
* https://github.com/paper-design/shaders *
|
|
4
|
+
* * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
5
|
+
|
|
6
|
+
import { sizingVariablesDeclaration } from "../shader-sizing.js";
|
|
7
|
+
import { declarePI, textureRandomizerR, colorBandingFix } from "../shader-utils.js";
|
|
8
|
+
const smokeRingMeta = {
|
|
9
|
+
maxColorCount: 10,
|
|
10
|
+
maxNoiseIterations: 8
|
|
11
|
+
};
|
|
12
|
+
const smokeRingFragmentShader = `#version 300 es
|
|
13
|
+
precision mediump float;
|
|
14
|
+
|
|
15
|
+
uniform float u_time;
|
|
16
|
+
|
|
17
|
+
uniform sampler2D u_noiseTexture;
|
|
18
|
+
|
|
19
|
+
uniform vec4 u_colorBack;
|
|
20
|
+
uniform vec4 u_colors[${smokeRingMeta.maxColorCount}];
|
|
21
|
+
uniform float u_colorsCount;
|
|
22
|
+
|
|
23
|
+
uniform float u_thickness;
|
|
24
|
+
uniform float u_radius;
|
|
25
|
+
uniform float u_innerShape;
|
|
26
|
+
uniform float u_noiseScale;
|
|
27
|
+
uniform float u_noiseIterations;
|
|
28
|
+
|
|
29
|
+
${sizingVariablesDeclaration}
|
|
30
|
+
|
|
31
|
+
out vec4 fragColor;
|
|
32
|
+
|
|
33
|
+
${declarePI}
|
|
34
|
+
${textureRandomizerR}
|
|
35
|
+
float valueNoise(vec2 st) {
|
|
36
|
+
vec2 i = floor(st);
|
|
37
|
+
vec2 f = fract(st);
|
|
38
|
+
float a = randomR(i);
|
|
39
|
+
float b = randomR(i + vec2(1.0, 0.0));
|
|
40
|
+
float c = randomR(i + vec2(0.0, 1.0));
|
|
41
|
+
float d = randomR(i + vec2(1.0, 1.0));
|
|
42
|
+
vec2 u = f * f * (3.0 - 2.0 * f);
|
|
43
|
+
float x1 = mix(a, b, u.x);
|
|
44
|
+
float x2 = mix(c, d, u.x);
|
|
45
|
+
return mix(x1, x2, u.y);
|
|
46
|
+
}
|
|
47
|
+
float fbm(in vec2 n) {
|
|
48
|
+
float total = 0.0, amplitude = .4;
|
|
49
|
+
for (int i = 0; i < ${smokeRingMeta.maxNoiseIterations}; i++) {
|
|
50
|
+
if (i >= int(u_noiseIterations)) break;
|
|
51
|
+
total += valueNoise(n) * amplitude;
|
|
52
|
+
n *= 1.99;
|
|
53
|
+
amplitude *= 0.65;
|
|
54
|
+
}
|
|
55
|
+
return total;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
float getNoise(vec2 uv, vec2 pUv, float t) {
|
|
59
|
+
float noiseLeft = fbm(pUv + .03 * t);
|
|
60
|
+
float period = max(abs(u_noiseScale * TWO_PI), 1e-6);
|
|
61
|
+
pUv.x = fract(pUv.x / period) * period;
|
|
62
|
+
float noiseRight = fbm(pUv + .03 * t);
|
|
63
|
+
return mix(noiseRight, noiseLeft, smoothstep(-.25, .25, uv.x));
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
float getRingShape(vec2 uv) {
|
|
67
|
+
float radius = u_radius;
|
|
68
|
+
float thickness = u_thickness;
|
|
69
|
+
|
|
70
|
+
float distance = length(uv);
|
|
71
|
+
float ringValue = 1. - smoothstep(radius, radius + thickness, distance);
|
|
72
|
+
ringValue *= smoothstep(radius - pow(u_innerShape, 3.) * thickness, radius, distance);
|
|
73
|
+
|
|
74
|
+
return ringValue;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
void main() {
|
|
78
|
+
vec2 shape_uv = v_objectUV;
|
|
79
|
+
|
|
80
|
+
float t = u_time;
|
|
81
|
+
|
|
82
|
+
float cycleDuration = 3.;
|
|
83
|
+
float period2 = 2.0 * cycleDuration;
|
|
84
|
+
float localTime1 = fract((0.1 * t + cycleDuration) / period2) * period2;
|
|
85
|
+
float localTime2 = fract((0.1 * t) / period2) * period2;
|
|
86
|
+
float timeBlend = .5 + .5 * sin(.1 * t * PI / cycleDuration - .5 * PI);
|
|
87
|
+
|
|
88
|
+
float atg = atan(shape_uv.y, shape_uv.x) + .001;
|
|
89
|
+
float l = length(shape_uv);
|
|
90
|
+
vec2 polar_uv1 = vec2(atg, localTime1 - (.5 * l) + 1. / pow(max(1e-4, l), .5));
|
|
91
|
+
polar_uv1 *= u_noiseScale;
|
|
92
|
+
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
|
+
float noise2 = getNoise(shape_uv, polar_uv2, t);
|
|
97
|
+
|
|
98
|
+
float noise = mix(noise1, noise2, timeBlend);
|
|
99
|
+
|
|
100
|
+
shape_uv *= (.8 + 1.2 * noise);
|
|
101
|
+
|
|
102
|
+
float ringShape = getRingShape(shape_uv);
|
|
103
|
+
|
|
104
|
+
float mixer = ringShape * ringShape * (u_colorsCount - 1.);
|
|
105
|
+
vec4 gradient = u_colors[int(u_colorsCount) - 1];
|
|
106
|
+
gradient.rgb *= gradient.a;
|
|
107
|
+
for (int i = ${smokeRingMeta.maxColorCount} - 2; i >= 0; i--) {
|
|
108
|
+
float localT = clamp(mixer - float(int(u_colorsCount) - 1 - i - 1), 0., 1.);
|
|
109
|
+
vec4 c = u_colors[i];
|
|
110
|
+
c.rgb *= c.a;
|
|
111
|
+
gradient = mix(gradient, c, localT);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
vec3 color = gradient.rgb * ringShape;
|
|
115
|
+
float opacity = gradient.a * ringShape;
|
|
116
|
+
|
|
117
|
+
vec3 bgColor = u_colorBack.rgb * u_colorBack.a;
|
|
118
|
+
color = color + bgColor * (1. - opacity);
|
|
119
|
+
opacity = opacity + u_colorBack.a * (1. - opacity);
|
|
120
|
+
|
|
121
|
+
${colorBandingFix}
|
|
122
|
+
|
|
123
|
+
fragColor = vec4(color, opacity);
|
|
124
|
+
}
|
|
125
|
+
`;
|
|
126
|
+
export {
|
|
127
|
+
smokeRingFragmentShader,
|
|
128
|
+
smokeRingMeta
|
|
129
|
+
};
|
|
130
|
+
//# sourceMappingURL=smoke-ring.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/shaders/smoke-ring.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, textureRandomizerR, colorBandingFix } from '../shader-utils.js';\n\nexport const smokeRingMeta = {\n maxColorCount: 10,\n maxNoiseIterations: 8,\n} as const;\n\n/**\n * Radial gradient with layered FBM displacement, masked with ring shape\n *\n * Uniforms:\n * - u_colorBack (RGBA)\n * - u_colors (vec4[]), u_colorsCount (float used as integer)\n * - u_thickness, u_radius, u_innerShape: ring mask settings\n * - u_noiseIterations, u_noiseScale: how detailed is the noise (number of fbm layers & noise frequency)\n *\n * - u_noiseTexture (sampler2D): pre-computed randomizer source\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\n${sizingVariablesDeclaration}\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}\nfloat fbm(in vec2 n) {\n float total = 0.0, amplitude = .4;\n for (int i = 0; i < ${smokeRingMeta.maxNoiseIterations}; i++) {\n if (i >= int(u_noiseIterations)) break;\n total += valueNoise(n) * amplitude;\n n *= 1.99;\n amplitude *= 0.65;\n }\n return total;\n}\n\nfloat getNoise(vec2 uv, vec2 pUv, float t) {\n float noiseLeft = fbm(pUv + .03 * t);\n float period = max(abs(u_noiseScale * TWO_PI), 1e-6);\n pUv.x = fract(pUv.x / period) * period;\n float noiseRight = fbm(pUv + .03 * t);\n return mix(noiseRight, noiseLeft, 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 vec2 polar_uv1 = vec2(atg, localTime1 - (.5 * l) + 1. / pow(max(1e-4, l), .5));\n polar_uv1 *= u_noiseScale;\n float noise1 = getNoise(shape_uv, polar_uv1, t);\n\n vec2 polar_uv2 = vec2(atg, localTime2 - (.5 * l) + 1. / pow(max(1e-4, l), .5));\n polar_uv2 *= u_noiseScale;\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 vec4 gradient = u_colors[int(u_colorsCount) - 1];\n gradient.rgb *= gradient.a;\n for (int i = ${smokeRingMeta.maxColorCount} - 2; i >= 0; i--) {\n float localT = clamp(mixer - float(int(u_colorsCount) - 1 - 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,SAAS,kCAAsF;AAC/F,SAAS,WAAW,oBAAoB,uBAAuB;AAExD,MAAM,gBAAgB;AAAA,EAC3B,eAAe;AAAA,EACf,oBAAoB;AACtB;AAeO,MAAM,0BAAkC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAQvB,cAAc,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASjD,0BAA0B;AAAA;AAAA;AAAA;AAAA,EAI1B,SAAS;AAAA,EACT,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAeI,cAAc,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iBA0DvC,cAAc,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAcxC,eAAe;AAAA;AAAA;AAAA;AAAA;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { ShaderMotionParams } from '../shader-mount.js';
|
|
2
|
+
import { type ShaderSizingParams, type ShaderSizingUniforms } from '../shader-sizing.js';
|
|
3
|
+
/**
|
|
4
|
+
* 2-color spiral shape
|
|
5
|
+
*
|
|
6
|
+
* Uniforms:
|
|
7
|
+
* - u_colorBack, u_colorFront (RGBA)
|
|
8
|
+
* - u_density: spacing falloff to simulate radial perspective (0 = no perspective)
|
|
9
|
+
* - u_strokeWidth: thickness of stroke
|
|
10
|
+
* - u_strokeTaper: stroke loosing width further from center (0 for full visibility)
|
|
11
|
+
* - u_distortion: per-arch shift
|
|
12
|
+
* - u_strokeCap: extra width at the center (no effect on u_strokeWidth = 0.5)
|
|
13
|
+
* - u_noiseFrequency, u_noise: simplex noise distortion over the shape
|
|
14
|
+
* - u_softness: color transition sharpness (0 = hard edge, 1 = smooth fade)
|
|
15
|
+
*
|
|
16
|
+
*/
|
|
17
|
+
export declare const spiralFragmentShader: string;
|
|
18
|
+
export interface SpiralUniforms extends ShaderSizingUniforms {
|
|
19
|
+
u_colorBack: [number, number, number, number];
|
|
20
|
+
u_colorFront: [number, number, number, number];
|
|
21
|
+
u_density: number;
|
|
22
|
+
u_distortion: number;
|
|
23
|
+
u_strokeWidth: number;
|
|
24
|
+
u_strokeTaper: number;
|
|
25
|
+
u_strokeCap: number;
|
|
26
|
+
u_noise: number;
|
|
27
|
+
u_noiseFrequency: number;
|
|
28
|
+
u_softness: number;
|
|
29
|
+
}
|
|
30
|
+
export interface SpiralParams extends ShaderSizingParams, ShaderMotionParams {
|
|
31
|
+
colorBack?: string;
|
|
32
|
+
colorFront?: string;
|
|
33
|
+
density?: number;
|
|
34
|
+
distortion?: number;
|
|
35
|
+
strokeWidth?: number;
|
|
36
|
+
strokeTaper?: number;
|
|
37
|
+
strokeCap?: number;
|
|
38
|
+
noise?: number;
|
|
39
|
+
noiseFrequency?: number;
|
|
40
|
+
softness?: number;
|
|
41
|
+
}
|