在opengl中

时间:2015-05-17 17:10:45

标签: opengl alphablending premultiplied-alpha

我经常使用OpenGL查找,当我尝试在纹理上绘制某些内容然后使用glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)绘制到另一个表面上时,我总是最终得到一个彩色光环(通常是深色带)我的源图像靠近边缘的半透明部分是什么?这显然是由于制作本质上是由该混合风格引起的预乘alpha的问题引起的。对于3D场景,我通常使用画家算法,并且为了渲染2d内容,我喜欢先绘制最后面的对象并在其上覆盖其他对象。值得注意的是,在进行这样的2D绘制时,我通常不能像3d中那样依赖像az缓冲区这样的功能,这就是为什么渲染像guis这样的东西比3D场景图更多的问题

我认为值得注意的是,当目标缓冲区恰好已完全不透明时,上述混合风格实际上是完美的,但如果目标是透明的,那么在这种情况下实际需要的是{{1}例如,因为任何在源中部分透明的全白像素应该保持与颜色完全饱和,并且不与实际上不存在的背景“混合”,因为使用{{1}实际上会渲染一个部分透明和全白的像素作为前景和背景之间的混合,这是我想要的,但不是alpha信息丢失的程度,也不是实际改变颜色的程度。 / p>

因此,对我来说,那种可能完美的混合函数实际上会混合在由glBlendFunc(GL_SRC,GL_ZERO)导致的内容和由glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)导致的内容之间。 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)本身的价值。

因此,理想情况下:

glBlendFunc(GL_SRC,GL_ZERO)

这样,如果目标已经是不透明的,则正常的alpha乘法会适当地混合,而如果目标是透明的或部分透明的,它将使用更多的源图像的真实颜色,而不是使用alpha预乘的形式说颜色。

然而,似乎没有明显的方法来描述这种混合机制到OpenGL。似乎这些问题在我的情况下几乎不应该是独一无二的,而且对于我来说,似乎没有任何方法可以实现这一点......即使在可编程的管道中也是如此。

到目前为止,我发现的唯一解决方法是每当我绘制一个纹理时都要反转绘图顺序,我稍后会在其他地方绘制,并使用DST_ALPHA

在我正在渲染纹理的情况下绘制顺序的特殊情况以后会正常渲染是一种妥协,但这对我来说没有吸引力,因为它缺乏可重用性,除非执行绘图的代码总是如此让我们意识到目的地的类型是什么,以便它可以扭转自己通常的绘图顺序,我可以毫不必要地使它复杂化。

最后,尽管反转整个场景的绘制顺序并不一定完全不可能,但它要求在绘制第一个对象之前确定将在每个图形帧中显示的完整对象列表。我对此有一个核心问题是虽然在渲染3D场景时这可能是可持续的,但在绘制像2d gui这样的东西时,绘制的各种各样的东西以及绘制它们的方式都是如此之大以至于没有将它们概括为单个对象列表的方法,该列表总是可以在以后以相反的顺序遍历。在我看来,它需要一个完全不同的观点,就如何按照我习以为常的“向后”顺序构建2D场景,我现在根本无法理解可维护的解决方案。

那么......有另一种方法吗?我错过了什么吗?或者我是否必须学习一种完全不同的方式来构建2D图像?我不可能是唯一有这个问题的人,但我还没有找到任何好的和干净的解决方案。

编辑:

如果存在任何常用的OpenGL扩展,通过NVIDIA或其他方式,允许混合模式可以执行此操作:

Cr = Cs * (1 - Ad) + (Cs * As + Cd * (1 - As)) * Ad
Ar = As * (1 - Ad) + Ad * Ad

(其中Cs和Cd是源和目标颜色,As和Ad是源和目标alpha值,Cr和Ar是结果颜色和alpha值),我真的想知道扩展名是什么,以及如何使用它......只要它可以在消费类硬件上生产。

1 个答案:

答案 0 :(得分:1)

我已经写了各种各样的东西,将半透明的2D叠加合成到半透明的3D内容上,并且永远感觉OpenGL在glBlendFunc / glBlendFuncSeparate领域缺少一些至关重要的东西(至少是这样)直到你开始担心sRGB内容和帧缓冲区的伽玛校正合成无论如何。)

我主要怀疑你使用glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) 预乘alpha版(对不起,虽然你的问题很长,我实际上并没有发现它很清楚;一些简单测试用例的图像可能有帮助)。为了合成预乘的alpha内容,我希望看到GL_ONE作为glBlendFunc个参数之一(哪一个取决于你是否正在执行上/下操作)。

在混合/合成方面有一个非常好的幻灯片(包括正确使用预乘"直和#34;颜色)here(幻灯片20-35相关材料)。 / p>

(尽管我声称已经可以使用的内容通常已经足够了......但是值得一提的是NVidia最近在这个new features中添加了一些area