5-2.多边形偏移,解决Z-fighting的问题

2020-09-29  本文已影响0人  Pufus

开启深度测试后可能会引起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)方案。

glDisable(GL_POLYGON_OFFSET_FILL)

多边形偏移参数.png

使用多边形偏移,主要有以下三个步骤

//开启多边形偏移
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);

增加偏移值后的效果

增加偏移值后.gif

预防ZFighting闪烁

上一篇下一篇

猜你喜欢

热点阅读