本文正在参加「金石方案」

什么是深度测验?

前面咱们在讲解屏幕坐标的时分,运用的是3D坐标,包含:x,y,z三个轴,其中x和y表明屏幕的x和y坐标,z坐标是当时片段Fragment离屏幕的间隔,由于咱们平时运用的都是右手坐标系:则z值越大,片段越接近屏幕,z轴越小,片段离屏幕的间隔就越远,而这儿的远和近在OpenGL的概念里边便是深度的意思。

【安卓OpenGLES】 开发入门(五):深度测试

这儿需求留意的一点便是,深度范围是在[0,1]之间的,深度值越大,则说明当时片段离屏幕间隔越远,而此刻z轴的值就越小。

深度测验是指在片段着色器运行之后在屏幕空间中履行的操作:意在对当时片段的深度值和深度缓冲区的值进行比较,然后决议是否丢掉的进程

什么是深度缓冲区?

深度缓冲就像颜色缓冲区一样用来存储每个片段的信息,只是其是用来存储当时片段的深度信息,深度能够运用16,24,32位为精度,大多数系统选择折中的24位。

当敞开深度缓冲之后,OpenGL会主动测验当时片段的深度值,然后根据对应的战略来决议片段的丢掉。

怎么完成深度测验?

要启用深度测验,咱们需求用GL_DEPTH_TEST选项来翻开它:

glEnable(GL_DEPTH_TEST);

一旦启用深度测验,假如片段经过深度测验,OpenGL主动在深度缓冲区存储片段的 z 值,假如深度测验失败,那么相应地丢掉该片段。假如启用深度测验,那么在每个渲染之前还应运用GL_DEPTH_BUFFER_BIT铲除深度缓冲区,不然深度缓冲区将保存上一次进行深度测验时所写的深度值

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

当然在某些特殊情况下,咱们在敞开深度测验之后,需求丢掉片段,但是又不去更新缓冲区,可运用函数glDepthMask设置为GL_FALSE禁用深度缓冲区的写入。

glDepthMask(GL_FALSE);

上面只是敞开深度测验的几个办法,默许情况下敞开深度测验后,在深度测验进程中,会主动丢掉深度值越小的片段。那可不能够自己定义深度测验的战略呢?

咱们能够经过调用glDepthFunc来设置比较运算符 (或叫做深度函数(depth function)):

glDepthFunc(GL_LESS);

该函数接受在下表中列出的几个比较运算符:

运算符 描述
GL_ALWAYS 永久经过测验
GL_NEVER 永久不经过测验
GL_LESS 在片段深度值小于缓冲区的深度时经过测验
GL_EQUAL 在片段深度值等于缓冲区的深度时经过测验
GL_LEQUAL 在片段深度值小于等于缓冲区的深度时经过测验
GL_GREATER 在片段深度值大于缓冲区的深度时经过测验
GL_NOTEQUAL 在片段深度值不等于缓冲区的深度时经过测验
GL_GEQUAL 在片段深度值大于等于缓冲区的深度时经过测验

默许情况下运用GL_LESS,这将丢掉深度值高于或等于当时深度缓冲区的值的片段。

下面咱们来比较下,不同深度测验战略下的图像比较:

  • 默许情况下:GL_LESS

    【安卓OpenGLES】 开发入门(五):深度测试

  • GL_ALWAYS

    【安卓OpenGLES】 开发入门(五):深度测试

  • GL_NEVER

    【安卓OpenGLES】 开发入门(五):深度测试

能够看到

在GL_NEVER形式下:显现的是黑屏,这是因为每次都不经过,所有片段都会被丢掉。

在GL_LESS的形式下3D作用更加真实

在GL_ALWAYS:每次都经过测验,后面的片段会掩盖之前的片段。

深度抵触现象

深度测验中,深度抵触现象需求值得留意。深度抵触(Z-fighting)是指两个平面(或三角形)相互平行且接近的过于紧密,模板缓冲区不具有足够的精度确认哪一个平面靠前,导致这两个平面的内容不断交替显现,看上去像平面内容抢夺顶靠前的方位

防止深度抵触的办法

  • 不要让物体之间靠得过近,避免它们的三角形面片发生重叠;
  • 把近平面设置得远一些(越接近近平面的方位精度越高);
  • 献身一些功能,运用更高精度的深度值。