← каталог
Shader Flow
Full-bleed WebGL-градиент на Three.js: плавно перетекающая плазма с IQ-палитрой. Настоящий шейдер, не CSS.
threeautoparallaxadvanced~165 КБreduced-motion ✓
Установка
npx shadcn@latest add https://motiva.pages.dev/r/shader-flow.jsonзависимости: three@^0.185.1 · @react-three/fiber@^9.6.1
Что нужно в проекте до установки
components.jsonв корне — с алиасами в форме"components": "@/components". Нет файла — CLI не поймёт, куда класть.- Алиас
@объявлен дважды:"paths": {"@/*": ["./src/*"]}в корневомtsconfig.json(в Vite он часто содержит толькоreferences— тогда CLI создаёт папку@) иresolve.aliasв конфиге сборщика. - Токены подключены один раз на приложение:
import "@/styles/motiva-tokens.css"— они приезжают вместе с записью. Без них секция потеряет цвета, ритм и тему. - Своя типографика не должна спорить: если у вас на обёртке
text-align: center, он протечёт внутрь блоков. - Проект без TypeScript? Всё равно нужен минимальный
tsconfig.jsonсpathsи"tsx": trueвcomponents.json: CLI грузит tsconfig безусловно, а с"tsx": falseидёт заjsconfig.jsonи падает так же. Приехавший рядом.tsxможно не трогать — вам нужен.vanilla.js.
Экспорт
Код
"use client";
import { Canvas, useFrame, useThree } from "@react-three/fiber";
import { useMemo, useRef } from "react";
import * as THREE from "three";
const vertexShader = /* glsl */ `
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`;
const fragmentShader = /* glsl */ `
precision highp float;
uniform float uTime;
varying vec2 vUv;
// IQ cosine palette
vec3 palette(float t) {
return vec3(0.5) + vec3(0.5) * cos(6.28318 * (vec3(1.0) * t + vec3(0.0, 0.33, 0.67)));
}
void main() {
vec2 uv = vUv * 2.0 - 1.0;
float t = uTime * 0.15;
// domain warp → плавные перетекающие полосы
float w = sin(uv.x * 3.0 + t) + cos(uv.y * 3.0 - t * 1.3);
float n = sin(uv.x * 4.0 + w + t) * cos(uv.y * 4.0 - w - t);
vec3 col = palette(0.55 + 0.45 * n + t * 0.1);
col *= 1.0 - 0.35 * dot(uv, uv); // виньетка
gl_FragColor = vec4(col, 1.0);
}
`;
function ShaderPlane() {
const { viewport } = useThree();
const mat = useRef<THREE.ShaderMaterial>(null);
const uniforms = useMemo(() => ({ uTime: { value: 0 } }), []);
useFrame((state) => {
const u = mat.current?.uniforms.uTime;
if (u) u.value = state.clock.elapsedTime;
});
return (
<mesh scale={[viewport.width, viewport.height, 1]}>
<planeGeometry args={[1, 1]} />
<shaderMaterial ref={mat} vertexShader={vertexShader} fragmentShader={fragmentShader} uniforms={uniforms} />
</mesh>
);
}
/** Full-bleed WebGL-градиент на Three.js. `?noanim`/data-shot → рендер одного кадра (frameloop demand). */
export function ShaderFlow() {
const frozen =
typeof document !== "undefined" && document.documentElement.hasAttribute("data-shot");
return (
<div style={{ position: "absolute", inset: 0 }}>
<Canvas frameloop={frozen ? "demand" : "always"} dpr={[1, 2]} gl={{ antialias: true }}>
<ShaderPlane />
</Canvas>
</div>
);
}
Похожие эффекты
лицензия: MITавтор: Motivaисточник: оригинал (Motiva)v1.0.0