OpenGL正背面剔除与深度测试

1,520 阅读4分钟

首先我们看下面的一个圆环gif图的例子,我们从中可以发现,

圆圈正面是红色,底部边缘是黑色的光芒,当我们移动圆圈的时候,如果正面跟背面(正面是初始化时相对于观察者看到的页面)均显示在观察者前面时候会显示出黑色的背景,这样的效果明显不是我们想要的效果,我们想要的是无论怎么移动圆环,我们看到的都是红色,那么我们该如何解决这个问题呢?因此我们使用正背面剔除以及深度测试来解决。

正背面剔除(Face Culling)

引出背景

从一个3D图形中我们最多可以看到三个面,其余的面我们是无法看到,因此在绘制3D图形的时候我们可以仅绘制看到的面,那些看不到的OpenGL不进行渲染则会提升超过50%的性能。

正面、背面

对于固定的角度看3D图形而言

  • 正面:按照逆时针方向顶点连接的三角形面
  • 反面:按照顺时针方向顶点连接的三角形面

因此当从不同角度观看3D图形时,正面背面有可能发生变换,如图

当观察者左侧看,左边三角形123是逆时针则是正面,右边三角形123是顺时针则是背面,

当观察者在右侧看,左边三角形123是顺时针是背面,右边三角形123是逆时针则是正面,

总结:正面背面是根据观察者以及组成三角形的顶点定义顺序决定的

如何开启背面剔除

  • 开启背面剔除,代码放在绘制页面之前

//开启背面剔除
        glEnable(GL_CULL_FACE);
        //下面两行代码可以不写,此处只是为了展示如何写
        //设置哪儿是正面(使用默认就行)
        glFrontFace(GL_CCW);
        //剔除背面(默认就是剔除背面的)
        glCullFace(GL_BACK);

  • 关闭背面剔除

    glDisable(GL_CULL_FACE);
    

开启背面剔除效果


深度测试

我们从上面背面剔除的gif图中发现圆环缺失了一部分,缺失的时候恰好圆环的两部重叠了,那么这个如何形成的呢?下面我们引出深度测试的概念。

什么是深度

深度就是3D图形中像素点距离观察者的距离,即Z值,注意的是z值是个非负数

深度缓冲区

深度换冲区就是一块专门存储像素点深度值的内存区域,深度值越大距离观察者越远。

那么为什么需要深度缓冲区呢?

在不开启深度测试的时候,我们绘制3D图形都是先绘制距离比较近的物理,然后再绘制距离远的物理,因此距离较远物理就有可能把距离较近的物理给覆盖住,如果我们使用深度缓冲区则无需担心覆盖的问题,因为每个像素点的深度都会写入深度缓冲区。

深度测试

深度缓冲区跟颜色缓冲区是相对应的,颜色缓冲区存储像素的色值信息,当绘制一个物理的时候,会比较将要绘制的深度值跟当前的深度值的大小,如果大于当前的深度值,则该顶点绘制废弃掉,这就是深度测试。

开启深度测试

glEnable(GL_DEPTH_TEST);

关闭深度测试

glDisable(GL_DEPTH_TEST);

开启深度测试效果


深度测试开启导致的闪烁问题

当我们开启深度测试的时候,虽然被遮挡的部分(背面)不再进行绘制,但是当两个顶点的深度值相同时,OpenGL就不能识别出来哪个绘制哪个放弃了,因此会出现交错显示的画面,如下面两画面交错闪烁展示

那么如何解决这个问题呢?

  • 第一步,启⽤用 Polygon Offset ⽅方式解决 ,让深度值之间产生间隔

    //启⽤用Polygon Offset ⽅方式
        glEnable(GL_POLYGON_OFFSET_FILL);
    
  • 第二步,设置偏移量,通过glPolygonOffset来设置偏移量,一般设置-1,1即可,如 

    glPolygonOffset(-1,1);

  • 关闭Polygon Offset

    glDisable(GL_POLYGON_OFFSET_FILL);