ZFighting闪烁问题的原因
因为开启深度测试后,OpenGL 就不会再去绘制模型被遮挡的部分. 这样实现的显示更加真实.但是由于深度缓冲区精度的限制对于深度相差非常小的情况下.(例如在同一平⾯上进行2次 制),OpenGL 就可能出现不能正确判断两者的深度值,会导致深度测试的结果不可预测.显示出来的现象交错闪烁.
583E8C6E3C09B77F9E95238AF514B822.png
F313A48CBD3007088C42DD64387A18E4.png
ZFighting闪烁问题问题解决
第一步: 启⽤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 对应光栅化模式: GL_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 基本可以满足需求.
void glPolygonOffset(Glfloat factor,Glfloat units);
应⽤用到⽚片段上总偏移计算⽅方程式:
Depth Offset = (DZ * factor) + (r * units);
DZ:深度值(Z值)
r:使得深度缓冲区产生变化的最⼩值
负值,将使得z值距离我们更近,⽽正值,将使得z值距离我们更远.
第三步: 关闭Polygon Offset
glDisable(GL_POLYGON_OFFSET_FILL)
ZFighting闪烁问题预防
不要将两个物体靠的太近,避免渲染时三角形叠在一起。这种方式要求对场景中物体插入⼀个少量的偏移,那么就可能避免ZFighting现象。例如上⾯的立⽅体和平⾯问题中,将平面下移0.001f就可以解决这个问题。当然手动去插⼊这个⼩的偏移是要付出代价的。
尽可能将近裁剪面设置得离观察者远一些。上⾯我们看到,在近裁剪平面附近,深度的精确度是很⾼ 的,因此尽可能让近裁剪面远⼀些的话,会使整个裁剪范围内的精确度变高⼀些。但是这种⽅方式会使离观察者较近的物体被裁减掉,因此需要调试好裁剪⾯参数。
使用更高位数的深度缓冲区,通常使用的深度缓冲区是24位的,现在有一些硬件使用32位的缓冲区,使精确度得到提⾼。
网友评论