Files
site-portfolio/public/vendor/paper-shaders/shaders/warp.js
T
root daa623fe73 feat(mesh-bg): fade-in шейдера фона + modulepreload графа
- canvas стартует с opacity:0 и плавно проявляется (0.9s) при .is-ready
- initPageMeshShader ставит is-ready после первого кадра
- modulepreload page-mesh-shader.js для параллельной загрузки с main.js
- пересборка страниц (build:pages)
2026-09-24 21:37:40 +02:00

133 lines
3.6 KiB
JavaScript

/* * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Paper Shaders *
* https://github.com/paper-design/shaders *
* * * * * * * * * * * * * * * * * * * * * * * * * * * */
import {} from "../shader-sizing.js";
import { declarePI, rotation2, colorBandingFix } from "../shader-utils.js";
const warpMeta = {
maxColorCount: 10
};
const warpFragmentShader = `#version 300 es
precision mediump float;
uniform float u_time;
uniform float u_scale;
uniform sampler2D u_noiseTexture;
uniform vec4 u_colors[${warpMeta.maxColorCount}];
uniform float u_colorsCount;
uniform float u_proportion;
uniform float u_softness;
uniform float u_shape;
uniform float u_shapeScale;
uniform float u_distortion;
uniform float u_swirl;
uniform float u_swirlIterations;
in vec2 v_patternUV;
out vec4 fragColor;
${declarePI}
${rotation2}
float randomG(vec2 p) {
vec2 uv = floor(p) / 100. + .5;
return texture(u_noiseTexture, fract(uv)).g;
}
float valueNoise(vec2 st) {
vec2 i = floor(st);
vec2 f = fract(st);
float a = randomG(i);
float b = randomG(i + vec2(1.0, 0.0));
float c = randomG(i + vec2(0.0, 1.0));
float d = randomG(i + vec2(1.0, 1.0));
vec2 u = f * f * (3.0 - 2.0 * f);
float x1 = mix(a, b, u.x);
float x2 = mix(c, d, u.x);
return mix(x1, x2, u.y);
}
void main() {
vec2 uv = v_patternUV;
uv *= .5;
const float firstFrameOffset = 118.;
float t = 0.0625 * (u_time + firstFrameOffset);
float n1 = valueNoise(uv * 1. + t);
float n2 = valueNoise(uv * 2. - t);
float angle = n1 * TWO_PI;
uv.x += 4. * u_distortion * n2 * cos(angle);
uv.y += 4. * u_distortion * n2 * sin(angle);
float swirl = u_swirl;
for (int i = 1; i <= 20; i++) {
if (i >= int(u_swirlIterations)) break;
float iFloat = float(i);
// swirl *= (1. - smoothstep(.0, .25, length(fwidth(uv))));
uv.x += swirl / iFloat * cos(t + iFloat * 1.5 * uv.y);
uv.y += swirl / iFloat * cos(t + iFloat * 1. * uv.x);
}
float proportion = clamp(u_proportion, 0., 1.);
float shape = 0.;
if (u_shape < .5) {
vec2 checksShape_uv = uv * (.5 + 3.5 * u_shapeScale);
shape = .5 + .5 * sin(checksShape_uv.x) * cos(checksShape_uv.y);
shape += .48 * sign(proportion - .5) * pow(abs(proportion - .5), .5);
} else if (u_shape < 1.5) {
vec2 stripesShape_uv = uv * (2. * u_shapeScale);
float f = fract(stripesShape_uv.y);
shape = smoothstep(.0, .55, f) * (1.0 - smoothstep(.45, 1., f));
shape += .48 * sign(proportion - .5) * pow(abs(proportion - .5), .5);
} else {
float shapeScaling = 5. * (1. - u_shapeScale);
float e0 = 0.45 - shapeScaling;
float e1 = 0.55 + shapeScaling;
shape = smoothstep(min(e0, e1), max(e0, e1), 1.0 - uv.y + 0.3 * (proportion - 0.5));
}
float mixer = shape * (u_colorsCount - 1.);
vec4 gradient = u_colors[0];
gradient.rgb *= gradient.a;
float aa = fwidth(shape);
for (int i = 1; i < ${warpMeta.maxColorCount}; i++) {
if (i >= int(u_colorsCount)) break;
float m = clamp(mixer - float(i - 1), 0.0, 1.0);
float localMixerStart = floor(m);
float softness = .5 * u_softness + fwidth(m);
float smoothed = smoothstep(max(0., .5 - softness - aa), min(1., .5 + softness + aa), m - localMixerStart);
float stepped = localMixerStart + smoothed;
m = mix(stepped, m, u_softness);
vec4 c = u_colors[i];
c.rgb *= c.a;
gradient = mix(gradient, c, m);
}
vec3 color = gradient.rgb;
float opacity = gradient.a;
${colorBandingFix}
fragColor = vec4(color, opacity);
}
`;
const WarpPatterns = {
checks: 0,
stripes: 1,
edge: 2
};
export {
WarpPatterns,
warpFragmentShader,
warpMeta
};
//# sourceMappingURL=warp.js.map