提要
计算机的性能一直是大家关心的,即使在一个相对简单应用中,比如一个打字应用,如果有剩余的性能可以榨取,我们都可以用它来增加新的特性,比如联想拼写,语法检查,抗日锯齿文字显示,语音识别输入等等。
在实时渲染中没我们至少有四个表现上可以去追求的目标:提高帧率,提高渲染的分辨率,实现更加真实的光照和材质,实现更多的细节。60-85的FPS算是够快了。
一些 imge processing 如抗锯齿和motion blur 会明显消耗大量的cpu性能,降低FPS,这种情况下,添加一些加速渲染算法是非常必须的。
空间数据结构 Spatial Data Structures
空间数据结构指的是将图形数据存放在n维数组中,其中 n >= 2. 组织空间数据结构通常是层级的(hierarchy),这意味着它是层级包含的,这样,空间的物体都集合在一起了,并且是递归的,用层级的原因是这对访问速度的提升很有帮助,可以从o(n)提升到0(logn).但这种结构通常是precomputed的,初始化和修改都会很费劲。
下面是几种常见的空间数据结构,包括:
BVH(bounding volume hierarchies),BSP(binary space partitioning tree),octrees.
BVH
一个BV是包含一系列物体的volume,而这个volume是一个相对简单的物体,比如sphere,box等,这样在进行一些检测的时候用BV就会快很多。、
一个BV对渲染上的帮助并不是直接的,它像一个它所包含的物体的代理,用于物体拾取,碰撞检测中。
对于3D real time rendering,BVH通常用于的阶段是视井剔除(Frustum culling)。场景用一树状结构组织,有根,叶子等等。叶子节点就是场景中的物体,没有有子孙。中间节点包含物体,树中除叶子节点外的结点都对应于一个bounding volume,所以叫BVH。root节点包含整个场景。
BVHs字啊查询中也很好使,例如在Ray tracing算法中,光线和场景中物体求交,假如没有BVH,则光线每次都要判断是否与场景中的每个物体相交,使用BVH的话,只有在光线和BV相交的情况下才会进一步对子物体(包含BV)进行求交,而光线与正方体、球体求交的方法会很简单,这也是BV使用Sphere和Box的原因。
BVHs也能用于动态场景中,当场景中的一个物体移动了,检测它是否还在BV中,若还在,则不作任何改变,若物体不完全包含在原BV中 了,则要对父级BV进行哦那个重新计算,这种做法可能会进行递归运算,耗费时间,或者把树变得不平衡,一种方法就是将BV完全包含物体的运动轨迹,比如一个单摆就很好处理,这种方法称为 temporal bounding volume.
BSP Trees
BSP (Binary Space Partition)表示二叉空间分割。使用这种方法可以使我们在运行时使用一个预先计算好的树来得到多边形从后向前的列表。
一个BSP Trees如同它的名字一样是一个层次树的结构,这个树的叶节点保存了分割室内空间所得到的图元集合。现在随着硬件加速Z缓冲的出现,我们只需要用很小的代价就可以对空间中的图元进行排序,但是在90年代初由于硬件的限制,使用BSP的主要原因是因为它可以对空间中的图元进行排序来保证渲染图元的顺序是按照由后至前进行的,换句话说,Z值最小的物体总是最后被渲染。当然还有其他的算法可以完成这个功能,例如著名的画家算法,但是它与BSP比较起来速度太慢了,这是因为BSP通常对图元排序是预先计算好的而不是在运行时进行计算。从某种意义上说BSP技术实际上是画家算法的扩展,正如同BSP技术的原始设计一样,画家算法也是使用由后至前的顺序对场景中的物体进行渲染。但是画家算法有以下的缺点:
l 如果一个物体从另一个物体中穿过时它不能被正确的渲染;
l 在每一帧对被渲染的物体进行排序是非常困难的,同时运算的代价非常大;
l 它无法管理循环覆盖的情况,如图所示
根据切分方法的不同,BSP树会分为对齐轴 (Axis aligned)对齐多边形 (Polygon aligned), 下面分别举例,首先是对齐轴的。
场景中有五個物体,以平行轴的方式來切割空间,如上图可以四条线(四个平面)來得到五个子空间,构造出一颗BSP树如下:
以切平面来当作内部节点,建立起二元空间分割树,有此图就可以很快地找到目标物体。
下面是对齐多边形的例子。
场景有六道墙,以平行多边形的方式来切割空间,如上图可以三条线(三个平面)来得到四个子空间,生成二叉树如下:
以切平面来当作内部节点,建立起二元空间分割树,有此图就可以很快地找到目标物体。
将例子中的哦线换成面,图形换成空间物体,则就是三维情况下的BSP。
Octree
Octree也叫8叉树,和平行轴的BSP树类似,但Octree所作的分割都是均分,这样做的目的是让结构更加规整,让搜索变得更加有效。
建树过程:
(1). 设定最大递归深度
(2). 找出场景的最大尺寸,并以此尺寸建立第一个立方体
(3). 依序将单位元元素丢入能被包含且没有子节点的立方体
(4). 若没有达到最大递归深度,就进行细分八等份,再将该立方体所装的单位元元素全部分担给八个子立方体
(5). 若发现子立方体所分配到的单位元元素数量不为零且跟父立方体是一样的,则该子立方体停止细分,因为跟据空间分割理论,细分的空间所得到的分配必定较少,若是一样数目,则再怎么切数目还是一样,会造成无穷切割的情形。
(6). 重复3,直到达到最大递归深度。
BSP Tree和Octree对比
1. BSP Tree将场景分割为1个面,而Octree分割为3个面。
2.BSP Tree每个节点最多有2个子结点,而Octree最多有8个子结点,bsp是二分空间,因此在判断上比octtree的八叉要容易,方向性很强。
3.bsp可以替代z-buffer解决物体之间的遮挡问题
4.bsp是场景的组织模式
5.bsp对于碰撞检测的执行和方便
6.bsp分割面的任意方向性可以把空间切分得和物体一样(OCTTREE做不到)
参考
八叉树Octree原理及简单实现 - http://bbs.iieeg.com/archiver/?tid-1222.html
二元空間分割樹 (BSP Tree) - 逍遥文工作室
real time rendering 3rd