Если ты хоть раз открывал сайты-победители фестиваля Awwwards или интерактивные промо-страницы продуктов Apple, то наверняка замирал от восторга: объемные светящиеся объекты плавно покачиваются вслед за курсором мыши, свет преломляется сквозь шероховатое стекло, а при скролле страницы частицы разлетаются в кинематографичном вихре.
Но если ты открывал исходный код таких страниц, восторг быстро сменялся тихим ужасом. Трехмерная графика в вебе на базе библиотеки Three.js и низкоуровневых шейдеров GLSL (OpenGL Shading Language) — это одна из самых хардкорных областей фронтенда. Здесь нужно одновременно быть художником, математиком, разбирающимся в матрицах трансформации, и программистом, вручную контролирующим утечки памяти GPU.
Появление терминального агента Claude Code CLI от компании Anthropic полностью перевернуло этот пайплайн. В отличие от обычных чат-ботов, которые выплевывают обрывки кода в текстовое поле, Claude Code живет прямо в твоем терминале. Он видит дерево файлов, ставит пакеты через npm, компилирует шейдеры и на лету устраняет ошибки рендеринга WebGL. Давай разберем пошаговый рецепт, как собрать интерактивную 3D-сцену агентскими силами.
Архитектура пайплайна: почему агент справляется с 3D лучше человека
Почему обычный копипаст из веб-интерфейса нейросети в Three.js почти всегда приводит к черному экрану? Дело в том, что трехмерный рендеринг требует идеальной согласованности сразу нескольких слоев:
- Инициализации холста Canvas и рендерера WebGLRenderer;
- Настройки пропорций перспективной камеры (PerspectiveCamera) и матрицы проекции при ресайзе окна;
- Цикла перерисовки
requestAnimationFrame; - Создания геометрий, физических материалов и источников света;
- И компиляции внешних фрагментных шейдеров через плагины сборщика.
Если пропустить хоть одну строчку, сцена просто не отрендерится, не выдав даже ошибки в консоль. Терминальный агент берет эту рутину на себя целиком. Он самостоятельно инициализирует чистый проект на Vite, конфигурирует сборщик и шаг за шагом связывает модули в единую систему.
Практический воркфлоу: от пустого терминала до парящего узла
Давай пройдем этот путь за пять минут. Все, что требуется на старте, — установленный Node.js 18+ и глобальный пакет Claude Code CLI.
Первым делом разворачиваем проект и устанавливаем зависимости:
# Создаем проект на Vite и ставим Three.js
npm create vite@latest 3d-interactive-showcase -- --template vanilla
cd 3d-interactive-showcase
npm install three
claude
Внутри сессии Claude Code мы не пишем код руками. Мы формулируем архитектурное ТЗ на естественном языке: «Спроектируй интерактивную 3D-сцену в main.js: центральный парящий тор-узел (TorusKnot), реагирующий с эффектом плавной инерции (LERP 0.05) на перемещение курсора мыши, систему из двух тысяч светящихся частиц и динамическую адаптацию под изменение размеров окна браузера».
Агент анализирует задачу и создает сбалансированную структуру main.js. Взгляни, как изящно решается проблема сглаживания движений:
import * as THREE from 'three';
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 5;
const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
document.body.appendChild(renderer.domElement);
const geometry = new THREE.TorusKnotGeometry(1.2, 0.35, 128, 32);
const material = new THREE.MeshStandardMaterial({
color: 0x6366f1,
roughness: 0.2,
metalness: 0.8
});
const torusKnot = new THREE.Mesh(geometry, material);
scene.add(torusKnot);
const pointLight = new THREE.PointLight(0xffffff, 2, 50);
pointLight.position.set(5, 5, 5);
scene.add(pointLight, new THREE.AmbientLight(0x222233, 1.5));
let mouseX = 0, mouseY = 0;
let targetX = 0, targetY = 0;
window.addEventListener('mousemove', (event) => {
mouseX = (event.clientX / window.innerWidth - 0.5) * 2;
mouseY = (event.clientY / window.innerHeight - 0.5) * 2;
});
function animate() {
requestAnimationFrame(animate);
// Плавная интерполяция координат (LERP)
targetX += (mouseX - targetX) * 0.05;
targetY += (mouseY - targetY) * 0.05;
torusKnot.rotation.y = targetX * 1.5;
torusKnot.rotation.x = targetY * 1.5;
torusKnot.rotation.z += 0.005;
renderer.render(scene, camera);
}
animate();
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
Генерация кастомных шейдеров: эффект свечения Френеля
Если стандартных материалов Three.js недостаточно и тебе нужен авторский эффект (например, неоновое свечение по контуру объекта), агент подключает кастомные шейдеры GLSL.
Вместо многочасового штудирования математических формул ты просишь Claude: «Добавь шейдерный эффект свечения Френеля с пульсацией во времени». Модель проектирует фрагментный шейдер:
uniform float uTime;
varying vec2 vUv;
varying vec3 vNormal;
void main() {
vec3 normal = normalize(vNormal);
float pulse = sin(uTime * 2.0) * 0.5 + 0.5;
float fresnel = pow(1.0 - dot(normal, vec3(0.0, 0.0, 1.0)), 2.0);
vec3 glowColor = mix(vec3(0.2, 0.4, 1.0), vec3(0.9, 0.2, 0.8), pulse);
gl_FragColor = vec4(glowColor * (fresnel + 0.3), 1.0);
}
Claude Code автоматически правит конфигурационный файл сборщика vite.config.js, прописывая импорт расширений .glsl, и связывает формулу с переменными времени uTime.
Ловушки WebGL: батарея смартфона и утечки видеопамяти
В разработке 3D-интерфейсов есть две опасные ямы, в которые новички падают регулярно.
Первая — прожорливость к ресурсам. Если на дисплее смартфона с высокой плотностью пикселей (Retina 3x) запустить рендеринг в нативном разрешении с включенным сглаживанием, частота кадров упадет до 15 FPS, а батарея растает на глазах. Обрати внимание на строчку renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)): искусственное ограничение плотности пикселей двойкой спасает мобильные устройства от перегрева.
Вторая ловушка — утечки памяти (Memory Leaks). В обычном JavaScript сборщик мусора автоматически удаляет неиспользуемые переменные. Но в WebGL объекты геометрий и текстуры загружаются напрямую в память видеокарты! Если ты просто удалишь объект со сцены командой scene.remove(mesh), меш исчезнет с экрана, но продолжит висеть в VRAM. При каждой смене вкладки память будет утекать, пока вкладка браузера не упадет с ошибкой WebGL Context Lost. Claude Code обучен правилам очистки и при уничтожении компонентов принудительно вызывает методы geometry.dispose() и material.dispose().
Связка Three.js и терминального агента сокращает дистанцию между смелой дизайнерской идеей и работающим кодом до считаных минут. Больше не нужно быть гуру линейной алгебры, чтобы удивлять пользователей живой кинематографичной графикой.
