GLKit/OpenGLES 2.0: Как заказать примитивы?

Я хотел бы нарисовать полупрозрачные примитивы с помощью GLKit. Я уже отключил глубинное тестирование через glDisable(GL_DEPTH_TEST) и включил смешивание через

glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

Теперь для больших альфа-значений (например, 0,9) мне нужно сначала нарисовать самые дальние треугольники, чтобы они не появлялись выше ближайших треугольников. Это также указано в документации для glBlendFunc:

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

А в FAQ по прозрачности OpenGL:

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

Но так как угол обзора может измениться (когда я изменяю эффект рендеринга modelViewMatrix) самый дальний-ближайший порядок зависит от текущего угла обзора.

Есть ли способ сделать так, чтобы OpenGL автоматически отображал мои примитивы в правильном порядке, и если нет, то каким будет лучший способ продолжить? Я думаю, что вычисление z-положения (в зависимости от текущего угла обзора) и упорядочение нескольких тысяч треугольников для каждого кадра (или, точнее, каждый раз, когда изменяется угол обзора, который может быть для каждого кадра), будет слишком затратным тем более, что мне нужно выдвинуть этот порядок в GPU для каждого кадра.

Обратите внимание, что я не связан с использованием текстур (только цветные вершины).

2 ответа

Решение

Там нет автоматического решения, потому что нет надежного решения в реальном времени из-за проблемы взаимного перекрытия. Если вы простите искусство ASCII, рассмотрим четыре четырехугольника:

     +--+             +--+
     |  |             |  |
+---------------------|  |------+
|                     |  |      |
+---------------------|  |------+
     |  |             |  |
     |  |             |  |
     |  |             |  |
+----|  |-----------------------+
|    |  |                       |
+----|  |-----------------------+
     |  |             |  |
     +--+             +--+

Там нет правильного заказа. Вам нужно было бы разбить хотя бы один из четырех квадратов - это то, что будет делать такая своевременная схема, как построение дерева BSP. Вот почему существует глубокая буферизация; решить эту проблему для каждого пикселя на основе того, что большая часть геометрии непрозрачна.

Итак, лучшие способы продолжить это:

  • построить дерево BSP для вашей прозрачной геометрии (для полной точности);
  • построить BSP-дерево для каждого объекта для прозрачной геометрии, сортировать объекты обратно на передний план (для довольно хорошей точности);
  • требовать, чтобы объекты имели только более или менее выпуклые прозрачные сегменты, чтобы в итоге вы получили дерево BSP с одним листом, если бы вы строили его, сортировали обратно на передний план (для разумной точности, в зависимости от вашего искусства);
  • используйте аддитивное смешивание и рисуйте в любом порядке со списанием глубины, нарисовав всю непрозрачную геометрию (для другого вида, но без проблем с упорядочением).

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

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

  • Невыпуклая геометрия в одном визуализируемом элементе. Обычно решается путем предварительного разделения геометрии вручную или игнорирования артефактов.
  • Пересекающаяся геометрия разных элементов. Обычно не решается.

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

Продвинутые техники

Для совершенно другого подхода, посмотрите глубину пилинга и аналогичные методы. Если все сделано правильно, у этих методов есть что предложить. Тем не менее, я не знаю ни одной версии OpenGL ES, реализующей их. Это не значит, что это не вариант.

Тем не мение...

Если вы еще не очень хорошо знакомы с 3D-программированием в целом, я настоятельно рекомендую придерживаться ручной сортировки и стараться свести артефакты к минимуму. Таким образом, вы можете принять обоснованное решение, является ли такая реализация достаточной или нет для вашего конкретного случая.

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

Другие вопросы по тегам