在 OpenGL 中绘制到半透明帧缓冲区时如何抗锯齿?

问题描述

我目前正在学习 OpenGL 并尝试制作一个简单的 GUI。到目前为止,我对着色器知之甚少,也没有使用过。

我用来加速文本渲染的技巧之一是将文本四边形渲染到透明的帧缓冲区对象,然后再将它们渲染到屏幕上。加速很重要,但我注意到文本在边缘绘制得很差。我注意到,如果我将透明纹理设为另一种透明颜色,则文本会与该颜色混合。在示例中,我渲染为透明的绿色纹理:

enter image description here

我使用以下参数进行混合:

glBlendFuncSeparate(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA,GL_ONE,GL_ONE)

glBlendEquation 为认值 (GL_ADD)。

我对文档的理解是,每个像素都通过一个 source_rgb * blend_factor + dest_rgb * blend_factor 等式发送。

我通常希望这样,当纹理是透明的时,RGB 会被忽略,混合的两边,所以如果可以的话,我会用类似的方程计算 rgb:

source_rgb * source_alpha / total_alpha + dest_rgb * dest_alpha / total_alpha

其中 total_alpha 是 alpha 的总和。似乎不受支持

有什么可以帮助我减轻头痛的吗?我乐于接受建议,从修复到重写所有内容,再到使用已经执行此操作的库。

如果您有兴趣,可以查看完整的源代码 here。如果您需要相关摘录,请告诉我。

编辑:我之前确实尝试从我的 alpha 混合中删除 GL_ONE、GL_ONE,并简单地将 (GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA) 用于 RGBA,但结果也不是很好。我得到了类似的结果。

按照建议使用预乘法解决了问题。

enter image description here

解决方法

首先,total_alpha 不是 alpha 的总和,而是以下内容:

total_alpha = 1 - (1 - source_alpha)*(1 - dest_alpha)

正如您正确指出的那样,OpenGL 不支持 total_alpha 的最终除法。但它不需要。您所需要的只是切换到预乘 alpha 方面的思考和工作。有了这个简单的

glBlendFunc(GL_ONE,GL_ONE_MINUS_SRC_ALPHA)

做正确的事。