Проблемы с альфа-тестированием OpenGL ES2
Я отрисовываю в 3D несколько объектов с текстурами, имеющими альфа-формат. Все текстуры загружаются нормально, но когда я пытаюсь отрисовывать их друг перед другом, я получаю следующее:
Слева - это то, что у меня есть. Справа - это то, что должно быть. Сетка предназначена только для визуализации перспективы.
Текстура перед текстурой красного круга обрезана. Я поискал ответ, и там сказано, что мне следует использовать:
GLES20.glEnable( GLES20.GL_BLEND );
GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA );
Но я использую его, и он по-прежнему не работает. Моя настройка, в которой я правильно разместил функцию onSurfaceCreated (), является:
GLES20.glClearColor( 0.75f, 0.85f, 1f, 1.0f );
GLES20.glEnable( GLES20.GL_BLEND );
GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA );
GLES20.glEnable( GLES20.GL_DEPTH_TEST );
GLES20.glDepthFunc( GLES20.GL_LEQUAL );
GLES20.glDepthMask( true );
GLES20.glClearDepthf( 1f );
Мой фрагментный шейдер:
uniform sampler2D texture;
varying vec2 texCoord;
void main(){
gl_FragColor = texture2D( texture, texCoord );
}
Должен ли я включать что-либо в манифест Android, чтобы включить альфа-тестирование? Я не хочу в конечном итоге организовывать свои полигоны вручную или использовать alpha discard (), потому что мне нужно, чтобы некоторые пиксели были полупрозрачными.
Как мне заставить работать буферы глубины 3D альфа-тестирования?
Переведено автоматически
Ответ 1
Вот обзор нескольких методов рендеринга с прозрачностью в OpenGL, с преимуществами и недостатками для каждого.
Альфа-тестирование
Это очень ограниченный метод, но его достаточно для конкретного случая, о котором спрашивал постер. Показанный пример на самом деле не требует прозрачности, потому что все либо полностью непрозрачно, либо полностью прозрачно (alpha = 1.0 или alpha = 0.0).
Раньше в OpenGL для этой цели существовал альфа-тест, но это устаревшая функция, и, конечно, ее нет в ES. Вы можете эмулировать то же самое в своем фрагментном шейдере, который будет выглядеть примерно так:
vec4 val = texture2D(tex, texCoord);
if (val.a > 0.5) {
gl_FragColor = val;
} else {
discard;
}
Преимущества:
- Просто.
- Никакой дополнительной работы на стороне приложения.
Недостатки:
- Only works for full opacity/transparency, cannot deal with semi-transparency.
- Can hurt performance because it typically means that depth testing before the fragment shader has to be disabled.
Sorting and Blending
Rendering transparency is a primary use case for blending. The most common approach is to set the blend function toSRC_ALPHA, ONE_MINUS_SRC_ALPHA
, enable blending, and render with the alpha component of the rendered fragments containing the desired opacity.
Если сцена содержит смесь полностью непрозрачных объектов и объектов с прозрачностью, полностью непрозрачные объекты могут быть визуализированы первыми без необходимости их сортировки. Сортировать нужно только объекты с прозрачностью. Тогда последовательность такова:
- Визуализация полностью непрозрачной геометрии.
- Визуализация непрозрачной геометрии, отсортированная задом наперед.
Преимущества:
- Может работать с полупрозрачностью.
- Может обрабатывать несколько слоев прозрачной геометрии.
- Рендеринг сам по себе очень эффективен.
Недостатки:
- Для корректного результата требуется сортировка. Для функции blend, упомянутой выше, геометрия должна отображаться задом наперед. В зависимости от приложения, это может быть как несложно, так и практически невозможно. Например, чтобы правильно отобразить пересекающуюся геометрию, вам, возможно, придется начать разбивать треугольники, что далеко не привлекательно.
Проверка глубины
Это очень разумное использование функций OpenGL, ИМХО, и может быть хорошим практическим решением. Для этого требуется несколько проходов рендеринга. Для простой формы требуется 3 прохода:
- Визуализируйте сцену с обычными настройками (тестирование глубины включено, функция глубины МЕНЬШЕ, запись цвета и глубины включена), но визуализируйте только полностью непрозрачную геометрию. Если для каждого объекта задана непрозрачность, вы можете справиться с этим, пропустив вызовы draw для непрозрачных объектов. В противном случае вам придется отбросить непрозрачные фрагменты с помощью шейдера, аналогичного тому, который описан в альфа-тестировании выше.
- Отрисовка непрозрачной геометрии с теми же настройками, что и выше, за исключением того, что запись цвета отключена.
- Снова отрисовываем непрозрачную геометрию, но на этот раз с равной функцией глубины, снова включена запись цвета, отключена запись глубины и используется смешивание.
Для прохождения 2 можно использовать минимальный шейдер, поскольку ему не нужно создавать какие-либо допустимые цвета фрагментов.
Преимущества:
- Прост в реализации.
- Достаточно эффективен, не требует сортировки.
- Корректно обрабатывает полупрозрачность.
Недостатки:
- Простая форма отображает только самый передний слой прозрачной геометрии. Это может показаться серьезным ограничением, но на самом деле результаты могут выглядеть очень хорошо. Существуют более продвинутые формы, в которых дополнительные слои визуализируются с дополнительными проходами. Помимо накладных расходов на эти дополнительные проходы, это также становится более сложным, поскольку требует нескольких буферов глубины. Я полагаю, что на веб-сайте NVIDIA есть технический документ об этом.
От альфа до покрытия
Я сам этим не пользовался, поэтому следующее основано на моем ограниченном теоретическом понимании. Похоже, это еще один интересный метод. Для этого требуется рендеринг с несколькими выборками. Функция включена с помощью glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE)
, которая затем преобразует альфа-значения в маску покрытия, в результате чего записываются только части выборок в зависимости от альфа-значения. Это приводит к эффекту прозрачности, когда в буфере с несколькими выборками происходит уменьшение выборки до конечного цветового буфера.
Преимущества:
- Может работать с полупрозрачностью.
- Корректно обрабатывает несколько уровней прозрачности.
- Эффективно, особенно если MSAA использовался бы в любом случае. Сортировка не требуется.
Недостатки:
- Требуется MSAA. Современные графические процессоры очень эффективны при рендеринге MSAA, так что в этом нет ничего сложного. Часто вы, вероятно, захотите использовать MSAA в любом случае.
- Эффективное разрешение альфа-значения очень мало, если только я чего-то не упускаю. Например, с 4x MSAA вы можете представить только 5 возможных альфа-значений (0, 1, 2, 3, 4 образцы, заданные в маске покрытия).
Ответ 2
Принятый ответ этого не касается.
В вашем случае решение состоит в том, чтобы отключить глубинное тестирование и, возможно, изменить порядок, который вы рисуете.
Удаление шейдера - это хак, который будет выглядеть ужасно, если вам нужен диапазон альфа-значений.