Depth test и depth write

В графике реального времени глубинные тесты и запись глубины играют важную роль в управлении видимостью объектов в 3D-пространстве. В PlayCanvas эти операции реализованы через параметры depthTest и depthWrite. Настройка этих параметров может существенно повлиять на производительность и визуальное отображение сцены.

Depth test

Depth test — это процесс, при котором определяется, должен ли текущий пиксель быть видимым в зависимости от его глубины относительно других пикселей на экране. В 3D-графике каждый объект на сцене имеет определенную глубину, которая указывает на его положение относительно камеры. Когда несколько объектов перекрывают друг друга, важно правильно выбрать, какой из них должен отображаться на экране.

В PlayCanvas параметр depthTest управляет этим процессом. Он сравнивает глубину пикселя, который рисуется в текущем кадре, с глубиной пикселя, уже существующего на экране. Если новый пиксель находится дальше или ближе, чем предыдущий, его цвет не будет отрисован, и будет оставаться старое изображение.

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

  • pc.depthTest.Always: Тест глубины всегда возвращает “истина”, что означает, что каждый пиксель будет отрисован, независимо от его глубины.
  • pc.depthTest.Never: Тест глубины всегда возвращает “ложь”, и все пиксели игнорируются, вне зависимости от их глубины.
  • pc.depthTest.Less: Пиксель рисуется только если его глубина меньше (то есть он ближе к камере), чем глубина существующего пикселя.
  • pc.depthTest.LessEqual: Пиксель рисуется, если его глубина меньше или равна глубине существующего пикселя.
  • pc.depthTest.Greater: Пиксель рисуется, если его глубина больше (то есть он дальше от камеры), чем глубина существующего пикселя.
  • pc.depthTest.GreaterEqual: Пиксель рисуется, если его глубина больше или равна глубине существующего пикселя.
  • pc.depthTest.Equal: Пиксель рисуется, если его глубина равна глубине существующего пикселя.
  • pc.depthTest.NotEqual: Пиксель рисуется, если его глубина не равна глубине существующего пикселя.

Для оптимизации рендеринга часто выбирается pc.depthTest.Less или pc.depthTest.LessEqual, поскольку они позволяют отрисовывать только те объекты, которые находятся ближе к камере, а не те, которые скрыты за другими объектами.

Depth write

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

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

Параметр depthWrite может быть настроен следующим образом:

  • true: Запись глубины разрешена. Глубина пикселя будет записана в буфер.
  • false: Запись глубины запрещена. Глубина пикселя не будет записана, и другие объекты не будут проверяться на его основе.

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

Взаимодействие depthTest и depthWrite

Настройка параметров depthTest и depthWrite одновременно дает возможность гибко управлять тем, как и какие объекты влияют на финальный рендеринг сцены.

  • Если depthTest включен, а depthWrite выключен, то глубина объекта не будет записываться в буфер, но тест глубины все равно будет выполняться.
  • Если и depthTest, и depthWrite включены, объект будет и проверяться на глубину, и записывать свою глубину в буфер.
  • Если depthTest отключен, а depthWrite включен, объект будет записывать свою глубину в буфер, но не будет учитывать глубину других объектов при своем рендеринге.

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

Пример использования

Рассмотрим пример, как настроить параметры depthTest и depthWrite для определенного материала в PlayCanvas:

// Создание материала
var material = new pc.Material();

// Включение теста глубины и записи глубины
material.depthTest = pc.depthTest.Less;
material.depthWrite = true;

// Создание объекта с материалом
var entity = new pc.Entity();
entity.addComponent('model', {
    type: 'box',
    material: material
});

// Добавление объекта в сцену
app.root.addChild(entity);

В этом примере создается материал, для которого включен тест глубины с условием Less (пиксель рисуется, если его глубина меньше существующего), и разрешена запись глубины. Затем создается объект, на который применяется этот материал, и добавляется в сцену.

Применение в реальных задачах

Depth test и depth write играют важную роль в оптимизации рендеринга сложных сцен. Например, при создании графических эффектов, таких как тени или объемные эффекты, часто нужно отключать запись глубины, чтобы эффекты не взаимодействовали с другими объектами в сцене.

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

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

Таким образом, настройка depthTest и depthWrite в PlayCanvas позволяет точно контролировать, какие объекты будут видны на экране, а какие — скрыты, обеспечивая тем самым правильное отображение сцены.