渲染部分不透明和部分完全透明的对象

问题描述 投票:0回答:1

当我尝试渲染透明对象时遇到问题。我只有一个网格,所以只有一个绘制调用,如果对象有点复杂,比如植物,我可以透过对象看到,你可以看到我们可以看到大对象顶部的叶子,但它们通常在后面。

我的绘图功能代码:

glDepthFunc(GL_LESS);
glEnable(GL_CULL_FACE);
glFrontFace(GL_CCW);
glEnable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDepthMask(GL_FALSE);

glBindVertexArray(subMesh.VAO);
glDrawElements(GL_TRIANGLES, subMesh.index_count, GL_UNSIGNED_SHORT, 0);

有人知道问题出在哪里吗? 我的引擎支持固定管道和着色器,我希望有一个适用于这两种技术的解决方案。

Transparent objet

当 glDepthMask 设置为 GL_TRUE 时

enter image description here

这就是我想要的效果图

Rendering in Unity

看起来在Unity中,当渲染模式设置为FadeTransparent时,也有同样的问题,但当我将其设置为Cutout时,没有问题。也许制作一个剪切系统是解决方案?

我尝试缩放对象,减少远平面,所以我不认为这是深度精度问题。

我也尝试使用

glDepthFunc(GL_LEQUAL);

c++ opengl transparency
1个回答
2
投票

首先,目标是渲染特定类型的透明对象:其中各部分“完全透明”或“完全不透明”。在 Unity 中,可以使用 Transparent Cutout Shader 来渲染此类对象。 为了实现这一点,应启用深度测试,包括写入深度缓冲区。因此,请使用

glDepthMask(GL_TRUE)

(默认设置)。

从问题的截图中,我们现在可以看到问题是黑色部分应该是完全透明的。有两种方法可以解决这个问题:

重新设计对象,使几何形状与不透明部分完全匹配。
  1. 使用 Alpha 测试。

Alpha 测试

要使用 Alpha 测试,纹理需要具有 Alpha 分量。由于对象在 Unity 中使用透明剪切着色器按需要渲染,因此我们可以假设它已经渲染了。如何实现,取决于API:

    旧版 OpenGL(“固定管道”)
  1. 使用以下代码,它

    保留
    alpha 值大于 0.5 的片段并丢弃其他片段。 glAlphaFunc(GL_GREATER, 0.5); glEnable(GL_ALPHA_TEST);

  2. 现代 OpenGL(“使用着色器”)
  3. 这是在片段着色器中手动实现上述内容:


    if (texel.a <= 0.5) // Note: the documentation uses <, which is not exactly equivalent. discard;

    LearnOpenGL

    有一个很好的教程,并有详细的解释。

附加信息:如果目标是渲染半透明物体(例如由彩色玻璃制成的植物),则需要完全不同的方法。最简单的是,首先对各个图元(例如三角形)进行深度排序,然后从后到前一次渲染这些图元(
ref

)。这在计算上是昂贵的,并且可能不会产生 100% 正确的结果。其他更准确的方法存在于顺序独立透明度领域。

© www.soinside.com 2019 - 2024. All rights reserved.