【问题标题】:Blending issue porting from OpenGLES 1.0 to 2.0 (iOS)从 OpenGLES 1.0 移植到 2.0 (iOS) 的混合问题
【发布时间】:2013-07-03 20:15:25
【问题描述】:

我正在将一段非常简单的代码从 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;
}

这个着色器给了我以下信息:

【问题讨论】:

  • 抱歉,您的问题对我来说有点不清楚。你需要的究竟是什么结果?你也在 ES 2.0 中使用混合吗?
  • 如果不清楚,我深表歉意。是的,我以同样的方式在 ES 2.0 中启用了混合。我基本上需要与 ES 1.0 中相同的结果,但无法清楚地描述它。我试图描述我是如何在 ES 1.0 中进行设置的。可能还不够……
  • 我觉得这个问题现在应该清楚很多了

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


【解决方案1】:

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

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

sd 参数由glBlendFunc 设置。 GL_ONEs 设置为(1, 1, 1, 1)GL_ONE_MINUS_SRC_ALPHAd 设置为(1-As, 1-As, 1-As, 1-As),其中As 是源的alpha 值。因此,您的混合正在这样做(以矢量形式):

O = S + (1-As) * DGLSL 中是O = mix(D, S, As),或者: gl_FragColor = mix(DestinationColor, TexCoordOut, As).

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

【讨论】:

  • 我想我需要像 Vasaka 指出的那样继续混合(除非我渲染到纹理并读取着色器中的现有帧缓冲区)。我认为我需要的只是一种将顶点颜色应用于我的纹理的方法,就像在 ES 1.0 中所做的那样
【解决方案2】:

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

你的方程式是:

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

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

【讨论】:

  • 我根本不想在着色器中进行混合。我只需要将我的代码移植到 OpenGL 2.0 即可尝试最近在 iOS 中添加的实例化绘图。我只是想复制与我的 OpenGL 1.0 代码完全相同的东西。
  • 刚刚发布的图片,也许会有帮助
  • 我同意使用glBlend。但是,从 iOS 6 开始,这可以通过使用 GL_EXT_shader_framebuffer_fetch 扩展名使用着色器来完成。
【解决方案3】:

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

【讨论】:

  • 作为提示,您不需要自己对它们进行规范化。这正是glVertexAttribPointer(您可能一直设置为GL_FALSE)的normalize 参数的用途。
  • 如果它是您问题的解决方案,请随时 accept 您的最佳答案。
  • 需要等待 48 小时...但会的
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-10
  • 1970-01-01
  • 2014-05-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多