我正在使用OpenGL将屏幕尺寸四边形绘制到每个帧上具有低alpha(小于0.1
)的相同位置,而它们之间没有glClear(GL_COLOR_BUFFER_BIT)
。这样四边形应该越来越多地抑制前一帧图形的可见性。
然而,阻尼效果在几秒钟后停止。如果我对四边形使用不低于0.1
的alpha值,它会按预期工作。在我看来,OpenGL混合方程经过多次迭代后失败(更高的alpha值需要更少的迭代来累积到1
,所以如果alpha >= 0.1
问题没有发生)。 8位的alpha下限约为0.0039
,即1/255
,因此alpha 0.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;
}
我该如何解决这个问题?
答案 0 :(得分:4)
在我看来,OpenGL混合方程在一个数字之后失败了 迭代次数(较高的alpha值需要较少的迭代才能累积 到1,所以如果alpha> = 0.1,则不会出现问题)。的下限 8位的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的差值才能获得不同的值: x - x * (1-alpha) > 0.5
,或只是x > 0.5 / alpha
。
所以在你的情况下,你得到x> 50,这就是混合会“停止”的地方(下面的所有东西都会保持原样,所以你得到了黑暗部分的“阴影”)。对于0.1的alpha,它将在x = 5处结束,这可能接近零而你没有注意到它(使用你的特定显示和设置)。
修改强>
让我推荐一款能够奏效的怯懦。您必须避免迭代compontation(至少使用非浮点帧缓冲区)。你想实现淡出黑色效果。因此,您可以将原始内容渲染为纹理,并一遍又一遍地渲染,同时通过逐帧更改alpha值将其混合为黑色,因此您最终将alpha作为时间(或帧编号)的函数)。使用线性过渡可能最有意义,但你甚至可以使用一些非线性函数来减慢淡出,因为你的原始方法具有无限精度。
请注意,您根本不需要混合,只需将纹理中的颜色值与片段着色器中的某些统一“alpha”值相乘即可。