深度缓冲区的概念
- 深度其实就是该像素点在3D世界中距离摄像机的距离,Z值
- 深度缓存区,就是一块内存区域,专门存储着每个像素点(绘制在屏幕上的)深度值.深度值(Z值)越大,则离摄像机就越远.
- 在不使用深度测试的时候,如果我们先绘制一个距离比较近的物体,再绘制距离较远的物体,则距离远的位图因为后绘制,会把距离近的物体覆盖掉如图a所示. 有了深度缓冲区后,绘制物体的顺序就不那么重要的. 实际上,只要存在深度缓冲区,OpenGL 都会把像素的深度值写入到缓冲区中. 除非调用glDepthMask(GL_FALSE).来禁止写入.
图a
深度测试
深度缓冲区(DepthBuffer)和颜⾊色缓存区(ColorBuffer)是对应的.颜色缓存区存储像素的颜色信息,而深度缓冲区存储像素的深度信息. 在决定是否绘制一个物体表面时, 首先要将表面对应的像素的深度值与当前深度缓冲区中的值进行比较. 如果大于深度缓冲区中的值,则丢弃这部分.否则 利用这个像素对应的深度值和颜⾊色值.分别更新深度缓冲区和颜色缓存区. 这个过程称为”深度测试”。
- 深度缓冲区,⼀一般由窗⼝口管理理系统,GLFW创建.深度值⼀一般由16位,24位,32位值表示. 通常是24位.位数越高,深度精确度更好.
- 开启深度测试:glEnable(GL_DEPTH_TEST);
- 在绘制场景前,清除颜⾊色缓存区,深度缓冲glClearColor(0.0f,0.0f,0.0f,1.0f);glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- 清除深度缓冲区默认值为1.0,表示最大的深度值,深度值的范围为(0,1)之间. 值越小表示越靠近观察者,值越大表示 越远离观察者
ZFighting闪烁问题
因为开启深度测试后,OpenGL 就不会再去绘制模型被遮挡的部分. 这样实现的显示更加真实.但是由于深度缓冲区精度的限制对于深度相差非常小的情况下.(例如在同一平面上进行2次绘制),OpenGL 就可能出现不能正确判断两者的深度值,会导致深度测试的结果不可预测.显示出来的现象出现交错闪烁,如图b所示
图bZFighting闪烁问题问题解决
第一步: 启用 Polygon Offset 方式解决
解决⽅方法: 让深度值之间产⽣生间隔.如果2个图形之间有间隔,是不不是意味着就不不会产⽣生⼲ 干涉.可以理理 解为在执⾏行行深度测试前将⽴立⽅方体的深度值做⼀一些细微的增加.于是就能将叠的2个图形深度值之 前有所区分.
//启⽤用Polygon Offset 方式glEnable(GL_POLYGON_OFFSET_FILL)
参数列列表:
GL_POLYGON_OFFSET_POINT 对应光栅化模式: GL_POINT
GL_POLYGON_OFFSET_LINE 对应光栅化模式: GL_LINE
GL_POLYGON_OFFSET_FILL
第二步: 指定偏移量
- 通过glPolygonOffset 来指定.glPolygonOffset 需要2个参数: factor , units
- 每个Fragment 的深度值都会增加如下所示的偏移量量:Offset = ( m * factor ) + ( r * units);m : 多边形的深度的斜率的最⼤大值,理理解⼀一个多边形越是与近裁剪⾯面平⾏行行,m 就越接近于0.r : 能产⽣生于窗⼝口坐标系的深度值中可分辨的差异最⼩小值.r 是由具体是由具体OpenGL 平台指定的 ⼀一个常量量.
- 一个大于0的Offset 会把模型推到离你(摄像机)更远的位置,相应的一个小于0的Offset 会把模型拉近
- 一般而言,只需要将-1.0 和 -1 这样简单赋值给glPolygonOffset 基本可以满⾜足需求.
glDisable(GL_POLYGON_OFFSET_FILL)
ZFighting闪烁问题预防
- 不要将两个物体靠的太近,避免渲染时三角形叠在一起。这种方式要求对场景中物体插入一个少量量的偏移,那么就可能避免ZFighting现象。例如上面的立方体和平面问题中,将平面下移0.001f就可以解决这个问题。当然⼿手动去插⼊入这个⼩小的偏移是要付出代价的。
- 尽可能将近裁剪面设置得离观察者远一些。上面我们看到,在近裁剪平面附近,深度的精确度是很⾼的,因此尽可能让近裁剪⾯面远一些的话,会使整个裁剪范围内的精确度变⾼一些。但是这种⽅方式会使离观察者较近的物体被裁减掉,因此需要调试好裁剪⾯面参数。
- 使⽤更高位数的深度缓冲区,通常使用的深度缓冲区是24位的,现在有一些硬件使用32位的缓冲 区,使精确度得到提高。
网友评论