在同一纹理中多次渲染迭代的Alpha混合问题(OpenGL)

在同一纹理中多次渲染迭代的Alpha混合问题(OpenGL),opengl,opengl-es,rendering,framebuffer,alphablending,Opengl,Opengl Es,Rendering,Framebuffer,Alphablending,场景 我正在创建帧缓冲区对象并将纹理绑定到颜色附件0。我没有使用深度缓冲区。创建后,我将其解除绑定 在稍后的某个时间点,绑定帧缓冲区,向其渲染三角形条带(某些部分部分透明),然后再次解除绑定。用不同的三角形条重复多次 最终,绘制到主帧缓冲区的是一个带纹理的四边形,其纹理附着到我创建的帧缓冲区对象 问题 我发现绘制到纹理中的三角形条带的部分透明部分与其他三角形条带重叠,没有正确混合。它们似乎与白色混合,而不是纹理中已有的颜色。即使我用纯绿色填充纹理(例如),混合时拾取的颜色仍然是白色 下面是我用来

场景

我正在创建帧缓冲区对象并将纹理绑定到颜色附件0。我没有使用深度缓冲区。创建后,我将其解除绑定

在稍后的某个时间点,绑定帧缓冲区,向其渲染三角形条带(某些部分部分透明),然后再次解除绑定。用不同的三角形条重复多次

最终,绘制到主帧缓冲区的是一个带纹理的四边形,其纹理附着到我创建的帧缓冲区对象

问题

我发现绘制到纹理中的三角形条带的部分透明部分与其他三角形条带重叠,没有正确混合。它们似乎与白色混合,而不是纹理中已有的颜色。即使我用纯绿色填充纹理(例如),混合时拾取的颜色仍然是白色

下面是我用来完成所有这些工作的一些代码片段:

初始化

渲染到纹理(在上迭代)

将纹理渲染到主帧缓冲区

我所看到的例子

看到白线的部分是三角形条重叠的部分。它们应该是部分透明的,并与先前绘制的黑色混合

更新

自从我发布这篇文章以来,我有了一些发现:

  • “白色”部分实际上是完全透明的,因此它只显示纹理后面渲染的任何颜色
  • 我将更复杂的三角形网格替换为随机放置的正方形,这些正方形由顶点组成,这些顶点从正方形一侧的完全透明变为另一侧的完全不透明,我看不到相同的混合问题。这是正方形的图片:

所以这似乎是我使用的三角形网格的问题,而不是混合


事实上,仔细观察“良好混合”图像,我可以看到,当另一个正方形在其上方渲染时,正方形的完全不透明部分实际上被照亮了。所以问题就在这里,它并没有那么极端。

当渲染到纹理时,请尝试

glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE);
而不是:

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
在这种情况下,渲染到纹理时,alpha通道也会混合

为了让事情更清楚,我们考虑在一个不透明的三角形条带上渲染半透明的边缘。让边缘的alpha值为0.5(源alpha),渲染缓冲区中的alpha值为1.0(目标值)。因此,结果值为:

r = SrcAlpha * SrcAlpha  + DstAlpha * (1.0 - SrcAlpha) = 0.5 * 0.5 + 0.5 * 0.5 = 0.5
如您所见,渲染缓冲区中alpha的值不等于1.0,正如您所期望的那样。因此,源颜色将与主帧缓冲区中的目标颜色混合

因此,不需要混合alpha通道。例如,您可以简单地将源alpha值添加到目标alpha值,这可以通过使用glBlendFuncSeparate为alpha通道指定不同的混合函数来实现

有关更多详细信息,请参阅和

另外,请确保已设置了适当的混合方程式:

glBlendEquation(GL_FUNC_ADD);

有关更多详细信息,请参见

我无法完全解释“白色”部分。我认为把FBO清除为黑色可能会得到最好的结果。您正在使用着色器吗?片段着色器是否生成正确的alpha值?无论如何,这看起来与我之前详细回答的一个问题(赏金!)非常相似,也许会有所帮助:。我尝试过将FBO清除为各种颜色,但没有成功。是的,我正在使用顶点和片段着色器(非常类似于OpenGL ES 2.0编程指南第8章中的着色器)。我确实看到了另一个问题,我尝试了很多不同的混合函数,但都没有用。请看我上面的更新——我相信这是三角形网格的问题。非常好的建议(如果可以的话,我会投票支持这个答案)!我以前使用过glBlendFuncSeparate(),但没有使用这些特定参数。我尝试了你的两个建议,但还是没有成功。它似乎与三角形网格中使用的顶点有关,在我的纹理中打了一些“洞”。忽略最后的评论。我忘记了三角形网格渲染正在进行批处理,并且批处理渲染器应用了自己的混合功能。一旦我把你的混合方程放入批渲染器,它就解决了这个问题!
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
r = SrcAlpha * SrcAlpha  + DstAlpha * (1.0 - SrcAlpha) = 0.5 * 0.5 + 0.5 * 0.5 = 0.5
glBlendEquation(GL_FUNC_ADD);