我在3D中渲染具有alpha纹理的多个对象。所有的纹理加载都很好但是当我尝试将它们渲染在彼此的前面时,我得到以下结果:
左边是我的。它应该是正确的。网格只是为了帮助可视化透视。
红色圆圈纹理前面的纹理被剪裁。我四处寻找答案,它告诉我使用:
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 );
我的片段着色器是:
uniform sampler2D texture;
varying vec2 texCoord;
void main(){
gl_FragColor = texture2D( texture, texCoord );
}
我是否必须在Android清单中包含任何内容才能启用Alpha测试?我不想最终必须手动组织我的多边形或使用alpha discard(),因为我需要并希望一些像素是半透明的。
如何让3D alpha测试深度缓冲区工作?
答案 0 :(得分:27)
以下概述了在OpenGL中使用透明度进行渲染的几种方法,每种方法各有优缺点。
这是一种非常有限的方法,但足以满足海报所询问的特定情况。显示的示例并不真正需要透明度,因为所有内容都是完全不透明或完全透明(alpha = 1.0或alpha = 0.0)。
在OpenGL中曾经有过针对此目的的alpha测试,但这是一个不推荐使用的功能,当然不在ES中。您可以在片段着色器中模拟相同的内容,它看起来像这样:
vec4 val = texture2D(tex, texCoord);
if (val.a > 0.5) {
gl_FragColor = val;
} else {
discard;
}
优点:
缺点:
渲染透明度是混合的主要用例。最常见的方法是将混合函数设置为SRC_ALPHA, ONE_MINUS_SRC_ALPHA
,启用混合,并使用包含所需不透明度的渲染片段的alpha分量进行渲染。
如果场景包含完全不透明的对象和具有透明度的对象的混合,则可以首先渲染完全不透明的对象,而无需对它们进行排序。只需要对具有透明度的对象进行排序。然后是序列:
优点:
缺点:
这是一个非常巧妙的使用OpenGL功能,恕我直言,并且可以是一个很好的实用解决方案。它确实需要多次渲染过程。简单形式需要3次通过:
最小着色器可用于第2遍,因为它不需要产生任何有效的片段颜色。
优点:
缺点:
我自己没有使用过,所以以下是基于我有限的理论理解。它看起来像另一个有趣的方法。这需要多次采样渲染。该功能已使用glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE)
启用,然后将alpha值转换为coverage掩码,从而导致仅根据alpha值编写部分样本。当多样本缓冲区被下采样到最终颜色缓冲区时,这会产生透明效果。
优点:
缺点:
答案 1 :(得分:-1)
接受的答案并未涵盖。
在您的情况下,解决方案是禁用深度测试并可能反转您正在绘制的顺序。
如果你需要一系列alpha值,着色器丢弃是一个看起来很糟糕的黑客。