Draw Call — это команда, которую движок WebGL отправляет видеокарте для отрисовки определённого объекта на экране. В контексте Three.js каждый объект сцены с уникальным материалом обычно формирует отдельный draw call. Чем больше объектов и материалов используется, тем больше draw call, и тем выше нагрузка на графический процессор. Это напрямую влияет на FPS и общую производительность сцены, особенно на мобильных устройствах.
Каждый draw call включает в себя:
Даже при небольшой геометрической сложности сцены чрезмерное количество draw call может привести к торможению.
Множество объектов с уникальными материалами Каждый объект с отдельным материалом создаёт отдельный draw call. Например, сцена с сотней кубов, где у каждого своя текстура, генерирует сто draw call, даже если геометрия идентична.
Использование прозрачных материалов Прозрачные объекты требуют сортировки по глубине и дополнительных вычислений, что увеличивает количество draw call и сложность рендеринга.
Частые смены состояний WebGL Изменение текстур, шейдеров или параметров рендеринга между объектами вынуждает движок завершать один draw call и запускать новый.
Сложная иерархия объектов Группы объектов с множеством дочерних элементов, каждый со своим материалом, создают цепочку draw call.
Three.js предоставляет BufferGeometryUtils.mergeBufferGeometries(), позволяющий объединять несколько геометрий в одну. Объединённая геометрия с одним материалом создаёт всего один draw call вместо множества.
Пример:
import { BufferGeometryUtils } from 'three/examples/jsm/utils/BufferGeometryUtils.js';
import { BoxGeometry, Mesh, MeshStandardMaterial } from 'three';
const geometries = [];
for (let i = 0; i < 50; i++) {
const box = new BoxGeometry(1, 1, 1);
box.translate(i * 2, 0, 0);
geometries.push(box);
}
const mergedGeometry = BufferGeometryUtils.mergeBufferGeometries(geometries);
const material = new MeshStandardMaterial({ color: 0x00ff00 });
const mesh = new Mesh(mergedGeometry, material);
scene.add(mesh);
Ключевой эффект: количество draw call снижается до одного.
InstancedMesh позволяет рендерить один и тот же объект несколько раз с разными трансформациями (позиция, масштаб, поворот) в рамках одного draw call.
Пример:
import { InstancedMesh, BoxGeometry, MeshStandardMaterial, Matrix4 } from 'three';
const geometry = new BoxGeometry(1, 1, 1);
const material = new MeshStandardMaterial({ color: 0xff0000 });
const count = 100;
const instancedMesh = new InstancedMesh(geometry, material, count);
const matrix = new Matrix4();
for (let i = 0; i < count; i++) {
matrix.setPosition(Math.random() * 10, Math.random() * 10, Math.random() * 10);
instancedMesh.setMatrixAt(i, matrix);
}
scene.add(instancedMesh);
Преимущество: сотни или тысячи объектов рендерятся за один draw call.
Создание texture atlas позволяет объединять несколько текстур в одну большую текстуру. Это уменьшает количество материалов и, как следствие, draw call.
Особенности:
Сложные модели можно разбивать на логические группы, объединяя геометрию и используя instancing для повторяющихся частей. Это особенно полезно для:
Three.js не показывает draw call напрямую в стандартной сборке, но можно использовать:
WebGLRenderer, которое хранит количество вызванных draw
call за кадр.Пример:
console.log(renderer.info.render.calls);
Регулярный мониторинг позволяет выявлять узкие места и оптимизировать сцену.
Эти подходы обеспечивают значительное улучшение производительности и позволяют Three.js справляться с большими сценами без падения FPS.