@paper-design/shaders 0.0.26 → 0.0.28
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/get-shader-color-from-string.d.ts +1 -1
- 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 +23 -0
- package/dist/get-shader-noise-texture.js.map +7 -0
- package/dist/index.d.ts +30 -16
- package/dist/index.js +79 -1767
- package/dist/index.js.map +4 -4
- 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 +48 -17
- package/dist/shader-mount.js +568 -0
- package/dist/shader-mount.js.map +7 -0
- package/dist/shader-sizing.d.ts +35 -0
- package/dist/shader-sizing.js +196 -0
- package/dist/shader-sizing.js.map +7 -0
- package/dist/shader-utils.d.ts +5 -0
- package/dist/shader-utils.js +59 -0
- package/dist/shader-utils.js.map +7 -0
- package/dist/shaders/dithering.d.ts +47 -0
- package/dist/shaders/dithering.js +197 -0
- package/dist/shaders/dithering.js.map +7 -0
- package/dist/shaders/dot-grid.d.ts +35 -22
- package/dist/shaders/dot-grid.js +100 -0
- package/dist/shaders/dot-grid.js.map +7 -0
- package/dist/shaders/dot-orbit.d.ts +27 -18
- package/dist/shaders/dot-orbit.js +120 -0
- package/dist/shaders/dot-orbit.js.map +7 -0
- package/dist/shaders/god-rays.d.ts +35 -26
- package/dist/shaders/god-rays.js +134 -0
- package/dist/shaders/god-rays.js.map +7 -0
- package/dist/shaders/grain-gradient.d.ts +25 -0
- package/dist/shaders/grain-gradient.js +219 -0
- package/dist/shaders/grain-gradient.js.map +7 -0
- package/dist/shaders/liquid-metal.d.ts +19 -0
- package/dist/shaders/liquid-metal.js +224 -0
- package/dist/shaders/liquid-metal.js.map +7 -0
- package/dist/shaders/mesh-gradient.d.ts +23 -13
- package/dist/shaders/mesh-gradient.js +97 -0
- package/dist/shaders/mesh-gradient.js.map +7 -0
- package/dist/shaders/metaballs.d.ts +22 -15
- package/dist/shaders/metaballs.js +109 -0
- package/dist/shaders/metaballs.js.map +7 -0
- package/dist/shaders/neuro-noise.d.ts +13 -8
- package/dist/shaders/neuro-noise.js +66 -0
- package/dist/shaders/neuro-noise.js.map +7 -0
- package/dist/shaders/perlin-noise.d.ts +26 -15
- package/dist/shaders/perlin-noise.js +193 -0
- package/dist/shaders/perlin-noise.js.map +7 -0
- package/dist/shaders/pulsing-border.d.ts +54 -0
- package/dist/shaders/pulsing-border.js +218 -0
- package/dist/shaders/pulsing-border.js.map +7 -0
- package/dist/shaders/simplex-noise.d.ts +29 -0
- package/dist/shaders/simplex-noise.js +103 -0
- package/dist/shaders/simplex-noise.js.map +7 -0
- package/dist/shaders/smoke-ring.d.ts +34 -12
- package/dist/shaders/smoke-ring.js +141 -0
- package/dist/shaders/smoke-ring.js.map +7 -0
- package/dist/shaders/spiral.d.ts +31 -21
- package/dist/shaders/spiral.js +75 -0
- package/dist/shaders/spiral.js.map +7 -0
- package/dist/shaders/swirl.d.ts +26 -0
- package/dist/shaders/swirl.js +80 -0
- package/dist/shaders/swirl.js.map +7 -0
- package/dist/shaders/voronoi.d.ts +39 -29
- package/dist/shaders/voronoi.js +143 -0
- package/dist/shaders/voronoi.js.map +7 -0
- package/dist/shaders/warp.d.ts +43 -32
- package/dist/shaders/warp.js +124 -0
- package/dist/shaders/warp.js.map +7 -0
- package/dist/shaders/waves.d.ts +26 -16
- package/dist/shaders/waves.js +60 -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/package.json +2 -1
- package/dist/get-shader-color-from-string.test.d.ts +0 -1
- package/dist/shaders/stepped-simplex-noise.d.ts +0 -24
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
/* * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
2
|
+
* Paper Shaders *
|
|
3
|
+
* https://github.com/paper-design/shaders *
|
|
4
|
+
* * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
5
|
+
|
|
6
|
+
import { sizingVariablesDeclaration } from "../shader-sizing";
|
|
7
|
+
import { declarePI, colorBandingFix } from "../shader-utils";
|
|
8
|
+
const pulsingBorderMeta = {
|
|
9
|
+
maxColorCount: 5,
|
|
10
|
+
maxSpotsPerColor: 5
|
|
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_softness;
|
|
23
|
+
uniform float u_intensity;
|
|
24
|
+
uniform float u_spotSize;
|
|
25
|
+
uniform float u_spotsPerColor;
|
|
26
|
+
uniform float u_pulse;
|
|
27
|
+
uniform float u_smoke;
|
|
28
|
+
uniform float u_smokeSize;
|
|
29
|
+
|
|
30
|
+
uniform sampler2D u_pulseTexture;
|
|
31
|
+
uniform sampler2D u_noiseTexture;
|
|
32
|
+
|
|
33
|
+
${sizingVariablesDeclaration}
|
|
34
|
+
|
|
35
|
+
out vec4 fragColor;
|
|
36
|
+
|
|
37
|
+
${declarePI}
|
|
38
|
+
|
|
39
|
+
float roundedBox(vec2 uv, vec2 halfSize, float radius, float distance, float edgeSoftness) {
|
|
40
|
+
|
|
41
|
+
float borderDistance = abs(distance) - .5 * u_thickness;
|
|
42
|
+
float border = 1. - smoothstep(-.5 * edgeSoftness, .5 * edgeSoftness, borderDistance);
|
|
43
|
+
border *= border;
|
|
44
|
+
|
|
45
|
+
vec2 v0 = uv + halfSize;
|
|
46
|
+
vec2 v1 = uv - vec2(-halfSize.x, halfSize.y);
|
|
47
|
+
vec2 v2 = uv - vec2(halfSize.x, -halfSize.y);
|
|
48
|
+
vec2 v3 = uv - halfSize;
|
|
49
|
+
|
|
50
|
+
float mult = (.07 - .25 * radius);
|
|
51
|
+
float m0 = mult * clamp(pow(1. - abs(v0.x - v0.y), 20.), 0., 1.);
|
|
52
|
+
float m1 = mult * clamp(pow(1. - abs(v1.x + v1.y), 20.), 0., 1.);
|
|
53
|
+
float m2 = mult * clamp(pow(1. - abs(v2.x + v2.y), 20.), 0., 1.);
|
|
54
|
+
float m3 = mult * clamp(pow(1. - abs(v3.x - v3.y), 20.), 0., 1.);
|
|
55
|
+
|
|
56
|
+
float l = edgeSoftness * .5 + .75 * u_thickness;
|
|
57
|
+
float fade0 = 1. - clamp(length(v0) / l, 0., 1.);
|
|
58
|
+
float fade1 = 1. - clamp(length(v1) / l, 0., 1.);
|
|
59
|
+
float fade2 = 1. - clamp(length(v2) / l, 0., 1.);
|
|
60
|
+
float fade3 = 1. - clamp(length(v3) / l, 0., 1.);
|
|
61
|
+
|
|
62
|
+
m0 *= fade0;
|
|
63
|
+
m1 *= fade1;
|
|
64
|
+
m2 *= fade2;
|
|
65
|
+
m3 *= fade3;
|
|
66
|
+
|
|
67
|
+
float fillFix = m0 + m1 + m2 + m3;
|
|
68
|
+
fillFix *= step(distance, 0.);
|
|
69
|
+
fillFix *= (1. + 3. * u_thickness);
|
|
70
|
+
fillFix *= (1.5 - .5 * smoothstep(0., .5, edgeSoftness));
|
|
71
|
+
fillFix = clamp(fillFix, 0., 1.);
|
|
72
|
+
|
|
73
|
+
return border + fillFix;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
float roundedBoxSmoke(vec2 uv, vec2 halfSize, float radius, float distance, float size) {
|
|
77
|
+
float borderDistance = abs(distance);
|
|
78
|
+
float border = 1. - smoothstep(-.75 * size, .75 * size, borderDistance);
|
|
79
|
+
border *= border;
|
|
80
|
+
|
|
81
|
+
vec2 v0 = uv + halfSize;
|
|
82
|
+
vec2 v1 = uv - vec2(-halfSize.x, halfSize.y);
|
|
83
|
+
vec2 v2 = uv - vec2(halfSize.x, -halfSize.y);
|
|
84
|
+
vec2 v3 = uv - halfSize;
|
|
85
|
+
|
|
86
|
+
float l_mask = .5;
|
|
87
|
+
float mask = smoothstep(0., 1., length(v0) / l_mask);
|
|
88
|
+
mask *= smoothstep(0., 1., length(v1) / l_mask);
|
|
89
|
+
mask *= smoothstep(0., 1., length(v2) / l_mask);
|
|
90
|
+
mask *= smoothstep(0., 1., length(v3) / l_mask);
|
|
91
|
+
|
|
92
|
+
return border * mask;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
vec2 rand(vec2 p) {
|
|
96
|
+
vec2 uv = floor(p) / 100. + .5;
|
|
97
|
+
return texture(u_noiseTexture, uv).gb;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
float noise(vec2 st) {
|
|
101
|
+
vec2 i = floor(st);
|
|
102
|
+
vec2 f = fract(st);
|
|
103
|
+
float a = rand(i).x;
|
|
104
|
+
float b = rand(i + vec2(1.0, 0.0)).x;
|
|
105
|
+
float c = rand(i + vec2(0.0, 1.0)).x;
|
|
106
|
+
float d = rand(i + vec2(1.0, 1.0)).x;
|
|
107
|
+
vec2 u = f * f * (3.0 - 2.0 * f);
|
|
108
|
+
float x1 = mix(a, b, u.x);
|
|
109
|
+
float x2 = mix(c, d, u.x);
|
|
110
|
+
return mix(x1, x2, u.y);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
float getWaveformValue(float time) {
|
|
114
|
+
float dur = 5.;
|
|
115
|
+
float wrappedTime = mod(time, dur);
|
|
116
|
+
float normalizedTime = wrappedTime / dur;
|
|
117
|
+
float value = texture(u_pulseTexture, vec2(normalizedTime, 0.5)).r;
|
|
118
|
+
return value * 2. - 1.;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
void main() {
|
|
122
|
+
|
|
123
|
+
float t = .5 * u_time + 20.;
|
|
124
|
+
|
|
125
|
+
vec2 borderUV = v_responsiveUV;
|
|
126
|
+
|
|
127
|
+
float angle = atan(borderUV.y, borderUV.x) / TWO_PI;
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
float borderRatio = v_responsiveBoxGivenSize.x / v_responsiveBoxGivenSize.y;
|
|
131
|
+
borderUV.x *= borderRatio;
|
|
132
|
+
vec2 halfSize = vec2(.5);
|
|
133
|
+
halfSize.x *= borderRatio;
|
|
134
|
+
float radius = min(.5 * u_roundness, halfSize.x);
|
|
135
|
+
vec2 d = abs(borderUV) - halfSize + radius;
|
|
136
|
+
float outsideDistance = length(max(d, 0.)) - radius;
|
|
137
|
+
float insideDistance = min(max(d.x, d.y), 0.0);
|
|
138
|
+
float distance = outsideDistance + insideDistance;
|
|
139
|
+
|
|
140
|
+
float border = roundedBox(borderUV, halfSize, radius, distance, .5 * u_softness);
|
|
141
|
+
|
|
142
|
+
float pulse = u_pulse * getWaveformValue(.18 * u_time);
|
|
143
|
+
|
|
144
|
+
border *= (1. + .1 * pulse);
|
|
145
|
+
border *= (1. + u_intensity);
|
|
146
|
+
|
|
147
|
+
vec2 smokeUV = .001 * u_smokeSize * v_patternUV;
|
|
148
|
+
float smoke = clamp(3. * noise(2.7 * smokeUV + .5 * t), 0., 1.);
|
|
149
|
+
smoke -= noise(3.4 * smokeUV - .5 * t);
|
|
150
|
+
smoke *= roundedBoxSmoke(borderUV, halfSize, radius, distance, u_smoke);
|
|
151
|
+
smoke = 50. * pow(smoke, 2.);
|
|
152
|
+
smoke *= u_smoke;
|
|
153
|
+
smoke *= (.8 + .4 * pulse);
|
|
154
|
+
smoke = clamp(smoke, 0., 1.);
|
|
155
|
+
|
|
156
|
+
border += smoke;
|
|
157
|
+
|
|
158
|
+
float sectorsTotal = 0.;
|
|
159
|
+
|
|
160
|
+
vec3 color = vec3(0.);
|
|
161
|
+
float opacity = 0.;
|
|
162
|
+
|
|
163
|
+
vec3 accumColor = vec3(0.);
|
|
164
|
+
float accumAlpha = 0.;
|
|
165
|
+
|
|
166
|
+
for (int i = 0; i < ${pulsingBorderMeta.maxSpotsPerColor}; i++) {
|
|
167
|
+
if (i >= int(u_spotsPerColor)) break;
|
|
168
|
+
float idx = float(i);
|
|
169
|
+
|
|
170
|
+
for (int j = 0; j < ${pulsingBorderMeta.maxColorCount}; j++) {
|
|
171
|
+
if (j >= int(u_colorsCount)) break;
|
|
172
|
+
float colorIdx = float(j);
|
|
173
|
+
|
|
174
|
+
vec2 randVal = rand(vec2(idx * 10. + 2., 40. + colorIdx));
|
|
175
|
+
|
|
176
|
+
float time = (.1 + .15 * abs(sin(idx * (2. + colorIdx)) * cos(idx * (2. + 2.5 * colorIdx)))) * t + randVal.x * 3.;
|
|
177
|
+
time *= mix(1., -1., step(.5, randVal.y));
|
|
178
|
+
|
|
179
|
+
float mask = .2 + mix(
|
|
180
|
+
sin(t + idx * (5. - 1.5 * colorIdx)),
|
|
181
|
+
cos(t + idx * (3. + 1.3 * colorIdx)),
|
|
182
|
+
step(mod(colorIdx, 2.), .5)
|
|
183
|
+
);
|
|
184
|
+
|
|
185
|
+
mask += pulse;
|
|
186
|
+
if (mask < 0.) continue;
|
|
187
|
+
|
|
188
|
+
float atg1 = fract(angle + time);
|
|
189
|
+
float sector = smoothstep(.5 - u_spotSize, .5, atg1) * smoothstep(.5 + u_spotSize, .5, atg1);
|
|
190
|
+
sector *= border;
|
|
191
|
+
sector *= mask;
|
|
192
|
+
sector = clamp(sector, 0., 1.);
|
|
193
|
+
|
|
194
|
+
sectorsTotal += sector;
|
|
195
|
+
|
|
196
|
+
float alpha = sector * u_colors[j].a;
|
|
197
|
+
accumColor += u_colors[j].rgb * alpha;
|
|
198
|
+
accumAlpha += alpha;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
color = accumColor;
|
|
203
|
+
opacity = clamp(accumAlpha, 0., 1.);
|
|
204
|
+
|
|
205
|
+
vec3 bgColor = u_colorBack.rgb * u_colorBack.a;
|
|
206
|
+
color = color + bgColor * (1. - opacity);
|
|
207
|
+
opacity = opacity + u_colorBack.a * (1. - opacity);
|
|
208
|
+
|
|
209
|
+
${colorBandingFix}
|
|
210
|
+
|
|
211
|
+
fragColor = vec4(color, opacity);
|
|
212
|
+
}
|
|
213
|
+
`;
|
|
214
|
+
export {
|
|
215
|
+
pulsingBorderFragmentShader,
|
|
216
|
+
pulsingBorderMeta
|
|
217
|
+
};
|
|
218
|
+
//# 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';\nimport type { ShaderMotionParams } from '../shader-mount';\nimport { sizingVariablesDeclaration, type ShaderSizingParams, type ShaderSizingUniforms } from '../shader-sizing';\nimport { declarePI, colorBandingFix } from '../shader-utils';\n\nexport const pulsingBorderMeta = {\n maxColorCount: 5,\n maxSpotsPerColor: 5,\n} as const;\n\n/**\n * Pulsing Border Pattern with Smoke Effect\n * This shader creates a rounded border mask with multiple color spots\n * traveling along the border\n *\n * Uniforms include:\n * u_colorBack - The background color of the pattern\n * u_colors - An array of colors for the pulsing spots (with up to `u_colorsCount` entries)\n * u_colorsCount - The number of colors used in the pattern\n * u_roundness - The roundness of the border corners\n * u_thickness - The thickness of the border\n * u_softness - The blur around the border edges\n * u_intensity - The intensity multiplier for the pulsing effect\n * u_spotSize - The size of the color spots\n * u_spotsPerColor - The number of spots for each color (not all the spots are visible all the time)\n * u_pulse - A multiplier for the pulsing strength (pulsing signal taken from the u_pulseTexture)\n * u_smoke - The strength of the smoke effect (the noise aroung the border)\n */\n\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_softness;\nuniform float u_intensity;\nuniform float u_spotSize;\nuniform float u_spotsPerColor;\nuniform float u_pulse;\nuniform float u_smoke;\nuniform float u_smokeSize;\n\nuniform sampler2D u_pulseTexture;\nuniform sampler2D u_noiseTexture;\n\n${sizingVariablesDeclaration}\n\nout vec4 fragColor;\n\n${declarePI}\n\nfloat roundedBox(vec2 uv, vec2 halfSize, float radius, float distance, float edgeSoftness) {\n \n float borderDistance = abs(distance) - .5 * u_thickness;\n float border = 1. - smoothstep(-.5 * edgeSoftness, .5 * edgeSoftness, borderDistance);\n border *= border;\n\n vec2 v0 = uv + halfSize;\n vec2 v1 = uv - vec2(-halfSize.x, halfSize.y);\n vec2 v2 = uv - vec2(halfSize.x, -halfSize.y);\n vec2 v3 = uv - halfSize;\n \n float mult = (.07 - .25 * radius);\n float m0 = mult * clamp(pow(1. - abs(v0.x - v0.y), 20.), 0., 1.);\n float m1 = mult * clamp(pow(1. - abs(v1.x + v1.y), 20.), 0., 1.);\n float m2 = mult * clamp(pow(1. - abs(v2.x + v2.y), 20.), 0., 1.);\n float m3 = mult * clamp(pow(1. - abs(v3.x - v3.y), 20.), 0., 1.);\n \n float l = edgeSoftness * .5 + .75 * u_thickness;\n float fade0 = 1. - clamp(length(v0) / l, 0., 1.);\n float fade1 = 1. - clamp(length(v1) / l, 0., 1.);\n float fade2 = 1. - clamp(length(v2) / l, 0., 1.);\n float fade3 = 1. - clamp(length(v3) / l, 0., 1.);\n \n m0 *= fade0;\n m1 *= fade1;\n m2 *= fade2;\n m3 *= fade3;\n \n float fillFix = m0 + m1 + m2 + m3;\n fillFix *= step(distance, 0.);\n fillFix *= (1. + 3. * u_thickness);\n fillFix *= (1.5 - .5 * smoothstep(0., .5, edgeSoftness));\n fillFix = clamp(fillFix, 0., 1.);\n\n return border + fillFix;\n}\n\nfloat roundedBoxSmoke(vec2 uv, vec2 halfSize, float radius, float distance, float size) {\n float borderDistance = abs(distance);\n float border = 1. - smoothstep(-.75 * size, .75 * size, borderDistance);\n border *= border;\n\n vec2 v0 = uv + halfSize;\n vec2 v1 = uv - vec2(-halfSize.x, halfSize.y);\n vec2 v2 = uv - vec2(halfSize.x, -halfSize.y);\n vec2 v3 = uv - halfSize;\n \n float l_mask = .5;\n float mask = smoothstep(0., 1., length(v0) / l_mask);\n mask *= smoothstep(0., 1., length(v1) / l_mask);\n mask *= smoothstep(0., 1., length(v2) / l_mask);\n mask *= smoothstep(0., 1., length(v3) / l_mask);\n\n return border * mask;\n}\n\nvec2 rand(vec2 p) {\n vec2 uv = floor(p) / 100. + .5;\n return texture(u_noiseTexture, uv).gb;\n}\n\nfloat noise(vec2 st) {\n vec2 i = floor(st);\n vec2 f = fract(st);\n float a = rand(i).x;\n float b = rand(i + vec2(1.0, 0.0)).x;\n float c = rand(i + vec2(0.0, 1.0)).x;\n float d = rand(i + vec2(1.0, 1.0)).x;\n vec2 u = f * f * (3.0 - 2.0 * f);\n float x1 = mix(a, b, u.x);\n float x2 = mix(c, d, u.x);\n return mix(x1, x2, u.y);\n}\n\nfloat getWaveformValue(float time) {\n float dur = 5.;\n float wrappedTime = mod(time, dur);\n float normalizedTime = wrappedTime / dur;\n float value = texture(u_pulseTexture, vec2(normalizedTime, 0.5)).r;\n return value * 2. - 1.;\n}\n\nvoid main() {\n\n float t = .5 * u_time + 20.;\n \n vec2 borderUV = v_responsiveUV;\n\n float angle = atan(borderUV.y, borderUV.x) / TWO_PI;\n \n \n float borderRatio = v_responsiveBoxGivenSize.x / v_responsiveBoxGivenSize.y;\n borderUV.x *= borderRatio;\n vec2 halfSize = vec2(.5);\n halfSize.x *= borderRatio;\n float radius = min(.5 * u_roundness, halfSize.x);\n vec2 d = abs(borderUV) - halfSize + radius;\n float outsideDistance = length(max(d, 0.)) - radius;\n float insideDistance = min(max(d.x, d.y), 0.0);\n float distance = outsideDistance + insideDistance;\n \n float border = roundedBox(borderUV, halfSize, radius, distance, .5 * u_softness);\n\n float pulse = u_pulse * getWaveformValue(.18 * u_time);\n \n border *= (1. + .1 * pulse);\n border *= (1. + u_intensity);\n\n vec2 smokeUV = .001 * u_smokeSize * v_patternUV;\n float smoke = clamp(3. * noise(2.7 * smokeUV + .5 * t), 0., 1.);\n smoke -= noise(3.4 * smokeUV - .5 * t);\n smoke *= roundedBoxSmoke(borderUV, halfSize, radius, distance, u_smoke);\n smoke = 50. * pow(smoke, 2.);\n smoke *= u_smoke;\n smoke *= (.8 + .4 * pulse);\n smoke = clamp(smoke, 0., 1.);\n\n border += smoke;\n\n float sectorsTotal = 0.;\n\n vec3 color = vec3(0.);\n float opacity = 0.;\n \n vec3 accumColor = vec3(0.);\n float accumAlpha = 0.;\n \n for (int i = 0; i < ${pulsingBorderMeta.maxSpotsPerColor}; i++) {\n if (i >= int(u_spotsPerColor)) break;\n float idx = float(i);\n \n for (int j = 0; j < ${pulsingBorderMeta.maxColorCount}; j++) {\n if (j >= int(u_colorsCount)) break;\n float colorIdx = float(j);\n\n vec2 randVal = rand(vec2(idx * 10. + 2., 40. + colorIdx));\n \n float time = (.1 + .15 * abs(sin(idx * (2. + colorIdx)) * cos(idx * (2. + 2.5 * colorIdx)))) * t + randVal.x * 3.;\n time *= mix(1., -1., step(.5, randVal.y));\n \n float mask = .2 + mix(\n sin(t + idx * (5. - 1.5 * colorIdx)),\n cos(t + idx * (3. + 1.3 * colorIdx)),\n step(mod(colorIdx, 2.), .5)\n );\n \n mask += pulse;\n if (mask < 0.) continue;\n \n float atg1 = fract(angle + time);\n float sector = smoothstep(.5 - u_spotSize, .5, atg1) * smoothstep(.5 + u_spotSize, .5, atg1);\n sector *= border;\n sector *= mask;\n sector = clamp(sector, 0., 1.);\n \n sectorsTotal += sector;\n \n float alpha = sector * u_colors[j].a;\n accumColor += u_colors[j].rgb * alpha;\n accumAlpha += alpha;\n }\n }\n \n color = accumColor;\n opacity = clamp(accumAlpha, 0., 1.);\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 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_softness: number;\n u_intensity: number;\n u_spotsPerColor: number;\n u_spotSize: number;\n u_pulse: number;\n u_smoke: number;\n u_smokeSize: number;\n u_pulseTexture?: HTMLImageElement;\n}\n\nexport interface PulsingBorderParams extends ShaderSizingParams, ShaderMotionParams {\n colorBack?: string;\n colors?: string[];\n roundness?: number;\n thickness?: number;\n softness?: number;\n intensity?: number;\n spotsPerColor?: number;\n spotSize?: number;\n pulse?: number;\n smoke?: number;\n smokeSize?: number;\n}\n"],
|
|
5
|
+
"mappings": ";;;;;AAEA,SAAS,kCAAsF;AAC/F,SAAS,WAAW,uBAAuB;AAEpC,MAAM,oBAAoB;AAAA,EAC/B,eAAe;AAAA,EACf,kBAAkB;AACpB;AAqBO,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,EAerD,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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAiIa,kBAAkB,gBAAgB;AAAA;AAAA;AAAA;AAAA,0BAIhC,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,IAuCrD,eAAe;AAAA;AAAA;AAAA;AAAA;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { vec4 } from '../types';
|
|
2
|
+
import type { ShaderMotionParams } from '../shader-mount';
|
|
3
|
+
import { type ShaderSizingParams, type ShaderSizingUniforms } from '../shader-sizing';
|
|
4
|
+
export declare const simplexNoiseMeta: {
|
|
5
|
+
readonly maxColorCount: 10;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* Simplex Noise animation by Ksenia Kondrashova
|
|
9
|
+
* Calculates a combination of 2 simplex noises with result mapped as
|
|
10
|
+
* a gradient with dynamic number of main colors and steps between them
|
|
11
|
+
*
|
|
12
|
+
* Uniforms include:
|
|
13
|
+
* - u_colors (vec4[]): Input RGBA colors
|
|
14
|
+
* - u_colorsCount (float): Number of active colors (`u_colors` length)
|
|
15
|
+
* - u_stepsPerColor (float, used as int): Number of rendered colors per input color
|
|
16
|
+
* - u_softness (float, 0..1): Amount of blur applied to the color steps
|
|
17
|
+
*/
|
|
18
|
+
export declare const simplexNoiseFragmentShader: string;
|
|
19
|
+
export interface SimplexNoiseUniforms extends ShaderSizingUniforms {
|
|
20
|
+
u_colors: vec4[];
|
|
21
|
+
u_colorsCount: number;
|
|
22
|
+
u_stepsPerColor: number;
|
|
23
|
+
u_softness: number;
|
|
24
|
+
}
|
|
25
|
+
export interface SimplexNoiseParams extends ShaderSizingParams, ShaderMotionParams {
|
|
26
|
+
colors?: string[];
|
|
27
|
+
stepsPerColor?: number;
|
|
28
|
+
softness?: number;
|
|
29
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/* * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
2
|
+
* Paper Shaders *
|
|
3
|
+
* https://github.com/paper-design/shaders *
|
|
4
|
+
* * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
5
|
+
|
|
6
|
+
import { sizingVariablesDeclaration } from "../shader-sizing";
|
|
7
|
+
import { declareSimplexNoise, colorBandingFix } from "../shader-utils";
|
|
8
|
+
const simplexNoiseMeta = {
|
|
9
|
+
maxColorCount: 10
|
|
10
|
+
};
|
|
11
|
+
const simplexNoiseFragmentShader = `#version 300 es
|
|
12
|
+
precision highp 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
|
+
${declareSimplexNoise}
|
|
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 t, float steps, float softness) {
|
|
36
|
+
float stepT = floor(t * steps) / steps;
|
|
37
|
+
float f = t * steps - floor(t * steps);
|
|
38
|
+
|
|
39
|
+
float fw = 0.005 / u_scale;
|
|
40
|
+
float smoothed = smoothstep(.5 - softness * .5 - fw, .5 + softness * .5 + fw, f);
|
|
41
|
+
|
|
42
|
+
return stepT + smoothed / steps;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
void main() {
|
|
46
|
+
vec2 shape_uv = v_patternUV;
|
|
47
|
+
|
|
48
|
+
shape_uv *= .001;
|
|
49
|
+
|
|
50
|
+
float t = .2 * u_time;
|
|
51
|
+
|
|
52
|
+
float shape = .5 + .5 * getNoise(shape_uv, t);
|
|
53
|
+
|
|
54
|
+
bool u_extraSides = true;
|
|
55
|
+
|
|
56
|
+
float mixer = shape * (u_colorsCount - 1.);
|
|
57
|
+
if (u_extraSides == true) {
|
|
58
|
+
mixer = (shape - .5 / u_colorsCount) * u_colorsCount;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
float steps = max(1., u_stepsPerColor);
|
|
62
|
+
|
|
63
|
+
vec4 gradient = u_colors[0];
|
|
64
|
+
gradient.rgb *= gradient.a;
|
|
65
|
+
for (int i = 1; i < ${simplexNoiseMeta.maxColorCount}; i++) {
|
|
66
|
+
if (i >= int(u_colorsCount)) break;
|
|
67
|
+
|
|
68
|
+
float localT = clamp(mixer - float(i - 1), 0., 1.);
|
|
69
|
+
localT = steppedSmooth(localT, steps, u_softness);
|
|
70
|
+
|
|
71
|
+
vec4 c = u_colors[i];
|
|
72
|
+
c.rgb *= c.a;
|
|
73
|
+
gradient = mix(gradient, c, localT);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (u_extraSides == true) {
|
|
77
|
+
if ((mixer < 0.) || (mixer > (u_colorsCount - 1.))) {
|
|
78
|
+
float localT = mixer + 1.;
|
|
79
|
+
if (mixer > (u_colorsCount - 1.)) {
|
|
80
|
+
localT = mixer - (u_colorsCount - 1.);
|
|
81
|
+
}
|
|
82
|
+
localT = steppedSmooth(localT, steps, u_softness);
|
|
83
|
+
vec4 cFst = u_colors[0];
|
|
84
|
+
cFst.rgb *= cFst.a;
|
|
85
|
+
vec4 cLast = u_colors[int(u_colorsCount - 1.)];
|
|
86
|
+
cLast.rgb *= cLast.a;
|
|
87
|
+
gradient = mix(cLast, cFst, localT);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
vec3 color = gradient.rgb;
|
|
92
|
+
float opacity = gradient.a;
|
|
93
|
+
|
|
94
|
+
${colorBandingFix}
|
|
95
|
+
|
|
96
|
+
fragColor = vec4(color, opacity);
|
|
97
|
+
}
|
|
98
|
+
`;
|
|
99
|
+
export {
|
|
100
|
+
simplexNoiseFragmentShader,
|
|
101
|
+
simplexNoiseMeta
|
|
102
|
+
};
|
|
103
|
+
//# 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';\nimport type { ShaderMotionParams } from '../shader-mount';\nimport { sizingVariablesDeclaration, type ShaderSizingParams, type ShaderSizingUniforms } from '../shader-sizing';\nimport { declareSimplexNoise, colorBandingFix } from '../shader-utils';\n\nexport const simplexNoiseMeta = {\n maxColorCount: 10,\n} as const;\n\n/**\n * Simplex Noise animation by Ksenia Kondrashova\n * Calculates a combination of 2 simplex noises with result mapped as\n * a gradient with dynamic number of main colors and steps between them\n *\n * Uniforms include:\n * - u_colors (vec4[]): Input RGBA colors\n * - u_colorsCount (float): Number of active colors (`u_colors` length)\n * - u_stepsPerColor (float, used as int): Number of rendered colors per input color\n * - u_softness (float, 0..1): Amount of blur applied to the color steps\n */\nexport const simplexNoiseFragmentShader: string = `#version 300 es\nprecision highp 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${declareSimplexNoise}\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 t, float steps, float softness) {\n float stepT = floor(t * steps) / steps;\n float f = t * steps - floor(t * steps);\n \n float fw = 0.005 / u_scale;\n float smoothed = smoothstep(.5 - softness * .5 - fw, .5 + softness * .5 + fw, f);\n \n return stepT + smoothed / steps;\n}\n\nvoid main() {\n vec2 shape_uv = v_patternUV;\n\n shape_uv *= .001;\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 localT = clamp(mixer - float(i - 1), 0., 1.);\n localT = steppedSmooth(localT, steps, u_softness); \n \n vec4 c = u_colors[i];\n c.rgb *= c.a;\n gradient = mix(gradient, c, localT);\n }\n \n if (u_extraSides == true) {\n if ((mixer < 0.) || (mixer > (u_colorsCount - 1.))) {\n float localT = mixer + 1.;\n if (mixer > (u_colorsCount - 1.)) {\n localT = mixer - (u_colorsCount - 1.);\n }\n localT = steppedSmooth(localT, steps, 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, localT);\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,qBAAqB,uBAAuB;AAE9C,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,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,wBAuCG,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
|
+
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import type { vec4 } from '../types';
|
|
2
|
+
import type { ShaderMotionParams } from '../shader-mount';
|
|
3
|
+
import { type ShaderSizingParams, type ShaderSizingUniforms } from '../shader-sizing';
|
|
4
|
+
export declare const smokeRingMeta: {
|
|
5
|
+
readonly maxColorCount: 10;
|
|
6
|
+
readonly maxNoiseIterations: 8;
|
|
7
7
|
};
|
|
8
8
|
/**
|
|
9
9
|
* Smoke Ring by Ksenia Kondrashova
|
|
@@ -11,10 +11,32 @@ export type SmokeRingUniforms = {
|
|
|
11
11
|
* polar coordinates masked with ring shape
|
|
12
12
|
*
|
|
13
13
|
* Uniforms include:
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
14
|
+
* - u_colorBack: the background color of the scene
|
|
15
|
+
* - uColors (vec4[]): Input RGBA colors
|
|
16
|
+
* - uColorsCount (float): Number of active colors (`uColors` length) * u_noiseScale - the resolution of noise texture
|
|
17
|
+
* - u_thickness (float): the thickness of the ring
|
|
18
|
+
* - u_radius (float): the radius of the ring (u_radius = 0.5 to fit in contain mode)
|
|
19
|
+
* - u_innerShape (float): if we fill the shape inside the radius (u_innerShape = 1 to render only the thickness)
|
|
20
|
+
* - u_noiseIterations (float): how detailed is the noise (number of fbm layers)
|
|
19
21
|
*/
|
|
20
|
-
export declare const smokeRingFragmentShader
|
|
22
|
+
export declare const smokeRingFragmentShader: string;
|
|
23
|
+
export interface SmokeRingUniforms extends ShaderSizingUniforms {
|
|
24
|
+
u_colorBack: [number, number, number, number];
|
|
25
|
+
u_colors: vec4[];
|
|
26
|
+
u_colorsCount: number;
|
|
27
|
+
u_noiseScale: number;
|
|
28
|
+
u_thickness: number;
|
|
29
|
+
u_radius: number;
|
|
30
|
+
u_innerShape: number;
|
|
31
|
+
u_noiseIterations: number;
|
|
32
|
+
u_noiseTexture?: HTMLImageElement;
|
|
33
|
+
}
|
|
34
|
+
export interface SmokeRingParams extends ShaderSizingParams, ShaderMotionParams {
|
|
35
|
+
colorBack?: string;
|
|
36
|
+
colors?: string[];
|
|
37
|
+
noiseScale?: number;
|
|
38
|
+
thickness?: number;
|
|
39
|
+
radius?: number;
|
|
40
|
+
innerShape?: number;
|
|
41
|
+
noiseIterations?: number;
|
|
42
|
+
}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/* * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
2
|
+
* Paper Shaders *
|
|
3
|
+
* https://github.com/paper-design/shaders *
|
|
4
|
+
* * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
5
|
+
|
|
6
|
+
import { sizingVariablesDeclaration } from "../shader-sizing";
|
|
7
|
+
import { declarePI, declareRandom, colorBandingFix } from "../shader-utils";
|
|
8
|
+
const smokeRingMeta = {
|
|
9
|
+
maxColorCount: 10,
|
|
10
|
+
maxNoiseIterations: 8
|
|
11
|
+
};
|
|
12
|
+
const smokeRingFragmentShader = `#version 300 es
|
|
13
|
+
precision highp 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_noiseScale;
|
|
24
|
+
uniform float u_thickness;
|
|
25
|
+
uniform float u_radius;
|
|
26
|
+
uniform float u_innerShape;
|
|
27
|
+
uniform float u_noiseIterations;
|
|
28
|
+
|
|
29
|
+
${sizingVariablesDeclaration}
|
|
30
|
+
|
|
31
|
+
out vec4 fragColor;
|
|
32
|
+
|
|
33
|
+
${declarePI}
|
|
34
|
+
//$ {declareRandom}
|
|
35
|
+
|
|
36
|
+
float random(vec2 p) {
|
|
37
|
+
vec2 uv = floor(p) / 100. + .5;
|
|
38
|
+
return texture(u_noiseTexture, uv).r;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
float noise(vec2 st) {
|
|
42
|
+
vec2 i = floor(st);
|
|
43
|
+
vec2 f = fract(st);
|
|
44
|
+
float a = random(i);
|
|
45
|
+
float b = random(i + vec2(1.0, 0.0));
|
|
46
|
+
float c = random(i + vec2(0.0, 1.0));
|
|
47
|
+
float d = random(i + vec2(1.0, 1.0));
|
|
48
|
+
|
|
49
|
+
// Smoothstep for interpolation
|
|
50
|
+
vec2 u = f * f * (3.0 - 2.0 * f);
|
|
51
|
+
|
|
52
|
+
// Do the interpolation as two nested mix operations
|
|
53
|
+
// If you try to do this in one big operation, there's enough precision loss to be off by 1px at cell boundaries
|
|
54
|
+
float x1 = mix(a, b, u.x);
|
|
55
|
+
float x2 = mix(c, d, u.x);
|
|
56
|
+
return mix(x1, x2, u.y);
|
|
57
|
+
|
|
58
|
+
}
|
|
59
|
+
float fbm(in vec2 n) {
|
|
60
|
+
float total = 0.0, amplitude = .4;
|
|
61
|
+
for (int i = 0; i < ${smokeRingMeta.maxNoiseIterations}; i++) {
|
|
62
|
+
if (i >= int(u_noiseIterations)) break;
|
|
63
|
+
total += noise(n) * amplitude;
|
|
64
|
+
n *= 1.99;
|
|
65
|
+
amplitude *= 0.65;
|
|
66
|
+
}
|
|
67
|
+
return total;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
float getNoise(vec2 uv, vec2 pUv, float t) {
|
|
71
|
+
float noiseLeft = fbm(pUv + .03 * t);
|
|
72
|
+
pUv.x = mod(pUv.x, u_noiseScale * TWO_PI);
|
|
73
|
+
float noiseRight = fbm(pUv + .03 * t);
|
|
74
|
+
return mix(noiseRight, noiseLeft, smoothstep(-.25, .25, uv.x));
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
float getRingShape(vec2 uv) {
|
|
78
|
+
float radius = u_radius;
|
|
79
|
+
float thickness = u_thickness;
|
|
80
|
+
|
|
81
|
+
float distance = length(uv);
|
|
82
|
+
float ringValue = 1. - smoothstep(radius, radius + thickness, distance);
|
|
83
|
+
ringValue *= smoothstep(radius - pow(u_innerShape, 3.) * thickness, radius, distance);
|
|
84
|
+
|
|
85
|
+
return ringValue;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
void main() {
|
|
89
|
+
vec2 shape_uv = v_objectUV;
|
|
90
|
+
|
|
91
|
+
float t = u_time;
|
|
92
|
+
|
|
93
|
+
float cycleDuration = 3.;
|
|
94
|
+
float localTime1 = mod(.1 * t + cycleDuration, 2. * cycleDuration);
|
|
95
|
+
float localTime2 = mod(.1 * t, 2. * cycleDuration);
|
|
96
|
+
float timeBlend = .5 + .5 * sin(.1 * t * PI / cycleDuration - .5 * PI);
|
|
97
|
+
|
|
98
|
+
float atg = atan(shape_uv.y, shape_uv.x) + .001;
|
|
99
|
+
float l = length(shape_uv);
|
|
100
|
+
vec2 polar_uv1 = vec2(atg, localTime1 - (.5 * l) + 1. / pow(l, .5));
|
|
101
|
+
polar_uv1 *= u_noiseScale;
|
|
102
|
+
float noise1 = getNoise(shape_uv, polar_uv1, t);
|
|
103
|
+
|
|
104
|
+
vec2 polar_uv2 = vec2(atg, localTime2 - (.5 * l) + 1. / pow(l, .5));
|
|
105
|
+
polar_uv2 *= u_noiseScale;
|
|
106
|
+
float noise2 = getNoise(shape_uv, polar_uv2, t);
|
|
107
|
+
|
|
108
|
+
float noise = mix(noise1, noise2, timeBlend);
|
|
109
|
+
|
|
110
|
+
shape_uv *= (.8 + 1.2 * noise);
|
|
111
|
+
|
|
112
|
+
float ringShape = getRingShape(shape_uv);
|
|
113
|
+
|
|
114
|
+
float mixer = pow(ringShape, 3.) * (u_colorsCount - 1.);
|
|
115
|
+
vec4 gradient = u_colors[0];
|
|
116
|
+
gradient.rgb *= gradient.a;
|
|
117
|
+
for (int i = 1; i < ${smokeRingMeta.maxColorCount}; i++) {
|
|
118
|
+
if (i >= int(u_colorsCount)) break;
|
|
119
|
+
float localT = clamp(mixer - float(i - 1), 0., 1.);
|
|
120
|
+
vec4 c = u_colors[i];
|
|
121
|
+
c.rgb *= c.a;
|
|
122
|
+
gradient = mix(gradient, c, localT);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
float opacity = gradient.a * ringShape;
|
|
126
|
+
opacity += u_colorBack.a;
|
|
127
|
+
|
|
128
|
+
vec3 color = gradient.rgb * ringShape;
|
|
129
|
+
color += u_colorBack.rgb * u_colorBack.a * (1. - ringShape);
|
|
130
|
+
color += u_colorBack.rgb * u_colorBack.a * ringShape * (1. - gradient.a);
|
|
131
|
+
|
|
132
|
+
${colorBandingFix}
|
|
133
|
+
|
|
134
|
+
fragColor = vec4(color, opacity);
|
|
135
|
+
}
|
|
136
|
+
`;
|
|
137
|
+
export {
|
|
138
|
+
smokeRingFragmentShader,
|
|
139
|
+
smokeRingMeta
|
|
140
|
+
};
|
|
141
|
+
//# 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';\nimport type { ShaderMotionParams } from '../shader-mount';\nimport { sizingVariablesDeclaration, type ShaderSizingParams, type ShaderSizingUniforms } from '../shader-sizing';\nimport { declarePI, declareRandom, colorBandingFix } from '../shader-utils';\n\nexport const smokeRingMeta = {\n maxColorCount: 10,\n maxNoiseIterations: 8,\n} as const;\n\n/**\n * Smoke Ring by Ksenia Kondrashova\n * Renders a fractional Brownian motion (fBm) noise over the\n * polar coordinates masked with ring shape\n *\n * Uniforms include:\n * - u_colorBack: the background color of the scene\n * - uColors (vec4[]): Input RGBA colors\n * - uColorsCount (float): Number of active colors (`uColors` length) * u_noiseScale - the resolution of noise texture\n * - u_thickness (float): the thickness of the ring\n * - u_radius (float): the radius of the ring (u_radius = 0.5 to fit in contain mode)\n * - u_innerShape (float): if we fill the shape inside the radius (u_innerShape = 1 to render only the thickness)\n * - u_noiseIterations (float): how detailed is the noise (number of fbm layers)\n */\n\nexport const smokeRingFragmentShader: string = `#version 300 es\nprecision highp 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_noiseScale;\nuniform float u_thickness;\nuniform float u_radius;\nuniform float u_innerShape;\nuniform float u_noiseIterations;\n\n${sizingVariablesDeclaration}\n\nout vec4 fragColor;\n\n${declarePI}\n//$ {declareRandom}\n\nfloat random(vec2 p) {\n vec2 uv = floor(p) / 100. + .5;\n return texture(u_noiseTexture, uv).r;\n}\n\nfloat noise(vec2 st) {\n vec2 i = floor(st);\n vec2 f = fract(st);\n float a = random(i);\n float b = random(i + vec2(1.0, 0.0));\n float c = random(i + vec2(0.0, 1.0));\n float d = random(i + vec2(1.0, 1.0));\n\n // Smoothstep for interpolation\n vec2 u = f * f * (3.0 - 2.0 * f);\n\n // Do the interpolation as two nested mix operations\n // If you try to do this in one big operation, there's enough precision loss to be off by 1px at cell boundaries\n float x1 = mix(a, b, u.x);\n float x2 = mix(c, d, u.x);\n return mix(x1, x2, u.y);\n\n}\nfloat 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 += noise(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 pUv.x = mod(pUv.x, u_noiseScale * TWO_PI);\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 localTime1 = mod(.1 * t + cycleDuration, 2. * cycleDuration);\n float localTime2 = mod(.1 * t, 2. * cycleDuration);\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(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(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 = pow(ringShape, 3.) * (u_colorsCount - 1.);\n vec4 gradient = u_colors[0];\n gradient.rgb *= gradient.a;\n for (int i = 1; i < ${smokeRingMeta.maxColorCount}; i++) {\n if (i >= int(u_colorsCount)) break;\n float localT = clamp(mixer - float(i - 1), 0., 1.);\n vec4 c = u_colors[i];\n c.rgb *= c.a;\n gradient = mix(gradient, c, localT);\n }\n\n float opacity = gradient.a * ringShape;\n opacity += u_colorBack.a;\n\n vec3 color = gradient.rgb * ringShape;\n color += u_colorBack.rgb * u_colorBack.a * (1. - ringShape);\n color += u_colorBack.rgb * u_colorBack.a * ringShape * (1. - gradient.a);\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,eAAe,uBAAuB;AAEnD,MAAM,gBAAgB;AAAA,EAC3B,eAAe;AAAA,EACf,oBAAoB;AACtB;AAiBO,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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBA4Ba,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,wBAwDhC,cAAc,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAe/C,eAAe;AAAA;AAAA;AAAA;AAAA;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|