美文网首页视觉学习
OpenGL-消除隐藏面之深度测试

OpenGL-消除隐藏面之深度测试

作者: 一代千禧 | 来源:发表于2020-07-13 10:16 被阅读0次

    首先直观的感受下,在不消除隐藏面的情况下,图形旋转中会出现的场景: 正背面不消除问题图片

    针对上述问题,提供两种解决方法:

    1、正背面消除:根据顶点数据顺序判断用户可见部分(阳面)与隐藏面(阴面),隐藏面直接丢弃,不绘制,只绘制可见部分
    2、深度测试:不管图层数量,只显示绘制可见图层,剩余不可见的直接丢弃

    正背面消除:该方法不能从根本上解决上述场景的问题,会出现缺口,如下图; 缺口问题

    上述场景出现的原因:甜甜圈旋转过程中,当前后两部分重叠时,OpenGL中并不能清楚地区分,两个图层谁显示在前,谁显示在后,导致甜甜圈产生了缺口。
    关于正背面消除方法具体实现原理,这里不详细阐述(主要需了解下阳面,阴面的判定)

    针对正背面消除方法存在的缺陷,深度测试应运而生,首先理解下以下几个概念

    深度:指OpenGL坐标系中,像素点的Z坐标距观察者的距离,存在如下关系:

    1、如果观察者在Z轴的正方向,Z值越大则越靠近观察者
    2、如果观察者在Z轴的负方向,Z值越小则越靠近观察者

    图解如下: 深度值与Z坐标值的关系(基于 观察者不动,物体动的观察方式)

    深度缓存区(Depth Buffer):

    指一块专门内存区域,存储在显存中,用于存储屏幕上所绘制图形的每个像素点的深度值,对应关系如下:
    1、深度值越大,离观察者越远
    2、深度值越小,里观察者越近
    注意事项:
    1、深度缓存区中,每个像素点和深度值一一对应
    2、深度缓冲区的范围是[0, 1]之间,默认值是1.0,表示深度值的最大值
    3、每次绘制前需清空深度缓存区,否则会存在上次绘制缓存的深度值,影响当前图形的绘制

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    

    深度测试:

    一个物体在绘制时,像素点新的深度值与深度缓存中已经存在的深度值作比较,若新值 > 旧值,则丢弃,反之,将新的深度值更新至深度缓存区,由于深度缓存区与颜色缓存区是一一对应的,同时也需要更新该像素点的颜色值到颜色缓存区,该过程就是深度测试
    开启深度测试

    glEnable(GL_DEPTH_TEST);
    

    关闭深度测试

    glDisable(GL_DEPTH_TEST);
    
    开启深度测试后,效果图如下: 开启深度测试后效果图

    多边形偏移(Polygon Offset)

    深度测试虽然解决了上述出现的缺口问题,但同时引出了Z-Fighting(Z冲突,闪烁)问题,发生z冲突的原因如下:开启深度测试后,由于深度缓冲区精度限制,导致深度值在误差极小时,OpenGL出现无法判断的情况,出现画面交错闪现的现象,举例如下: Z冲突剧烈

    开启深度测试

    glEnable(GL_POLYGON_OFFSET_FILL)
    

    关闭深度测试

    glDisable(GL_POLYGON_OFFSET_FILL)
    

    预防解决Z冲突方法:

    1、避免两个物体靠的太近:在绘制时,插入一个小偏移
    指定偏移量glPolygonOffset (GLfloat factor, GLfloat units),参数一般填 -1 和 -1
    2、将近裁剪面(设置透视投影时设置)设置的离观察者远一些:提高裁剪范围内的精确度
    2、使用更高位数的深度缓冲区:提高深度缓冲区的精确度

    相关文章

      网友评论

        本文标题:OpenGL-消除隐藏面之深度测试

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