gpt4 book ai didi

java - OpenGL ES2 Alpha 测试问题

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:19:19 25 4
gpt4 key购买 nike

我正在渲染具有 alpha 纹理的 3D 多个对象。所有纹理都可以正常加载,但是当我尝试在彼此面前渲染它们时,我得到以下信息:

Left is what I have. Right is what I want

左边是我所拥有的。正确是应该的。网格只是为了帮助可视化视角。

红色圆圈纹理前面的纹理被剪裁。我四处寻找答案,它说我可以使用:

GLES20.glEnable( GLES20.GL_BLEND );
GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA );

但是我正在使用它,它仍然无法正常工作。我正确放置在 onSurfaceCreated() 函数中的设置是:
GLES20.glClearColor( 0.75f, 0.85f, 1f, 1.0f );
GLES20.glEnable( GLES20.GL_BLEND );
GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA );
GLES20.glEnable( GLES20.GL_DEPTH_TEST );
GLES20.glDepthFunc( GLES20.GL_LEQUAL );
GLES20.glDepthMask( true );
GLES20.glClearDepthf( 1f );

我的 fragment 着色器是:
uniform sampler2D texture;
varying vec2 texCoord;
void main(){
gl_FragColor = texture2D( texture, texCoord );
}

我是否必须在 Android list 中包含任何内容才能启用 alpha 测试?我不想最终不得不手动组织我的多边形或使用 alpha discard() 因为我需要并希望一些像素是半透明的。

如何让 3D alpha 测试深度缓冲区工作?

最佳答案

以下是在 OpenGL 中使用透明渲染的几种方法的概述,以及每种方法的优点和缺点。

阿尔法测试

这是一种非常有限的方法,但对于发帖人询问的特定情况已经足够了。显示的示例并不真正需要透明度,因为所有内容要么完全不透明,要么完全透明(alpha = 1.0 或 alpha = 0.0)。

在 OpenGL 中曾经有一个用于此目的的 alpha 测试,但这是一个已弃用的功能,当然在 ES 中没有。您可以在 fragment 着色器中模拟相同的内容,如下所示:

vec4 val = texture2D(tex, texCoord);
if (val.a > 0.5) {
gl_FragColor = val;
} else {
discard;
}

优点:
  • 简单。
  • 在应用程序方面没有额外的工作。

  • 缺点:
  • 仅适用于完全不透明/透明,无法处理半透明。
  • 可能会影响性能,因为这通常意味着必须禁用 fragment 着色器之前的深度测试。

  • 排序和混合

    渲染透明度是混合的主要用例。最常见的方法是将混合函数设置为 SRC_ALPHA, ONE_MINUS_SRC_ALPHA ,启用混合,并使用包含所需不透明度的渲染 fragment 的 alpha 分量进行渲染。

    如果场景包含完全不透明对象和具有透明度的对象的混合,则可以首先渲染完全不透明对象,而无需对它们进行排序。只需要对具有透明度的对象进行排序。那么顺序是:
  • 渲染完全不透明的几何体。
  • 渲染非不透明几何体,从后到前排序。

  • 优点:
  • 可以处理半透明。
  • 可以处理多层透明几何体。
  • 渲染本身非常有效。

  • 缺点:
  • 需要排序以获得正确的结果。对于上面提到的混合函数,几何体必须从前到后渲染。根据应用程序的不同,这可能在没什么大不了的情况下几乎不可能。例如,要正确渲染相交几何体,您可能必须开始分割三角形,这远没有吸引力。

  • 深度剥离

    这是对 OpenGL 功能的非常巧妙的使用,恕我直言,并且可以是一个很好的实用解决方案。它确实需要多个渲染 channel 。简单形式需要 3 次传递:
  • 使用通常的设置渲染场景(启用深度测试,深度功能 LESS,启用颜色和深度写入),但仅渲染完全不透明的几何体。如果不透明度是每个对象,您可以通过跳过非不透明对象的绘制调用来处理。否则,您将不得不使用类似于上面 Alpha 测试下的着色器丢弃非不透明 fragment 。
  • 使用与上述相同的设置渲染非不透明几何体,除了禁用颜色写入。
  • 再次渲染非不透明几何体,但这次使用深度函数 EQUAL,再次启用颜色写入,禁用深度写入,并使用混合。

  • 最小着色器可用于第 2 遍,因为它不需要生成任何有效的 fragment 颜色。

    优点:
  • 实现简单。
  • 合理高效,不需要排序。
  • 正确处理半透明。

  • 缺点:
  • 简单形式只绘制最前面的透明几何体层。这听起来像是一个主要限制,但结果实际上看起来非常好。有更高级的形式,其中附加层通过附加 channel 进行渲染。除了这些额外 channel 的开销之外,它还变得更加复杂,因为它需要多个深度缓冲区。我相信 NVIDIA 网站上有一份关于它的白皮书。

  • Alpha 到 Coverage

    这个我自己没用过,所以以下是我有限的理论理解。这看起来是另一种有趣的方法。这需要多采样渲染。该功能通过 glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE) 启用,然后将 alpha 值转换为覆盖掩码,导致仅根据 alpha 值写入部分样本。当多样本缓冲区被下采样到最终颜色缓冲区时,这会导致透明效果。

    优点:
  • 可以处理半透明。
  • 正确处理多层透明度。
  • 高效,特别是如果无论如何都会使用 MSAA。无需排序。

  • 缺点:
  • 需要 MSAA。现代 GPU 在 MSAA 渲染方面非常有效,因此这没什么大不了的。很多时候,您可能无论如何都想使用 MSAA。
  • alpha 值的有效分辨率非常小,除非我遗漏了什么。例如,使用 4x MSAA,您只能表示 5 个可能的 alpha 值(覆盖掩码中设置的 0、1、2、3、4 个样本)。
  • 关于java - OpenGL ES2 Alpha 测试问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23280692/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com