深度测试

深度测试

在使用OpenGL绘制完下面图形进行旋转时,则出现了下面的情况:


1594797028631.jpg

1594797033130.jpg

在了解相关资料之后,后面的这种情况出现是因为当图形进行旋转时,两个部分重叠,此时OpenGL不能清楚分辨哪个图层在前,哪个图层在后,则会出现这种仿佛被咬了一个口的现象。当这种情况出现后,可以通过开启深度测试来解决此问题。

什么是深度

深度其实就是该像素点在OpenGL 坐标系中距离观察者的距离,即Z值。观察者可以放在坐标系的任意位置,但是不能简单的说Z值越大或者越小,则观察者就越靠近物体。而是当观察者在Z轴的正方向,Z值越大则靠近观察者;当观察者在Z轴负方向,Z值越小则靠近观察者。

什么是深度缓存区

深度缓存区就是显存中的一块区域,存储着每个像素点(绘制在屏幕上的)深度值,深度值越大,则离观察者越远。

深度测试

深度缓存区(DepthBuffer)和颜色缓存区(ColorBuffer)是对应的。颜色缓存区存储像素的颜色信息,而深度缓存区存储像素的深度信息。在决定是否绘制一个物体表面时,首先要将表面对应的像素的深度值与当前缓存区中的值进行对比。如果大于深度缓存区中的值,则丢弃这部分。否则利用这个像素对应的深度值和颜色值。分别更新深度缓存取和颜色缓存区,这个过程称为“深度测试”。
当开启了深度测试时,在绘制每个像素前,OpenGL会把它的深度值与目前像素点对应存储的深度值进行比较。如果像素点新对应深度值<像素点对应的深度值,(就是比较两个当前图层时,哪一个图层更接近观察者)那么此时就会将该像素点的深度值进行取而代之;相反,则像素点上的新颜色值距离观察者更同时会被遮挡,那么此时它对应的深度值与颜色值就会被抛弃,不进行绘制。

开启深度测试

glEnable(GL_DEPTH_TEST);

关闭深度测试

glDisable(GL_DEPTH_TEST);

深度测试规则

深度缓存区的默认值为1.0,为最大深度值,深度值的范围是[0,1]之间。
深度测试的测试规则为多个枚举值,我们可以通过glDepthFunc(GLenum func)来修改。其中具体枚举值如下图:

1594802589660.jpg

深度测试的潜在风险ZFighting

在我们开启深度测试后,OpenGL就不会再去绘制模型被遮挡的部分,这会使得显示效果更加真实。但是当深度缓存区精度的限制对于深度相差非常小的情况下(在同一平面上进行两次绘制),OpenGL就可能出现不能正确判断两者的深度值,会导致深度测试的结果不可预测,从而导致显示出来的现象交错闪烁两个图像交错出现。


1594803959187.jpg

那么如何解决ZFighting

既然是因为因为靠的太近,无法区分图层先后。那么我们可以在图层之间加入一个微妙的间隔。其中OpenGL有提供相应的解决方案,即“多边形偏移”。

  1. 启用多边形偏移Polygon Offset。在深度值之间产生间隔,让两个图形之间有间隔,那么就意味着就不会因为深度值相差过小而导致深度测试无法预测,将两个重叠的图形之间的深度值区分开来。
 //启用多边形偏移
  /*
    GL_POLYGON_OFFSET_POINT  对应模式:GL_POINT
    GL_POLYGON_OFFSET_LINE   对应模式:GL_LINE
    GL_POLYGON_OFFSET_FILL   对应模式:GL_FILL
   */
  glEnable(GL_POLYGON_OFFSET_FILL);
  ```

2. 指定偏移量
 通过glPolygonOffset来指定。当Offset大于0会把模型推到离你(观察者)更远的位置,当offset小于0时会把模型拉近。一般而言,只需要将-1和-1这样简单赋值就基本上满足需求了。

/*
应用到片段上的总偏移计算公式
Depth Offset = (DZfactor)+(runits);
DZ:深度值(Z)
r:使得深度缓存区产生变化的最小值
*/
glPolygonOffset(GLfloat factor, GLfloat units);

3. 关闭多边形偏移
```//关闭多边形偏移
    glDisable(GL_POLYGON_OFFSET_FILL);

预防ZFighting闪烁问题

  1. 不要将两个物体相隔太近,避免渲染时三角形叠在一起。
  2. 尽可能将近裁剪面离观察者远一些。
  3. 使用更高位数的深度缓存区,通常使用的深度缓存区是24位,现在有一些硬件使用32/64位缓存区,使得精确度得到提高
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。