GLKit не отображает текстуру при использовании GL_MODULATE с альфа-каналом в цвете вершины

У меня есть изображение текстуры, которое я использую с GLKit. Если я использую GL_MODULATE для текстуры и имею вершину RGBA (1.0, 1.0, 1.0, 1.0), тогда текстура отображается полностью, как это было бы в GL_REPLACE. Полностью непрозрачный. Затем, если я использую красный (1.0, 0.0, 0.0, 1.0) для вершинного RGB, текстура снова отображается как красный, модулирующий текстуру. Все идет нормально. Но когда я изменяю прозрачность цвета вершины и использую RGBA (1.0, 0.0, 0.0, 0.5), тогда виден только светло-красный цвет, а текстура не видна, поэтому цвет полностью заменяет текстуру. Сама текстура не имеет альфы, это текстура RGB565.
Я использую GLKit с GLKTextureEnvModeModulate.

self.effect.texture2d0.envMode = GLKTextureEnvModeModulate;

Любая помощь в том, почему текстура исчезнет, ​​когда я укажу альфу?

Добавление снимков:


Исходная текстураЭто исходная текстура.


RGBA (1.0, 1.0, 1.0, 1.0)RGBA (1.0, 1.0, 1.0, 1.0) - белый цвет, без предварительного умножения, непрозрачный, текстура видна


RGBA (1.0, 1.0, 1.0, 0.5)RGBA (1.0, 1.0, 1.0, 0.5) - белый цвет, без предварительного умножения, альфа = 0,5, текстура потеряна


RGBA (1.0, 0, 0, 1.0)RGBA (1.0, 0, 0, 1.0) - красный цвет, без предварительного умножения, непрозрачный, текстура видна


RGBA (1.0, 0, 0, 0.5)RGBA (1.0, 0, 0, 0.5) - красный цвет, без предварительного умножения, альфа = 0,5, текстура потеряна


RGBA (0.5, 0, 0, 0.5) - после предварительного вычисления a = 0.5 на @andonRGBA ( 0,5, 0, 0, 0,5) - красный цвет, предварительное умножение, альфа = 0,5 на @andon, текстура видна, но вам может потребоваться увеличить, чтобы увидеть ее


RGBA (0.1, 0, 0, 0.1) - после предварительного вычисления a = 0.5 на @andonRGBA ( 0,1, 0, 0, 0,1) - красный цвет, предварительное умножение, альфа = 0,1 на @andon, текстура потеряна, вероятно, из-за недостаточного контраста


RGBA (0.9, 0, 0, 0.9) - после предварительного вычисления a = 0.5 на @andonRGBA ( 0,9, 0, 0, 0,9) - красный цвет, предварительное умножение, альфа = 0,9 на @andon, текстура видна, но вам может потребоваться увеличить, чтобы увидеть ее


person nishant    schedule 12.03.2015    source источник
comment
Сама текстура не имеет альфы. Таким образом, при загрузке он генерирует изображение 565 RGB. Полагаю, это означает, что альфа равна 1 и умножена на предварительное умножение. Моя функция смешивания предназначена для предварительного умножения - One, One - Src. Я экспериментирую, если 565 сам по себе является проблемой, и почему-то шейдеры GLKit не работают, если отсутствует альфа текстуры. Итак, мой следующий план - создать текстуру с альфа-каналом, даже если она равна 1, и посмотреть, работает ли GLKit по-другому.   -  person nishant    schedule 13.03.2015
comment
Как я уже сказал, альфа уже является константой 1.0, когда вы используете 565 (или любой другой формат RGB). Это всего лишь одна из тех вещей, которые GL делает за вас автоматически: четвертому компоненту атрибута вершины или цвету присваивается 1.0, если он не сохранен явно. Учитывая вашу функцию наложения, вы должны соответствующим образом отрегулировать цвет вершины, что означает умножение ее RGB на ее A.   -  person Andon M. Coleman    schedule 13.03.2015


Ответы (1)


Сама текстура не имеет альфы, это текстура RGB565.

RGB565 неявно имеет постоянную альфа (непрозрачность - ›1.0). Это может показаться неважным, но изменение цвета вершины цветом текстуры выполняет покомпонентное умножение, и это вообще не сработало бы, если бы альфа не была равна 1.0.

Моя функция смешивания предназначена для предварительного умножения - One, One - Src.

Это требует предварительного умножения компонентов RGB цвета вершины на компонент A. Все цвета должны быть предварительно умножены, включая цвета текселей и вершин.

Вы можете увидеть почему ниже:

Vtx = (1.0, 0.0, 0.0, 0.5)
Tex = (R,   G,   B,   1.0)

// Modulate Vertex and Tex
Src = Vtx * Tex = (R, 0, 0, 0.5)

// Pre-multiplied Alpha Blending (done incorrectly)
Blend_RGB = Src * 1    +  (1 - Src.a) * Dst
          = Src        +          Dst / 2.0
          = (R, 0, 0)  +          Dst / 2.0

Единственное, что это делает, - это делит целевой цвет на 2 и добавляет к нему неизменный исходный цвет. Это предполагается, чтобы напоминать линейную интерполяцию (a * c + (1 - c) * b).

Правильное смешивание должно выглядеть так:

// Traditional Blending
Blend_RGB = Src * Src.a   +  (1 - Src.a) * Dst
          = (0.5R, 0, 0)  +          Dst / 2.0

Этого можно добиться с помощью исходной функции наложения, если вы умножите часть RGB цвета вершины на A.

Правильное альфа-смешение с предварительным умножением (путем предварительного умножения цвета вершины):

Vtx = (0.5, 0.0, 0.0, 0.5) // Pre-multiply: RGB *= A
Tex = (R,   G,   B,   1.0)

// Modulate Vertex and Tex
Src = Vtx * Tex = (0.5R, 0, 0, 0.5)

// Pre-multiplied Alpha Blending (done correctly)
Blend_RGB = Src * 1       +  (1 - Src.a) * Dst
          = (0.5R, 0, 0)  +          Dst / 2.0
person Andon M. Coleman    schedule 13.03.2015
comment
Это было очень полезно и очень хорошо объяснено. Спасибо. Я полностью пропустил предварительное умножение цвета вершины. Тем не менее, я до сих пор не уверен, почему исчезла текстура. В моем случае у меня есть текстура в виде более темных серых заштрихованных линий на светло-сером фоне. Итак, после объяснения того, как это работает, не должен ли я по-прежнему видеть красный компонент заштрихованных линий? Так какие-то красные заштрихованные линии на красном фоне? Возможно, я плохо обдумываю это, поэтому я попытаюсь также предварительно умножить цвет вершины и посмотреть, верну ли я заштрихованные линии. Я отчитаюсь. - person nishant; 13.03.2015
comment
хорошо, я думаю, что все так, как вы это сказали. Я пытаюсь использовать высокую прозрачность, то есть низкую альфа-канал. И когда я делаю это и умножаю предварительно, это снижает и красное значение, так что разница между заштрихованными линиями и фоном незначительна. Итак, они исчезают. Я пробовал несколько значений между R и A, и были некоторые, где появлялись заштрихованные линии. Так что, возможно, мне нужно начать с более темных заштрихованных линий на изображении, чтобы это сработало. Но ваше объяснение это прибило. Спасибо за потрясающую ясность вашего ответа (и за математику). - person nishant; 13.03.2015
comment
Я думаю, что моя текстура была слишком тонкой, и при модуляции цвет вершины подавляет небольшие различия, поэтому цвет вершины был всем, что осталось после модуляции. Я думаю, это эффект умножения. - person nishant; 13.03.2015
comment
@nishant: Если вы можете приложить скриншот, я могу взглянуть на него утром. Возможно, мне нужно добавить некоторые дополнительные детали. Если это для наложения нескольких слоев, то необходимо будет обсудить альфа-часть уравнения смешения (вы заметите, что указанное уравнение смешения предназначено только для RGB - я сделал это для простоты). - person Andon M. Coleman; 13.03.2015
comment
добавлены в снимки. @andon Я также добавил их после предварительного умножения. Текстура присутствует, даже если она кажется едва заметной. Возможно, вам придется увеличить браузер, чтобы увидеть это. - person nishant; 13.03.2015
comment
@nishant: Я считаю, что это нормально. Вы можете попробовать очистить буфер цвета до (0.0f, 0.0f, 0.0f, 1.0f), чтобы увидеть, выявляются ли при этом скрытые детали на предпоследнем изображении. Я думаю, что чистый цвет подавляет то небольшое количество цвета, которое присутствует в модулированной текстуре во время смешивания. - person Andon M. Coleman; 13.03.2015
comment
хорошо, я тоже попробую! Спасибо за помощь в этом. Очень ценится. Вы научили меня математически думать о смешивании tex env +, и это упростит работу. - person nishant; 14.03.2015