【问题标题】:Qt & OpenGL : texture transparencyQt & OpenGL:纹理透明度
【发布时间】:2018-11-07 18:50:30
【问题描述】:

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

这是渲染纹理的 paintGL 方法的 sn-p 代码。

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对象,所以新的纹理值应该随着每一帧更新。

我哪里做错了?谢谢!

【问题讨论】:

  • 旁白:每次渲染时无需调用glTexImage2DglGenerateMipmap。只有在纹理实际发生变化时才上传纹理并生成 mipmap。

标签: c++ qt opengl textures transparency


【解决方案1】:

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

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

如果它们是透明的,您也可以将片段着色器写入discard 片段。但是,如果您有半透明片段,这会导致伪影,因为纹理过滤和 mipmaps。

【讨论】:

  • 也许,通过使用gl_FragDepth,而不是discard透明片段更好地改变它们的深度
  • @Ripi2 不,在 OpenGL 的早期,解决方案是 alpha 测试。如今,等效的解决方案是通过 discard 关键字在片段着色器中丢弃片段,这取决于片段的 alpha 值 - 换句话说,在片段着色器中编写 alpha 测试。
  • @thomas 非常感谢!如果我在绘制它们之前根据它们的深度值(position.z)对纹理进行排序,问题就解决了! ;) 但是仍然存在这种策略不起作用的情况:当两个纹理的深度完全相同时,即两个纹理的 position.z 值相等。有什么建议么?谢谢!
  • 好吧,在这种情况下你想要发生什么...?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-03
  • 2015-03-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多