Как браузер рендерит 3D

Three.js — это высокоуровневая библиотека JavaScript для работы с WebGL, которая позволяет создавать интерактивные 3D-сцены в браузере. Для понимания того, как браузер отображает 3D-графику, важно изучить ключевые компоненты рендеринга и их взаимодействие.

Сцена, камера и рендерер

Сцена (THREE.Scene) — это контейнер для всех объектов 3D-модели: мешей, источников света, вспомогательных элементов и эффектов. Она хранит иерархию объектов, их трансформации и свойства материалов.

Камера (THREE.Camera) определяет точку зрения и перспективу. Основные типы:

  • THREE.PerspectiveCamera — имитирует человеческое зрение, объекты дальше становятся меньше.
  • THREE.OrthographicCamera — сохраняет размеры объектов независимо от расстояния, используется для изометрических проекций.

Рендерер (THREE.WebGLRenderer) отвечает за отрисовку сцены через WebGL. Он создаёт буфер изображения и переводит данные объектов, камер и света в пиксели на экране. Ключевые методы:

const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.render(scene, camera);

Геометрия и меши

Геометрия (THREE.Geometry / THREE.BufferGeometry) определяет форму объекта через вершины, грани и нормали. В Three.js предпочтительнее BufferGeometry из-за высокой производительности. Каждая вершина хранит координаты, нормаль и текстурные UV-координаты.

Меш (THREE.Mesh) — это комбинация геометрии и материала (THREE.Material), которая визуализируется на сцене. Пример создания куба:

const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshStandardMaterial({ color: 0x00ff00 });
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);

Материалы и освещение

Материалы определяют, как объект взаимодействует со светом:

  • MeshBasicMaterial — не реагирует на свет, используется для простых цветных объектов.
  • MeshStandardMaterial — физически корректный материал, поддерживает отражения и свет.
  • MeshPhongMaterial — использует модель освещения Фонга для бликов и мягких отражений.

Освещение в сцене делится на несколько типов:

  • Направленное (DirectionalLight) — имитирует солнечный свет, имеет направление, но нет позиции источника.
  • Точечное (PointLight) — свет из одной точки, распространяется во всех направлениях.
  • Прожектор (SpotLight) — свет с конусообразным направлением.
  • Амбиентное (AmbientLight) — равномерное освещение сцены без теней.

Освещение напрямую влияет на материалы, создавая тени, блики и глубину. Для корректной визуализации используют renderer.shadowMap.enabled = true.

Камера и матрицы трансформации

Каждый объект имеет локальную матрицу трансформации, которая включает:

  • позицию (position)
  • вращение (rotation)
  • масштаб (scale)

Эти локальные матрицы комбинируются с матрицей родителя для получения мировой матрицы. Камера также использует матрицы вида (view matrix) и проекции (projection matrix), чтобы перевести 3D-координаты в 2D-плоскость экрана.

Цикл рендеринга и анимация

Three.js использует цикл рендеринга для обновления сцены:

function animate() {
    requestAnimationFrame(animate);
    cube.rotation.x += 0.01;
    cube.rotation.y += 0.01;
    renderer.render(scene, camera);
}
animate();

requestAnimationFrame синхронизирует обновление с частотой кадров экрана, минимизируя дергание и перегрузку процессора.

Буферы и GPU

WebGL работает с GPU напрямую через буферы:

  • Вершинный буфер (Vertex Buffer) — содержит позиции, нормали, UV.
  • Индексный буфер (Index Buffer) — определяет порядок соединения вершин в треугольники.
  • Фреймбуфер (Framebuffer) — конечное изображение перед выводом на экран.

Three.js автоматически создает и управляет этими буферами. При вызове renderer.render() данные объектов загружаются на GPU, применяются шейдеры и формируется пиксельное изображение.

Тени и постобработка

Для реалистичных сцен используется карта теней (shadow map). Источники света создают карту глубины, по которой вычисляется видимость объектов относительно источника. Для улучшения визуальных эффектов применяются:

  • Bloom — имитация свечения ярких объектов.
  • Depth of Field — размытость в зависимости от расстояния.
  • Tone Mapping — корректировка яркости и контраста сцены.

Three.js интегрирует эти эффекты через THREE.EffectComposer и Pass-модули.

Оптимизация производительности

Основные методы оптимизации:

  • Использование BufferGeometry вместо старой Geometry.
  • Минимизация числа объектов и материалов.
  • Использование InstancedMesh для повторяющихся объектов.
  • Ограничение количества теней и сложных шейдеров.
  • Лодирование текстур и уменьшение разрешения при необходимости.

Эти подходы позволяют сохранять высокую частоту кадров и плавность анимации даже на слабых устройствах.

Работа с текстурами

Текстуры (THREE.Texture) добавляют детализацию и реализм. Основные типы:

  • Цветовая (map) — базовый цвет объекта.
  • Нормал карта (normalMap) — имитирует мелкие детали поверхности без увеличения геометрии.
  • Спекулярная карта (specularMap) — контролирует отражения света.
  • Карта высот (displacementMap) — смещает вершины геометрии для рельефа.

Текстуры загружаются через THREE.TextureLoader и поддерживают сжатие и повторение (wrapS, wrapT) для оптимизации.

Подсистемы Three.js

Three.js включает:

  • Шейдеры — небольшие программы для обработки вершин и пикселей.
  • Raycaster — система для обнаружения пересечений луча с объектами, используется для интерактивности.
  • Controls — готовые модули для управления камерой (OrbitControls, FlyControls).

Эти подсистемы делают библиотеку универсальным инструментом для интерактивной 3D-графики в браузере.