- canvas стартует с opacity:0 и плавно проявляется (0.9s) при .is-ready - initPageMeshShader ставит is-ready после первого кадра - modulepreload page-mesh-shader.js для параллельной загрузки с main.js - пересборка страниц (build:pages)
124 lines
3.3 KiB
JavaScript
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
|