1.首先我们来绘制一个甜甜圈(openGL中自带的,效果图如下)

当我们去旋转这个甜甜圈的时候会发现如下的问题(如下图)

我们来分析一下这个原因,正常的情况下,一个物体在光照下是有两面的:阳面(光照覆盖的面)和阴面(背光的面),上图中红色部分就是我们理解的阳面,黑色即为阴面,但是上图的甜甜圈,看起来特别奇怪,本该显示阳面的部分确显示了阴面。但是我们在旋转这个甜甜圈的时候,此时OpenGL就不知道哪个面是正面,哪个面是反面,所以会导致出现上面这种情况。
解决方案:正背面剔除
正背面剔除是openGL针对无法区分正反面所出现的一个解决方案,它主要是用于处理立面体绘制图形时,只绘制观察者能看到的部分,看不到的部分就丢弃不绘制,这种做法可以将渲染性能提高50%左右。
那么openGL应用了正背面剔除之后是如何区分正反面的呐?
其实在OpenGL中默认规定了逆时针方向绘制的三角形是正面,当然你可以改为顺时针为正面,但是一般不建议这么操作,主要是由于这个设置不仅仅是作用于你的项目,而是作用于OpenGL全局的。我们习惯OpenGL中默认的即可。OpenGL内部会通过分析顶点数据的顺序来确认正反面,并且需要结合开发者的位置,我们只需将正背面剔除,开启/关闭即可。
开启正背面剔除 void glEnable(GL_CULL_FACE);(默认背面剔除)
关闭正背面剔除 void glDisable(GL_CULL_FACE);(默认背面剔除)
设置需要剔除的面 void glCullFace(GLenum mode);
model主要有三大类 1.1:GL_FRONT剔除正面 1.2:GL_BACK剔除背面,是默认值 1.3 GL_FRONT_AND_BACK剔除正背面。
至此我们就可以用正背面剔除来解决openGL无法区分正反面的情况。效果图如下:

细看这张加了正背面剔除的甜甜圈,又会发现这甜甜圈怎么少了一块?这其实是openGL没有开启深度测试的原因。
深度(z):观察者距离像素点的距离。
深度缓冲区:就是把距离观察者的深度值与窗口的每个像素点1对1进行关联以及储存。
深度测试:深度缓冲区与颜色缓冲区是对应的,在决定是否绘制一个物体的表面时,首先要将该点当前的深度值与深度缓冲区的该点的深度值进行比较,如果当前的深度值距观察者较近,那么就存储该点的深度值和对应的颜色值,并绘制出来,这个过程叫做深度测试。
下面让我们看看该如何用代码实现深度测试
开启深度测试:void glEnable(GL_DEPTH_TEST);
关闭深度测试:void glDisable(GL_DEPTH_TEST);
当然我们也可以用glDepthFunc(GLenum func)来修改深度测试的测试规则,那么测试的规则主要是该函数的枚举值如下:

开启了深度测试截图如下:

思考:开启了深度测试就一定没有问题了吗?

其实不然,如下图所示,三个图形在深度值相等的情况下,深度测试无法判断深度值,会导致无法预测的问题。会造成上图2个画面交替出现的问题,这个问题叫 ZFighting 闪烁问题。
那么如何解决这个问题呢?
启用Polygon Offset(多边形偏移),在执行深度测试之前,细微的增加深度值,使得两个重叠的图形之间有细微的差异
开启多边形偏移void glEnable(GL_POLYGON_OFFSET_FILL);
关闭多边形偏移void glDisable(GL_POLYGON_OFFSET_FILL);
提示: 如何避免ZFighting闪烁问题?
不要将两个物体靠的太近,避免渲染时三⻆形叠在⼀一起。这种⽅方式要求对场景中物体插⼊一个少量的偏移,那么就可能避免ZFighting现象。例例如上面的⽴方体和平⾯面问题中,将平⾯下移0.001f就可以解决这个问题,当然手动去插入这个小的偏移是要付出代价的.
尽可能将近裁剪⾯面设置得离观察者远一些。上面我们看到,在近裁剪平⾯附近,深度的精确度是很⾼的,因此尽可能让近裁剪面远一些的话,会使整个裁剪范围内的精确度变⾼一些。但是这种⽅方式会使•离观察者较近的物体被裁减掉,因此需要调试好裁剪⾯面参数。
使⽤更高位数的深度缓冲区,通常使⽤的深度缓冲区是24位的,现在有⼀些硬件使⽤32/64位的缓冲区,使精确度得到提⾼.
以上问题深度测试问题是正对于不透明图层之间的,那么对于透明的图层之间该如何处理呐?我们把问题留在下一遍博客中解析。