第十三课,深度测试

开启深度测试

glEnable(GL_DEPTH_TEST);

清除深度缓存

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

深度测试函数

OpenGL允许我们禁用深度缓冲的写入,只需要设置它的深度掩码(Depth Mask)设置为GL_FALSE就可以了:

glDepthMask(GL_FALSE);

注意这只在深度测试被启用的时候才有效果。

注:这通常在深度缓存中已经存储了部分的数据时开启,且存储的数据不想被正在后来的数据替代。

OpenGL允许我们修改深度测试中使用的比较运算符。

这与禁用深度缓冲的写入不同,而是改变写入的条件。

glDepthFunc(比较运算符);
函数 描述
GL_ALWAYS 永远通过深度测试
GL_NEVER 永远不通过深度测试
GL_LESS 在片段深度值小于缓冲的深度值时通过测试
GL_EQUAL 在片段深度值等于缓冲区的深度值时通过测试
GL_LEQUAL 在片段深度值小于等于缓冲区的深度值时通过测试
GL_GREATER 在片段深度值大于缓冲区的深度值时通过测试
GL_NOTEQUAL 在片段深度值不等于缓冲区的深度值时通过测试
GL_GEQUAL 在片段深度值大于等于缓冲区的深度值时通过测试

默认情况下使用的深度函数是GL_LESS,它将会丢弃深度值大于等于当前深度缓冲值的所有片段。
即当glEnable(GL_DEPTH_TEST);系统会默认使用glDepthFunc(GL_LESS);函数。

深度值精度

在这里插入图片描述
这个(从观察者的视角)变换z值的方程是嵌入在投影矩阵中的,所以当我们想将一个顶点坐标从观察空间至裁剪空间的时候这个非线性方程就被应用了。
(下面验证glm的投影矩阵中是否有这种变化)。

深度缓冲的可视化

内建gl_FragCoord向量的z值包含了那个特定片段的深度值。

void main()
{
    FragColor = vec4(vec3(gl_FragCoord.z), 1.0);
}

即可将深度值变换为颜色属性。
在这里插入图片描述
当距离适中时,整个人物却是全白,说明z值很大,趋近于1。
当只包含一个鞋边时,只有距离非常近的地方才会变灰,而距离先对远一点的地方z值还是会趋于1。
在这里插入图片描述
这种优化使得近处的物体具有更高的深度精度。

也可以让片段非线性的深度值变换为线性的

#version 330 core
out vec4 FragColor;

float near = 0.1; 
float far  = 100.0; 

float LinearizeDepth(float depth) 
{
    float z = depth * 2.0 - 1.0; // back to NDC 
    return (2.0 * near * far) / (far + near - z * (far - near));    
}

void main()
{             
    float depth = LinearizeDepth(gl_FragCoord.z) / far; // 为了演示除以 far
    FragColor = vec4(vec3(depth), 1.0);
}

具体为啥变成了线性的,我懒,不想知道了。

实验照片如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

深度冲突

深度冲突是深度缓冲的一个常见问题,当物体在远处时效果会更明显(因为深度缓冲在z值比较大的时候有着更小的精度)。深度冲突不能够被完全避免,但一般会有一些技巧有助于在你的场景中减轻或者完全避免深度冲突。

防止深度冲突

  • 永远不要把多个物体摆得太靠近,以至于它们的一些三角形会重叠。
  • 尽可能将近平面设置远一些
  • 使用更高精度的深度缓冲

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片