by STANCH
标签:#计算机图形学 #深度测试 #深度测试 #隐藏面消除
1.概述
根据我们的日常经验,近处的物体会挡住后面的物体,在三维场景中通常通过深度缓冲来实现这样的效果。深度缓冲记录着屏幕对应的每个像素的深度值。模型一开始所在的局部空间无深度,通过模型矩阵变换到世界空间,此时模型坐标已经变换到了齐次坐标(x,y,z,w),深度存在z分量。通过视图矩阵变换到观察空间,此时深度存在z分量(线性)。通过投影矩阵变换到裁剪空间,此时深度缓冲中裁剪空间的z分量变为z/w(已经变成了非线性的深度,下图),最后通过一些投影映射变换到屏幕空间。通过深度缓冲区,可以进行深度测试,从而确定像素的遮挡关系,保证渲染正确。这是深度缓冲最主要的作用。
来源:《细说图形学渲染管线》
深度测试的原理很简单:比较当前片段的深度值是否比深度缓冲中预设的值小(默认比较方式),如果是则更新深度缓冲和颜色缓冲;否则丢弃片段不更新缓冲区的值。
来源:《细说图形学渲染管线》
2.Z-Fighting
当渲染两个重叠的共面表面时,一个常见的问题是“Z-fighting”,即渲染器无法确定两个表面中的哪个更靠近相机,从而在重叠区域产生视觉伪影。产生Z-fighting是由于深度缓冲精度不够带来的问题。当同一个位置的片段具有相似的深度值时,由于深度缓冲精度不够无法决定应该显示那个片段,导致片段之间抢占深度的至高点,造成了视觉上的假象, 如下图所示。
来源:《细说图形学渲染管线》
解决z-fighting的一个常见技巧是让物体之间有一些偏移,不要将物体靠的太近;另一种技巧是使用高精度的深度缓冲。比如使用32bits的深度缓冲,但是这样会占用更多的显存资源。
3.隐藏面消除 (Hidden Surface Removal, HSR)
在绘制3D场景的时候,我们需要决定哪些部分对观察者是可见的,或者说哪些部分对观察者不可见,对于不可见的部分,我们应该及早的丢弃,例如在一个不透明的墙壁后的物体就不应该渲染。这种问题称之为隐藏面消除(Hidden surface elimination),或者称之为可见面确定(Visible surface detemination)。
来源:OpenGL学习脚印:深度测试(depth testing)
其实隐藏面消除的技术我们来说并不陌生,在渲染管线中图元组装的裁剪(Clipping)、背面剔除和Z-Buffer技术其实就是隐藏面消除的一种,只不过剔除的粒度有所不同,其中裁剪操作针对的是图元,而Z-Buffer是针对像素点。不同的隐藏面消除技术的主要区别在于剔除的粒度以及不同的剔除目的,但是最终目的都是相同的:减少到达片段着色器的片段的数量,提高渲染的性能。除了裁剪之外,我们下面还将介绍几种比较常见的HSR技术!
- 视椎体剔除 (Viewing-Frustum Culling)
视椎体剔除是最常见的一种剔除技术,对于大场景我们根本不可能每帧对每个物体都进行渲染,我们其实只需要渲染那些摄像机看得到的物体,也就是位于视椎体内的物体,其他位于视椎体外的物体根本不需要渲染,我们可以将其进行剔除,不送入渲染管线,提升渲染效率。一般来说,视椎体剔除是在CPU端进行剔除工作。视椎体剔除利用的是射线检测的方法,根据视椎体的六个平面来检测物体。我们一般利用物体包围盒(Bounding Box)来做交差检测,常见的包围盒有轴对齐包围盒(AABB)和有向包围盒(OBB)两种。由于场景中物体可能非常多,所以一般需要借助高效的数据结构来提升碰撞检测的性能,常见的用于3D场景碰撞检测的数据结构有:八叉树(OcTree)、二分空间划分(Binary Space Partitioning)、四叉树(Quad Tree)、场景图 (Scene Graphs)、kd树(K-DimensionalTree)和层次包围(Bounding Volume Hierarchies)。
来源:《基于无人机与深度学习的建筑震害评估方法》
- 入口剔除 (Portal Culling)
当我们位于室内时,我们就可以使用入口剔除技术进行裁剪优化了。我们可以将室内的门或者窗户看做视椎体来进行裁剪。不过我们其实看到入口剔除有很大的局限性,一般只能在室内环境下使用,无法再室外场景使用该技术,对于室外的大场景我们一般需要使用下面介绍的遮挡剔除技术。
来源:《细说图形学渲染管线》
- 遮挡剔除 (Occlusion Culling)
在城市或者森林这种大场景中,我们很容易发现物体之间有很多的遮挡关系,我们需要遮挡剔除技术去掉那些被挡住的物体,来提升渲染效率,如下图所示,左边的图是遮挡剔除前视椎体示意图,右边的图是进行遮挡剔除后需要渲染的物体,可以说大大减少了需要被渲染的物体数量。遮挡剔除的实现方法有很多,既有基于CPU的,也有基于GPU的,也可以混合使用CPU和GPU进行处理。一般进行遮挡剔除时,我们需要通过离线烘焙的犯法来预先计算出潜在可视集合(Potentially Visible Set,PVS)。PVS记录了每个地形块(Tiles)可能看到的物体的集合,用于运行时查找计算。在计算PVS时我们会将场景划分为小的地形块,在每个块上随机选取N个采样点,以这些采样点为起点发出射线来获取场景中相交的物体,记录下物体的ID,求出每个块对应的ID的集合。在运行时根据摄像机的位置获取每个块可见的物体进行渲染。
来源:《细说图形学渲染管线》
提高烘焙的精度通常有两种方法:一是通过减小地形块的大小;二是增加采样点数量。采样的方式有很多,如下面所示。增加采样点的数量可以获得更加精确的结果,减少在块之间切换出现物体闪现或闪失的情况。不过过多的采样点会大大增加离线烘焙的时间,所以需要根据实际情况进行选择采样的数量。我们发现其实基于烘焙的方法缺点还是很明显的:烘焙时间长,需要额外的包体以及无法处理动态的物体。
来源:《细说图形学渲染管线》
参考:
OpenGL学习脚印:深度测试(depth testing)_关闭深度测试时colour buffer-CSDN博客
关注Mapmost,持续更新GIS、三维美术、计算机技术干货
Mapmost是一套以三维地图和时空计算为特色的数字孪生底座平台,包含了空间数据管理工具(Studio)、应用开发工具(SDK)、应用创作工具(Alpha)。平台能力已覆盖城市时空数据的集成、多源数据资源的发布管理,以及数字孪生应用开发工具链,满足企业开发者用户快速搭建数字孪生场景的切实需求,助力实现行业领先。
欢迎进入官网体验使用:Mapmost——让人与机器联合创作成为新常态