开启深度测试后可能会引起ZFighting闪烁问题
因为开启深度测试后,OpenGL 就不会再去绘制模型被遮挡的部分. 这样实现的显示更加真实。但是由于深度缓冲区精度的限制对于深度相差⾮非常⼩小的情况下。(例如在同一平面上进行2次绘制),OpenGL 就可能出现不能正确判断两者的深度值,会导致深度测试的结果不可预测.显示出来的现象时交错闪烁。
ZFighting闪烁问题.png如果AB两个深度值特别相近,已经超出了深度值的精度位数,就无法比较两个值的大小,会出现可能一会儿显示A的图像,一会儿显示B的图像,造成一种闪烁的现象,这个现象叫做Z-Fighting 或者 Z闪烁。
我们通过一个金字塔的案例,来观察Z冲突现象。先画一个金字塔,默认使用多边形填充模式。然后再为三角形画上黑色的边。这是在边的位置上,由于既有黑边也有颜色填充,且两者的深度值一样。变会产生下图中的闪烁现象。一会儿可以从底部看到黑色边线,一会儿看不到。
// 使用多边形填充模式
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
// 设置平面着色器,颜色为绿色
shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(), vGreen);
// 绘制
pBatch->Draw();
// 使用多边形线框模式
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
//设置线条宽度
glLineWidth(2.5f);
// 设置平面着色器,颜色为黑色
shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(), vBlack);
// 绘图
pBatch->Draw();
// 复原原本的设置
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
Z冲突.gif
针对该问题,OpenGL提供了一种多边形偏移(Polygon Offset)方案。
多边形偏移参数.pngglDisable(GL_POLYGON_OFFSET_FILL)
使用多边形偏移,主要有以下三个步骤
//开启多边形偏移
glDisable(GL_POLYGON_OFFSET_FILL)
//指定偏移量 参数一般填 -1 和 -1
glPolygonOffset (GLfloat factor, GLfloat units);
//关闭多边形偏移
glDisable(GL_POLYGON_OFFSET_FILL)
多边形偏移步骤.png
上面金字塔案例中,增加如下修改:
// 设置偏移值
glPolygonOffset(-1.0f, -1.0f);
// 开启多边形偏移
glEnable(GL_POLYGON_OFFSET_LINE);
...
// 绘制后,关闭多边形偏移
glDisable(GL_POLYGON_OFFSET_LINE);
增加偏移值后的效果
预防ZFighting闪烁
- 避免两个物体靠的太近:在绘制时,插入一个小偏移
- 将近裁剪面(设置透视投影时设置)设置的离观察者远一些:提高裁剪范围内的精确度
- 使用更高位数的深度缓冲区:提高深度缓冲区的精确度
网友评论