一.深度
所谓深度,就是在openGL坐标系中,像素点Z坐标距离摄像机/观察者的距离。摄像机可能放在坐标系的任何位置,那么,就不能简单的说Z数值越大或越小,就是越靠近摄像机。观察者A距离A,B平面的距离都可以叫做为深度。观察者B距离B,A平面的距离都可以叫做深度。
二.深度缓冲区
深度缓冲区原理就是把一个距离观察平面(近裁剪面)的深度值(或距离)与窗口中的每个像素相关联。首先,使用glClear(GL_DEPTH_BUFFER_BIT),把所有像素的深度值设置为最大值(一般是远裁剪面)。
然后,在场景中以任意次序绘制所有物体。硬件或者软件所执行的图形计算把每一个绘制表面转换为窗口上一些像素的集合,此时并不考虑是否被其他物体遮挡。
其次,OpenGL会计算这些表面和观察平面的距离。如果启用了深度缓冲区,在绘制每个像素之前,OpenGL会把它的深度值和已经存储在这个像素的深度值进行比较。新像素深度值<原先像素深度值,则新像素值会取代原先的;反之,新像素值被遮挡,他颜色值和深度将被丢弃。
对于观察者A来说,在OpenGL绘制图形的时候,B页面是看不到的,它在Z轴上距离观察者A的距离(绿色线段)>A平面距离观察者的距离(蓝色线段),那么,距离观察者A近的就是A平面,则B平面像素&深度值将会被丢弃,A平面的像素深度值将会被存储到深度缓冲区,并绘制,相反,对于观察者B来说,则是A平面的像素&深度值被丢弃,B平面像素深度值存在深度缓冲区并绘制
为了启动深度缓冲区,必须先启动它,即glEnable(GL_DEPTH_TEST)。每次绘制场景之前,需要先清除深度缓冲区,即glClear(GL_DEPTH_BUFFER_BIT),然后以任意次序绘制场景中的物体。
三.深度测试
OpenGL中的深度测试是采用深度缓存器算法,消除场景中的不可见面。在默认情况下,深度缓存中深度值的范围在0.0到1.0之间,这个范围值可以通过函数:
glDepthRange (nearNormDepth, farNormalDepth);
将深度值的范围变为nearNormDepth到farNormalDepth之间。这里nearNormDepth和farNormalDepth可以取0.0到1.0范围内的任意值,甚至可以让nearNormDepth > farNormalDepth。这样,通过glDepthRange函数可以在透视投影有限观察空间中的任意区域进行深度测试。
另一个非常有用的函数是:
glClearDepth (maxDepth);
参数maxDepth可以是0.0到1.0范围内的任意值。glClearDepth用maxDepth对深度缓存进行初始化,而默认情况下,深度缓存用1.0进行初始化。由于在进行深度测试中,大于深度缓存初始值的多边形都不会被绘制,因此glClearDepth函数可以用来加速深度测试处理。这里需要注意的是指定了深度缓存的初始化值之后,应调用:
glClear(GL_DEPTH_BUFFER_BIT); 完成深度缓存的初始化。
在深度测试中,默认情况是将需要绘制的新像素的z值与深度缓冲区中对应位置的z值进行比较,如果比深度缓存中的值小,那么用新像素的颜色值更新帧缓存中对应像素的颜色值。这种比较测试的方式可以通过函数:
glDepthFunc(func);
进行修改。
四.案例(以甜甜圈为例)
如图所示,你可以理解成这里的AB为图1-1的AB,当AB两个平面距离观察者在Z轴的深度一样,则都绘制,当甜甜圈发生旋转,到一定角度时,
对于此时的观察者来说,AB两个面,只能看到一个,在不开启深度测试的情况下,计算机不知道它是应该以A面的像素值去画,还是以B面的像素值区画,开启深度测试后
其原因是,开启深度测试,则B页面是看不到的,它在Z轴上距离观察者的距离>A平面距离观察者的距离,那么,距离观察者A近的就是A平面,则B平面像素&深度值将会被丢弃,A平面的像素深度值将会被存储到深度缓冲区,并绘制,
五.多边形偏移
在开启深度测试后,当z轴的位置靠的足够近,而深度缓冲区进度不足以分辨出这些,就会出现Z-Fighting(Z冲突,闪烁)问题,我们就要开启多边形偏移
多边形偏移流程
glEnable(GL_POLYGON_OFFSET_FILL)对应的枚举
指定偏移量glPolygonOffset (GLfloat factor, GLfloat units);,参数一般填 -1 和 -1
预防ZFighting闪烁
(1)避免两个物体靠的太近:在绘制时,插入一个小偏移
(2)将近裁剪面(设置透视投影时设置)设置的离观察者远一些:提高裁剪范围内的精确度
(3)使用更高位数的深度缓冲区:提高深度缓冲区的精确度
六.混合
当开启深度测试后,如果距离观察者的平面是半透明的,即观察者可以透过A平面看到B平面,两者重合的部分该怎么绘制了?此时就不能来比较深度值,而是将两个像素值的颜色进行混合
说明:设置混合因子--默认值是 GL_SRC_ALPHA 和GL_ONE_MINUS_SRC_ALPHA
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
混合因子计算方程式 ://Cf -- 最终组合的颜色值//Cd:源颜色 -- 当前渲染命令传入的颜色值//CS:目标颜色 -- 颜色缓冲区中已经存在的颜色值//S:源混合因子//D:目标混合因子 Cf=(Cs*S)+(Cd*D)。
在颜色缓冲区中,每个像素点只能存储一种颜色,它主要用于半透明的绘制,注意距离观察者近的为半透明,否则没有效果
最后附上demo:链接: https://pan.baidu.com/s/10-TvWXJ3sSHjhTBfzGBChA 提取码: 2759。链接: https://pan.baidu.com/s/1a57KFaoXDHlCBSi7awrzsw 提取码: zgyg