首先我们看下面的一个圆环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);