正确的擦除方法,用于与中间帧缓冲区的油漆混合

时间:2019-06-10 19:42:10

标签: opengl framebuffer alphablending

我的场景由渲染到帧缓冲区的图层组成。在帧缓冲区内,元素被拉回到最前面,并与ColorWithAlphaEraseWithAlpha混合。帧缓冲区与相应的* WithPremultipliedAlpha版本混合。以下代码控制混合:

switch (m_blendMode)
{
case BlendMode::ColorWithAlpha:
{
    glBlendEquation(GL_FUNC_ADD);
    glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
    break;
}
case BlendMode::ColorWithPremultipliedSrcAlpha:
{
    glBlendEquation(GL_FUNC_ADD);
    glBlendFuncSeparate(GL_ONE, GL_ONE, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
    break;
}
case BlendMode::EraseWithAlpha:
{
    glBlendEquation(GL_FUNC_ADD);
    glBlendFuncSeparate(GL_ZERO, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA);
    break;
}
case BlendMode::EraseWithPremultipliedSrcAlpha:
{
    glBlendEquation(GL_FUNC_ADD);
    glBlendFuncSeparate(GL_ZERO, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA);
    break;
}

我正在努力消除跨越帧缓冲区边界的工作。使用ColorWithAlpha将所有元素从前向后绘制到一个帧缓冲区中,等同于将除一个元素以外的所有元素绘制到一个帧缓冲区中,然后使用ColorWithAlpha将最后一层绘制到单独的帧缓冲区中,然后混合单独的帧缓冲区使用ColorWithPremultipliedAlpha转换成原始图像。擦除并非如此。我尝试使用ColorWithAlpha从后到前绘制图层,然后使用EraseWithPremultipliedAlpha将目标FBO与目标FBO混合。不幸的是,这不等于使用EraseWithAlpha将顶部FBO中的所有元素直接绘制到目标FBO中。是否可以使擦除混合模式具有关联性,从而实现与着色模式相同的设置?如果没有,是否存在可以关联并可以在此处交换的伪擦除混合模式?

1 个答案:

答案 0 :(得分:0)

数学是正确的。原来是由Alpha通道中的量化伪像引起的。当使用ColorWithAlpha将要擦除的图层从前向后绘制到中间帧缓冲区中时,浮点截断会减少累积的alpha。所得的alpha为

destAlpha *(1-(a [i] +((1-a [i])a [i-1])...)

我从0到层数-1。当使用EraseWithAlpha拖回到最前面时,结果alpha为

destAlpha [i] *(1-a [i])

这两个重复之间的唯一区别是关联。对于将每个擦除层顺序绘制到目标中的情况,在初始绘制之后,将目标Alpha乘以所有图层的组合Alpha。对于使用帧缓冲区的情况,dest alpha仅在末尾考虑,导致不同的浮点截断。对于这两个用例,如果有一种巧妙的方法可以使浮点错误累积相同的方法,请发表评论。现在,我已经通过确保需要重绘的图层以与原始绘图相同的方式进行分组来解决了这个问题。