【问题标题】:Correct way to erase for paint blending with intermediate framebuffers使用中间帧缓冲区擦除油漆混合的正确方法
【发布时间】:2019-06-10 19:42:10
【问题描述】:

我的场景由渲染到帧缓冲区的层组成。在帧缓冲区中,元素被拉回前面并与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。擦除也不一样。我尝试使用ColorWithAlphaEraseWithPremultipliedAlpha 将图层重新绘制到前面,以将目标FBO 与dest FBO 混合。不幸的是,这并不等同于使用EraseWithAlpha 将顶部 FBO 中的所有元素直接绘制到 dest FBO 中。是否可以使擦除混合模式关联,启用与着色模式相同的设置?如果没有,是否有关联的伪擦除混合模式可以在这里交换?

【问题讨论】:

    标签: opengl framebuffer alphablending


    【解决方案1】:

    数学是正确的。事实证明,这是由 Alpha 通道中的量化伪影引起的。当使用ColorWithAlpha 将要擦除的图层拉回前面到中间帧缓冲区时,浮点截断会减少累积的 alpha。得到的 alpha 是

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

    其中 i 从 0 到层数 - 1。当使用EraseWithAlpha 将结果拉回前面时,结果 alpha 为

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

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

    【讨论】:

      猜你喜欢
      • 2013-06-05
      • 2013-02-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-06
      相关资源
      最近更新 更多