Three.js предоставляет мощные возможности для работы с 3D-графикой в
браузере, включая эффективное управление памятью при построении
геометрий. Одним из ключевых инструментов для этого является
индексированная геометрия, реализованная через свойство
index объекта BufferGeometry. Она позволяет
уменьшить объем используемой памяти и ускорить отрисовку сложных
моделей.
BufferGeometry и вершинВ Three.js базовой единицей геометрии является
BufferGeometry. Она хранит массивы данных о вершинах,
нормалях, текстурных координатах и цветах. Например:
const geometry = new THREE.BufferGeometry();
const vertices = new Float32Array([
0, 0, 0,
1, 0, 0,
0, 1, 0,
1, 1, 0
]);
geometry.setAttribute('position', new THREE.BufferAttribute(vertices, 3));
Здесь каждая вершина состоит из трёх чисел (x, y, z). Для четырёх вершин потребуется 12 значений. Если строить множество треугольников с повторяющимися вершинами, обычный массив вершин быстро растет.
Индексированная геометрия решает проблему повторяющихся вершин с
помощью массива index. Этот массив хранит индексы
вершин, которые формируют треугольники:
const indices = new Uint16Array([
0, 1, 2,
2, 1, 3
]);
geometry.setIndex(new THREE.BufferAttribute(indices, 1));
В этом примере два треугольника образуют прямоугольник. Вместо того чтобы дублировать вершины для каждого треугольника, используется всего четыре вершины и шесть индексов.
Преимущества:
Three.js поддерживает различные типы массивов индексов, в зависимости от числа вершин:
Uint16Array — для моделей до 65 536 вершин.Uint32Array — для больших моделей, когда число вершин
превышает 65 536.Важно выбирать подходящий тип, чтобы не расходовать лишнюю память.
let indexArray;
if (vertices.length / 3 > 65535) {
indexArray = new Uint32Array([...]);
} else {
indexArray = new Uint16Array([...]);
}
geometry.setIndex(new THREE.BufferAttribute(indexArray, 1));
Индексированная геометрия автоматически взаимодействует с любыми
атрибутами, установленными через setAttribute:
const colors = new Float32Array([
1, 0, 0, // красная
0, 1, 0, // зеленая
0, 0, 1, // синяя
1, 1, 0 // желтая
]);
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
Каждый индекс в index ссылается на конкретный набор
атрибутов. Это позволяет использовать одну и ту же вершину с разными
свойствами для разных треугольников без дублирования данных.
1. Куб с индексами
const geometry = new THREE.BoxGeometry(1, 1, 1);
console.log(geometry.index); // Uint16Array с 36 элементами (12 треугольников)
Даже для куба с 8 уникальными вершинами используется 36 индексов, так как каждый треугольник требует трех ссылок на вершины.
2. Сложные модели
Для моделей из GLTFLoader или OBJLoader
индексы часто уже встроены в файлы. Three.js автоматически использует
индексированную геометрию, что существенно снижает нагрузку на память и
ускоряет отрисовку.
Индексы можно изменять динамически для анимации или генеративных сцен:
geometry.index.array[0] = 2; // меняем первый треугольник
geometry.index.needsUpdate = true; // уведомляем рендерер о изменении
Установка needsUpdate обязательна, иначе GPU продолжит
использовать старые данные.
Uint16Array
или Uint32Array).BufferGeometryUtils.mergeBufferGeometries для уменьшения
draw calls.Индексированная геометрия в Three.js — это ключевой инструмент для
управления памятью и производительностью. Понимание работы
index позволяет создавать сложные сцены с миллионами вершин
без лишней нагрузки на GPU и без дублирования данных в памяти.