深度缓冲区

2022-07-23  本文已影响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);

当它启用的时候

还应该在每个渲染迭代之前使用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很大的时候,精度很低

深度冲突

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

防止冲突

使用

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

上一篇下一篇

猜你喜欢

热点阅读