OpenGL深度测试

作者:奉灬孝
链接:https://www.jianshu.com/p/1c34ba2fba9b
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

在上一篇OpenGL正背面剔除中提到了正背面剔除的弊端:如果前后两个点都是正面或是背面,这时OpenGL无法区分哪个面在前,哪个面在后,就可能出现下图所示的问题。

 为了解决这个问题,就引出了深度测试。在二维图形渲染时一般是用不到深度测试的。

一、什么是深度?

1. 定义

深度其实就是该像素点在3D世界中距离观察者的距离—Z值

2.深度值计算

深度值⼀般由16位,24位或者32位值表示,通常是24位。位数越⾼高的话,深度的精确度越好。

深度缓冲主要是通过计算深度值来比较⼤小,在深度缓冲区中包含深度值介于 0.0 和 1.0 之间, 从观察者看到其内容与场景中的所有对象的 z 值进⾏了⽐较。这些视图空间中的 z 值可以在投影平头截体的近平面和远平面之间的任何值。我们因此需要一些方法来转换这些视图空间 z 值到 [0,1] 的范围内,下面的 (线性) 方程把 z 值转换为 0.0 和 1.0 之间的值 :

3. Z值与观察者的关系

观察者可以放在坐标系的任意位置。所以,不能简单的说Z值越大或越小,观察者就越靠近物体。

  • 如果观察者在Z轴的正方向,Z值则越靠近观察者;
  • 如果观察者在Z轴的负方向,Z值则越靠近观察者

二、什么是深度缓冲区?

1. 定义

深度缓存区,就是⼀块内存区域,专⻔门存储着每个像素点(绘制在屏幕上的)深度值。

2. 深度缓冲区在哪里?

深度缓冲区存储在显存中。

3. 深度缓冲区原理

深度缓冲区就是把距离观察者平面(近裁剪面)的深度值与窗口中的每个像素点1对1进行关联和存储。分辨率为 120 * 120 图片则存储 120 * 120 个深度值。

三、深度测试

深度缓冲区(DepthBuffer)颜⾊色缓存区(ColorBuffer)是对应的。颜⾊缓存区存储像素的颜⾊信息,⽽深度缓冲区存储像素的深度信息.。在决定是否绘制一个物体表面时,首先要将要绘制像素的深度值(新值)与当前深度缓冲区的深度值(旧值)进行比较。如果 新值 > 旧值,则丢弃这部分不进行绘制。否则,将这个像素对应的深度值和颜⾊色值—新值,更新到深度缓冲区和颜色缓存区。这个过程称为深度测试

深度测试主要函数

  • 开启深度测试

glEnable(GL_DEPTH_TEST);

在绘制场景前,清除颜⾊缓存区,深度缓冲。清除深度缓冲区默认值为1.0。

glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  • 指定深度测试判断模式

void glDepthFunc(GLEnum mode);
函数说明
GL_ALWAYS总是通过测试
GL_NEVER总是不通过测试
GL_LESS在当前深度值 < 存储的深度值时通过
GL_GREATER在当前深度值 > 存储的深度值时通过
GL_EQUAL在当前深度值 == 存储的深度值时通过
GL_LEQUAL在当前深度值 <= 存储的深度值时通过
GL_GEQUAL在当前深度值 >= 存储的深度值时通过
GL_NOTEQUAL在当前深度值 != 存储的深度值时通过
  • 深度缓冲区写入开关

//value: GL_TURE,开启深度缓冲区写入; GL_FALSE,关闭深度缓冲区写⼊
void glDepthMask(GLBool value);

四、正背面剔除问题解决

到这里上图中正背面剔除弊端的问题就迎刃而解了,开启深度测试将新旧深度值的对比,决定像素点是绘制还是丢弃,就不会出现分不清正背面的问题了。

设置深度测试开关

开启和关闭的逻辑,主要取决于右键菜单的点击次数,第一次打开,第二次关闭,以此类推

//根据设置iDepth标记来判断是否开启深度测试
    if(iDepth)
        glEnable(GL_DEPTH_TEST);
    else
        glDisable(GL_DEPTH_TEST);

五、深度测试ZFighting闪烁问题

开启深度缓冲区后,由于深度值精度的限制,对于相差非常小的深度值(比如在同一个深度进行2次渲染),就可能出现不能正确区分两个深度值的问题,导致测试的结果随机出现。所以,显示时2个画⾯交错出现,就会出现闪烁问题。如下图所示:

1. 解决方案 — 多边形偏移(Polygon Offset)

其问题产生的主要原因是由于图形靠的太近,导致无法区分出图层先后次序,针对该问题,OpenGL提供了一种多边形偏移(Polygon Offset)方案

  • 启用多边形偏移(Polygon Offset)

glEnable(GL_POLYGON_OFFSET_FILL)
多边形偏移枚举值对应的光栅化模式
GL_POLYGON_OFFSET_FILLGL_FILL
GL_POLYGON_OFFSET_LINEGL_LINE
GL_POLYGON_OFFSET_POINTGL_POINT
  • 指定偏移量 (参数一般填 -1 和 -1)

void glPolygonOffset(Glfloat factor, Glfloat units);
  • 关闭多边形偏移(Polygon Offset)

// 参数和开启的参数相同
glDisable(GL_POLYGON_OFFSET_FILL);

2. 问题预防

  • 不要将两个物体靠的太近。
    避免渲染时三⻆形叠在一起。
  • 尽可能将近裁剪面设置得离观察者远一些。
    如果观察者离近裁剪平⾯很近,那么深度测试对精确度要求很⾼。因此,可以适当推远近裁剪平⾯的位置来避免这个问题,但是可能导致离观察者较近的物体被裁减掉,使用时需要小心。
  • 使用更高位数的深度缓冲区。
    默认的深度缓冲区精度是24位的,如果硬件支持32位的缓冲区,就可以提供更高的精度。


 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值