尾随效果,使用透明四边形清除帧缓冲区

时间:2019-07-04 21:50:23

标签: ios objective-c opengl-es blending

我想获得线索效果。我正在将粒子绘制到帧缓冲区。永远不会清除(累积抽奖)。通过绘制带有小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);

1 个答案:

答案 0 :(得分:2)

Blending不仅由混合函数glBlendFunc定义,还由混合方程glBlendEquation定义。
默认情况下,源值和目标值在由blend函数处理后进行汇总。

使用混合函数,该函数从目标缓冲区中减去一个很小的值,因此目标颜色在每帧中都会略有减少,最终变为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);