Каковы некоторые методы визуализации прозрачности в OpenGL?

14

Альфа-смешивание можно включить, чтобы сделать поверхности прозрачными, например:

glDisable(GL_DEPTH_TEST); //or glDepthMask(GL_FALSE)? depth tests break blending
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

Но это работает, только если объекты отображаются в обратном порядке. В противном случае вещи на заднем плане появляются перед более близкими объектами, такими как пол на изображении ниже. Для частиц и элементов GUI сортировка была бы в порядке, но для треугольных сеток кажется, что это будет слишком много усилий и медленных, как обсуждено здесь: https://www.opengl.org/wiki/Transparency_Sorting .

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

введите описание изображения здесь

jozxyqk
источник
Я не уверен, должен ли это быть ответом или нет, но ошибки в вашем изображении вызваны рендерингом без проверки глубины на всех примитивах. Вы должны визуализировать сцену в 2 прохода: сначала визуализируйте всю твердую геометрию. После этого отключите запись глубины (не GL_DEPTH_TEST) и визуализируйте полупрозрачную геометрию примерно в обратном порядке. Это гарантирует, что прозрачная геометрия не будет нарисована перед геометрией сплошной, которая перед ней.
Юрикс
@yuriks В данном случае это, вероятно, плохой пример с моей стороны, но все должно быть прозрачным. Я хотел что-то, чтобы показать, как неправильная прозрачность может выглядеть, когда сделано плохо. Также пример, где сортировка геометрии была бы удивительно трудной (например, здесь пол представляет собой один гигантский многоугольник и покрывает весь диапазон глубины).
jozxyqk

Ответы:

10

Набор методов, позволяющих избежать явного упорядочения, называется «Независимая прозрачность заказа» (сокращенно OIT).

Есть много методов OIT.

Исторически одним из них является пилинг глубины . При таком подходе вы сначала визуализируете самые передние фрагменты / пиксели, затем вы находите ближайший к тому, который был найден на предыдущем шаге, и так далее, имея столько «слоев», сколько вам нужно. Это называется глубинный пилинг, потому что на каждом проходе вы «очищаете» один слой глубины. После этого весь ваш слой может быть перекомбинирован задом наперед. Для реализации этого алгоритма вам необходимо иметь копию буфера глубины.

Другой набор техник - это смешанные OIT. Одним из последних и интересных является взвешенный смешанный OIT, предложенный McGuire и Bavoil . Это в основном применяет взвешенную сумму для всех поверхностей, которые занимают данный фрагмент. Предлагаемая ими схема взвешивания основана на пространстве камеры Z (в приближении к окклюзии) и непрозрачности.
Идея состоит в том, что, если вы можете свести проблему к взвешенной сумме, вас не волнует порядок.

Помимо оригинальной статьи, в блоге Мэтта Петтинео есть отличный ресурс для подробностей реализации и проблем, связанных с Weighted Blended OIT . Как вы можете прочитать из его поста, эта техника не является серебряной пулей. Основная проблема заключается в том, что схема взвешивания является центральной и должна быть настроена в соответствии с вашей сценой / контентом. Из его экспериментов, хотя техника, кажется, работает нормально для относительно низкой и средней непрозрачности, она терпит неудачу, когда непрозрачность приближается к 1, и поэтому не может быть использована из материалов, где большая часть поверхности непрозрачна (он приводит пример листвы).

Опять же, все сводится к тому, как вы настраиваете свои веса глубины, и найти те, которые идеально соответствуют вашим сценариям использования, не обязательно тривиально.

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

cifz
источник
6

Одним из вариантов является использование глубинного пилинга.

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

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

Повторное применение теста глубины вернет второй слой. Повторите по мере необходимости.

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

es1024
источник
1
Благодарность! Похоже, мне понадобятся два буфера глубины для этого. То есть один, чтобы сохранить и отфильтровать последние глубины, и один, чтобы сделать проверку глубины для текущего рендера. Поправьте меня, если я ошибаюсь, но я предполагаю, что мне понадобятся две текстуры глубины для FBO, которые я меняю между каждым проходом пилинга.
jozxyqk
1
@jozxyqk Правильно, для этой процедуры необходимы два буфера глубины.
es1024
1

Крем де ла крем однопроходного нет (или несколько) ставит под угрозу прозрачность в OpenGL является A-буфером. С современным OpenGL возможно реализовать:

http://blog.icare3d.org/2010/06/fast-and-accurate-single-pass-buffer.html

Это позволяет избежать многократных глубинных отслаиваний и не требует обременительной сортировки.

XenonofArcticus
источник
3
В идеале ответы должны быть автономными и жизненно важными для внешних ссылок. Наличие ссылок хорошо для дополнительного материала, но ответ должен состоять не только из ключевого слова. Если бы вы могли включить некоторые подробности о том, что такое A-буфер и как он работает, это значительно улучшило бы ваш ответ.
Мартин Эндер