Дайджесты новостей
Трехмерная геометрическая сцена в браузере с интерактивной полигональной сферой и кодом шейдеров Three.js.

Интерактивные 3D-сайты через Claude Code: связка Three.js, WebGL и генерации шейдеров

Если ты хоть раз открывал сайты-победители фестиваля 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 и терминального агента сокращает дистанцию между смелой дизайнерской идеей и работающим кодом до считаных минут. Больше не нужно быть гуру линейной алгебры, чтобы удивлять пользователей живой кинематографичной графикой.