Instanced Mesh — это метод оптимизации рендеринга большого количества
однотипных объектов в 3D-сцене. В отличие от создания множества
отдельных сущностей <a-entity> с одинаковой
геометрией и материалом, instanced mesh позволяет GPU обрабатывать все
экземпляры за один вызов, значительно снижая нагрузку на CPU и
увеличивая производительность.
В A-Frame instanced mesh реализуется через компонент
instanced-mesh, который использует возможности Three.js
THREE.InstancedMesh. Основная идея заключается в том, что
создается одна геометрия и один материал, а все экземпляры рендерятся с
разными матрицами трансформации.
<a-scene>
<a-entity id="tree" instanced-mesh="geometry: box; material: color: green; count: 100"></a-entity>
</a-scene>
В этом примере создается 100 экземпляров кубов с зеленым материалом. Ключевые параметры компонента:
geometry — тип геометрии (box,
sphere, cylinder, или пользовательская).material — свойства материала (color,
metalness, roughness и т.д.).count — количество экземпляров.Каждому экземпляру можно задать собственную позицию, поворот и масштаб через массивы данных:
const el = document.querySelector('#tree');
const positions = [];
const rotations = [];
const scales = [];
for (let i = 0; i < 100; i++) {
positions.push({x: Math.random()*50-25, y: 0, z: Math.random()*50-25});
rotations.push({x: 0, y: Math.random()*360, z: 0});
scales.push({x: 1, y: 1 + Math.random()*2, z: 1});
}
el.setAttribute('instanced-mesh', {positions, rotations, scales});
positions) — массив объектов
с координатами {x, y, z}.rotations) — массив объектов
{x, y, z} в градусах.scales) — массив объектов
{x, y, z}.Instanced Mesh автоматически применяет эти трансформации при рендеринге, не создавая отдельные сущности в DOM.
Можно использовать кастомные модели, загруженные через
<a-asset-item> и gltf-model. Для
instanced mesh это требует создания
THREE.BufferGeometry:
AFRAME.registerComponent('instanced-trees', {
schema: {
src: {type: 'model'},
count: {type: 'int', default: 50}
},
init() {
const loader = new THREE.GLTFLoader();
loader.load(this.data.src, (gltf) => {
const geometry = gltf.scene.children[0].geometry;
const material = gltf.scene.children[0].material;
const mesh = new THREE.InstancedMesh(geometry, material, this.data.count);
const dummy = new THREE.Object3D();
for (let i = 0; i < this.data.count; i++) {
dummy.position.set(Math.random()*50-25, 0, Math.random()*50-25);
dummy.rotation.y = Math.random()*Math.PI*2;
dummy.scale.set(1, 1 + Math.random(), 1);
dummy.updateMatrix();
mesh.setMatrixAt(i, dummy.matrix);
}
this.el.object3D.add(mesh);
});
}
});
Этот подход позволяет создавать тысячи экземпляров сложных моделей с минимальной нагрузкой на сцену.
Instanced Mesh поддерживает динамическое изменение трансформаций после создания:
const mesh = el.getObject3D('mesh');
const dummy = new THREE.Object3D();
dummy.position.set(0, 5, 0);
dummy.rotation.y = Math.PI / 4;
dummy.updateMatrix();
mesh.setMatrixAt(0, dummy.matrix);
mesh.instanceMatrix.needsUpdate = true;
setMatrixAt(index, matrix) — обновляет трансформацию
конкретного экземпляра.instanceMatrix.needsUpdate = true — сигнализирует GPU,
что матрицы изменились.Это позволяет реализовать анимацию и интерактивные эффекты без создания новых объектов.
Преимущества instanced mesh:
Ограничения:
click,
mouseenter) к отдельным экземплярам напрямую. Для
интерактивности приходится использовать raycasting на кастомные
объекты.Использование instanced mesh в сочетании с LOD (уровнями детализации) и динамическим рендерингом позволяет создавать реалистичные и масштабные 3D-сцены, оставаясь в пределах производительности браузера.
Instanced Mesh полностью совместим с другими компонентами A-Frame,
включая animation, shader и
light. Для пользовательских шейдеров можно передавать
uniform-параметры каждому экземпляру через instanced attributes, что
расширяет возможности визуальных эффектов.
Использование instanced mesh является ключевым инструментом для разработки сложных, оптимизированных VR и WebXR сцен на платформе A-Frame.