У меня было много проблем, пытаясь заставить функцию смешивания OpenGL работать так, как я ожидал, с тем, что я ожидал (или с любой разумной программой для редактирования изображений). В качестве примера, я буду использовать эти два изображения для смешивания (немного сложно увидеть на белом фоне, поэтому цвета помечены):
Изображения для смешивания
Это то, что я ожидаю (и что происходит в paint.net):
ожидаемый результат
Очевидно, что функция смешивания opengl по умолчанию выглядит так (очень неправильно):
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
После тонны тестирования это самое близкое к созданию «хорошей» функции наложения:
glBlendFuncSeparate (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA)
Оглядываясь назад на исходный ожидаемый результат, вы заметите, что некоторые цвета немного тусклее, чем должны быть (средняя левая часть). В частности, они предварительно умножаются на половину значения цвета (из-за альфа-версии .5), и я не могу создать функцию, которая этого не делает (не вызывая странных проблем с смешиванием с едва видимой красной прозрачной частью).
Кто-нибудь знает решение этой проблемы? Я использовал предварительно умноженную альфу в исходных кодах (хотя я не хочу этого делать, потому что это требует дополнительной работы, чтобы преобразовать каждый цвет, который я использую в моей игре, в предварительное умножение или просто написать некоторые вещи в каждом шейдере) и сделать это так. :
glBlendFuncSeparate (GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA) (без предварительного умножения)
Очевидно, это тоже неправильно, но на самом деле это единственный правильный результат, который я получил до сих пор:
glBlendFuncSeparate (GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA) (предварительно умноженные входы)
Единственная проблема в том, как мне избавиться от предварительного умножения, чтобы отобразить его на экране? Вероятно, потребуется дополнительный цикл рендеринга для каждой вещи, которую я смешиваю, и это кажется слишком сложным для этой проблемы, поэтому я все еще ищу ответ (интересно, что я ничего не могу найти по этому вопросу, потому что OpenGL настолько широко используется, что Я представляю, кто-то другой столкнулся с этой проблемой).
Источники:
Онлайн-тестирование функции смешивания - http://www.andersriggelsen.dk/glblendfunc.php
Изображение нижнего слоя - http://i.stack.imgur.com/XjLNW.png
Изображение верхнего слоя - http: //i.stack.imgur .com / 9CN6w.png
источник
Ответы:
В первом примере (
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
) вы говорите смешивать цвета на основе альфа-изображения изображения, которое рисуется сверху («переднего плана»). Поэтому, когда вы смешиваете 50% между цветом переднего плана и цветом(38,50,168)
фона(38,50,168)
в левом нижнем углу изображения, неудивительно, что вы получаете точно такой же цвет(38,50,168)
. Потому что именно это смешивание - именно то, что вы сказали OpenGL.Судя по вашему «ожидаемому» изображению, вы не хотите делать перекрестное смешение между двумя цветами - вы хотите наложить цвет переднего плана поверх полноцветного цвета фона, а не смешивать между ними.
Чтобы сделать это, вы хотите использовать glBlendFuncSeparate (так как вы обрабатываете цвет фона иначе, чем его альфа), и указать, что во время операции наложения значение альфа фонового значения должно рассматриваться как 100%.
Для облегчения просмотра вот вывод окончательных значений RGB:
И вот окончательные значения прозрачности выводятся.
(Эта область прозрачности «100%» на самом деле должна быть помечена как прозрачная на 99,7%, а нижняя правая область «50%» должна быть помечена как прозрачная на 49,7%, оба из-за красного цвета на правой стороне первого изображения). Кроме того, извините за перечисление номеров с использованием «прозрачности», а не непрозрачности, возможно, немного запутывает.)
Если есть конкретные проблемы, укажите область RGB или альфа-изображения, которые выдают неправильные значения.
источник
GL_ONE
таким же? В противном случае уравнение альфа выглядит следующим образомdest_alpha = src_alpha * src_alpha + 1 * dest_alpha
(0,0,0)
. Из Конечно , это темнее , чем когда вы смешиваете его на 50% против(255,255,255)
.finalAlpha = srcAlpha + destAlpha * (1 - srcAlpha)
и бит в расчете цвета может быть сделано в шейдерах путем вывода предварительно умноженных значений, но Тереза нет способа разделить на finalAlpha , чтобы избавиться от premultiplication. (Взято отсюда )finalColor = ((srcColor * srcAlpha) + (destColor * destAlpha * (1 - srcAlpha))) / finalAlpha
Color * Alpha
У меня была точно такая же проблема, когда я хотел визуализировать набор перекрывающихся объектов кадрового буфера, таких как слои. Проблема заключается в том, что функции смешивания Open GL являются линейными, и они работают, когда фон назначения является непрозрачным. Но фактическое уравнение смешивания для смешивания двух прозрачных слоев не является линейным уравнением и содержит разделительную часть.
out_color = {src_color * src_alpha + dest_color * dest_alpha * (1-src_alpha)} / out_alpha
Я не думаю, что это возможно сделать с текущими реализациями OpengGL. Поэтому в качестве обходного пути мне пришлось использовать пиксельный шейдер, чтобы вручную вычислить выход каждого пикселя.
источник