问题描述
我正在渲染具有 alpha 纹理的 3D 多个对象.所有纹理都加载良好,但是当我尝试在彼此面前渲染它们时,我得到以下信息:
I am rendering in 3D multiple objects with textures that have alpha. All the textures load fine but when I try to render them in front of each other I get the following:
左边是我所拥有的.正确是应该的.网格只是为了帮助可视化视角.
Left is what I have. Right is what it should be. The grid is just to help visualize the perspective.
红色圆圈纹理前面的纹理被剪裁了.我四处寻找答案,它说我可以使用:
The texture in front of the red circle texture is clipped. I searched around for an answer and it says for me to use:
GLES20.glEnable( GLES20.GL_BLEND );
GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA );
但我正在使用它,但它仍然无法正常工作.我正确放置在 onSurfaceCreated() 函数中的设置是:
But I am using it and it still isn't working. My setup in which I correctly placed in the onSurfaceCreated() function is:
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 );
我的片段着色器是:
uniform sampler2D texture;
varying vec2 texCoord;
void main(){
gl_FragColor = texture2D( texture, texCoord );
}
我是否必须在 Android 清单中包含任何内容才能启用 Alpha 测试?我不想最终不得不手动组织我的多边形或使用 alpha discard() 因为我需要并希望一些像素是半透明的.
Do I have to include anything in the Android manifest to enable alpha testing? I do not want to end up having to manually organize my polygons or use alpha discard() because I need and want some pixels to be translucent.
如何让 3D Alpha 测试深度缓冲区发挥作用?
推荐答案
这里概述了一些在 OpenGL 中使用透明渲染的方法,以及每种方法的优缺点.
Here is an overview of a few methods to render with transparency in OpenGL, with advantages and disadvantages for each.
这是一种非常有限的方法,但对于发帖人询问的特定情况已经足够了.所示示例并不真正需要透明度,因为所有内容要么完全不透明,要么完全透明(alpha = 1.0 或 alpha = 0.0).
This is a very limited method, but is sufficient for the specific case the poster asked about. The example shown does not really need transparency because everything is either fully opaque or fully transparent (alpha = 1.0 or alpha = 0.0).
在 OpenGL 中曾经有一个用于此目的的 alpha 测试,但这是一个已弃用的功能,当然在 ES 中没有.您可以在片段着色器中模拟相同的内容,如下所示:
There used to be an alpha test for this purpose in OpenGL, but that is a deprecated feature, and is of course not in ES. You can emulate the same thing in your fragment shader, which will look something like this:
vec4 val = texture2D(tex, texCoord);
if (val.a > 0.5) {
gl_FragColor = val;
} else {
discard;
}
优点:
- 简单.
- 应用方面无需额外工作.
缺点:
- 仅适用于完全不透明/透明,无法处理半透明.
- 可能会影响性能,因为这通常意味着必须禁用片段着色器之前的深度测试.
渲染透明度是混合的主要用例.最常见的方法是将混合函数设置为SRC_ALPHA, ONE_MINUS_SRC_ALPHA
,启用混合,并使用包含所需不透明度的渲染片段的 alpha 分量进行渲染.
Rendering transparency is a primary use case for blending. The most common approach is to set the blend function toSRC_ALPHA, ONE_MINUS_SRC_ALPHA
, enable blending, and render with the alpha component of the rendered fragments containing the desired opacity.
如果场景包含完全不透明对象和具有透明度的对象的混合,则可以首先渲染完全不透明对象,而无需对它们进行排序.只需要对具有透明度的对象进行排序.顺序是:
If the scene contains a mixture of fully opaque objects and objects with transparency, the fully opaque objects can be rendered first, without a need for them to be sorted. Only the objects with transparency need to be sorted. The sequence is then:
- 渲染完全不透明的几何体.
- 渲染非不透明几何体,从后到前排序.
优点:
- 可以处理半透明.
- 可以处理多层透明几何体.
- 渲染本身非常高效.
缺点:
- 需要排序以获得正确的结果.对于上面提到的混合函数,几何体必须从后向前渲染.根据应用程序的不同,这可能在没什么大不了的情况下几乎不可能.例如,要正确渲染相交的几何图形,您可能必须开始分割三角形,这远没有吸引力.
恕我直言,这是对 OpenGL 功能的非常巧妙的使用,并且可以是一个很好的实用解决方案.它确实需要多个渲染通道.简单形式需要 3 次传递:
This is a very clever use of OpenGL features, IMHO, and can be a good practical solution. It does require multiple rendering passes. The simple form requires 3 passes:
- 使用通常的设置渲染场景(启用深度测试、深度功能 LESS、启用颜色和深度写入),但仅渲染完全不透明的几何体.如果不透明度是每个对象,您可以通过跳过非不透明对象的绘制调用来处理.否则,您将不得不使用类似于上述 Alpha 测试中的着色器丢弃非不透明片段.
- 使用与上述相同的设置渲染非不透明几何体,除了禁用颜色写入.
- 再次渲染非不透明几何体,但这次使用深度函数 EQUAL,再次启用颜色写入,禁用深度写入,并使用混合.
最小着色器可用于第 2 遍,因为它不需要生成任何有效的片段颜色.
A minimal shader can be used for pass 2, since it does not need to produce any valid fragment colors.
优点:
- 易于实施.
- 合理高效,不需要排序.
- 正确处理半透明.
缺点:
- 简单形式仅绘制透明几何体的最前面层.这听起来像是一个主要限制,但结果实际上看起来非常好.有更高级的形式,其中附加层通过附加通道进行渲染.除了这些额外通道的开销之外,它还变得更加复杂,因为它需要多个深度缓冲区.我相信 NVIDIA 网站上有一份关于它的白皮书.
我自己没有用过这个,所以以下是基于我有限的理论理解.这看起来是另一种有趣的方法.这需要多采样渲染.该功能通过 glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE)
启用,然后将 alpha 值转换为覆盖掩码,导致仅根据 alpha 值写入部分样本.这会在将多样本缓冲区下采样到最终颜色缓冲区时产生透明效果.
I haven't used this myself, so the following is based on my limited theoretical understanding. It looks like another interesting method. This requires multi-sampled rendering. The feature is enabled with glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE)
, which then translates alpha values into a coverage mask, resulting in only parts of the samples being written depending on alpha value. This results in a transparency effect when the multi-sample buffer is downsampled to the final color buffer.
优点:
- 可以处理半透明.
- 正确处理多层透明度.
- 高效,尤其是在无论如何都会使用 MSAA 的情况下.无需排序.
缺点:
- 需要 MSAA.现代 GPU 在 MSAA 渲染方面非常有效,因此这没什么大不了的.很多时候,您可能无论如何都想使用 MSAA.
- alpha 值的有效分辨率非常小,除非我遗漏了什么.例如,使用 4x MSAA,您只能表示 5 个可能的 alpha 值(覆盖掩码中设置的 0、1、2、3、4 个样本).
这篇关于OpenGL ES2 Alpha 测试问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!