Occlusion culling и frustum culling

В разработке 3D-приложений на основе WebVR и WebXR важным аспектом является оптимизация рендеринга для достижения высокой частоты кадров и снижения нагрузки на GPU. Две ключевые техники — occlusion culling и frustum culling — позволяют сократить количество объектов, которые необходимо отрисовывать в каждой сцене, тем самым повышая производительность.


Frustum Culling

Frustum culling — это метод исключения из рендеринга объектов, которые находятся за пределами видимой области камеры. Видимая область определяется камерной проекцией (view frustum), которая имеет форму усечённой пирамиды в 3D-пространстве. Все объекты, находящиеся за пределами этой пирамиды, не видны пользователю и, соответственно, их отрисовка является лишней.

Применение в A-Frame:

  • Каждая сущность a-entity имеет компонент geometry и position. Для фрустум-каллинга достаточно использовать положение объекта и его bounding box или bounding sphere.
  • A-Frame на базе Three.js автоматически использует frustum culling для всех объектов с frustumCulled = true (значение по умолчанию). При необходимости можно отключить этот механизм для объектов, которые должны всегда оставаться в рендере:
AFRAME.registerComponent('always-render', {
  init: function () {
    this.el.object3D.frustumCulled = false;
  }
});
  • Для сложных сцен с множеством динамических объектов стоит проверять, не создаёт ли frustumCulled = true визуальных артефактов при анимации объектов, выходящих за границы камеры и возвращающихся обратно.

Преимущества:

  • Существенное снижение числа отрисовываемых объектов на кадр.
  • Простота реализации, так как встроена в Three.js и не требует дополнительных вычислений.

Ограничения:

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

Occlusion Culling

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

Подходы к реализации:

  1. Hardware Occlusion Queries — использование GPU для проверки видимости объектов. Three.js поддерживает ограниченные возможности через WebGL, но A-Frame напрямую не предоставляет встроенного компонента для автоматического occlusion culling.

  2. Manual Occlusion Culling — разработчик сам проверяет пересечения объектов с raycasting или с помощью bounding volumes:

AFRAME.registerComponent('occlusion-check', {
  tick: function () {
    const camera = this.el.sceneEl.camera;
    const object3D = this.el.object3D;
    const frustum = new THREE.Frustum();
    const projScreenMatrix = new THREE.Matrix4();

    projScreenMatrix.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse);
    frustum.setFromProjectionMatrix(projScreenMatrix);

    this.el.object3D.visible = frustum.intersectsObject(object3D);
  }
});
  1. Portals и зональные системы — сцена разбивается на зоны или комнаты. При переходе в одну из зон загружаются и отображаются только объекты в ней, а все остальные временно скрываются. Это эффективно для больших сцен с множеством объектов.

Преимущества:

  • Снижение нагрузки на GPU за счёт исключения полностью скрытых объектов.
  • В больших сценах может существенно повысить производительность, особенно при сложной геометрии.

Ограничения:

  • Более сложная реализация по сравнению с frustum culling.
  • Требует отслеживания взаимного положения объектов и, при динамических сценах, частых пересчётов видимости.

Комбинированное использование

На практике frustum culling и occlusion culling работают совместно, обеспечивая оптимальное сокращение числа рендерящихся объектов:

  • Frustum culling первым исключает объекты, которые вне поля зрения камеры.
  • Occlusion culling дополнительно исключает объекты, которые скрыты другими элементами сцены.

Такой подход особенно актуален для VR-проектов, где высокая частота кадров критична для комфорта пользователя.


Рекомендации по оптимизации в A-Frame

  • Использовать frustumCulled = true по умолчанию для всех объектов, кроме декоративных или UI-элементов.
  • Для больших статических объектов, закрывающих значительные части сцены (стены, здания), применять manual occlusion culling или зональные подходы.
  • Минимизировать количество мелких объектов в сцене, которые одновременно видны, либо объединять их в группы и применять culling на уровне группы.
  • Для динамических объектов проверять видимость через bounding volumes и, при необходимости, отключать рендеринг через object3D.visible = false.
  • Сценарии с VR-шлемами требуют тестирования производительности на целевых устройствах, так как накладные расходы на вычисления видимости могут быть значительными для слабых GPU.

Эффективное применение frustum и occlusion culling позволяет создавать масштабные интерактивные сцены в A-Frame с высокой производительностью, снижая нагрузку на графический процессор и обеспечивая плавное отображение для пользователей.