美文网首页
OpenGL深度测试

OpenGL深度测试

作者: 旅行者_sz | 来源:发表于2020-07-13 11:31 被阅读0次

一、概念

  • 深度:深度其实就是该像素点在3D世界中距离摄像机的距离,Z值。

  • 深度缓冲区:深度缓存区,就是一块内存区域,专⻔存储着每个像素点(绘制在屏幕上的)深度值.深度值(Z值)越大, 则离摄像机就越远.

  • 深度缓冲区的作用:在不使用深度测试的时候,如果我们先绘制一个距离比较近的物体,再绘制距离较远的物体,则距离 远的位图因为后绘制,会把距离近的物体覆盖掉. 有了深度缓冲区后,绘制物体的顺序就不那么􏰂重要的. 实际上,只要存在深度缓冲区,OpenGL 都会把像素的深度值写入到缓冲区中. 除非调⽤glDepthMask(GL_FALSE).来禁止写入.

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

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

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

二、使用深度测试

深度测试主要函数

开启深度测试
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个画⾯交错出现,就会出现闪烁问题。如下图所示:

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

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

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

多边形偏移枚举值 对应的光栅化模式
GL_POLYGON_OFFSET_FILL GL_FILL
GL_POLYGON_OFFSET_LINE GL_LINE
GL_POLYGON_OFFSET_POINT GL_POINT
  • 指定偏移量 (参数一般填 -1 和 -1)
void glPolygonOffset(Glfloat factor, Glfloat units);

  • 关闭多边形偏移(Polygon Offset)
// 参数和开启的参数相同
glDisable(GL_POLYGON_OFFSET_FILL);

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

相关文章

  • OpenGL:背面剔除和深度测试

    OpenGL:背面剔除和深度测试

  • 六、OpenGL 渲染技巧:深度测试、多边形偏移、 混合

    OpenGL + OpenGL ES +Metal 系列文章汇总 深度测试 在上一篇五、OpenGL 渲染技巧:正...

  • 13. opengl高级-深度测试

    1. opengl深度测试原理,“测试”理解为“检测规则”更容易懂 关闭深度测试,后绘制的团会覆盖先绘制的纹理: ...

  • OpenGL 深度测试

    什么叫深度? 所谓深度,就在坐标系中,像素Z坐标距离观察者的距离.观察者,可以在任何位置.OpenGL 会有专门有...

  • OpenGL 深度测试

    正背面剔除遗留问题 进行了背面剔除之后,当旋转到侧边时,出现了缺口的现象. 当环旋转到侧边时观察者和环的关系如上图...

  • OpenGL深度测试

    一、概念 深度:深度其实就是该像素点在3D世界中距离摄像机的距离,Z值。 深度缓冲区:深度缓存区,就是一块内存区域...

  • OpenGL深度测试

    在上一篇OpenGL正背面剔除中提到了正背面剔除的弊端:如果前后两个点都是正面或是背面,这时OpenGL无法区分哪...

  • OpenGL 深度测试

    OpenGL 在绘制三维立体图形时, 如果不做处理, 就会产生一些不符合常理或者逻辑问题, 本次讲述被遮挡面显示...

  • OpenGL中ZFighting、颜色混合

    接上篇OpenGL深度测试已经明白处理前后重叠造成缺口问题的解决方案是使用深度测试 glEnable(GL_DEP...

  • NDK OpenGLES3.0 开发(十):深度测试

    该原创文章首发于微信公众号:字节流动 深度测试 OpenGL 深度测试是指在片段着色器执行之后,利用深度缓冲所保存...

网友评论

      本文标题:OpenGL深度测试

      本文链接:https://www.haomeiwen.com/subject/nkcacktx.html