使用透明度渲染纹理时,OpenGL出现多余像素

3
我已经苦恼了一段时间。当我使用OpenGL渲染2D纹理时,这些纹理在不透明和半透明之间的过渡处有透明度值,会出现一些令人讨厌的灰色像素,我认为这是像素值插值的产物。您有什么好的改进方法吗?
我附上一张图片来说明我的问题:红箭头显示了一些不想要的像素可见部分 虽然我认为这不会有任何区别,但我正在使用Qt创建QGLWidget和C++。
解决方案: 我一直在尝试解决这个问题。我尝试使用带有预乘alpha通道的图像,为颜色和alpha使用单独的混合函数...对我来说没有什么效果,我可能做错了,我不知道。对我而言,有效的方法是在Adobe Illustrator上导出带有反锯齿的png图像,使用glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)。
希望这能帮助其他遇到同样问题的人 :)
再次感谢您的回答。

2
了解预乘 alpha 的工作原理。 - Nicol Bolas
1个回答

3
简短回答:Nicol Bolas是正确的,你应该研究预乘alpha,以下是解释这个问题的数学原理。
为什么它不会正确工作:
使用非预乘alpha时,当你将带有颜色和alpha(CS,αS)的源纹理合成到目标(CD,αD)上时,你得到以下公式:
C = αS CS + (1 - αS) CD 现在,如果我们有两个纹理层,首先是(C1,α1),然后是(C2,α2),我们得到以下公式:
C = α2 C2 + (1 - α2) (α1 C1 + (1 - α1) CD)
如果我们想用一个预合成纹理一步完成此操作,就像你渲染到纹理的方式一样,我们需要重新排列此公式以匹配原始公式:
C = (α2 C2 + (1 - α2) α1 C1) + (1 - α2) (1 - α1) CD αS CS = α2 C2 + (1 - α2) α1 C1 (1 - αS) CD = (1 - α2) (1 - α1) CD 我们可以解出αS
αS = 1 - (1 - α1) (1 - α2) = α1 + α2 - α1 α2 但当我们解出CS时:

CS = (α2 C2 + (1 - α2) α1 C1) / (α1 + α2 - α1 α2)

但如果alpha是预乘的呢?预乘的alpha混合公式不同:

C = CS + (1 - αS) CD

对于两个纹理,我们有:

C = C2 + (1 - α2) (C1 + (1 - α1) CD)

通过重新排列以匹配第一个公式,我们得到:

C = C2 + (1 - α2) C1 + (1 - α2) (1 - α1) CD

然后我们解决:

αS = 1 - (1 - α1) (1 - α2) = α1 + α2 - α1 α2

CS = C2 + (1 - α2) C1

这与第一个公式完全相同:

glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

因此,如果您对所有纹理使用预乘α,则所有数学计算都可以完美地运行,您不必担心这些问题。只需在所有地方使用相同的混合函数,使用预乘α,并且可以按任何顺序组合物品。

预乘α还可以正确插值,非预乘α则不是这种情况,但这是一个单独的问题。

摘要

预乘合成运算符是可关联的,这意味着您可以将一堆图层压缩成一个纹理,以完全希望的方式。

没有预乘α,数学计算结果与您想要的不同。


非常抱歉回复这么晚。使用glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA),我只能得到白色,而不是应该有的alpha值... - Pedro Leal
@PedroLeal:你的纹理首先必须是预乘 alpha 格式。你不能只改变混合模式并期望它能正常工作。 - Dietrich Epp
好的,我会仔细看一下。我只是匆匆浏览了一下,发现除了更改混合模式之外还有更多需要注意的地方。谢谢@Dietrich。 - Pedro Leal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接