• 深度测试以及透视除法的一些相关内容


    深度测试内容并不难,但是一开始对一些概念性质的东西还是有点迷迷糊糊的,这里写篇bolg帮助理解一下。对应的Learn OpenGL的章节:深度测试 以及 坐标系统


    首先是透视投影(perspective)中的透视除法。相对的,也有平行投影。透视除法是当坐标变换到裁剪空间之后进行的,并且透视除法是由GPU自己做的。

    现实生活(3D世界)中,我们知道有“近大远小”的概念,在图形学中为了模拟这种现象,我们画出来的各个物体或者物体的各个面,也要符合“近大远小”的现象。这个时候,透视除法就登场了。简单的说,就是将三维坐标(x, y, z)分别除以w分量,使得

    egin{pmatrix} x'
    \ y'
    \z'
    end{pmatrix}

    egin{pmatrix} x/w
    \ y/ w
    \ z/ w
    end{pmatrix}

    离观察者越远的顶点坐标,w分量越大(设置w分量是通过透视矩阵自动完成的,关于透视投影矩阵,参照这里)。通过这个操作,就实现了近大远小的现象。


    但是问题又来了,为了模拟现实生活(3D世界)光是做一个透视除法够不够呢?当然不够,透视除法只是将物体以及它的各个面设置为“近大远小”,而我们现实生活中,除了近大远小,还有“遮挡”的概念,也就是不能透视看到整个物体。

    在OpenGL中,这种现象我们可以通过深度测试(depth testing)来实现。

    什么是深度?简单理解为物体片段距离人(摄像机)的距离,也就是(片段的)Z坐标(当然,是做了透视除法之后,顶点Z坐标使得相应生成的片段改变之后的Z坐标;透视除法 -->顶点Z坐标 -->片段Z坐标)。

    显而易见,对于不同片段想要渲染同一个像素点的行为,我们只要比较它们之间的深度值,来决定渲染哪个点就好(这里不讲深度,是因为深度值由深度(Z坐标)通过公式计算出来的)。

    那么就涉及到一个比较深度值的问题,实际上OpenGL有一个叫深度缓冲(depth buffer)或者叫Z缓冲(Z - buffer)的东西,顾名思义,就是存储深度值(depth value)的地方。它是由窗口系统自动创建的,会以16, 24, 32位float的形式存储深度值。并且一开始深度缓冲内的深度值会自动初始化为1.0(深度值取值范围为[0.0, 1.0]。

    除去深度缓冲内初始化的深度值,片段的深度值该怎么计算呢?

    还记得我们创建透视投影矩阵时候用到的near 以及 far 平面吗?我们可以采取线性变化和非线性变换的方式来将片段Z值转化为取值范围为[0.0, 1.0]的深度值(其实Z值实际上就是物体概念上的深度值,但是由于深度缓冲中深度值取值范围为[0, 1],故我们需要将它实际上的深度值映射到[0, 1]的范围,成为新的深度值,从而与深度缓冲的内容进行比较):

    1. 线性变换

      [F_{depth}=frac{z-near}{far-near}]

      一般在实际应用中我们不采用这种方式去计算深度值(取值范围当然是限定在[0.0, 1.0]啦),为什么?因为采取线性深度缓冲的话会导致精度没有区别。我们真的需要对1000单位远的深度值和只有1单位远的充满细节的物体使用相同的精度吗?线性方程并不会考虑这一点。
      PS:精度,也就是同样取值范围的Z值,精度高的可以表示更多的深度值。
    2. 非线性变换

      [F_{depth} = frac{ 1/z - 1/near}{1/far - 1/ near}]

      采用这个公式有更高的精度。

    同样,这个变换的方程也存在于投影变换矩阵当中(说实话,由于推导过程是全英的,所以我并没有看懂XD)。

    以上的操作基本都由投影变换矩阵去搞定,因此我们需要做的,便是启用深度测试(默认关闭),并且在每次渲染循环中清除深度缓冲:

    glEnable(GL_DEPTH_TEST);
    
    while ( ...)
    {
        ...    
        glClear(GL_DEPTH_BUFFER_BIT);
        ...
    }

    同时我们也可以认为设置测试函数来修改深度测试中的比较运算符,比如GL_LESS, GL_ALWAYS之类的(具体自己看文档)。

    以上!

    参考文章:

    [1] milo-yip的回答



    原来人类的悲欢并不相通, 我只觉得他们吵闹。
  • 相关阅读:
    最大期望算法 Expectation Maximization概念
    Apriori 关联算法学习
    mysql小问题
    C4.5决策树算法概念学习
    线性回归概念学习
    决策树概念学习
    Flink on Yarn运行机制
    Flink单机版安装与wordCount
    Kmeans算法学习与SparkMlLib Kmeans算法尝试
    数据挖掘10大算法详细介绍
  • 原文地址:https://www.cnblogs.com/zhlabcd/p/11742910.html
Copyright © 2020-2023  润新知