OpenGL — использование альфа-канала текстуры И «глобального» уровня непрозрачности

#opengl

#opengl

Вопрос:

Я пытаюсь получить довольно простой эффект; я бы хотел, чтобы мои спрайты могли использовать альфа-каналы, используемые GL (то есть, просвечивать части изображения, но не все), а также чтобы весь спрайт имел уровень «непрозрачности», который влияет на весь спрайт.

У меня есть последняя часть, которая была достаточно простой в использовании GL_MODULATE и передаче color4d (непрозрачность, непрозрачность, непрозрачность, непрозрачность). Работает как мечта.

Но проблема в первой части; частично полупрозрачные изображения. Я думал, что мог бы просто запустить glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); и включить смешивание, но, к сожалению, это не работает. Похоже, что это «отбеливает» цвет рассматриваемого изображения, а не делает его полупрозрачным. Любые другие спрайты, проходящие под ним, ведут себя так, как если бы это был сплошной цветной блок, и напрямую обрезаются.

Для справки, я отключил освещение, z-буфер, цветовой материал и альфа-тест. Сделал модель затенения плоской, на всякий случай. Но в остальном я использую настройки ortho по умолчанию. Я использую teximage2d для рассматриваемой текстуры, и я был уверен, что все форматы и GL_RGBA установлены правильно.

Как я могу заставить GL учитывать альфа-канал текстуры во время наложения?

Комментарии:

1. Вы включили смешивание с помощью glEnable? Кроме того, чтобы задать непрозрачность спрайта, вам не нужен GL_MODULATE, просто используйте color4d(1, 1, 1, alpha);

2. Я согласен с @Bahbar. То, что вы описали, должно работать (и работает для меня). Я думаю, что если бы вы опубликовали часть своего кода, это было бы полезно. Один незначительный момент: я думаю, вам следует использовать color4d (1, 1, 1, непрозрачность). Используемый вами цвет означает, что спрайт будет одновременно становиться темнее по мере того, как он становится более прозрачным.

Ответ №1:

Самое простое и быстрое решение — использовать фрагментный шейдер.

 uniform float alpha;
uniform sampler2D texture;
main(){
    gl_FragColor = texture2d(texture, gl_TexCoords);
    gl_FragColor.a *= alpha;
}
  

Ответ №2:

  • GL_MODULATE — это способ сообщить GL использовать текстуру alpha для окончательной альфа-версии фрагмента (это также используется по умолчанию).
  • Ваше смешивание также верно в отношении того, как использовать сгенерированную альфа-версию на этапе смешивания.

Итак, проблема заключается в другом… Ваше описание звучит так, как будто вы на самом деле не отключали Z-test и не отображаете свои спрайты задом наперед. Альфа-смешивание в GL будет делать то, что вы хотите, только если вы рисуете свои спрайты задом наперед. В противном случае спрайты будут смешаны в неправильном порядке, и это не приведет к правильному результату.

Было бы проще проверить это с помощью изображения того, что вы наблюдаете.

Комментарии:

1. Я попытался использовать шейдер, но безуспешно.

2. Я попытался использовать шейдер, но безуспешно. — Я также вполне уверен, что спрайты отображаются задом наперед, поскольку Z-буфер полностью отключен. В противном случае абсолютно никакая форма альфа-версии не работала бы корректно (в настоящее время работает только непрозрачность «для каждого спрайта»). Я должен повторить эту заметку, что альфа выглядит двоичной. Если альфа-код изображения полностью маскирует какую-либо часть изображения. По сути, он функционирует как двоичный альфа-канал, хотя я точно знаю, что изображения находятся в 32-битном argb (который, конечно, правильно заменен на rgba).

3. Поправьте меня, если я ошибаюсь, но GL_MODULATE приведет к умножению альфа-символов текстуры и лежащего в ее основе полигона (что, конечно, и требуется в исходном вопросе).

4. @Rich: то, что делает GL_MODULATE, зависит от того, каков именно базовый формат текстуры. Но для случаев, в которых есть альфа (I, A, LA, RGBA), да, они умножаются. И да, это то, о чем он просит.