Z Buffer(Z 缓存),Z-buffering是在为物件进行着色时,执行“隐藏面消除”工作的一项技术,所以隐藏物件背后的部分就不会被显示出来。 在3D环境中每个像素中会利用一组数据资料来定义像素在显示时的纵深度(即Z轴坐标值)。Z Buffer所用的位数越高,则代表该显示卡所提供的物件纵深感也越精确。目前的3D加速卡一般都可支持16位的Z Buffer,新推出的一些高级的卡已经可支持到32位的Z Buffer。对一个含有很多物体连接的较复杂3D模型而言,能拥有较多的位数来表现深度感是相当重要的事情。


  生物上指Z缓冲液,用于ß-半乳糖苷酶基因表达量的ONPG分析,配方如下:


  0.80g Na2HPO4.7H2O (0.06M),0.28g NaH2PO4.H2O (0.04M),0.5 mL 1M KCl (0.01M),0.05 mL 1M MgSO4 (0.001M),0.135 mL b-mercaptoethanol (BME) (0.05M),溶于约40 mL的H2O , 调PH值至7.0,用量筒定容至 50 mL,4℃保存。


  几乎所有目前的 3D 显示晶片都有 Z buffer 或 W buffer。不过,还是常常可以看到有人对 Z buffer 和 W buffer 有一些基本的问题,像是 Z buffer 的用途、Z buffer 和 W buffer 的差别、或是一些精确度上的问题等等。这篇文章的目的就是要简单介绍一下 Z buffer 和 W buffer。


  Z buffer 和 W buffer 是做什么用的呢?它们的主要目的,就是去除隐藏面,也就是 Hidden surface elimination(或是找出可见面,Visible surface detemination,这是同样意思)。在 3D 绘图中,只要有两个以上的三角面,就可能会出现某个三角面会遮住另一个三角面的情形。这是很明显的现象,因为近的东西总是会遮住远的(假设这些三角面都是不透明的)。所以,在绘制 3D 场景时,要画出正确的结果,就一定要处理这个问题。


  不过,这个问题是相当困难的,因为它牵扯到三角面之间的关系,而不只是某个三角面本身而已。所以,在做去除隐藏面的动作时,是需要考虑场景中所有的三角面的。这让问题变得相当的复杂。而且,三角面往往并不是整个被遮住,而常常是只有一部分被遮住。所以,这让问题变得更复杂。


  要做到去除隐藏面的最简单方法,就是「画家演算法」(Painter's algorithm)。这个方法的原理非常简单,也就是先画远的东西,再画近的东西。这样一来,近的东西自然就会盖住远的东西了。因为油画的画家通常会用这样的方法,所以这个方法被称为「画家演算法」。下图是一个例子


  

zabbix 增加缓存 zb缓存目录_外排序


  上图中,红色的圆形最远,所以最先画。然后是黄色的三角形,最后是灰色的方形。照远近的顺序来画,就可以达到去除隐藏面的效果。所以,只要把 3D 场景中的三角面,以对观察者的距离远近排序,再从远的三角面开始画,应该就可以画出正确的结果了。


  不过,实际上并没有这么理想。在 3D 场景中,一个三角面可能有些地方远,有些地方近,因为三角面有三个顶点,而这三个顶点和观察者的距离,通常都是不同的。所以,要以哪个顶点来排序呢?或是以三角面的中心来排序?事实上,不管以什么为依据来排序,都可能会有问题。下图是一个「画家演算法」无法解决的情形:


  

zabbix 增加缓存 zb缓存目录_外排序_02


  上图中,三个三角面互相遮住对方,所以不管用什么顺序去画,都无法得到正确的结果。另外,这个方法也无法处理三角面有交叉的情形。


  当然,如果相当确定场景中不会出现这么奇怪的情形,那「画家演算法」一般还是可以用的。不过,它还有一个很大的问题,就是效率不佳。首先,画家演算法需要对场景中,在视角范围内所有的三角面做一个排序的动作。最好的排序演算法也需要 O(n log n) 的时间。也就是说,(大致上来说)如果三角面的数目从一千个变一万个,排序需要的时间会变成约 13.3 倍。而且,因为这需要对场景中所有的三角面来做,因此也不适合用特别的硬体来做加速。另外,这个方法还有一个很大的问题,就是它会花很多时间去画一些根本就会被遮住的部分,因为每个三角面的每个 pixel 都需要画出来。这也会让效率变差。


  如果场景是静态(不动)的,只有观察者会变动的话,那是有方法可以加快排序的速度。一个很常用的方法是 binary space paritioning(BSP)。这个方法需要事先对场景建立一个树状结构。建立这个结构后,不管观察者的位置、角度是如何,都可以很快找出正确的绘制顺序。而且,BSP 会视需要切开三角面,以处理像上图那样,三个三角面互相遮住对方的情形。


  不过,BSP 结构在建立时,要花很多时间,所以不太可能即时运算。因此,通常只能用在场景中的静态部分,而会动的部分还是需要另外排序。而且,BSP 常会需要切开三角面,也会让三角面的数目增加。另外,BSP 仍然无法解决需要画出那些被遮住的 pixel 的问题。


  另一种去除隐藏面的方法,是直接以 pixel 为单位,而不是以三角面为单位,来考虑这个问题。其中最简单的方法是由 Catmull 在 1974 年时提出来的,也就是 Z buffer(或称 depth buffer)。这个方法非常简单,又容易由特别设计的硬体来执行,所以在记忆体容量不再是问题后,就变得非常受欢迎。


  Z buffer 的原理非常简单。在绘制 3D 场景时,除了存放绘制结果的 frame buffer 外,另外再使用一个额外的空间,也就是 Z buffer。Z buffer 记录 frame buffer 上,每个 pixel 和观察者的距离,也就是 Z 值。在开始绘制场景前,先把 Z buffer 中所有的值先设定成无限远。然后,在绘制三角面时,对三角面的每个 pixel 计算该 pixel 的 Z 值,并和 Z buffer 中存放的 Z 值相比较。如果 Z buffer 中的 Z 值较大,就表示目前要画的 pixel 是比较近的,所以应该要画上去,并同时更新 Z buffer 中的 Z 值。如果 Z buffer 中的 Z 值较小,那就表示目前要画的 pixel 是比较远的,会被目前 frame buffer 中的 pixel 遮住,所以就不需要画,也不用更新 Z 值。这样一来,就可以用任意的顺序去画这些三角面,即可得到正确的绘制结果。下图是一个例子:

zabbix 增加缓存 zb缓存目录_3D_03