Правильный способ стирания для смешивания краски с промежуточными кадровыми буферами - PullRequest
0 голосов
/ 10 июня 2019

Моя сцена состоит из слоев, которые отображаются в кадровые буферы. Внутри кадровых буферов элементы рисуются спереди назад и смешиваются с ColorWithAlpha или EraseWithAlpha. Кадровые буферы смешиваются с соответствующими версиями * WithPremultipliedAlpha. Следующий код контролирует смешивание:

switch (m_blendMode)
{
case BlendMode::ColorWithAlpha:
{
    glBlendEquation(GL_FUNC_ADD);
    glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
    break;
}
case BlendMode::ColorWithPremultipliedSrcAlpha:
{
    glBlendEquation(GL_FUNC_ADD);
    glBlendFuncSeparate(GL_ONE, GL_ONE, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
    break;
}
case BlendMode::EraseWithAlpha:
{
    glBlendEquation(GL_FUNC_ADD);
    glBlendFuncSeparate(GL_ZERO, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA);
    break;
}
case BlendMode::EraseWithPremultipliedSrcAlpha:
{
    glBlendEquation(GL_FUNC_ADD);
    glBlendFuncSeparate(GL_ZERO, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA);
    break;
}

Я изо всех сил пытаюсь стереть работу через границы буфера кадра. Рисование всех элементов спереди в один кадровый буфер с использованием ColorWithAlpha является эквивалентом рисования всех элементов, кроме одного, в один кадровый буфер, а затем рисование конечного слоя в отдельном кадровом буфере с использованием ColorWithAlpha, а затем смешивание отдельного кадрового буфера с оригиналом с использованием ColorWithPremultipliedAlpha. То же самое не верно для стирания. Я попытался отрисовать слои назад, используя ColorWithAlpha, а затем EraseWithPremultipliedAlpha, чтобы смешать целевое FBO с Dest FBO. К сожалению, это не эквивалентно рисованию всех элементов в верхнем FBO непосредственно в dest FBO с помощью EraseWithAlpha. Можно ли сделать режим стирания наложения ассоциативным, включив ту же настройку, что и в режимах раскраски? Если нет, существует ли режим псевдо-стирания, который является ассоциативным и может быть заменен здесь?

1 Ответ

0 голосов
/ 12 июня 2019

Математика верна.Оказалось, что это вызвано артефактами квантования в альфа-канале.Усечение с плавающей точкой уменьшает накопленную альфу, когда слои, предназначенные для стирания, отрисовываются на передний план с помощью ColorWithAlpha в промежуточный кадровый буфер.Итоговая альфа:

destAlpha * (1 - (a [i] + ((1 - a [i]) a [i-1]) ...)

, куда я идуот 0 до количества слоев - 1. При обратном отображении с использованием EraseWithAlpha, альфа-результат будет

destAlpha [i] * (1 - a [i])

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

...