Files
site-portfolio/public/vendor/paper-shaders/shaders/paper-texture.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

249 lines
6.6 KiB
JavaScript

/* * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Paper Shaders *
* https://github.com/paper-design/shaders *
* * * * * * * * * * * * * * * * * * * * * * * * * * * */
import {} from "../shader-sizing.js";
import { rotation2, declarePI, fiberNoise, textureRandomizerR } from "../shader-utils.js";
const paperTextureFragmentShader = `#version 300 es
precision mediump float;
uniform vec2 u_resolution;
uniform float u_pixelRatio;
uniform vec4 u_colorFront;
uniform vec4 u_colorBack;
uniform sampler2D u_image;
uniform float u_imageAspectRatio;
uniform float u_contrast;
uniform float u_roughness;
uniform float u_fiber;
uniform float u_fiberSize;
uniform float u_crumples;
uniform float u_crumpleSize;
uniform float u_folds;
uniform float u_foldCount;
uniform float u_drops;
uniform float u_seed;
uniform float u_fade;
uniform sampler2D u_noiseTexture;
in vec2 v_imageUV;
out vec4 fragColor;
float getUvFrame(vec2 uv) {
float aax = 2. * fwidth(uv.x);
float aay = 2. * fwidth(uv.y);
float left = smoothstep(0., aax, uv.x);
float right = 1. - smoothstep(1. - aax, 1., uv.x);
float bottom = smoothstep(0., aay, uv.y);
float top = 1. - smoothstep(1. - aay, 1., uv.y);
return left * right * bottom * top;
}
${declarePI}
${rotation2}
${textureRandomizerR}
float valueNoise(vec2 st) {
vec2 i = floor(st);
vec2 f = fract(st);
float a = randomR(i);
float b = randomR(i + vec2(1.0, 0.0));
float c = randomR(i + vec2(0.0, 1.0));
float d = randomR(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);
}
float fbm(vec2 n) {
float total = 0.0, amplitude = .4;
for (int i = 0; i < 3; i++) {
total += valueNoise(n) * amplitude;
n *= 1.99;
amplitude *= 0.65;
}
return total;
}
float randomG(vec2 p) {
vec2 uv = floor(p) / 50. + .5;
return texture(u_noiseTexture, fract(uv)).g;
}
float roughness(vec2 p) {
p *= .1;
float o = 0.;
for (float i = 0.; ++i < 4.; p *= 2.1) {
vec4 w = vec4(floor(p), ceil(p));
vec2 f = fract(p);
o += mix(
mix(randomG(w.xy), randomG(w.xw), f.y),
mix(randomG(w.zy), randomG(w.zw), f.y),
f.x);
o += .2 / exp(2. * abs(sin(.2 * p.x + .5 * p.y)));
}
return o / 3.;
}
${fiberNoise}
vec2 randomGB(vec2 p) {
vec2 uv = floor(p) / 50. + .5;
return texture(u_noiseTexture, fract(uv)).gb;
}
float crumpledNoise(vec2 t, float pw) {
vec2 p = floor(t);
float wsum = 0.;
float cl = 0.;
for (int y = -1; y < 2; y += 1) {
for (int x = -1; x < 2; x += 1) {
vec2 b = vec2(float(x), float(y));
vec2 q = b + p;
vec2 q2 = q - floor(q / 8.) * 8.;
vec2 c = q + randomGB(q2);
vec2 r = c - t;
float w = pow(smoothstep(0., 1., 1. - abs(r.x)), pw) * pow(smoothstep(0., 1., 1. - abs(r.y)), pw);
cl += (.5 + .5 * sin((q2.x + q2.y * 5.) * 8.)) * w;
wsum += w;
}
}
return pow(wsum != 0.0 ? cl / wsum : 0.0, .5) * 2.;
}
float crumplesShape(vec2 uv) {
return crumpledNoise(uv * .25, 16.) * crumpledNoise(uv * .5, 2.);
}
vec2 folds(vec2 uv) {
vec3 pp = vec3(0.);
float l = 9.;
for (float i = 0.; i < 15.; i++) {
if (i >= u_foldCount) break;
vec2 rand = randomGB(vec2(i, i * u_seed));
float an = rand.x * TWO_PI;
vec2 p = vec2(cos(an), sin(an)) * rand.y;
float dist = distance(uv, p);
l = min(l, dist);
if (l == dist) {
pp.xy = (uv - p.xy);
pp.z = dist;
}
}
return mix(pp.xy, vec2(0.), pow(pp.z, .25));
}
float drops(vec2 uv) {
vec2 iDropsUV = floor(uv);
vec2 fDropsUV = fract(uv);
float dropsMinDist = 1.;
for (int j = -1; j <= 1; j++) {
for (int i = -1; i <= 1; i++) {
vec2 neighbor = vec2(float(i), float(j));
vec2 offset = randomGB(iDropsUV + neighbor);
offset = .5 + .5 * sin(10. * u_seed + TWO_PI * offset);
vec2 pos = neighbor + offset - fDropsUV;
float dist = length(pos);
dropsMinDist = min(dropsMinDist, dropsMinDist*dist);
}
}
return 1. - smoothstep(.05, .09, pow(dropsMinDist, .5));
}
float lst(float edge0, float edge1, float x) {
return clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0);
}
void main() {
vec2 imageUV = v_imageUV;
vec2 patternUV = v_imageUV - .5;
patternUV = 5. * (patternUV * vec2(u_imageAspectRatio, 1.));
vec2 roughnessUv = 1.5 * (gl_FragCoord.xy - .5 * u_resolution) / u_pixelRatio;
float roughness = roughness(roughnessUv + vec2(1., 0.)) - roughness(roughnessUv - vec2(1., 0.));
vec2 crumplesUV = fract(patternUV * .02 / u_crumpleSize - u_seed) * 32.;
float crumples = u_crumples * (crumplesShape(crumplesUV + vec2(.05, 0.)) - crumplesShape(crumplesUV));
vec2 fiberUV = 2. / u_fiberSize * patternUV;
float fiber = fiberNoise(fiberUV, vec2(0.));
fiber = .5 * u_fiber * (fiber - 1.);
vec2 normal = vec2(0.);
vec2 normalImage = vec2(0.);
vec2 foldsUV = patternUV * .12;
foldsUV = rotate(foldsUV, 4. * u_seed);
vec2 w = folds(foldsUV);
foldsUV = rotate(foldsUV + .007 * cos(u_seed), .01 * sin(u_seed));
vec2 w2 = folds(foldsUV);
float drops = u_drops * drops(patternUV * 2.);
float fade = u_fade * fbm(.17 * patternUV + 10. * u_seed);
fade = clamp(8. * fade * fade * fade, 0., 1.);
w = mix(w, vec2(0.), fade);
w2 = mix(w2, vec2(0.), fade);
crumples = mix(crumples, 0., fade);
drops = mix(drops, 0., fade);
fiber *= mix(1., .5, fade);
roughness *= mix(1., .5, fade);
normal.xy += u_folds * min(5. * u_contrast, 1.) * 4. * max(vec2(0.), w + w2);
normalImage.xy += u_folds * 2. * w;
normal.xy += crumples;
normalImage.xy += 1.5 * crumples;
normal.xy += 3. * drops;
normalImage.xy += .2 * drops;
normal.xy += u_roughness * 1.5 * roughness;
normal.xy += fiber;
normalImage += u_roughness * .75 * roughness;
normalImage += .2 * fiber;
vec3 lightPos = vec3(1., 2., 1.);
float res = dot(normalize(vec3(normal, 9.5 - 9. * pow(u_contrast, .1))), normalize(lightPos));
vec3 fgColor = u_colorFront.rgb * u_colorFront.a;
float fgOpacity = u_colorFront.a;
vec3 bgColor = u_colorBack.rgb * u_colorBack.a;
float bgOpacity = u_colorBack.a;
imageUV += .02 * normalImage;
float frame = getUvFrame(imageUV);
vec4 image = texture(u_image, imageUV);
image.rgb += .6 * pow(u_contrast, .4) * (res - .7);
frame *= image.a;
vec3 color = fgColor * res;
float opacity = fgOpacity * res;
color += bgColor * (1. - opacity);
opacity += bgOpacity * (1. - opacity);
opacity = mix(opacity, 1., frame);
color -= .007 * drops;
color.rgb = mix(color, image.rgb, frame);
fragColor = vec4(color, opacity);
}
`;
export {
paperTextureFragmentShader
};
//# sourceMappingURL=paper-texture.js.map