Trails 效果,清除带有透明四边形的帧缓冲区

Trails effect, clearing a frame buffer with a transparent quad

我想要一个轨迹效果。我正在将粒子绘制到帧缓冲区。永远不会被清除(累积绘图调用)。淡出是通过绘制一个带有小 alpha 的黑色四边形来完成的,例如 0.0, 0.0, 0.0, 0.1。两步过程,每帧重复: - 绘制黑色四边形 - 在新位置绘制粒子

一切正常,移动的粒子产生长尾迹,除了黑色四边形没有将 FBO 清除到完美的零。微弱的痕迹永远存在(例如缓冲区的 RGBA = 4,4,4,255)。

我假设当混合函数将 FBO 的 8 位 RGBA(目标颜色)的小值乘以例如 (1.0-0.1)=0.9 并且四舍五入阻止进一步减少时,问题就开始了。例如 4 * 0.9 = 3.6 -> 永远舍入为 4。

我的方法(画一个黑色四边形)对轨迹来说天生无用吗?我找不到可以提供帮助的混合函数,因为它们都将 DST 颜色乘以某个值,该值必须非常小才能产生长轨迹。

路径是使用代码绘制的:

    GLuint drawableFBO;
    glGetIntegerv(GL_FRAMEBUFFER_BINDING, &drawableFBO);


    glBindFramebuffer(GL_FRAMEBUFFER, FBO);   /// has an attached texture glFramebufferTexture2D -> FBOTextureId

    glEnable(GL_BLEND);
    glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

    glUseProgram(fboClearShader);
    glUniform4f(fboClearShader.uniforms.color, 0.0, 0.0, 0.0, 0.1);
    glUniformMatrix4fv(fboClearShader.uniforms.modelViewProjectionMatrix, 1, 0, mtx.m);
    glBindVertexArray(fboClearShaderBuffer);
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);


    glUseProgram(particlesShader);
    glUniformMatrix4fv(shader.uniforms.modelViewProjectionMatrix, 1, 0, mtx.m);
    glUniform1f(shader.uniforms.globalAlpha, 0.9);
    glBlendFunc(GL_ONE, GL_ONE);
    glBindTexture(particleTextureId);
    glBindVertexArray(particlesBuffer);
    glDrawArrays(GL_TRIANGLES, 0, 1000*6);


    /// back to drawable buffer
    glBindFramebuffer(GL_FRAMEBUFFER, drawableFBO);

    glUseProgram(fullScreenShader);
    glBindVertexArray(screenQuad);
    glBlendFuncGL_ONE dFactor:GL_ONE];
    glBindTexture(FBOTextureId);
    glDrawArrays(GL_TRIANGLES, 0, 6);

Blending is not only defined by the by the blend function glBlendFunc, it is also defined by the blend equation glBlendEquation.
默认情况下,源值和目标值在经过混合函数处理后相加。

使用混合函数从目标缓冲区中减去一个微小的值,因此目标颜色会在每一帧中略微降低,最终变为 0.0。
混合方程的结果被限制在 [0, 1].

范围内

例如

dest_color = dest_color - RGB(0.01)

从目标颜色中减去源颜色的混合方程是 GL_FUNC_REVERSE_SUBTRACT:

float dec = 0.01f; // should be at least 1.0/256.0

glEnable(GL_BLEND);
glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
glBlendFunc(GL_ONE, GL_ONE);

glUseProgram(fboClearShader);
glUniform4f(fboClearShader.uniforms.color, dec, dec, dec, 0.0);