0

我正在将一段非常简单的代码从 OpenGLES 1.0 移植到 OpenGLES 2.0。

在原始版本中,我启用了混合

glEnable(GL_BLEND);
glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

我在我的 ES 2.0 实现中使用了相同的代码,因为我需要将新渲染的四边形与渲染缓冲区中的内容混合(我保留了渲染缓冲区,我无法重新渲染场景)。

我正在使用用作 alpha 蒙版的纹理(alpha 值显示从中心到外部的径向渐变,alpha 从 1 到 0),仅包含具有不同 alpha 值的白色像素。我给我的顶点同样的颜色,比如红色,alpha 为 100/255。我的背景是透明的黑色。在此之下,我有一个纯白色的表面(UIView)。我渲染了 4 个四边形。

OpenGLES 1.0 的结果(期望的结果) 在此处输入图像描述

我的观察告诉我,片段着色器应该是:

gl_FragColor = DestinationColor * texture2D(Texture, TexCoordOut);

(我通过为我的顶点和纹理尝试不同的值得出了这个结论。这也是我在一些教程中读到的。)

我正在尝试编写一些 OpenGL 2.0 代码(包括顶点 + 片段着色器),它会给我与 OpenGLES 1.0 中完全相同的结果,仅此而已。除了在纹理上应用顶点颜色外,我不需要/不想在片段着色器中进行任何类型的混合。使用简单的着色器,这是我得到的结果: 在此处输入图像描述

我尝试了几乎所有我能想到的 *、+、mix 组合,但我无法重现相同的结果。这是迄今为止我得到的最接近的,但这绝对不是正确的(这也没有任何意义)

varying lowp vec4 DestinationColor;
varying lowp vec2 TexCoordOut;
uniform sampler2D Texture;

void main(void) {
    lowp vec4 texture0Color = texture2D(Texture, TexCoordOut);
    gl_FragColor.rgb = mix(texture0Color.rgb, DestinationColor.rgb, texture0Color.a);
    gl_FragColor.a = texture0Color.a * DestinationColor.a;
}

这个着色器给了我以下信息: 在此处输入图像描述

4

3 回答 3

0

通过阅读thisthis,可以构建混合函数。

由于您使用glBlendFunc而不是glBlendFuncSeparate,所有 4 个通道都被混合。使用GL_FUNC_ADD参数将输出 O 设置为O = sS + dD,其中sd是混合参数,S并且D是源颜色和目标颜色。

s参数d由 设置glBlendFuncGL_ONE设置s(1, 1, 1, 1),并GL_ONE_MINUS_SRC_ALPHA设置d(1-As, 1-As, 1-As, 1-As),其中As是源的 alpha 值。因此,您的混合正在执行此操作(以矢量形式):

O = S + (1-As) * D其中 inGLSLO = mix(D, S, As),或: gl_FragColor = mix(DestinationColor, TexCoordOut, As)

如果结果看起来不相似,请确认您没有使用glBlend或任何其他可能会改变最终结果外观的 OpenGL API。如果这没有帮助,请发布不同输出的屏幕截图。

于 2013-07-03T21:11:28.410 回答
0

这不能用着色器轻松完成,因为混合必须读取当前帧缓冲区状态。您可以通过渲染到纹理并将其传递给着色器来实现这一点,如果您可以获得颜色将在帧缓冲区中,那么您就可以了。

你的等式是:

gl_FragColor = wouldBeFramebufferColor + (1-wouldBeFramebufferColor.a) * texture0Color;

但是你为什么要在着色器中这样做 AFAIK 混合在 OpenGL ES 2.0 中没有被删除

于 2013-07-03T21:14:42.487 回答
0

愚蠢的错误。当我传入无符号字节时,我只需要在顶点着色器中标准化顶点颜色。

于 2013-07-04T02:37:04.220 回答