OpenGL Alpha混合突然停止 [英] OpenGL alpha blending suddenly stops

查看:53
本文介绍了OpenGL Alpha混合突然停止的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用OpenGL在每个帧上以低alpha(小于 0.1 )绘制一个四边形的屏幕大小四边形,而在两者之间没有 glClear(GL_COLOR_BUFFER_BIT)他们.这样,四边形将越来越多地削弱先前框架的图形的可见性.

I'm using OpenGL to draw a screen size quad to the same position with low alpha (lesser than 0.1) on every frame, without glClear(GL_COLOR_BUFFER_BIT) between them. This way the quad should increasingly damp the visibility of the drawings of the previous frames.

但是,阻尼效果会在几秒钟后停止.如果我对四边形使用不小于 0.1 的alpha值,它将按预期工作.在我看来,OpenGL混合方程式在多次迭代后会失败(较高的alpha值需要较少的迭代才能累积为 1 ,因此,如果 alpha> = 0.1 问题不会发生).在8位中,alpha的下限约为 0.0039 ,即 1/255 ,因此alpha 0.01 应该可以.

However the damping effect stops after some seconds. If I use alpha value no lower than 0.1 for the quad, it works as expected. It seems to me, that the OpenGL blending equation fails after a number of iterations (higher alpha values need less iteration to accumulate to 1, so if alpha >= 0.1 the problem doesn't occur). The lower limit of alpha in 8bit is about 0.0039, i.e. 1/255, so alpha 0.01 should be fine.

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

I have tried several blending settings, using the following render method:

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

以及简单的片段着色器:

And the simple fragment shader:

#version 450

uniform vec4 Color;
out vec4 FragColor;

void main()
{
    FragColor = Color;
}

如何解决此问题?

推荐答案

在我看来,OpenGL混合方程在经过一个数字后会失败迭代次数(较高的alpha值需要较少的迭代次数即可累加设为1,因此如果alpha> = 0.1,则不会出现此问题).下限8位中的alpha大约为0.0039(1/255),因此alpha 0.01应该是很好.

It seems to me, that the OpenGL blending equation fails after a number of iterations (higher alpha values need less iteration to accumulate to 1, so if alpha >=0.1 the problem doesn't occur). The lower limit of the alpha in 8bit is about 0.0039 (1/255), so alpha 0.01 should be fine.

您的推理在这里是错误的.如果您绘制一个黑色的四边形,其alpha为0.01,并描述了混合设置,则每次迭代基本上都会得到 new_color = 0.99 * old_color .作为迭代编号 i 的函数,它将是 new_color(i)= original_color * pow(0.99,i).现在,它具有无限的精度,它将接近0.

Your reasoning is wrong here. If you draw a black quad with alpha of 0.01 and the blending setup you described, you basically get new_color = 0.99 * old_color with every iteration. As a function of the iteration number i, it would be new_color(i) = original_color * pow (0.99,i). Now with unlimited precision, this will move towards 0.

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

But as you already noted, the precision is not unlimited. You get a requantization with every step. So if your new_color color value does not fall below the threshold for the integer value, it will stay the same as before. Now if we consider x the unnomralized color value in the range [0,255], and we assume that the quantization is just done by usual rounding rules, we must get at a difference of at least 0.5 to get a different value: x - x * (1-alpha) > 0.5, or simply x > 0.5 / alpha.

因此,在您的情况下,您得到x> 50,这就是混合将停止"的地方(下面的所有内容将保持开始时的状态,因此您会得到深色部分的阴影").对于0.1的alpha,它将以x = 5结尾,这很可能接近零,您没有注意到它(使用特定的显示和设置).

So in your case, you get x > 50, and that is where the blending will "stop" (and everything below that will stay as it was at the beginning, so you get a "shadow" of the dark parts). For alpha of 0.1, it will end at x=5, which is probably close enough to zero that you didn't notice it (with your particular display and settings).

编辑

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

Let me recommend a startegy that will work. You must avoid the iterative compontation (at least with non-floatingpoint framebuffers). You want to achieve a fade to black effect. So you could render your original content into a texture, and render that over and over again, while blending it to black by varying the alpha value from frame to frame, so you end up with alpha as a function of the time (or frame number). Using a linear transition would probably make the most sense, but you could even use some nonlinear function to get the slowdown of the fadeout as your original approach with unlimited precision would have done.

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

Note that you do not need blending at all for that, you simply can multiply the color value from the texture with some uniform "alpha" value in the fragment shader.

这篇关于OpenGL Alpha混合突然停止的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆