美文网首页
深度缓冲区

深度缓冲区

作者: 大旺旺的弟弟小旺旺 | 来源:发表于2022-07-23 06:53 被阅读0次

    深度缓冲(Depth Buffer)来防止被阻挡的面渲染到其它面的前面。讨论这些储存在深度缓冲(或z缓冲(z-buffer))
    中的深度值(Depth Value),以及它们是如何确定一个片段是处于其它片段后方的。

    每个片段都存储了信息,和颜色缓冲区一样有宽度和高度,深度缓存区是由窗口自己创建的。绝大多数是24深度值来存储的。一般的存储为16、24、32位float存储。

    开启深度之后,每一个片段的深度值进行对比,会执行一个深度测试,通过了就更新,失败了就丢弃.

    如果测试通过就更新,没有通过就丢弃了。

    执行位置

    深度缓存区在片段着色器之后执行,在屏幕空间执行

    屏幕空间坐标和viewport密切相关 可以通过gl_FragCoord进访问屏幕空间
    这个xy代表了屏幕的坐标,gl_FragCoord中也包含了一个z分量,它包含了片段真正的深度值。z值就是需要与深度缓冲内容所对比的那个值

    · 大多数的Gpu由一个提前深度测试,运行在运行之前,只要一个片段是永远不会可见的,就会丢弃它。

    默认关闭 开启

    glEnable(GL_DEPTH_TEST);
    

    当它启用的时候

    • 片段通过深度测试 OpenGL会在深度缓冲中储存该片段的z值
    • 如果没有通过深度缓冲 会丢弃该片段

    还应该在每个渲染迭代之前使用GL_DEPTH_BUFFER_BIT来清除深度缓冲,否则你会仍在使用上一次渲染迭代中的写入的深度值:

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    进行测试,但是不更新深度值

    一般的情况是使用只读深度测试,opengl可以禁用深度缓冲的写入,只需要设置掩码
    将掩码变为false
    glDepthMask(GL_FALSE);

    上面是在开启了深度测试,但是设置上面之后,会变为只读,只会读不会更新。

    深度测试的比较

    允许修改深度值使用比较运算符,我们可以控制丢弃和通过一个片段,什么时候更新缓冲区.

    GL_ALWAYS 永远通过深度测试
    GL_NEVER 永远不通过深度测试
    GL_LESS 在片段深度值小于缓冲的深度值时通过测试
    GL_EQUAL 在片段深度值等于缓冲区的深度值时通过测试
    GL_LEQUAL 在片段深度值小于等于缓冲区的深度值时通过测试
    GL_GREATER 在片段深度值大于缓冲区的深度值时通过测试
    GL_NOTEQUAL 在片段深度值不等于缓冲区的深度值时通过测试
    GL_GEQUAL 在片段深度值大于等于缓冲区的深度值时通过测试

    默认情况下使用的深度函数是GL_LESS,它将会丢弃深度值大于等于当前深度缓冲值的所有片段。

    比如3d绘制一个地板,地板上放一个椅子,如果设置为一直通过,那么这个椅子就会被地板盖住

    z值的大小

    观察空间的z值可能是投影平截头体的近平面(Near)和远平面(Far)之间的任何值。一般的我们会将他们放到0到1之间。

    F = z - near / far - near;

    near和far提供给投影的平截头体,需要一个Z值,变换到0,1之间。

    一般不适应线性的

    在实践中是几乎永远不会使用这样的线性深度缓冲(Linear Depth Buffer)的。要想有正确的投影性质,需要使用一个非线性的深度方程,它是与 1/z 成正比的。它做的就是在z值很小的时候提供非常高的精度,而在z值很远的时候提供更少的精度。

    花时间想想这个:我们真的需要对1000单位远的深度值和只有1单位远的充满细节的物体使用相同的精度吗?线性方程并不会考虑这一点。

    非线性方程与1/z成正比,1.0和2.0之间的z值变为1.0-0.5之间。深度缓冲中0.5的值并不代表着物体的z值是位于平截头体的中间了,这个顶点的z值实际上非常接近近平面!

    z越小,精度越大。

    深度缓冲可视化

    内建gl_FragCoord向量包含z值特定的深度值,加入深度用颜色表示。

    FragColor = vec4(vec3(gl_fragCoord.z),1.0)
    

    屏幕的空间深度值是非线性的,z值越小精度越高,如果z很大的时候,精度很低

    深度冲突

    两个屏幕或者三角形非常紧密深度没有足够的精度来区分,就会使得两个一直前后切换,这就是深度冲突。

    防止冲突

    • 永远不要将两个物体进行重叠,设置一个偏移值
    • 尽可能进平面设置远一些。(靠近进平面的精度高,所以远点不容易发现)
    • 使用更高精度的缓冲(牺牲性能)

    使用

    绘制之前开启深度测试,绘制不同深度的颜色值。

    相关文章

      网友评论

          本文标题:深度缓冲区

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