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

124 lines
3.3 KiB
JavaScript

/* * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Paper Shaders *
* https://github.com/paper-design/shaders *
* * * * * * * * * * * * * * * * * * * * * * * * * * * */
import {} from "../shader-sizing.js";
import { declarePI, rotation2, textureRandomizerR, textureRandomizerGB } from "../shader-utils.js";
const dotOrbitMeta = {
maxColorCount: 10
};
const dotOrbitFragmentShader = `#version 300 es
precision mediump float;
uniform float u_time;
uniform sampler2D u_noiseTexture;
uniform vec4 u_colorBack;
uniform vec4 u_colors[${dotOrbitMeta.maxColorCount}];
uniform float u_colorsCount;
uniform float u_stepsPerColor;
uniform float u_size;
uniform float u_sizeRange;
uniform float u_spreading;
in vec2 v_patternUV;
out vec4 fragColor;
${declarePI}
${rotation2}
${textureRandomizerR}
${textureRandomizerGB}
vec3 voronoiShape(vec2 uv, float time) {
vec2 i_uv = floor(uv);
vec2 f_uv = fract(uv);
float spreading = .25 * clamp(u_spreading, 0., 1.);
float minDist = 1.;
vec2 randomizer = vec2(0.);
for (int y = -1; y <= 1; y++) {
for (int x = -1; x <= 1; x++) {
vec2 tileOffset = vec2(float(x), float(y));
vec2 rand = randomGB(i_uv + tileOffset);
vec2 cellCenter = vec2(.5 + 1e-4);
cellCenter += spreading * cos(time + TWO_PI * rand);
cellCenter -= .5;
cellCenter = rotate(cellCenter, randomR(vec2(rand.x, rand.y)) + .1 * time);
cellCenter += .5;
float dist = length(tileOffset + cellCenter - f_uv);
if (dist < minDist) {
minDist = dist;
randomizer = rand;
}
}
}
return vec3(minDist, randomizer);
}
void main() {
vec2 shape_uv = v_patternUV;
shape_uv *= 1.5;
const float firstFrameOffset = -10.;
float t = u_time + firstFrameOffset;
vec3 voronoi = voronoiShape(shape_uv, t) + 1e-4;
float radius = .25 * clamp(u_size, 0., 1.) - .5 * clamp(u_sizeRange, 0., 1.) * voronoi[2];
float dist = voronoi[0];
float edgeWidth = fwidth(dist);
float dots = 1. - smoothstep(radius - edgeWidth, radius + edgeWidth, dist);
float shape = voronoi[1];
float mixer = shape * (u_colorsCount - 1.);
mixer = (shape - .5 / u_colorsCount) * u_colorsCount;
float steps = max(1., u_stepsPerColor);
vec4 gradient = u_colors[0];
gradient.rgb *= gradient.a;
for (int i = 1; i < ${dotOrbitMeta.maxColorCount}; i++) {
if (i >= int(u_colorsCount)) break;
float localT = clamp(mixer - float(i - 1), 0.0, 1.0);
localT = round(localT * steps) / steps;
vec4 c = u_colors[i];
c.rgb *= c.a;
gradient = mix(gradient, c, localT);
}
if ((mixer < 0.) || (mixer > (u_colorsCount - 1.))) {
float localT = mixer + 1.;
if (mixer > (u_colorsCount - 1.)) {
localT = mixer - (u_colorsCount - 1.);
}
localT = round(localT * steps) / steps;
vec4 cFst = u_colors[0];
cFst.rgb *= cFst.a;
vec4 cLast = u_colors[int(u_colorsCount - 1.)];
cLast.rgb *= cLast.a;
gradient = mix(cLast, cFst, localT);
}
vec3 color = gradient.rgb * dots;
float opacity = gradient.a * dots;
vec3 bgColor = u_colorBack.rgb * u_colorBack.a;
color = color + bgColor * (1. - opacity);
opacity = opacity + u_colorBack.a * (1. - opacity);
fragColor = vec4(color, opacity);
}
`;
export {
dotOrbitFragmentShader,
dotOrbitMeta
};
//# sourceMappingURL=dot-orbit.js.map