美文网首页
5-2.多边形偏移,解决Z-fighting的问题

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

作者: Pufus | 来源:发表于2020-09-29 09:22 被阅读0次

    开启深度测试后可能会引起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闪烁

    • 避免两个物体靠的太近:在绘制时,插入一个小偏移
    • 将近裁剪面(设置透视投影时设置)设置的离观察者远一些:提高裁剪范围内的精确度
    • 使用更高位数的深度缓冲区:提高深度缓冲区的精确度

    相关文章

      网友评论

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

          本文链接:https://www.haomeiwen.com/subject/ghwkuktx.html