我正在将一个非常简单的代码从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从1到0),用作alpha蒙版,仅包含具有不同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;
}
这个着色器给了我以下内容:
答案 0 :(得分:0)
由于您使用的是glBlendFunc
而非glBlendFuncSeparate
,因此所有4个频道都在混合使用。使用GL_FUNC_ADD
参数将输出O设置为O = sS + dD
,其中s
和d
是混合参数,S
和D
是源和目的地颜色。
s
和d
参数由glBlendFunc
设置。 GL_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
GLSL
中的{p> O = mix(D, S, As)
,或者:
gl_FragColor = mix(DestinationColor, TexCoordOut, As)
。
如果结果看起来不相似,请确认您没有使用glBlend
或任何其他可能会改变最终结果外观的OpenGL API。如果这没有帮助,请发布不同输出的屏幕截图。
答案 1 :(得分:0)
使用着色器无法轻松完成此操作,因为混合必须读取当前帧缓冲状态。 您可以通过渲染纹理并将其传递到着色器来实现此目的,如果您可以在帧缓冲区中获得颜色,那么您就可以了。
你的等式是:
gl_FragColor = wouldBeFramebufferColor + (1-wouldBeFramebufferColor.a) * texture0Color;
但为什么要在着色器中进行此操作AFAIK混合未在OpenGL ES 2.0中删除
答案 2 :(得分:0)
愚蠢的错误。我只需要在顶点着色器中对顶点颜色进行标准化,因为我正在传递无符号字节。