Three.js и WebGL: полный обзор 3D на сайтах
Что такое WebGL и Three.js, когда 3D на сайте окупается, а когда только добавляет вес: 8 сфер, плюсы и минусы, сравнение с Babylon.js, Spline и видео, правила скорости, WebGPU и примеры кода.
Коротко
WebGL — это доступ браузера к видеокарте, а Three.js — самая популярная бесплатная библиотека поверх него: она превращает низкоуровневые графические команды в сцену с камерой, светом, материалами и моделями. Вместе они дают настоящий 3D на странице без плагинов — просмотр и конфигураторы товаров, эффектные первые экраны, визуализацию данных, игры и AR. Новый стандарт WebGPU Three.js тоже поддерживает, а браузерная поддержка WebGPU растёт. Цена 3D — вес и батарея: модели нужно сжимать, сцены останавливать вне экрана, а слабым устройствам и тем, кто отключил движение, показывать облегчённую версию.
Three.js и WebGL коротко: паспорт
Главные факты о стандарте и библиотеке одной таблицей.
- WebGL
- Стандарт Khronos Group: доступ браузера к видеокарте; WebGL 2 поддерживается везде
- WebGPU
- Новое поколение: ближе к современным графическим API, с вычислениями на видеокарте; поддержка растёт
- Three.js
- 3D-библиотека Рикардо Кабельо (mrdoob), 2010 год; лицензия MIT
- Что даёт
- Сцены, камеры, свет, физически корректные материалы, загрузчики моделей, постобработка
- Рендереры
- WebGLRenderer и WebGPURenderer с автоматическим откатом на WebGL
- Формат моделей
- glTF — «JPEG для 3D»; сжатие Draco или Meshopt, текстуры в KTX2
- Релизы
- Примерно раз в месяц, нумеруются ревизиями (r186 на момент написания)
- С React
- React Three Fiber и drei — сцены как компоненты
- Альтернативы
- Babylon.js, PlayCanvas; для сцен без кода — Spline
- Модели делают в
- Blender и других 3D-редакторах, затем экспортируют в glTF
Для чего применяют Three.js: 8 сфер
3D окупает свой вес там, где показывает то, чего не покажет картинка.
-
01
Товар в 3D
Вращать, приближать и смотреть со всех сторон — до покупки.
-
02
Конфигураторы
Цвет, материал, размер — модель меняется в реальном времени.
-
03
Эффектные первые экраны
Запуски и премиальные бренды, которые должны запомниться.
-
04
Визуализация данных
Тысячи точек, глобусы и сети, которые не помещаются в 2D.
-
05
Недвижимость и интерьеры
Прогулка по квартире или офису до того, как их построили.
-
06
Игры и промо
Небольшие игры в браузере без установки.
-
07
AR и VR
WebXR ставит модель в комнату через камеру телефона.
-
08
Интерфейсы с глубиной
Лёгкие 3D-акценты в интерфейсе там, где они помогают понять.
Плюсы и минусы Three.js
Three.js делает 3D доступным, но не делает его бесплатным: каждая сцена стоит байтов и батареи.
Плюсы · 8
-
Настоящий 3D без плагинов
Работает во всех современных браузерах на телефонах и компьютерах.
-
Удобный уровень абстракции
Сцена, камера и объект вместо сотен строк низкоуровневого графического кода.
-
Огромное сообщество
Тысячи примеров, ответов и готовых эффектов.
-
glTF и хорошие загрузчики
Модели из Blender приходят с материалами и анимациями.
-
Физически корректные материалы
Металл, дерево и стекло выглядят правдоподобно при любом свете.
-
Готов к WebGPU
Одна и та же сцена может рисоваться через WebGPU и откатываться на WebGL.
-
Работает с React
React Three Fiber превращает сцены в компоненты.
-
Бесплатный
Лицензия MIT, без отчислений за коммерческое использование.
Минусы · 8
-
Вес
Библиотека плюс модели и текстуры — мегабайты, если не сжимать.
-
Батарея и нагрев
Сцена, которая рисуется 60 раз в секунду, постоянно нагружает видеокарту.
-
Слабые устройства
Старые телефоны дёргаются на тяжёлых эффектах — нужна облегчённая версия.
-
Невидимо для поиска
Нарисованное на холсте — не текст: содержание должно быть и в HTML.
-
Часто меняющийся API
Ежемесячные релизы иногда переименовывают и убирают части — обновления требуют внимания.
-
Нужны навыки 3D
Хорошим сценам нужны моделирование, свет и шейдеры, а не только код.
-
Доступность
Программы чтения с экрана не видят холст; управление с клавиатуры пишется вручную.
-
Не игровой движок
Физика, редактор и игровая логика приходят из других инструментов.
Three.js и другие: сравнение с Babylon.js, PlayCanvas, Spline и видео
Способы показать 3D на странице — от кода до заранее отрисованного ролика.
| Критерий | Three.js | Babylon.js | PlayCanvas | Spline | Видео |
|---|---|---|---|---|---|
| Что это | 3D-библиотека | 3D-движок | движок с редактором | инструмент дизайнера | заранее отрисованный ролик |
| Интерактив | полный | полный | полный | базовый | нет |
| Гибкость | самая высокая | высокая | высокая | в рамках инструмента | нет |
| Вес | средний | больше | средний | средний | зависит от файла |
| Кто делает | разработчик | разработчик | разработчик с редактором | дизайнер | 3D-художник |
| Лучше всего для | своих сцен и просмотра товаров | сложных 3D-приложений и игр | браузерных игр и рекламы | быстрого декоративного 3D | сложных сцен без взаимодействия |
Когда 3D на Three.js оправдан, а когда нет
Десять типичных задач с вердиктом.
-
Товар со всех сторон
Лучший выбор3D показывает то, чего не покажут фото.
-
Конфигуратор
Лучший выборСочетания меняются в реальном времени вместо сотен рендеров.
-
Запуск премиального бренда
Лучший выборЗапоминающийся первый экран стоит своего веса.
-
Визуализация больших данных
Лучший выборТысячи объектов рисует видеокарта.
-
Декоративный фон
ПодходитЧасто видео или CSS дают тот же эффект легче.
-
Сложная сцена без взаимодействия
ПодходитСжатое видео может быть дешевле для устройства.
-
Полноценная игра
ПодходитВозможно, но движок вроде Babylon.js или PlayCanvas даёт больше из коробки.
-
Корпоративный сайт «чтобы было современно»
Другой язык3D без задачи добавляет вес и отвлекает.
-
Аудитория на слабых телефонах
Другой языкФото и немного движения работают лучше.
-
Содержание, которое должны найти в поиске
Другой языкТексту место в HTML, а не на холсте.
Как сделать 3D быстрым: 8 правил
-
01
Сжимать модели
Draco или Meshopt уменьшают glTF в несколько раз.
-
02
Текстуры в KTX2
Они остаются сжатыми даже в памяти видеокарты.
-
03
Ограничить плотность пикселей
Выше 2x глаз разницы не видит, а видеокарта рисует вдвое больше.
-
04
Рисовать, только когда видно
Сцена за пределами экрана останавливается — батарея говорит спасибо.
-
05
Грузить по требованию
Библиотека и модель загружаются, когда посетитель доходит до блока.
-
06
Меньше вызовов отрисовки
Тысячи одинаковых объектов рисуются как один через InstancedMesh.
-
07
Сначала картинка
Неподвижное изображение стоит на месте сцены, пока она не готова, — а для слабых устройств вместо неё.
-
08
Учитывать «уменьшить движение»
Если в системе отключено движение, показывать один неподвижный кадр.
Экосистема Three.js: инструменты для частых задач
Библиотека рисует, а модели, сжатие и эффекты приходят вокруг неё.
| Задача | Инструменты |
|---|---|
| Моделирование | Blender |
| Сжатие glTF | gltf-transform, Draco, Meshopt |
| Текстуры | KTX2, Basis Universal |
| Сцены в React | React Three Fiber, drei |
| Постобработка | postprocessing, EffectComposer |
| Физика | Rapier, cannon-es |
| Таймлайн анимации | Theatre.js |
| Отладка | lil-gui, Spector.js |
| AR и VR | WebXR |
Частые ошибки с 3D на сайтах
-
Модель прямо из редактора
Десятки мегабайт несжатой геометрии и текстур — посетитель уходит раньше, чем она загрузится.
-
Бесконечная отрисовка
Сцена, которая рисуется, даже когда её никто не видит, впустую греет телефон.
-
Текст внутри сцены
Его не видят ни поисковики, ни программы чтения с экрана.
-
Нет запасного варианта
Если WebGL не запустился, посетитель видит пустой прямоугольник.
-
Забытые ресурсы
Геометрии и текстуры, которые не освободили, съедают память видеокарты при каждой смене страницы.
-
3D ради 3D
Если сцена не объясняет и не продаёт, она только добавляет вес.
Как выглядит Three.js: 3 примера
Минимальная сцена, просмотр товара и отрисовка только на виду. Проверены TypeScript 7 с Three.js r186; первый и третий запущены в Chromium.
Минимальная сцена
Вращающийся куб со светом, правильный размер при изменении окна и ограниченная плотность пикселей.
import * as THREE from 'three';
// сцена, камера и рендерер — три вещи, с которых начинается любая 3D-страница
const canvas = document.querySelector<HTMLCanvasElement>('#scene')!;
const renderer = new THREE.WebGLRenderer({ canvas, antialias: true });
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)); // выше 2x глаз разницы не видит, а видеокарта — видит
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(45, 1, 0.1, 100);
camera.position.set(0, 1.2, 4);
const cube = new THREE.Mesh(
new THREE.BoxGeometry(1, 1, 1),
new THREE.MeshStandardMaterial({ color: 0xe4ff4e, roughness: 0.4 }),
);
scene.add(cube, new THREE.HemisphereLight(0xffffff, 0x222222, 2.5));
function resize() {
const { clientWidth: w, clientHeight: h } = canvas;
renderer.setSize(w, h, false);
camera.aspect = w / h;
camera.updateProjectionMatrix();
}
window.addEventListener('resize', resize);
resize();
renderer.setAnimationLoop((time) => {
cube.rotation.y = time / 1000;
renderer.render(scene, camera);
});
Просмотр товара
Сжатая модель glTF, которую посетитель вращает и приближает в заданных пределах.
import * as THREE from 'three';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
// просмотр товара: сжатая модель glTF, которую посетитель вращает и приближает
export async function showProduct(canvas: HTMLCanvasElement, url: string) {
const renderer = new THREE.WebGLRenderer({ canvas, antialias: true, alpha: true });
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
renderer.setSize(canvas.clientWidth, canvas.clientHeight, false);
const scene = new THREE.Scene();
scene.add(new THREE.HemisphereLight(0xffffff, 0x444444, 3));
const camera = new THREE.PerspectiveCamera(35, canvas.clientWidth / canvas.clientHeight, 0.1, 50);
camera.position.set(0, 0.6, 2.4);
const draco = new DRACOLoader().setDecoderPath('/draco/'); // модель сжата в несколько раз
const gltf = await new GLTFLoader().setDRACOLoader(draco).loadAsync(url);
scene.add(gltf.scene);
const controls = new OrbitControls(camera, canvas);
controls.enableDamping = true;
controls.minDistance = 1;
controls.maxDistance = 4;
renderer.setAnimationLoop(() => {
controls.update();
renderer.render(scene, camera);
});
return renderer;
}
Рисовать, только пока видно
За пределами экрана сцена останавливается; при отключённом движении — один неподвижный кадр.
import type { WebGLRenderer } from 'three';
// 3D-сцена не должна сажать батарею: рисуем, только пока её видно
export function renderOnlyWhenVisible(
renderer: WebGLRenderer,
canvas: HTMLCanvasElement,
draw: (time: number) => void,
) {
const reduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
if (reduced) {
draw(0); // в системе отключено движение: один неподвижный кадр
return;
}
new IntersectionObserver(([entry]) => {
renderer.setAnimationLoop(entry?.isIntersecting ? draw : null);
}).observe(canvas);
}
Вопросы о Three.js и WebGL
Чем WebGL отличается от Three.js?
WebGL — низкоуровневый доступ браузера к видеокарте; Three.js — библиотека, которая превращает его в сцены, камеры и модели.
Будет ли 3D работать на телефонах?
Да, если сцена лёгкая: сжатые модели, ограниченная плотность пикселей и неподвижная версия для слабых устройств.
Вредит ли 3D продвижению в поиске?
Нет, если содержание остаётся в HTML, а сцена грузится лениво и не тормозит первый экран.
Откуда берутся 3D-модели?
Их делают в Blender или другом редакторе либо готовят из CAD-файлов производителя, затем выгружают в glTF и сжимают.
Что такое WebGPU и нужен ли он?
Стандарт графики нового поколения. Three.js умеет его использовать с откатом на WebGL, поэтому сайт работает в любом браузере.
Three.js или Spline?
Spline быстр для декоративного 3D от дизайнера; Three.js даёт полный контроль над весом, взаимодействием и логикой.
Можно ли использовать Three.js с React?
Да, через React Three Fiber: сцена описывается компонентами.
Не лучше ли видео, чем 3D?
Если взаимодействия нет — часто да. 3D выигрывает, когда посетителю нужно вращать, выбирать или исследовать.
Форма
3D для
вашего сайта
Делаю 3D-сцены на Three.js там, где они оправданы: просмотр товара, конфигураторы и эффектные первые экраны — сжатые модели, бюджет скорости и облегчённая версия для слабых устройств. Расскажите об идее — отвечу в течение рабочего дня.