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

Posted

技术标签:

【中文标题】在OpenGL中绘制到半透明帧缓冲区时如何抗锯齿? [复制]【英文标题】:How to antialias when drawing to semitransparent frame buffers in OpenGL? [duplicate] 【发布时间】:2021-01-24 13:31:36 【问题描述】:

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

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

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

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,但结果也不是很好。我得到了类似的结果。

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

【问题讨论】:

【参考方案1】:

首先,total_alpha 不是 alpha 的总和,而是以下各项:

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

正如您正确指出的那样,OpenGL 不支持最终除以 total_alpha。但它不需要。您所需要的只是转换为根据预乘 alpha 进行思考和工作。就这么简单

glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA)

做正确的事。

【讨论】:

以上是关于在OpenGL中绘制到半透明帧缓冲区时如何抗锯齿? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL 抗锯齿与 glAccum 和 glRasterPos

透明位图上的抗锯齿文本

OpenGL4 多重采样抗锯齿和渲染到纹理

将OpenGL帧缓冲区对象与Qt(QOpenGLWidget)一起使用,绘制到帧缓冲区时如何禁用多重采样

我的OpenGL学习进阶之旅解决OpenGL绘制带透明通道的png纹理时出现黑边问题,并彻底了解其原理

SDL2 OpenGL 抗锯齿没有效果