Hierarchical Z-Buffer Visibility (Hi-Z)

可见性算法的目的是丢弃隐藏面,

对于GPU可以节省CPU传入顶点信息的带宽&顶点ALU&Fragment ALU的消耗,

对于CPU可以减少DC(物件被剔除了)

有三种方式可以实现可见性算法

1.object-space coherence:

物件级别的剔除,粒度最大

传统Ray casting剔除就是这种方法

2.image-space coherence

屏幕空间像素级别剔除,粒度最小

传统ZBuffer剔除就是这种方法(Zbuffer的缺点包括不支持半透明剔除,因为半透明不写入深度。并且需要ZPrePass,会增加DC)

3.temporal coherence

是利用上一帧的可见性信息,来加速这一帧的可见性运算

Greene93论文中的提出方法利用了上面三种方式

 

object-space coherence

利用八叉树空间细分 octree spatial subdivision ray tracing来做到object-space coherence剔除

将物件放入八叉树中,在视椎体中进行相交测试,如果相交,我们再把物件primitive细分,然后递归进行相交测试,把通过测试的primitive提交DrawCall

 

image-space coherence

利用Z pyramid Z金字塔来做到image-space coherence剔除

实现方法:

首先ZPrePass画出一张ZBuffer原始分辨率的,再对这张Zbuffer进行降采样来构建Mip Chain,但是不能利用GL默认的生成MipChain方法,每小一个级别相当于4个像素变一个像素,我们需要选择四个像素中Z最远的像素

作为当前mip级别的像素,

个人理解:构建一套mipchain,相当于对屏幕划分不同大小的Tile,

先选取最粗级别的mipmap,也就相当于最大的Tile

先将polygon的每个顶点选取最近的顶点(Greene93中的方法2)与该Tile像素作比较,就相当于polygon最近的顶点与这个tile中最远的像素作比较,如果polygon最近的顶点都比整个tile中最远的深度还要远,就说明整个Polygon都是隐藏的,都在别人后面

如果在前面,就换上一级别粒度更小的进行测试,直到原始Zbuffer(mip0)

 

为什么要生成mipmap不直接用原始ZBuffer比较呢?

因为有大量Polygon连最粗级别mip都不会通过,而且粗级别mip分辨率低,要比原始分辨率省(带宽?)

 

Greene93中的方法2就是将每个polygon中最近顶点与Z比较

Greene93中的方法1是需要算出每个polygon在每个mip级别也就是一个Tile的大小中的最近深度(也就是一个像素的大小)进行比较,

方法2比方法1粒度更细,剔除精度更高,但是算出每个polygon在每个mip级别一像素范围中的最近深度也很昂贵,需要按需选择

 

该方法一般用compute shader将polygon信息传入Buffer,得出运算结果后返回可见的Polygon给CPU,在进行DC提交

如果用GPU Driven可以直接用于GPU剔除

 

The overhead of generating the HiZ mip chain and dispatching the culling process is the real bottleneck though, there’s little difference between 900 bounds and 10,000 bounds.

https://www.nickdarnell.com/hierarchical-z-buffer-occlusion-culling/

该方法最昂贵的地方在于降采样mipmap(需要采样作比较),和剔除的部分

 

temporal coherence

文中维护了上一帧的visible octree node列表用于这一帧的可见性算法

好处:

If there is sufficient frame-to-frame

coherence, most of the visible geometry will already be rendered,so the Z-pyramid test will be much more effective than when we start from scratch.

 

实现

所以文中方法的一套流程就是

1.进行octree spatial subdivision ray tracing,并利用上一帧visible octree node结果加速次运算,粗粒度的先剔除物件与部分polygon

2.然后用Z pyramid进行细粒度的剔除,cs返回一个可见polygon的buffer

3.CPU提交DC

 

缺点

两种方法都有消耗多的地方

octree spatial subdivision 

需要花费CPU时间进行细分与相交测试

 

Z pyramid 

需要ZprePass 增加一倍DC

降采样增加带宽,增加GPU ALU消耗

需要ReadBack Zbuffer,“Z Query”,使CPU等待GPU计算结果,并且增加TileMemory->SystemMemory读回带宽开销,,但是如果使用 GPU Driven,在GPU中剔除&提交DC,就不会有这个问题

如果遮挡关系不是那么复杂,如果不能剔除很多东西,使用这种方法权衡利弊

参考:

  1. Hierarchical Z-Buffer Visibility(Siggraph 1993)

  2. https://www.nickdarnell.com/hierarchical-z-buffer-occlusion-culling/

------wolf96  2019/9/15

 

 

### Z-buffer算法详解 #### 一、基本概念 Z-buffer算法,也称为深度缓冲器算法,在计算机图形学中用于隐藏表面处理,即决定哪些像素应该被绘制到屏幕上以表示最接近观察者的物体部分。该方法通过维护一个额外的二维数组——Z-buffer来存储每个像素位置处可见对象的最大深度值。 对于每一个要渲染的新多边形上的点,都会将其世界坐标系下的z轴数值(代表离摄像机的距离)与当前Z-buffer中相应位置所存贮的数据相比较: - 若新来的z值更小,则更新屏幕图像以及对应的Z-buffer- 否则保持原有状态不变[^3]。 这种方法简单易懂且易于硬件实现,因此成为现代实时三维图形系统中最常用的消隐技术之一。 #### 二、工作流程 以下是简化版的工作过程描述: 1. 初始化阶段设置所有颜色缓存和深度缓存为最大可能距离。 2. 对于场景内的每一帧画面遍历其内所有的几何体并逐片元地进行如下操作: - 计算片段的世界空间坐标(x,y,z)- 将此坐标的z分量同Z-buffer里相同xy坐标的旧有值做对比。 * 如果新的z小于等于已有的值,则覆盖掉原来的色彩信息,并把新的z写入Z-buffer;反之不做任何改变继续下一个片段。 ```cpp for each pixel (x, y){ z_new = calculate_depth(object); if(z_new < z_buffer[x][y]){ color_buffer[x][y] = object_color; z_buffer[x][y] = z_new; } } ``` #### 三、优化措施 为了提升效率,通常会结合一些加速手段如视锥剔除、背面裁剪等减少不必要的计算开销。另外还有Hierarchical Z Buffering分级管理机制能够进一步加快判断速度,适用于大规模复杂模型的高效显示。 #### 四、应用场景实例 在游戏中,当玩家角色位于多个重叠建筑物之间移动时,利用Z-buffer可以确保近景建筑遮挡住远景建筑的部分区域,从而让游戏环境看起来更加真实自然。另一个例子是在虚拟现实环境中模拟人类视觉特性,使得远处的对象显得模糊而前景清晰可辨。
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值