片段着色器输出会干扰条件语句

时间:2018-02-27 11:03:58

标签: ios opengl-es opengl-es-2.0

背景信息:我在iOS 11上使用OpenGLES 2进行以下所有操作

在实现用于将两个纹理混合在一起的不同混合模式时,我遇到了一个奇怪的问题,我设法将其缩减为以下内容:

我试图将以下两个纹理混合在一起,只使用片段着色器而不是OpenGL混合函数或方程。 GL_BLEND已停用。

底部 - dst:

enter image description here

热门 - src:

enter image description here

(底部图像与顶部图像相同,但旋转并混合到不透明的白色背景上,使用"普通"(如在Photoshop'普通'中)混合)

为了进行混合,我使用

#extension GL_EXT_shader_framebuffer_fetch

extension,所以在我的片段着色器中我可以写:

void main()
{
    highp vec4 dstColor = gl_LastFragData[0];
    highp vec4 srcColor = texture2D(textureUnit, textureCoordinateInterpolated);

    gl_FragColor = blend(srcColor, dstColor);
}

blend不执行任何混合。它仅根据统一的blendMode整数值选择要应用的正确混合函数。在这种情况下,第一个纹理使用已经测试的普通混合函数绘制,然后使用以下blendTest函数在顶部绘制第二个纹理:

现在问题就在这里:

highp vec4 blendTest(highp vec4 srcColor, highp vec4 dstColor) {

    highp float threshold = 0.7; // arbitrary
    highp float g = 0.0;

    if (dstColor.r > threshold && srcColor.r > threshold) {
        g = 1.0;
    }

    //return vec4(0.6, g, 0.0, 1.0); // no yellow lines (Case 1)
    return vec4(0.8, g, 0.0, 1.0); // shows yellow lines (Case 2)
}

这是我期望的输出(在Photoshop中制作):

enter image description here

在两个纹理都包含大于任意阈值的红色的区域中,所有处都是红色和绿色/黄色。

但是,我得到的结果由于某种原因取决于我为红色分量(0.60.8)选择的输出值,并且这些输出都不匹配预期的输出值。 这就是我所看到的(灰色边框只是背景):

案例1:

enter image description here

案例2:

enter image description here

总结一下:如果我返回一个大于阈值的红色值,例如

return vec4(0.8, g, 0.0, 1.0);

我看到垂直的黄线,而如果红色组件小于阈值,则结果中没有黄色/绿色。

问题:

为什么我的片段着色器的输出决定条件语句是否被执行,即便如此,为什么我最终会使用绿色垂直线而不是绿色框(这表示dstColor未被正确读取)?

是否与我正在使用的扩展程序有关?

我还想指出纹理都被正确加载和绑定。如果我只是在没有混合的情况下返回单独的纹理信息,或者甚至使用我已经实现的一切正常混合功能,我可以看到它们很好。

1 个答案:

答案 0 :(得分:0)

我发现问题是什么(我意识到这不是任何人只是通过阅读问题就知道的事情):

您可以在上面看到的两个纹理之间绘制一个额外的完全透明纹理,这是我忘记的。

透明纹理的颜色信息(dstColor,而不是考虑到这一点,只是在srcColor alpha为0的情况下返回(0.0, 0.0, 0.0, 0.0)。 )在混合时使用,因此改变帧缓冲内容。

透明纹理和最终纹理都是使用blendTest函数绘制的,因此在混合最终纹理时会读入第一个函数调用的输出。