我一直在努力解决这个问题。当我使用OpenGL渲染2D纹理时,在无透明度和一些透明度之间的过渡上具有透明度值,我得到一些恼人的灰色像素,我认为这是像素值插值的产物。关于如何改进的想法?
不是我认为它会有所作为,但我正在使用Qt来创建QGLWidget和C ++。
解决:
我一直试图解决这个问题。我尝试使用带有预乘Alpha通道的图像,使用单独的颜色和alpha混合函数...对我来说没有任何效果,我可能做错了,我不知道。对我来说,使用抗锯齿导出 .png 图像是有效的:Adobe Illustrator上的类型优化(提示)并使用glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
希望这有助于解决同样问题的其他人:)
再次感谢你的帮助。
答案 0 :(得分:3)
简短的回答:Nicol Bolas是对的,你应该调查预乘的alpha,这是解释原因的数学。
以下是非预乘alpha的工作原理。
将源纹理与颜色和alpha(C S ,α S )合成到目标(C D ,α< sub> D ),你得到公式:
C =α S C S +(1 - α S )C D
现在,如果我们有第二层纹理,首先(C 1 ,α 1 )然后(C 2 ,α 2 ),我们得到公式:
C =α 2 C 2 +(1 - α 2 )(α 1 C 1 +(1 - α 1 )C D )
如果我们想要使用预合成纹理一步完成此操作,就像渲染到纹理一样,我们需要重新排列此公式以匹配原始公式:
C =(α 2 C 2 +(1 - α 2 )α 1 C 1 )+(1 - α 2 )(1 - α 1 )C D
α S C S =α 2 C 2 +(1 - α 2 < / sub>)α 1 C 1
(1 - α S )C D =(1 - α 2 )(1 - α 1 )C D
我们可以求解α S :
α S = 1 - (1 - α 1 )(1 - α 2 )=α 1 +α 2 - α 1 α 2
但是当我们解决C S 时:
C S =(α 2 C 2 +(1 - α 2 )α 1 C 1 )/(α 1 +α 2 - α 1 α 2 子>)
没有OpenGL混合模式可以让我们正确地计算C S 。
预乘Alpha混合的公式不同:
C = C S +(1 - α S )C D
有两个纹理,
C = C 2 +(1 - α 2 )(C 1 +(1 - α 1 )C D )
当我们重新排列以匹配第一个公式时,我们得到:
C = C 2 +(1 - α 2 )C 1 +(1 - α 2 )(1 - α 1 )C D
然后我们解决:
α S = 1 - (1 - α 1 )(1 - α 2 )=α 1 +α 2 - α 1 α 2
C S = C 2 +(1 - α 2 )C 1
这与:
相同glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
因此,如果你对所有纹理使用预乘的alpha,那么所有数学运算都很完美,你不必担心这些东西。只需在任何地方使用相同的混合函数,在任何地方使用预乘的alpha,你可以按照自己喜欢的顺序组合事物。
预乘的alpha也会正确插值,但非预乘alpha不是这样,但这是一个单独的问题。
预乘的合成运算符是 associative ,这意味着你可以采用一堆图层并将它们压缩成一个纹理,完全按照你想要的方式。
如果没有预先乘以的alpha,数学就不会按照你想要的方式运行。