ИЗМЕНИТЬ
Кисть для наложения -> слой -> фон
Хорошо, происходит то, что glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
работает для смешивания мазков кисти с текстурой кисти, но результирующие альфа-значения в текстуре неверны. Каждый добавленный фрагмент должен 1. добавить его альфа к окончательному значению альфа - он должен удалить ровно столько света для взаимодействия и 2. масштабировать предыдущую альфу на остаток - предыдущие поверхности уменьшают свет на предыдущее значение, но поскольку добавляется новая поверхность, меньше света для их уменьшения. Я не уверен, что это имело смысл, но это приводит к следующему ...
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
Теперь цветовой канал текстуры кисти содержит общий цвет, который должен быть смешан с фоном (предварительно умноженный на альфа), а альфа-канал дает вес (или степень, в которой цвет закрывает фон). Поскольку цвет предварительно умножается на альфа, смешивание RenderTexture по умолчанию GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA
масштабируется с альфа снова и, следовательно, затемняет общий цвет. Теперь вам нужно смешать текстуру кисти с фоном, используя следующую функцию, которая, как я понимаю, должна быть установлена в Cocos2D:
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
Надеюсь, это возможно. Я не особо задумывался о том, как управлять возможностью настройки текстуры кисти для смешивания с GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA
, но может потребоваться текстура с плавающей запятой и / или дополнительный проход для разделения / нормализации альфа-канала, что звучит болезненно.
В качестве альтернативы, перед рисованием добавьте фон в текстуру рендеринга и оставьте там участок без смешивания слоев.
Это сработало для меня:
glDisable(GL_DEPTH_TEST);
glClear(GL_COLOR_BUFFER_BIT);
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
fbo.bind();
glClear(GL_COLOR_BUFFER_BIT);
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
drawTexture(brush1);
drawTexture(brush2);
fbo.unbind();
drawTexture(grassTex); //tex alpha is 1.0, so blending doesn't affect background
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
drawTexture(fbo.getColour(0)); //blend in the brush layer
Непрозрачность слоя кисти
Использование GL_ONE, GL_ONE_MINUS_SRC_ALPHA
вызывает проблемы с реализацией прозрачности в библиотеке при наложении слоев, поскольку предполагается, что цвет умножается на альфа-канал. При уменьшении значения opacity
альфа слоя кисти уменьшается во время смешивания. GL_ONE_MINUS_SRC_ALPHA
затем увеличивает количество цвета фона, однако GL_ONE
суммирует 100% слоя кисти и перенасыщает изображение.
Самое простое решение - это найти способ самостоятельно уменьшить цвет на глобальную непрозрачность слоя и продолжать использовать GL_ONE, GL_ONE_MINUS_SRC_ALPHA
.
- На самом деле использование
GL_CONSTANT_COLOR, GL_ONE_MINUS_SRC_ALPHA
могло бы быть ответом, если бы библиотека поддерживала его, но, по-видимому, это не так.
- Вы можете использовать фиксированный рендеринг конвейера для масштабирования цвета:
glColor4f(opacity, opacity, opacity, opacity)
, но для этого потребуется вторая цель рендеринга и выполнение смешивания вручную, как и в приведенном выше коде, где вы рисуете полноэкранный четырехугольник один раз для фона и еще раз для слоя кисти. .
- Если вы выполняете смешивание вручную, было бы более надежным использовать фрагментный шейдер вместо метода
glColor
. Это даст гораздо больший контроль, если вы когда-нибудь захотите поиграть с более сложными функциями смешивания, особенно когда речь идет о делениях и временных изменениях за пределами диапазона от 0 до 1: gl_FragColour = texture(brushTexture, coord) * layerOpacity;
КОНЕЦ РЕДАКТИРОВАНИЯ
Стандартная функция альфа-смешивания - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
, а не "начальная" функция / функция по умолчанию GL.
Суммирование альфа-значений, как в glBlendFuncSeparate, приведет к перенасыщению альфа-канала, и нижний цвет будет полностью заменен. Смешивание насыщенности может дать достойные результаты: glBlendFunc(GL_SRC_ALPHA_SATURATE, GL_ONE)
. Возможно, стоит поэкспериментировать с glBlendEquationSeparate и смешиванием MAX, если оно поддерживается. Преимущество игры с MAX будет заключаться в уменьшении перекрывающихся артефактов (жестких треугольных битов) из кода рисования линии - например, замена цвета, но только до тех пор, пока не будет достигнуто общее альфа-значение X. РЕДАКТИРОВАТЬ: в обоих случаях потребуется наложение и очистка после каждого штриха.
Я могу только предположить, что наложение текстуры рендеринга на фон действительно работает. (не для текущих значений слоя)
С одной стороны, и в значительной степени не имеющей отношения к этому, есть также "Under Blending", где вы сохраняете значение коэффициента пропускания вместо alpha / opacity (из здесь):
glBlendEquation(GL_FUNC_ADD);
glBlendFuncSeparate(GL_DST_ALPHA, GL_ONE, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA);
person
jozxyqk
schedule
11.09.2013