OpenGL alpha 混合突然停止

Posted

技术标签:

【中文标题】OpenGL alpha 混合突然停止【英文标题】:OpenGL alpha blending suddenly stops 【发布时间】:2014-08-28 11:54:56 【问题描述】:

我正在使用 OpenGL 将屏幕大小的四边形绘制到相同的位置,每帧上的 alpha 值都较低(小于 0.1),它们之间没有 glClear(GL_COLOR_BUFFER_BIT)。这样,四边形应该会越来越多地抑制先前帧的图形的可见性。

但是,阻尼效果会在几秒钟后停止。如果我对四边形使用不低于 0.1 的 alpha 值,它会按预期工作。在我看来,OpenGL 混合方程在多次迭代后失败(更高的 alpha 值需要更少的迭代才能累积到1,所以如果alpha >= 0.1 不会出现问题)。 8bit下alpha的下限约为0.0039,即1/255,所以alpha0.01应该没问题。

我尝试了几种混合设置,使用以下渲染方法:

glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glClear(GL_DEPTH_BUFFER_BIT);
// draw black quad with translucency (using glDrawArrays)

还有简单的片段着色器:

#version 450

uniform vec4 Color;
out vec4 FragColor;

void main()

    FragColor = Color;

我该如何解决这个问题?

【问题讨论】:

不清除深度缓冲区?同一个四边形在做 z-fighting? 按照建议,尝试禁用深度测试。我的另一个快速想法是:如果值太小,它可能不足以累积。你知道 alpha 通道只有 8 位。我认为这可能是精度问题。 深度测试被禁用。该值会累积一段时间,然后停止。 8bit的精度限制约为0.0039(1/255),所以alpha 0.01应该没问题。 【参考方案1】:

在我看来,OpenGL 混合方程在一个数字后失败了 迭代次数(更高的 alpha 值需要更少的迭代来累积 为 1,因此如果 alpha >=0.1,则不会出现问题)。的下限 8bit 的 alpha 约为 0.0039 (1/255),所以 alpha 0.01 应该是 很好。

你的推理在这里是错误的。如果你绘制一个 alpha 为 0.01 的黑色四边形和你描述的混合设置,你基本上每次迭代都会得到new_color = 0.99 * old_color。作为迭代次数i 的函数,它将是new_color(i) = original_color * pow (0.99,i)。现在以无限精度,这将向 0 移动。

但正如您已经指出的,精度不是无限的。每一步都会重新量化。因此,如果您的new_color 颜色值未低于整数值的阈值,它将与以前保持一致。现在,如果我们考虑 x 范围 [0,255] 内的未标准化颜色值,并且我们假设量化只是通过通常的舍入规则完成,我们必须得到至少 0.5 的差异才能获得不同的值:@987654326 @,或者只是x > 0.5 / alpha

所以在你的情况下,你得到 x > 50,这就是混合将“停止”的地方(并且下面的所有内容都将保持原样,所以你会得到黑暗部分的“阴影”) .对于 0.1 的 alpha,它将在 x=5 处结束,这可能足够接近于零,以至于您没有注意到它(使用您的特定显示和设置)。

编辑

让我推荐一个可行的策略。您必须避免迭代组合(至少使用非浮点帧缓冲区)。您想要实现淡入淡出的黑色效果。因此,您可以将原始内容渲染为纹理,并一遍又一遍地渲染,同时通过在帧与帧之间改变 alpha 值将其混合为黑色,因此您最终将 alpha 作为时间(或帧数)的函数)。使用线性过渡可能是最有意义的,但您甚至可以使用一些非线性函数来减慢淡出,因为您最初的方法具有无限精度。

请注意,您根本不需要混合,您只需将纹理中的颜色值与片段着色器中的某个统一“alpha”值相乘即可。

【讨论】:

以上是关于OpenGL alpha 混合突然停止的主要内容,如果未能解决你的问题,请参考以下文章

在小 alpha 值上错误地在 OpenGL 中混合

在 OpenGL 4.6 中没有适合我的 alpha 混合

Opengl,仅当目标像素的 alpha 值为正时才混合

重构复杂的 opengl 混合

Worklight 6.3 推送通知在 Android 上突然停止工作

OpenGL Alpha混合错误的颜色