Как обновлять объекты в «Вердж3Д»

Все объекты по умолчанию автоматически обновляют свои матрицы, если они были добавлены на сцену с помощью

const object = new v3d.Object3D(); scene.add(object);

или если они являются дочерними объектами другого объекта, который был добавлен в сцену:

const object1 = new v3d.Object3D(); const object2 = new v3d.Object3D(); object1.add(object2); scene.add(object1); // матрицы объектов object1 и object2 обновятся автоматически

Однако, если вы знаете, что объект будет статичным, вы можете отключить эту функцию и обновлять матрицу преобразования вручную только тогда, когда это необходимо.

object.matrixAutoUpdate = false; object.updateMatrix();

BufferGeometry

BufferGeometries хранят информацию (такую как позиции вершин, индексы граней, нормали, цвета, UV развертки и любые пользовательские атрибуты) в buffers — то есть, typed arrays. Это делает их в целом быстрее стандартной Геометрии, ценой того, что с ними несколько сложнее работать.

Что касается обновления BufferGeometries, самое важное, что нужно понять, это то, что вы не можете изменять размер буферов (это очень затратно, и эквивалентно созданию новой геометрии). Однако вы можете обновить содержимое буферов.

Это означает, что если вы знаете, что атрибут вашего BufferGeometry будет расти, например, количество вершин, вы должны предварительно выделить достаточно большой буфер, чтобы вместить все новые вершины, которые могут быть созданы. Конечно, это также означает, что существует максимальный размер вашего BufferGeometry - не существует способа создать BufferGeometry, который может эффективно расширяться бесконечно.

Мы будем использовать пример линии, которая удлиняется во время рендеринга. Мы выделим место в буфере для 500 вершин, но сначала нарисуем только две, используя BufferGeometry.drawRange.

const MAX_POINTS = 500; // геометрия const geometry = new v3d.BufferGeometry(); // атрибуты const positions = new Float32Array(MAX_POINTS * 3); // 3 координаты на вертекс geometry.addAttribute('position', new v3d.BufferAttribute(positions, 3)); // объём рендеринга const drawCount = 2; // рисовать только первые 2 вертекса geometry.setDrawRange(0, drawCount); // материал const material = new v3d.LineBasicMaterial({ color: 0xff0000, linewidth: 2 }); // линия const line = new v3d.Line(geometry, material); scene.add(line);

Далее мы произвольно добавим точки к линии, используя паттерн, например:

const positions = line.geometry.attributes.position.array; let x, y, z, index; x = y = z = index = 0; for (let i = 0, l = MAX_POINTS; i < l; i++) { positions[index++] = x; positions[index++] = y; positions[index++] = z; x += (Math.random() - 0.5) * 30; y += (Math.random() - 0.5) * 30; z += (Math.random() - 0.5) * 30; }

Если вы хотите изменить количество точек отображаемых после первого рендеринга, сделайте следующее:

line.geometry.setDrawRange(0, newValue);

Если вы хотите изменить значения данных о позиции после первого рендеринга, вам необходимо установить параметр needsUpdate следующим образом:

line.geometry.attributes.position.needsUpdate = true; // требуется после первого рендеринга

Если вы измените значения данных о положении после первоначального рендеринга, вам может потребоваться пересчитать охватывающие объекты.

line.geometry.computeBoundingBox(); line.geometry.computeBoundingSphere();

Материалы

Все юниформы можно свободно менять (например, цвета, текстуры, альфа-канал и т.д.),— их значения отправляются в шейдер каждый кадр.

Также параметры, связанные с состоянием ВебГЛ, могут изменяться в любое время (depthTest, blending, polygonOffset и т.д.).

Следующие свойства не могут быть легко изменены во время выполнения (после того, как материал будет отрисован хотя бы один раз):

Их изменение потребует создания новой шейдерной программы. Чтобы это сделать, выполните:

material.needsUpdate = true

Имейте в виду, что это может быть довольно медленно и вызвать рывки в частоте кадров (особенно на Виндоус, поскольку компиляция шейдеров в ДиректИкс происходит медленнее, чем в ОпенГЛ).

Для более плавного восприятия вы можете в некоторой степени эмулировать изменения этих характеристик, используя "фиктивные" значения, такие как освещение нулевой интенсивности, белые текстуры или туман нулевой плотности.

Вы можете свободно изменять материал, используемый для геометрических фрагментов, однако вы не можете изменить способ разделения объекта на фрагменты (в соответствии с материалами фейсов).

Если вам необходимо иметь различные конфигурации материалов во время работы:

Если количество материалов / фрагментов невелико, можно предварительно разделить объект (например, волосы / лицо / тело / верхняя одежда / брюки для человека, перед / бока / верх / стекло / шины / салон для автомобиля).

Если их количество велико (например, каждое лицо может быть потенциально разным), рассмотрите другое решение, например, использование атрибутов/текстур для управления различным внешним видом каждого лица.

Текстуры

Текстуры изображений, canvas, видео и данных должны иметь следующий параметр, если они изменяются:

texture.needsUpdate = true;

Рендер таргеты обновляются автоматически.

Камеры

Положение и цель камеры обновляются автоматически. Если вам необходимо изменить:

то вам нужно будет заново вычислить матрицу проекции:

camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix();