OpenGL 入门 12:深度测试

特征

1. 深度缓冲区具有颜色缓冲区一样的宽度和高度。
2. 深度值以16、24或32位float的形式储存,在大部分系统中为24位。
3. 片段着色器中可访问GLSL内建变量 gl_FragCoord。x和y为片段的屏幕空间坐标,z为深度值。
4. 深度测试模版测试之后。
// 深度测试默认禁用,需主动打开
glEnable(GL_DEPTH_TEST);
// 渲染循环中,需清除旧的深度缓冲
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// 设置深度缓冲为"只读"。需开启深度测试,设置深度掩码(Depth Mask)为GL_FALSE,此后缓冲区不可修改。
glDepthMask(GL_FALSE);

深度测试函数

即设定片元深度值深度缓冲区的比较方式。

// 默认情况下使用GL_LESS
glDepthFunc(GL_LESS);

函数

描述

GL_ALWAYS

永远通过深度测试

GL_NEVER

永远不通过深度测试

GL_LESS

在片段深度值小于缓冲的深度值时通过测试

GL_EQUAL

在片段深度值等于缓冲区的深度值时通过测试

GL_LEQUAL

在片段深度值小于等于缓冲区的深度值时通过测试

GL_GREATER

在片段深度值大于缓冲区的深度值时通过测试

GL_NOTEQUAL

在片段深度值不等于缓冲区的深度值时通过测试

GL_GEQUAL

在片段深度值大于等于缓冲区的深度值时通过测试

深度值精度

线性变换

变换公式:

z值与深度值的关系图:

深度图可视化:

分析:

1. 实践中是几乎永远不会使用这样的线性深度缓冲(Linear Depth Buffer)的。
2. 一般来说大部分的物体都是靠近近平面的,所以需要提供较大的精度。
3. 由于是线性的,可看到靠的比较近的地方是黑色的,当离得较远的地方有淡淡的灰色。

非线性变换

变换公式:

z值与深度值的关系图:

深度图可视化:

分析:

1.在1.0和2.0之间的z值将会变换至1.0到0.5之间的深度值,这就是一个float提供给我们的一半精度了,这在z值很小的情况下提供了非常大的精度。在50.0和100.0之间的z值将会只占2%的float精度。
2. 深度缓冲中的值在屏幕空间中不是线性的(在透视矩阵应用之前在观察空间中是线性的)。
3. 从图中可看到,只有距离立方体非常的近的距离,才能观察到变暗的效果,其他地方基本为白色。

深度值的非线性与线性的转换

// 首先将深度值变换为NDC
float z = depth * 2.0 - 1.0;
// 应用逆变换来获取线性的深度值
float linearDepth = (2.0 * near * far) / (far + near - z * (far - near));

深度冲突(Z-fighting)

原理

1.当两个待渲染物体的三角形网格比较接近,几乎平行排列在一起时会发生深度冲突

2. 又或者是离得较远的物体,由于深度值精度不够,导致计算之后具有相同的深度值。

其本质是深度缓冲没有足够的精度来决定哪个三角形在前面显示,于是这两个三角形会不断地在切换前后顺序导致闪烁。

解决方法

  1. 永远不要把多个物体摆得太靠近,以至于它们的一些三角形会重叠。

  1. 调整近平面与远平面之间的距离。

  1. 使用更高精度的深度缓冲。

Reversed Z

该方法是用于缓解决Z-fighting问题。

当z-buffer中的归一化的深度值属于[0, 1]范围内时,可使用该方法:

原本d = 0 对应near plane,d = 1对应 far plane。
改为 d = 0 对应far plane,d = 1对应 near plane。

原因如下:

1. 由于投影矩阵变幻后,ndc坐标z值并非线性变化的。接近近平面时,精度高,接近远平面时,精度低。
2. 浮点数自身在接近0 时精度是最高的。因此可以把far plane 对应到 d = 0,near plane对应到d = 1。从而可以一定程度上进行缓解。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值