В библиотеке Three.js работа с большим количеством
объектов может быть ресурсоёмкой, особенно если каждый объект
представляет собой отдельную геометрию и материал. Для повышения
производительности используется техника слияния
геометрий, позволяющая объединить несколько объектов в одну
геометрию, что снижает количество вызовов отрисовки
(draw calls) и оптимизирует использование памяти GPU.
Основным инструментом для этого является метод
BufferGeometryUtils.mergeGeometries.
BufferGeometryUtils.mergeGeometriesBufferGeometryUtils.mergeGeometries — это функция,
которая принимает массив объектов типа THREE.BufferGeometry
и возвращает одну объединённую геометрию. Она доступна через утилитарный
модуль BufferGeometryUtils, который необходимо
импортировать отдельно:
import { BufferGeometryUtils } from 'three/examples/jsm/utils/BufferGeometryUtils.js';
Синтаксис функции:
const mergedGeometry = BufferGeometryUtils.mergeGeometries(geometries, useGroups);
geometries — массив объектов
THREE.BufferGeometry.useGroups — булевый параметр, определяющий, нужно ли
сохранять группы для разных материалов. По умолчанию
false.Слияние атрибутов Каждая
BufferGeometry состоит из атрибутов (position,
normal, uv, color и других).
Функция mergeGeometries объединяет соответствующие атрибуты
всех геометрий в один массив. Это позволяет GPU обрабатывать данные как
единое целое.
Сохранение индексов Если геометрии используют
индексированные массивы (geometry.index), метод корректно
смещает индексы каждой геометрии, чтобы они не конфликтовали между
собой.
Группы для материалов При установке
useGroups = true каждая исходная геометрия получает
собственную группу в объединённой геометрии. Это необходимо, если разные
геометрии будут использовать разные материалы при рендеринге одной
меш-сущности.
Объединение простых кубов с одинаковым материалом:
import * as THREE from 'three';
import { BufferGeometryUtils } from 'three/examples/jsm/utils/BufferGeometryUtils.js';
const geometries = [];
for (let i = 0; i < 10; i++) {
const cube = new THREE.BoxGeometry(1, 1, 1);
cube.translate(i * 2, 0, 0); // перемещаем каждый куб
geometries.push(cube);
}
const mergedGeometry = BufferGeometryUtils.mergeGeometries(geometries);
const material = new THREE.MeshStandardMaterial({ color: 0x00ff00 });
const mesh = new THREE.Mesh(mergedGeometry, material);
scene.add(mesh);
В этом примере создаются 10 кубов, которые объединяются в одну
геометрию. Перемещение каждого куба происходит через метод
translate для BufferGeometry, что обеспечивает
правильное позиционирование в объединённой геометрии.
Если необходимо объединять геометрии с разными материалами, важно
использовать useGroups = true:
const geometries = [geom1, geom2, geom3];
const mergedGeometry = BufferGeometryUtils.mergeGeometries(geometries, true);
const materials = [
new THREE.MeshStandardMaterial({ color: 0xff0000 }),
new THREE.MeshStandardMaterial({ color: 0x00ff00 }),
new THREE.MeshStandardMaterial({ color: 0x0000ff })
];
const mesh = new THREE.Mesh(mergedGeometry, materials);
scene.add(mesh);
В объединённой геометрии автоматически создаются группы, соответствующие каждой исходной геометрии, что позволяет назначать отдельные материалы на один меш.
position, normal,
uv). Если некоторые атрибуты отсутствуют в одной из
геометрий, метод выбросит ошибку.mergeGeometries для объектов, которые не
изменяются динамически.THREE.InstancedMesh)
вместо слияния геометрий, если требуется анимация или частые
трансформации.normal или uv можно
выполнить вручную через geometry.setAttribute..glb,
.obj или .fbx. Перед объединением
рекомендуется вызывать geometry.computeVertexNormals() для
корректного расчёта освещения.BufferGeometry — сферы, цилиндры, плоскости
и кастомные формы. Главное — соответствие атрибутов.С помощью BufferGeometryUtils.mergeGeometries
достигается значительное упрощение сцен с большим числом
объектов, снижение количества draw calls и улучшение
производительности рендеринга WebGL в проектах на
Three.js.