编程语言
首页 > 编程语言> > java – OpenGL ES2 Alpha测试问题

java – OpenGL ES2 Alpha测试问题

作者:互联网

我在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测试深度缓冲区工作?

解决方法:

下面概述了在OpenGL中使用透明度进行渲染的几种方法,每种方法各有优缺点.

Alpha测试

这是一种非常有限的方法,但足以满足海报所询问的特定情况.显示的示例并不真正需要透明度,因为所有内容都是完全不透明或完全透明(alpha = 1.0或alpha = 0.0).

在OpenGL中曾经有过针对此目的的alpha测试,但这是一个不推荐使用的功能,当然不在ES中.您可以在片段着色器中模拟相同的内容,它看起来像这样:

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

好处:

>简单.
>在app方面没有额外的工作.

缺点:

>仅适用于完全不透明/透明,不能处理半透明.
>可能会损害性能,因为它通常意味着必须禁用片段着色器之前的深度测试.

排序和混合

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

如果场景包含完全不透明的对象和具有透明度的对象的混合,则可以首先渲染完全不透明的对象,而无需对它们进行排序.只需要对具有透明度的对象进行排序.顺序是:

>渲染完全不透明的几何体.
>渲染非不透明几何体,按顺序排序.

好处:

>可以处理半透明.
>可以处理多层透明几何体.
>渲染本身非常有效.

缺点:

>需要排序以获得正确的结果.对于上面提到的混合函数,几何体必须呈现在前面.根据应用程序的不同,这可能没什么大不了的.例如,要正确渲染相交的几何体,您可能必须开始分割三角形,这很不具吸引力.

深度剥皮

这是一个非常聪明的使用OpenGL功能,恕我直言,并且可以是一个很好的实用解决方案.它确实需要多次渲染过程.简单形式需要3次通过:

>使用常规设置渲染场景(启用深度测试,深度函数LESS,启用颜色和深度写入),但仅渲染完全不透明的几何体.如果不透明度是每个对象,则可以通过跳过非不透明对象的绘制调用来处理它.否则,您将不得不使用类似于上面的Alpha测试下的着色器丢弃非不透明片段.
>使用与上面相同的设置渲染非不透明几何体,但禁用颜色写入除外.
>再次渲染非不透明几何体,但这次使用深度函数EQUAL,再次启用颜色写入,禁用深度写入,并使用混合.

最小着色器可用于第2遍,因为它不需要产生任何有效的片段颜色.

好处:

>易于实施.
>合理有效,不需要排序.
>正确处理半透明度.

缺点:

>简单形式仅绘制最前面的透明几何图层.这可能听起来像一个主要的限制,但结果实际上看起来非常好.还有更多高级表单,其中使用其他通道呈现其他图层.除了这些额外传递的开销之外,它也变得更加复杂,因为它需要多个深度缓冲区.我相信在NVIDIA网站上有一篇关于它的白皮书.

Alpha覆盖范围

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

好处:

>可以处理半透明.
>正确处理多层透明度.
>高效,尤其是无论如何都会使用MSAA.无需排序.

缺点:

>需要MSAA.现代GPU在MSAA渲染方面非常有效,因此这不是什么大问题.很多时候,你可能还是想要使用MSAA.
>有效的alpha值分辨率非常小,除非我遗漏了一些东西.例如,对于4x MSAA,您只能表示5个可能的alpha值(覆盖掩码中设置的0,1,2,3,4个样本).

标签:3d,depth-buffer,android,java,opengl-es-2-0
来源: https://codeday.me/bug/20190915/1806232.html