【问题标题】:OpenGL background clear color bleeds into transparent textureOpenGL背景清除颜色渗入透明纹理
【发布时间】:2013-06-27 17:22:50
【问题描述】:

我正在使用 OpenGL 和 C++ 编写一个简单的 2D 框架,现在遇到了与透明纹理和混合相关的问题。我已将问题简化为以下问题。

我有两种纹理:地砖和鱼骨。后者包含透明像素。我将 OpenGL 清除颜色设置为“透明绿色”并启用深度测试和混合,如下所示:

glClearColor(0, 1, 0, 0)
glEnable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

通过两次调用glDrawElements(),我画了鱼,然后画了地板。鱼具有较高的 Z 值,因此应放置在地砖前面。 This is the result.

显然,我不希望像这样围绕鱼的绿色框。我认为发生的情况是鱼像素在绘制时与帧缓冲区的颜色渲染缓冲区中的任何内容混合,并且恰好是纯绿色(由于glClearColorglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT))。对于鱼纹理中的每个透明像素,我预计这种混合会解析为透明(因为我设置了透明的清晰颜色),但正如您所见,这不是发生的事情。

如果我先画地板,然后画鱼,它会起作用as expected

我的片段着色器非常简单:

varying lowp vec2 TexCoordOut;
uniform sampler2D Texture;

void main(void) {
    gl_FragColor = texture2D(Texture, TexCoordOut);
}

我真的必须手动管理绘图顺序(按 Z 坐标排序)还是有办法解决这个问题? OpenGL深度缓冲系统不就是为了解决这个问题吗?

我正在通过 Xcode 在 iOS 模拟器上测试我的程序。

【问题讨论】:

    标签: ios opengl-es opengl-es-2.0 transparency


    【解决方案1】:

    遇到了这个确切的问题,并尝试了各种方法来纠正它,但没有可靠的结果尝试处理大多数围绕更改正在进行的计算的建议。最后还是很简单的!

    我的代码中的罪魁祸首是这样的:

    glClearColor(1, 0, 1, 0);
    glClear(GL_COLOR_BUFFER_BIT);
    

    尽管它在背景和主体颜色之间混合时是透明的,但它会流血。为我解决的问题是包装此代码以掩盖 glClear 步骤。它看起来像这样:

    glColorMask(false, false, false, true);
    glClearColor(1, 0, 1, 0);
    glClear(GL_COLOR_BUFFER_BIT);
    glColorMask(true, true, true, true);
    

    这似乎通过从清除过程中消除除 alpha 通道之外的所有通道来消除出血问题。

    【讨论】:

      【解决方案2】:

      Z 值用于剔除。如果已经有另一个具有较小 z 值的片段或者它在视锥体之外,则不会绘制片段。但是所有顶点缓冲区对象都是按顺序绘制的。对于 2D,您可以使用任何排序“按 z”算法。如果您想稍后添加一些过滤器,例如模糊或边缘抗锯齿,丢弃片段将是有问题的。

      【讨论】:

        【解决方案3】:

        我确实相信深度排序是必要的——因为即使混合得到的像素是透明的,深度缓冲区也会被写入。所以任何要在这些透明像素后面(更高深度)绘制的东西都会被丢弃。不幸的是,深度缓冲区没有考虑透明度。

        如果您的纹理中没有任何半透明像素,您可以使用 alpha 测试,如果像素是透明的,它会丢弃一个像素,因此它不会写入深度缓冲区。这显然不适用于半透明像素,因为它们要么变得完全不透明,要么被丢弃,具体取决于您的实现/设置。您可以通过将着色器更改为:

        varying lowp vec2 TexCoordOut;
        uniform sampler2D Texture;
        
        void main(void) {
           vec4 tc = texture2D(Texture, TexCoordOut);
           if (tc.a < 0.5) //for example, change to any value suitable
             discard;
           gl_FragColor = tc;
        }
        

        除此之外,除了排序之外,我不知道用深度缓冲来修复透明度。

        您可以在此处阅读有关透明度排序和 alpha 测试的更多详细信息:http://www.opengl.org/wiki/Transparency_Sorting

        【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-11-05
        • 2012-06-26
        • 1970-01-01
        • 2021-09-13
        相关资源
        最近更新 更多