Qt和OpenGL:纹理透明度

时间:2018-11-07 18:50:30

标签: c++ qt opengl textures transparency

我用相同的方式渲染了两个纹理。绿色纹理在正确的位置具有适当的透明度,但是当我在前面移动粉色纹理时,它将在应该透明的位置显示背景色。

enter image description here

这是用于渲染纹理的 paintGL 方法的代码段。

void OpenGLWidget::paintGL()
{
    // ...

    for (int i = 0; i < lights.size(); i++)
    {
        glUseProgram(lights[i].program);

        setUniform3fv(program, "lightPosition", 1, &lights[i].position[0]);

        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, lights[i].texture);

        lights[i].svg.setColor(toColor(lights[i].diffuse));
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, lights[i].svg.width(), lights[i].svg.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, lights[i].svg.toImage().constBits());
        glGenerateMipmap(GL_TEXTURE_2D);

        glBindVertexArray(lights[i].vertexArray);
        glDrawElements(GL_TRIANGLES, lights[i].indices.size(), GL_UNSIGNED_BYTE, nullptr);
    }

    update();
}

svg 类的 toImage 方法会从svg文件生成一个新的QImage对象,因此新纹理值应随每一帧进行更新。

我在哪里做错了?谢谢!

1 个答案:

答案 0 :(得分:2)

这可能是因为您启用了深度测试。即使部分纹理是(部分或全部)透明的,OpenGL仍会写入深度缓冲区,因此,粉红光的四边形似乎会遮挡绿光。反之亦然,因为首先绘制了粉红色的光,所以此时尚未将绿光写入深度缓冲区。

通常的解决方案是按从前到后的顺序渲染透明纹理。

如果您的片段着色器是透明的,也可以将它们写入discard片段。但是,如果您具有半透明的片段,则会由于纹理过滤和mipmaps而产生伪像。