Pull to refresh

Comments 8

Интересно было бы сравнить результат с простым аддитивным смешиванием (возможно с premultiplied alpha).
Если просто из формулы (2) убрать деление на , то выглядит это так:


Вы это имели в виду?
Думаю, имелось в виду накопление прямо в буфере цвета, когда вместо смешения (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) используется накопление (GL_ONE, GL_ONE), причём цвет прозрачного объекта умножается на альфу. Это, как я понимаю, позволяет получить примерно те же результаты (хотя и с пониженной точностью), но в обычном цветовом буфере вместо сложной конструкции из фреймбуферов, описанной в статье, да ещё и без постпроцессинга.
Если я правильно понял, то это и есть то, что я нарисовал в предыдущем комментарии. Без деления на получается взвешенная сумма цветов вместо взвешенного среднего. Т.е. мы умножаем цвет каждого фрагмента на его альфу, складываем всё это и выводим на экран. Сложная конструкция из фреймбуферов нужна как раз для того, чтобы, во-первых, поделить на , во-вторых, особым образом смешать цвета прозрачных и непрозрачных объектов, раз уж мы решили рисовать их отдельно.

WBOIT, как и обычный блендинг, — это интерполяция; они не допускают того, чтобы цвет вышел за рамки смешиваемых цветов, поэтому они и используются для рендеринга прозрачных объектов. Аддитивное смешивание, насколько я знаю, рекомендуется применять для рисования источников света (частиц огня, например). Оно приводит к бесконтрольному осветлению цветов. Чем больше фрагментов смешивается, тем светлее получается результирующий цвет, вплоть до белого (в большинстве случаев). Это видно на картинке из предыдущего комментария. Единственное, что есть общего с WBOIT — это то, что нет необходимости в сортировке.
Да, это то, что я имел ввиду — накопление как с освещением.
Поскольку приведённые примеры на чёрном фоне — этого должно было быть достаточно для наглядной картинки с наложением.
Это очень простая техника — например ещё до шейдеров в древнем OpenGL прошлого века был буфер накопления (glAccum) c расширенным диапазоном для цветов.
Безусловно есть и недостатки, но на мой взгляд интересно сравнить как это работало 20 лет назад железно и сейчас с шейдерами.

Чтобы быстро не вываливаться в белый — лучше смешивать цвета в линейном цветовом пространстве (переводить из sRGB, работать с линейным, на выводе перевести назад в sRGB — это вроде включается расширением).
Можно добавить некий аналог экспозиции вместо обрезания значений сверху (clamp), выводить 1.0 — exp(-k*c), где с — это значение цвета, a k — некий коэффициент, подобранный чтобы было не слишком светло/темно.
Благодарю за то, что указали на отсутствие гамма-коррекции. Я полез разбираться с этой темой и многое для себя уяснил. У меня и правда отсутствовала гамма-коррекция, и это, наверное, было заметно по плохому антиалиасингу. Вычисления с цветом происходили в линейном пространстве, потом к ним применялась LUT монитора, к этому добавлялась низкая точность хранения тёмных тонов в 8-битном буфере, и получались рваные края примитивов. Теперь цвета преобразуются в линейное пространство перед отправкой в OpenGL, а при выводе на экран — в sRGB (аппаратно). Выглядит получше.

Непонятно, почему в Qt по умолчанию происходит вывод в рендербуфер с линейным цветовым пространством, и для поддержки sRGB приходится настраивать QOpenGLWidget.

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

Если всё ещё интересно, как выглядит аддитивный блендинг с нормальной гамма-коррекцией, то вот, что у меня получилось:



Внизу слева обычный аддитивный блендинг (Вы правы, в белый мы теперь вываливаемся медленнее), справа — с экспозицией 1.0 - exp(-0.8*c).

Теперь пара слов для тех, кто ещё считает, что WBOIT — это аналог аддитивного блендинга, с той же областью применения. Вот на этой картинке сверху видно, что тёмные цвета (у длинных радиальных треугольников с жёлтыми кромками) при аддитивном блендинге практически не влияют на результирующий цвет (именно потому что они тёмные, т.е. имеют маленькие числовые значения). При использовании WBOIT их вклад в результирующий цвет пропорционален значению opacity, они реально могут затемнить свой кусок экрана. Мы вычисляем взвешенную сумму цветов, значит, результат никогда не выйдет за пределы цветов, которые мы смешиваем. Это позволяет использовать метод для рендеринга прозрачных объектов. Аддитивный блендинг (хоть с экспозицией, хоть без) подходит для рендеринга источников света. Результат может выйти за пределы смешиваемых цветов, как в тёмную, так и в светлую сторону.

У меня вышло, что аддитивный блендинг с экспозицией по сравнению с WBOIT — это минус 2 текстуры, минус 1 фреймбуфер, и шейдер конечного постпроцессинга чуть попроще. Положа руку на сердце, это не сильно упрощает рендеринг. К тому же, коэффициент экспозиции надо подбирать для каждой конкретной сцены.
Рад что гамма-коррекцией в OpenGL разобрались, выглядит по-лучше :).
В фотосъёмке экспозицию тоже подбирают для каждого конкретного фото, так что это известная проблема.
У каждого метода свои особенности и область применения, зависит от поставленной задачи. Например, при использовании текстур сеток, решёток, витражей — когда часть текселей полностью непрозрачны (альфа=1) не обойтись без сортировки — результат WBOIT некорректен.
Ну да, я вообще никому не советовал бы использовать WBOIT с альфа > 0,5. В статье это всё объясняется с картинками :)
Sign up to leave a comment.

Articles