iOS OpenGL ES 2.0, добавляющая текстуры с низкой непрозрачностью на устройстве и в симуляторе

У меня проблема с множественной отрисовкой текстур в моей программе.

Режим наложения

glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glBlendEquation(GL_FUNC_ADD);

Значение a-channel передается в шейдер из cpu-code.

precision highp float;

uniform sampler2D tShape;

uniform vec4      vColor;
uniform float     sOpacity;

varying vec4 texCoords;\n"

void main() {
    float a = texture2D(tShape, texCoords.xy).x * sOpacity;
    gl_FragColor = vec4(vColor.rgb, a);
}

Он рассчитан ранее с

O = pow(O, 1.3);

для лучшего визуального эффекта.

Я рисую цветом (0; 0; 0) на черном прозрачном холсте (0; 0; 0; 0), но с очень низкой непрозрачностью:

0.03 -> 0.01048
0.06 -> 0.0258
0.09 -> 0.0437
0.12 -> 0.0635
...

Я ожидаю, что максимальное значение цвета точки будет (0;0;0;1) (черный, непрозрачный) после многократного рисования как на симуляторе: введите здесь описание изображения

но на устройстве это не так: введите здесь описание изображения

Есть идеи, почему так?

ОБНОВЛЕНИЕ:

Также некорректно работает ручное смешивание (и с отличием от стандартного).

glBlendFunc(GL_ONE, GL_ZERO);

Код фрагментного шейдера:

#extension GL_EXT_shader_framebuffer_fetch : require
precision highp float;

uniform sampler2D tShape;

uniform vec4      vColor;
uniform float     sOpacity;

varying vec4 texCoords;

void main() {
    float a = texture2D(tShape, texCoords.xy).x * sOpacity;
    gl_FragColor = vec4(vColor.rgb * a, a) + (gl_LastFragData[0] * (1.0 - a));
}

Результат на симуляторе: введите здесь описание изображения

Результат на устройстве: введите здесь описание изображения


person George    schedule 15.05.2013    source источник
comment
Можете ли вы опубликовать весь свой фрагментный шейдер? Это может быть какая-то проблема с округлением.   -  person Trax    schedule 15.05.2013
comment
Обновлено (добавлен код фрагментного шейдера)   -  person George    schedule 15.05.2013
comment
Довольно странно, можете ли вы сделать ручное смешивание и вывести 0 при достижении определенного порога? Просто чтобы убедиться, что проблема не в шейдере ваших входных данных. Выходное изображение должно быть черным в определенных областях.   -  person Trax    schedule 15.05.2013
comment
Шейдер и входные данные идентичны на устройстве и симуляторе, но результаты разные. Я думаю, что проблема в особенностях устройства или драйвере OpenGL (округление значений). Этим объясняется некорректная работа на приборе и правильная на тренажере.   -  person George    schedule 16.05.2013


Ответы (2)


Я пытаюсь понять ваш подход, поэтому я записал несколько уравнений:

Вот как выполняется новый рисунок (если не ошибся):

color = {pencil_shape}*sourceAlpha + {old_paint}*(1-sourceAlpha)
alpha = {pencil_shape} + {old_paint}*(1-sourceAlpha)

Таким образом, в основном ваша альфа приближается к 1 на каждом кадре, и ваш цвет каждый раз смешивается на основе альфа-канала src в *pencil_shape*.

Вопросы:

  • Вы собираетесь использовать альфу в выходном изображении для чего-либо?
  • Ваш *pencil_shape* полностью черный (0, 0, 0, 0)? (кроме углов, где, я полагаю, есть эффект сглаживания)
person Trax    schedule 15.05.2013
comment
1 - Да, альфа-канал может использоваться в выходном изображении в будущем. 2 — pencil_shape – это одноканальное изображение с черным (0) фоном и без черных (›0) пикселей формы. - person George; 15.05.2013
comment
srcAlpha = paramAlpha*{pencil_shape}; цвет = paramColor*srcAlpha + {old_paint}*(1-srcAlpha); альфа = srcAlpha + {old_paint}*(1-srcAlpha); - person George; 15.05.2013

После некоторых экспериментов я понял, что проблема в поддерживаемой точности устройства. Так что на iPad Air эта проблема проявляется реже, чем на iPad 4, 3.

person George    schedule 11.07.2014