面向GPU的多LOD因子的大规模场景可视化策略
面向GPU的多LOD因子的大规模场景可视化策略
张嘉华 梁成 陈利强 陈春华
newzjh@msn.com aliceliang@163.net sailmer@hotmail.com musalan@msn.com
华南理工大学计算机科学与工程学院(510640)
图 1. 多LOD因子控制的大规模地形渲染(C1=1.03,C2=19.55,C3=0.868 下山脉地区三维漫游)
伴随着计算机图形处理器,真实感图形学,虚拟现实等领域的快速发展,主流的NV30等GPU渲染吞吐量已经达到每秒渲染1.5亿个三角形,如何在地形渲染中充分地利用GPU能力呢?本文提出了一套面向GPU基于层迭四叉树下的多尺度LOD超大规模场景可视化策略。我们的策略能够提供稳定的视觉,高度的漫游流畅感和沉浸感,对于16K×16K grid Puget Sound和16K×8K grid Great canyon等场景,能够以每秒100帧以上速度漫游整个场景
关键字:
大规模场景 LOD GPU 四叉树 三角列
图 4. 澳洲大宝礁三维可视化漫游
(70400×54400 grid高分辨率Terra卫星影像)
引言
随着 “数字地球”构想的提出以及海量空间数据可视化等研究的开展,超大规模地形可视化在国家安全,高分辨率卫星、航拍、遥感影像空间数据可视化,大规模人工植物群、视景仿真、虚拟军事环境,电子沙盘等领域有着其广泛的发展空间,一直以来是计算机真实感图形学、虚拟现实、地学仿真等领域的研究热点,吸引了大量国内外学者的研究兴趣。
主要贡献:在本文中,我们提出了两级层迭泛型四叉树下的多LOD因子的超大规模场景可视化策略,它能够充分利用了GPU能力,对于Puget Sound等具有代表性的场景能够以100FPS稳定漫游,我们独立开发的World Builder 2005、World Explorer 2005、World Solution 2005展现了本文策略的效果,有效论证了我们策略的正确性,完成了多个领域的应用案例展示。下面是我们贡献的分点阐述:
l 在节点评价方面探讨了全局的LOD评价因子——摄像机移动速度,探讨了符合节点形状的静态误差评价方法 (Part4,Page11-12)
l 实验测定了每次调用渲染函数渲染的最佳三角形数目,论证了三角形带累积渲染的优势, 充分地通过Direct3D / OpenGL图形接口利用GPU (Part5,Page13-14)
l 在多分辨率地形组织方面,提出层迭泛型四叉树地形组织方法和泛型哈希表节点标记策略 (Part3,Page7-11)
l 在裂缝处理方面提出了边界样式和顶点位移的方法 (Part5,Page13-16)
C1=0.2 C1=0.4
C1=0.8 C1=1.6
图 3. 不同细节层次下的Puget Sound
本文是在我们过往对大规模场景的研究的基础上进行的,主要围绕大规模场景可视化流程组织的,伴随着论文的撰写同时我们独立开发了一整套分布式的大规模场景漫游、协同仿真平台,我们的灵感主要来源于寻找一种能够充分利用GPU的地形可视化策略,能够快速查询节点状态和属性,进行空间的拓扑索引;设计一种LOD策略,能够尽可能简化地形渲染,使地形屏幕贡献度大,人们视觉比较敏感的区域能够得到更高精度显示,减少动态细节层次改变带来的地形节点几何形状变化程度,保持视觉稳定性和漫游的流畅感和沉浸感。
我们的这套面向GPU的多LOD 评价因子的超大规模场景可视化策略具有下面这些优点:
l 多LOD评价因子
摒弃过往缺乏考虑节点几何形状的静态因子评价方法,提出适合四叉树能够通过地形起伏程度阈值控制的静态因子评价,同时引入摄像机移动速度作为评价因子,充分考虑更种因素在节点渲染过程中的屏幕贡献度和人的视觉敏感区域
l 稳定的视觉
双重帧约束(自适应的LOD帧约束和图形接口层上的帧约束),保持平滑流畅的漫游视觉
l 高的渲染吞吐量
Triangle Lists累积渲染大大降低调用渲染函数的次数,保持渲染流水线操作的尽可能连续,充分利用GPU
l 连续的索引缓冲和顶点缓冲
不同LOD级别差异的节点预定义的边界样式和顶点插值高程代替实际高程的裂缝消除方法能够有效地增加顶点缓冲和索引缓冲中连续的数据部分,加速图形渲染
l 多级地形组织
多级四叉树地形模型,既具有分块地形更新灵活的特点,又具有多分辨率LOD地形模型的多LOD因子控制的特点
l 丰富的无限级别地形细节
无限级别分形非线性自相似内插,能够提供无限的更丰富的地形细节
l 内存消耗和时间消耗动态平衡的节点标记
泛型哈希表节点标记策略,能够动态地调节哈希表控制因子,改变哈希表存储桶的大小,在节点状态标记内存消耗和时间消耗之间达到最佳平衡,
除前面引言部分外,本文由五部分组成,第一部分介绍在这个领域的过往相关工作,第二部分介绍探讨了我们的地形数据组织策略,第三部分介绍我们探讨的各种LOD评价因子,第四部分介绍我们提出的面向GPU的多分辨率LOD地形下的裂缝消除和顶点跃动消除的方法。最后介绍了我们的实验后的结论,并探讨了我们策略的应用前景。
1、相关工作
在大规模地形场景可视化和地形LOD模型问题上,过去已经有不少的工作。从网格特征考虑可分为基于非规则三角网格(Tin)和基于均匀网格(Grid)两种生成方法。从地形分层细分上考虑可以分为二叉树,四叉树,八叉树等,下面介绍几个主要的相关工作:
96年,Lindstrom等提出了连续的实时的LOD高度场方法,该方法使用规则格网,通过一个用户可以控制的屏幕空间误差阙值控制细节简化程度,使用层次四叉树从最高精度的底层自底向上(bottom-up)对整个场景地形逐步简化三角形直到达到指定控制量。该方法通过维持地形块的活动分割和只访问能够在连续的帧间改变的顶点实现帧约束,通过维持顶点拓扑关系的二叉树消除裂缝。
97年,Duchaineau等提出了ROAM实时自适应网格方法,该方法使用带有二元三角形树(BBT,binary triangle tree)基于优先级产生连续的地形网格。该方法通过两个优先级队列进行分割和合并三角形操作。一个队列负责维持具有优先级顺序的待分割三角形的列表,该队列中优先级最高的三角形首先细分,另一个队列包含具有优先级顺序的待合并的三角形列表。这使得ROAM方法具有帧约束的特点,分割和合并操作可以通过顶点渐变平滑进行。
98年,rottger等人在[Lindstrom96]的基础上,与Lindstrom等自底而上的方法不同,提出了一种基于四叉树的自顶而下的策略,该策略每帧只访问整个地形的一部分,但该方法需要分析整个地形数据[rottger 98]。该方法在裂缝处理上,通过忽略高分辨率节点边上中点顶点来消除裂缝。他们还探讨了LOD误差评价方法,具有两个评价因子,动态因子以节点到观察者的距离评价,静态因子以地形在世界空间的起伏程度来评价。对于静态因子,他们通过计算四叉树节点四条边的中点和两条斜边的中点误差最大值来计算。但是,这种取6个节点的误差最大值作为评价并没有充分考虑到节点的几何形状,缺乏理论依据,其误差评价因子只有两种,并不能充分准确地反映节点误差及其屏幕贡献度。
98年Hugues Hoppe等人在他们过往提供一种可以从任意网格增减三角形的方法[Hoppe96]的基础上通过提出了基于视向的渐进网格(VDPMs)。VDPMs提供了一个基于非规则格网(tin)的框架,能够提供更多渐进格网优化,具有处理凹陷等更为复杂的地形特征的能力,通过实时生成几何变形产生平滑的顶点分割和边折叠,通过屏幕误差来反映几何细分渐变,通过强制分块地形边界顶点不分割来处理裂缝。但是该方法具有难以支持随着地形动态改变而实时变化的网格的缺陷,需要跟踪网格的拓扑结构,难于生成和裁减。
2001年,Lindstrom和Pascucci提出了一种新的简单的容易实现的,易于内存管理和可靠的误差分析的地形LOD方法,该工作在过往许多地形可视化工作的基础上提供一个规则格网的自顶而下的框架,能够out-of-core的基于视向的大规模地形细化,支持快速的视锥剔除,三角带渲染,可选择的细化。该方法在磁盘上组织数据,通过操作系统内存映射,能够动态加载分块地形数据到物理内存。
随着近年来GPU的迅速发展,GPU的Vertex Shader和Pixel Shader图形芯片可编程能力已经日益受到重视,过往的工作诸如视锥剔除、分块映射内存等通用计算和海量数据管理在一定层面上已经可以部分移到GPU中,因此本文探讨了面向GPU的大规模场景可视化策略,提出了一些新的方法。
2、层迭泛型多分辨率LOD四叉树地形
四叉树结构可以直接地表示规则网格的数字地面模型。树中的每一个节点覆盖场景中一个2n×2n的地形区域,树的根节点表示整个地形。节点扩展时将地形沿平面上的两轴平分成四个子块,分别对应它的四个子节点依次逐层细分。
一个传统的四叉树结构可定义如下:
struct QuadtreeNode
{
QuadtreeNode *pSon[4] ; ∥4 个子结点指针
QuadtreeNode *pParent ; ∥父结点指针
∥消除拼接缝标志
Bool bCent ,bLeft ,bRight ,bTop ,bBottom;
float Error ; ∥结点覆盖区域最大误差
}
传统的四叉树模型生成时,每个节点都采样一次,从而不同的层对应不同的分辨率。建立全分辨率的四叉树对于超大规模场景来说会消耗大量内存。
2.1 两级四叉树地形组织
考虑到场景是超大规模的,本文把整个场景划分成三个层次,最顶层是World,中间是分块的Block,底层是QuadtreeNode结点。每个分块的Block是一可变的动态四叉树,每个结点类型为QuadtreeNode,而所有的Block又组成整个场景的静态全分辨率四叉树,也就是说,Block的数量跟场景大小成正比,LOD渐进简化是以Block为单位。因此,对整个超大规模场景,四叉树的设计可以分两种情况考虑:对于整个场景而言,整个场景所管理的各层Block是一棵全分辨率四叉树,以Block为单位;而对于每一个Block而言,是一个组织着大量QuadtreeNode的动态可变四叉树,以QuadtreeNode为单位。
图9. 两级四叉树地形组织
本文提出的上述组织方式有如下优点:
1. 与过去全分辨率四叉树方法相比,可以解决了过去整个场景中大量节点的问题,在我们的整个场景中,只存在一棵管理Block的全分辨率四叉树,以及当前活动的处于视锥范围内的Block里的动态可变四叉树。那些非活动Block里的大量节点不在生成,节省了大量的内存空间。
2. 与纯动态四叉树组织方法相比,地形数据的载入更新均以Block(块)为单位,避免了每帧都需要对整棵四叉树进行更新,只对当前处于视锥范围内活动的Block分别构建可变动态四叉树。同时方便本文后面部分能够实现后台异步的块的读入和更新。
3. 对于每个Block里的动态可变四叉树,我们把采样与四叉树模型分开,在建立四叉树模型时并没有采样的操作,得到的四叉树也不存在底层限制,当四叉树节点大小比Grid格网还要小的时候,不中止节点细分,而对节点内顶点进行分形内插高程,这对于距离屏幕相当近的节点,我们仍然能够达到一定精度,不存在约束四叉树由于约束带来的局部C2- LOD因素调整失效。
2.2 上层全分辨率分块地形四叉树
对于整个场景的以Block为单位的全分辨率四叉树,我们利用.net framework 2.0新提供的泛型直接构建一泛型类Quadtree<Block>,该类实现了IEnumerable<T>接口的GetEnumerator方法,使我们能够以for each方式快速地以根-左上-右上-左下-右下的顺序遍历整棵树,隐藏了具体迭代遍历的细节,对类外而言具有非常可观的面向接口优点。每个Block没有固定的大小,只有最底层的节点负责载入和释放数据,其他节点只负责记录有关的信息。
图10. 分块视锥剔除
我们首先按传统四叉树对上层分块地形四叉树进行视锥判断,对于渲染的每一帧,确定那些地形块处在视锥之内,对处在地形块之内的地形数据构建动态可变四叉树进行LOD简化,把简化后的树节点输出到负责地形渲染的类,因此在地形块类内需要静态的地形块队列,代表当前处在视锥范围内的地形块集合,当有新的地形块进入视锥范围,就添加到这集合,离开视锥范围就删除。
VB=Vertex Buffer S0=Stream Loader 0
VS=Vertex Shader
摄像机移动前 摄像机移动后
图11. 分块地形更新
通过上图发现,我们的地形分块更新策略与过往策略相比,我们能够充分利用GPU,我们的策略通过地形分块视锥判断,只对分块地形中刚进入视锥范围,离开视锥范围,以及细节层次需要较大变动的地形块进行处理,进行细节层次简化和顶点索引缓冲组织,并把这些缓冲加载到Video Memory中,确保显存中的前端部分对应大量较小改变的相对静态的存有分块地形顶点数据的Vertex Buffer。
传统的地形更新方法每帧都需要遍历一次所有的地形块以确定哪些块进入了视锥范围,哪些离开了,实际上,活动地形块集合(所有处于视锥范围内的地形块的总和)的变化速度是很慢的,除非用户有大幅度的镜头移动动作,否则对于超大规模地形场景而言,地形块集合甚至有可能在很长一段时间都不需要更新。近年来,有不少学者提出了多线程模型下的地形策略,本文在此基础上作了改进,充分利用.net的异步回调机制,提出了一种新的多线程更新模式。另一方面,传统的更新方法,在地形数据加载和释放的瞬间由于运算量的大幅增加,会占用大量时间,出现迟滞现象,使画面在加载或释放数据的时间内得不到渲染。我们的更新方法考虑到.net framework 2.0的自动内存回收服务,可使托管内存堆中没有引用的资源在后台自动缓慢回收,避免了瞬时更新或回收大量内存资源带来的渲染迟滞。因此,需要把需要加载或释放的数据分成几部分,每加载一部分,就交出控制权给系统,以分配更多的处理时间给其它线程,以使更新数据的同时仍然能够保持画面的连续性。
2.3 下层动态可变四叉树
对于处于视锥范围内的每个Block,分别构建动态可变四叉树,采取广度遍历,利用.net framework 2.0新提供的泛型队列(Collections.Generics.Queue < QuadtreeNode >)实现四叉树遍历。首先,我们建立一个QuadtreeNode结构,用以记录每个节点的信息。然后,我们使用两个队列current_queue 和 next_queue进行遍历,一个队列记录当前已遍历的节点,另一个队列则保存由已遍历节点生成的新节点。当处理某层节点的时候,我们先清空next_queue,再依次对current_queue的节点进行判断,如果当前节点在视锥之外,则可直接丢弃;如果当前节点在视锥之内且达到精度要求,则送入渲染;否则将节点分割成四个子节点,送入next_queue。
3 泛型哈希表节点标记策略
对于多分辨率地形,往往需要对于每一个节点记录很多情况,例如:四条边是否存在裂缝,当前节点是否被渲染了,子节点是否存在,子节点是否需要进行视锥剔除等等。这些情况过去比较常见的处理方法就是直接在节点数据结构里添加成员,如谭兵等提出的DEM四叉树节点数据结构就包含4个裂缝标记[19],采用这种方法需要每个节点都开辟一定的内存空间来存放这些布尔型的标记变量,并且节点四叉树如果在渲染时动态建立计算判断裂缝存在会消耗大量时间,如果在一开始就建立静态的全四叉树对于超大规模场景会消耗极大内存,并且如果对于分块地形,如果当前的活动地形块不止一个,不能处理两个相邻节点分别处在不同地形块所产生的裂缝,由此可见直接在树结构节点记录标记并不是最合适的方法。
潘李亮提出了采用二维的标记数组来记录这些如裂缝是否存在这样的状态变量。对于这种方法,首先创建一个跟场景一样大的M×N的二维数组,用布尔值true或者false记录节点的状态。如图12所示,节点中的9个顶点均对应场景中的一个位置,也对应标记数组的一个元素,可以用节点中心点对应的标记数组元素记录节点是否已经被渲染,用节点四边界点对应标记数组元素记录节点边界是否存在裂缝,或者裂缝是否已经被消除这样的布尔型值。使用标记数组可以很容易解决相邻节点处于不同地形块中的裂缝问题,然而它同样会消耗大量的内存空间。
图12. 标记数组
本文提出泛型哈希表代替二维标记数组,成功地解决了标记数组大内存消耗量的问题。使用VS.net2005 FrameWork2.0最新提供的泛型数据结构,结合大规模地形的节点情况,我们采用了Hashtable<long,mark>。Hashtable<long,mark>是一个“键-值”对的集合,它里面每一个元素都有一个键(key)值和一个数据值(Value)。
key为节点(x,y),sizex为场景横向大小,作为哈希表的长度,,获取key的哈希值。
Value标记值可以是布尔型,也可以是其它基本数据类型或枚举,以位向量的形式把各种标记组合起来。在本文工作中,我们定义了一个枚举来指定位的设置,清零,探测,如下:
Enum NodeFlag
{
Rendered=2 //节点是否已经被渲染了
Divided=4 //节点是否已经被分割为4个子节点
Can_be_divided=8//节点能够被分割
Disabled=16 //节点被禁用了
……
}
泛型Hashtable<long,mark>是一种与传统的哈希表完全不同的技术,称为二度哈希(rehasing,也有称其为双精度哈希double hashing)。其工作原理如下:首先定义一个包含多个哈希函数的(H1,H2,…,Hn)的集合,当我们要从哈希表中添加或获取元素时,首先用H1;如果产生冲突,则尝试H2,…,一直到Hn。各个哈希函数基本相似,只是选用不同的乘法因子,如式3-1。
在检索时候,二度哈希执行了sizex次挖掘,表中的每一个位置都要有且仅有一次访问,即,对于给定的key,对哈希表中的同一位置不会同时使用Hi和Hj。而且,保证1 + (((GetRehash(key) >> 5) + 1) % (sizex – 1))与sizex互为素数。这样,使用二度哈希的策略,既避免了冲突,又提高了检索效率。
此外,哈希表为我们提供了在速度与内存消耗之间调整的初始化变量值,哈希表构造函数中的加载因子指示了元素与存储桶的最大比率。加载因子越大,哈希表越密集,空间越小,对于我们的超大规模场景标记越是有利。理论上,加载因子1.0是速度和大小之间的最佳平衡,但是,微软认为加载因子的最佳值为0.72,和.net framework1.1不同,.net framework2.0即是使用1.0作为加载因子,系统也会将其转变为0.72,因此,我们直接使用0.72, 当实际加载因子达到此加载因子时,存储桶的数目自动增加到比当前存储桶数大两倍的最小质数。如果不做精度上的严格要求,当发生冲突时,挖掘操作的预期次数为1/(1-lf)(lf为LoadFactor),取lf=0.72即为3.5。
二维标记数组与哈希表相比在具体实现细节上并不需要象哈希表一样在分类的存储桶中查找对象元素,从某个角度上看二维数组可以看作是m×n 个储存桶,每个储存桶对应同集同义词,速度显然比哈希表快,然而这样每个储存桶只存放一个数据或者甚至没有数据(该坐标位置对应点并没有需要标记的状态)大大消耗了很大内存,而且对与超大规模场景来说,使用超大范围下限的二维数组无论在访问或者清空整个数组来说都是需要很大的工程量。而哈希表由于灵活的储存桶方式,能够通过动态调整加载因子在速度和内存消耗上调整到一个合理的平衡位置。
除此之外,由于二维标记数组内存空间位置的固定性,当摄像机镜头发生大幅移动时,当前活动的Block发生改变,沽空了大量非活动Block数据对应的位置标记,形成了大面积的内存断片状待回收空间,使.net framework的GC自动垃圾回收线程服务带来了非常巨大的压力,容易产生视觉延迟和图像不稳定,而哈希表分桶存储的特点使得随着摄像机的移动,能够动态地从哈希表中删除远离摄像机的标记,有效地回收存储空间,尽可能的避免冲突。经过我们的实验验证,尽管仍然有冲突存在,但基本控制在本策略容忍的范围内。
E1不同的节点标记方法对比实验
前文提及了三种不同的多分辨率地形节点标记方法:二维标记数组,哈希表,节点数据结构添加标记成员。我们就这三种方法在不同的地形场景大小下进行了比较。实验时采用第三种优化后的视锥剔除方法,测试场景地形起伏平缓,地形静态误差对图形贡献度的影响足够小,多纹理通道下地形纹理和细节纹理同时渲染,实验时每帧分10次共渲染约10000个三角形,不进行帧约束,为了保证摄像机位置对帧速的影响足够小,摄像机位置在不同场景载入后置场景中心位置上方。改变节点标记方法时,不改变场景中其它参数。实验时,在不同场景大小,通过改变标记方法,观察FPS值的变化,比较各种标记方法对于不同大小场景的优异。下表给出了我们实验的数据,表中数据单元格中的数值表示该格对应状态下的FPS值。
表7. 各种标记策略对比
场景 大小 (数据点) | 标记 数组 (FPS) | 哈希表 | 节点数据结构添加标记成员(FPS) | ||
加载 因子 0.5 (FPS) | 加载 因子 0.72 (FPS) | 加载 因子 2.0 (FPS) | |||
105.3 | 99.7 | 96.6 | 88.4 | 82.6 | |
5122 | 102.2 | 97.2 | 96.0 | 87.1 | 81.5 |
10242 | 99.8 | 95.4 | 95.5 | 84.6 | 80.2 |
20482 | 97,6 | 94.3 | 95.2 | 83.5 | 76.8 |
40962 | 94.4 | 93.2 | 94.7 | 82.2 | 74.4 |
81922 | 89.6 | 90.2 | 92.2 | 79.5 | 72.5 |
163842 | 76.2 | 84.4 | 89.9 | 77.0 | 70.2 |
655362 | 59.8 | 66.6 | 78.8 | 71.5 | 61.6 |
从上表可以看出,标记数组由于其只需要根据索引坐标获取对应的二维数组元素查找速度相当快,但是消耗大量的内存。而节点数据结构直接添加标记成员方法耗内存小,但需要花费相当多时间进行遍历和查找节点状态。而哈希表正是介于两者之间,能够通过加载因子在查找速度和内存消耗之间调整。对于小的场景来说,场景小,标记数量不多,消耗的内存也不多,显然标记数组的高速查找更体现优势。然而随着场景大小的增加,标记数组需要对应更大的二维数组,消耗越多的内存,每帧清空重置整个数组的时候花费了相当多的时间,哈希表的优势逐渐体现出来。
我们通过实验发现,对于大小在4097×4097以下的场景,二维数组比哈希表快,在256×256场景中,二维数组快出差不多10帧每秒,而当场景大小超过4097×4097,哈希表的优势逐渐显现。在我们实验的Puget Sound场景中比二维数组快出了20多帧每秒。由此可见,当使用哈希表进行节点标记,并且加载因子处在1.0的最佳速度和内存大小平衡状态下,对于大于4096×4096大小的场景能取得较快的速度,基于哈系表的节点状态标记策略是目前大规模场景节点状态标记的一个最优策略。
4、LOD评价因子
通常在进行地形的LOD简化过程中,用以下两个因素作为衡量标准,一是动态因素,常通过计算待渲染节点经过投影后在屏幕的大小或节点到摄像机的距离来表示。二是静态因素,也就是地表粗糙程度以及地形的起伏程度。地形起伏的程度越厉害,需要的层次细节精度越高,地形起伏的程度越小,需要的层次细节精度越低,渲染较小的三角形就可以近似表达了。
4.1 节点静态因素的评价
节点的静态因素定义为一个能够准确衡量节点LOD程度的一个指标,直接影响着地形细节层次简化的效果。计算节点的静态因素到目前已经有比较多的方法,如谭兵等提出的评价误差平面方法等。通常对于基于二叉树的节点,只需要简单计算该节点继续细分与无细分相差的插值误差。
而对于四叉树则需要考虑更多的因素,潘李亮提出取以下各值的最大值为静态因素参考值:四边界插值误差值,两条对角线插值误差值,以及四个子节点最大误差值的一半(另一些学者认为应直接取四个子节点的最大误差)。这种计算方法中取四个子节点最大误差的方法相当直接快捷,但没有理论依据,并不符合节点几何形状。地形的静态因素是在地形生成过程中计算,属于预处理阶段,并不需要在渲染时每帧计算一遍,因此计算的复杂程度并不会影响渲染效果,并不需要进行任何粗略或者近似的计算。
本文采用了一种基于四叉树的静态因素评价方法。取(P1,P2,P3,P4,A1,A2,A3,A4,C5×2)10个误差中的最大误差为参考值,与上述方法相同首先需要计算四边界插值误差和两对角线插值误差,只是后四个误差不再简单地取四个子节点误差的某个倍数,我们以图7为例说明如何精确地求这4个误差。
图13. 节点静态因素计算
假设A1,A2,A3,A4四个子节点的静态误差已经求出,我们先把A1的静态误差值赋予A1节点的四个角点C1,P2,P1,C5,同理A2,A3,A4的静态误差值均赋予它们的四个角点。P1取A1,A3两个误差值的较大的那个,P2取A1,A2大的一个,同理P3,P4均取关联的两个子节点误差值的大者。然后把P1,P2,P3,P4四个点的静态误差值倍乘以一个K,K定义为下式:
其中C2为节点的静态因素控制量,用以调节节点地形起伏陡峭程度对细节层次精度效果的影响。倍乘K之后的四个误差值,以及四条边中点误差值和两条对角线的误差值,取这10个误差值的最大者作为C5该节点的静态误差值。下图说明了静态因素评价的方法。
图14. 节点静态因素计算
从上面可见,要求出C5的最大静态误差值必须先计算出A1,A2,A3,A4四个子节点的误差值,可见每一个节点的静态误差都必须先求它的四个子节点的静态误差值,这样一个过程可以迭代实现。
4.2 镜头移动速度——全局的LOD评价因子
在过去一般认为节点到摄像机的距离以及节点的静态因素(起伏陡峭程度)以及节点的大小是考虑是否需要继续对该节点进行LOD简化的重要选择尺度,然而考虑这些因素并不充分,因为我们镜头的运动速度也会对屏幕渲染效果产生重要影响,因此评估一个节点对屏幕效果的贡献度应该考虑上镜头移动速度这样一个因素。
在本文中,我们将探讨一个全局的LOD评价因子——镜头移动速度(待渲染节点的模糊程度)。相比之下,镜头移动速度作为一个因子比其它选择尺度并没那么重要,但它确确实实影响了渲染效果。当我们的镜头移动速度越快的时候,看到的景象越模糊,节点需要达到的精度越低,当我们镜头移动速度越慢的时候,看到的景象越清晰,节点需要达到的精度越高。因此,镜头移动速度是一个全局的LOD选择尺度,它是保持场景漫游平滑度的一个重要调整量。
一般认为通过调节其它几个LOD评价因子可以保持每帧渲染的节点数趋于稳定,然而当我们加入了镜头移动速度这个因子,如果每帧渲染的节点数还保持恒定就不符合实际情况了,因为镜头的快速移动会造成画面模糊,我们渲染的节点的精度都需要一定降低,因此镜头移动速度相对其它LOD评价因子,是一个后期考虑的因素。
镜头移动速度的评估目前还没有成熟的方法,我们初步用了一种方法,计算出前后两帧之间摄像机的位移矢量的大小(移动的距离)作为评价因子。
4.3 综合节点评价函数
综合考虑节点静态因素和节点到屏幕距离以及节点大小、摄像机移动速度这几个LOD评价因子,在[Rotter98]等工作的基础上,经过对各种可能情况的组合对比实验,选择最优实验结果,我们得到以下的节点评价公式:
L为节点到摄像机的距离,v为镜头移动速度,d为节点大小(节点宽度),d2为节点的静态误差(节点地形起伏陡峭程度),C1为节点的动态误差控制阙值,用以调节节点到摄像机距离对LOD节点屏幕贡献度的影响,C2为节点的地形起伏程度对LOD屏幕贡献度控制阙值,C3为摄像机移动速度对LOD节点屏幕贡献度控制阙值。
图15. 各LOD因素评价示意
5、基于Triangle List的累积渲染
Direct3D为我们提供了六种图元类型,如下表。其中在地形渲染中常用的是后三种。
表8. 各种三角形渲染模式
PointList | 表示一系列离散的点 |
LineList | 表示一系列离散的线段集合 |
LineStrip | 表示连续的折线段 |
TrangleList | 表示一系列离散的三角形集合。每三个顶点绘制一个单独的三角形,该种方法常常和顶点索引配合使用。 |
TrangleStrip | 三角形带是一系列相连的三角形,每两个相邻的三角形共享两个顶点。常用于复杂Mesh |
TrangleFan | 表示扇形组织的三角形集合,与三角形带相似,每个集合中的所有的三角形都共享一个中心顶点。 |
a . Triangle Lists
图16. DirectX 9.0提供的后三种图元
我们以一个四叉树节点为例,比较后三种以三角形形式组织的图元类型在地形渲染上的差别。一个四叉树节点包含9个顶点,我们的目标是以最快的速度把这9个顶点连接的三角形渲染出来。
Triangle Lists Triangle Strips Triangle Fans
图17. 单个四叉树节点在三种不同图元类型下对比
从上面三个图可以很容易看出对于单个四叉树,需要渲染的三角形数目是一样的,Triangle Lists以集合的形式通过索引把一个个的三角形组合到一起,然后一次全部渲染;Triangle Strips以三角形链形式组织,需要分两次渲染;而Triangle Fans以扇形形式组织,同样只需要一次即可,并且可以不使用索引。单从一个节点考虑,并不能容易看出三种模式在树结构地形渲染中的优缺。
注:也可以用Triangle Lists按扇形形式把三角形组合起来渲染,但组织相对不如直接用Triangle Lists简单
接下来考虑大面积多个节点的情况,以2×2个连续同细节层次级别的节点地形为例。三种图元类型组织如图11
Triangle Lists Triangle Strips Triangle Fans
图18. 2×2四叉树节点在三种不同图元类型下对比
三种图元类型需要渲染的三角形数是相等的,但是Triangle Lists只调用了一次渲染三角形的函数,而Triangle Strips有多少行三角形带就至少需要调用多少遍,对于2×2的地形块(如图11中)调用了4次,而Triangle Fans有多少个节点就需要调用多少次渲染函数, 对于2×2的地形(如图11右)共有4个节点因此共调用了4次。由此可见Triangle Lists随着节点的增多并不需要频繁增加调用渲染函数的次数。
在大量顶点的场景中,如果单纯使用顶点缓冲,很可能有大量的顶点重复添加到顶点缓冲中。比如说对于一个立方体,如果纯粹以顶点形式组织,我们需要创建36个顶点。实际上,我们只涉及8个不同的顶点而已,即立方体的8个顶点。对于小量顶点而言,没有什么区别,但是对于存在大量三角形的程序,减少重复顶点来节约空间就显得很重要了。Direct3D8之后都为我们提供了索引缓冲的机制让我们以索引形式组织三角形,避免顶点重复添加到顶点缓冲。
过往许多文献都认为triangle strip组织更有优势,认为在三角形带组织过程中三角形带可以把边界连续的三角形顶点共享,减少顶点缓冲中顶点数目,然而对地形节点而已,地形节点的细节层次确定后,顶点数目就基本一致,在无需处理边界裂缝改变节点拓扑关系的情况下,每个节点的顶点数目都是8个,对于每个分块地形,去除顶点缓冲中重复的顶点后,顶点数目是一致的。因此无论triangle List,triangle strip还是triangle fan顶点缓冲中顶点数目是基本一致的,交给GPU vertex shader进行顶点变换的顶点数目是一致的,差别只在于triangle strip索引数目相对triangle List要少,而每个索引只占16bit的存储空间相对每个顶点占200多bit的
// 48+64+32+32=176<192
Structure CustomVertex
{
//{float x, float y, float z}48bit
D3DVector3 Position;
//{float r, float g, float b,float z}64bit
D3DRGBAColor Diffuse;
// {float tv1 ,float tu1}24bit
D3DVector2 Texture1;
// {float tv2 ,float tu2}24bit
D3DVector2 Texture2;
}
注:我们这里假设顶点缓冲了显存初始地址
图19. Triangle List节点索引组织方案
在同时使用顶点缓冲和索引缓冲组织三角形时,对于任何地形结点而言,顶点数量是一致的,只是索引数量不同,Triangle Strips和Triangle Fans与纯顶点缓冲情况下相类似,用到的索引数量小了,但是图形接口需要比较多次调用渲染函数,而Triangle Lists虽然用索引数量增加了,但是却大大降低了调用渲染函数次数,很大程度上,使显示设备能够连续地渲染三角形。表9对比了图19所示意对于一个结点在同时使用顶点缓冲和索引缓冲的区别。
表9. 不同节点数量数据对比
结点数 | 顶点数 | 索引数 | 绘制函数 调用次数 | |
图5-3所示 Triangle Lists | 1 | 9 | 24 | 1 |
图5-3所示 Triangle Strips | 1 | 9 | 12 | 2 |
图5-3所示 Triangle Fans | 1 | 9 | 9 | 1 |
图5-4所示 Triangle Lists | 4 | 25 | 96 | 1 |
图5-4所示 Triangle Strips | 4 | 25 | 40 | 4 |
图5-4所示 Triangle Fans | 4 | 25 | 36 | 4 |
当前主流的图形显示卡都支持在每一次调用渲染函数时一并渲染多达数万个三角形,显然,对于有大量节点构成的地形来说,采用Triangle Strips或者Triangle Fans是不明智的,而采用Triangle Lists把三角形累积到一定数量再调用渲染函数一并渲染能够最大限度通过Direct3D / OpenGL图形接口利用GPU。
E2每次调用函数渲染三角形数量最优值测定
在每帧的图形渲染上,每次调用渲染函数渲染的三角形数量对整体渲染速度以及FPS值都有着一定的影响,每次调用渲染函数渲染的三角形数量小,需要调用渲染函数的次数相对就增多,花在循环控制运算量上的时间也就多了,渲染的三角形数量多,超出了图形接口的能力就会降低渲染速度,那么每次调用渲染函数渲染多少三焦形是最合适的呢?为了大致测定每次调用渲染函数最优的渲染三角形的数量,我们在FX6500带128M显存的图形卡上进行实验,图形卡支持多通道纹理,支持Direct9.0,支持顶点着色,实验时,为了避免额外运算,以循环形式把设置好顶点缓冲和索引缓冲的三角形交给DrawIndexedPrimitives函数渲染,限定每帧渲染10000个三角形,不约束帧数,实验时只改变每次调用渲染函数时的三角形数量,观察每秒钟渲染的三角形数量的变化以及FPS值的变化。实现时同时使用LOD简化方法。
图 20. Triangle Lists累积渲染
根据实验证明Direct3D的三角形渲染函数的每次调用处理1000个左右的三角形是最合适的,对于我们的地形场景来说,每帧大约渲染的三角形数稳定在8000-12000左右,也就是说每帧大约要调用渲染函数8-10次。为了保证该经验值的有效性,我们改变每帧渲染的三角形总数量,以及调整API相关的约束帧控制,发现总数量的变化以及受控制的FPS变化对每次调用渲染函数渲染的三角形数目的最优值影响不多,最能影响该经验值的是每帧调用该函数的次数,也就是循环的次数。我们初步认为如下经验值是比较合理的:对于GFMX400以上的显示卡累积约1200至1350个三角形调用一次渲染函数能够达到最大速度,在每帧平均渲染5000-8000个三角形状态下能够比每个节点用Triangle Fans模式渲染FPS(每秒渲染的帧数)值大9-11左右。
由此可见,采用Triangle Lists组织三角形比Triangle Fans组织三角形更具优势,Triangle Lists是三角形的集合,我们只要把三角形累计到一定数量,设置好顶点和索引,一次渲染就可,我们可以明显看出Triangle Fans方式组织对于每一个节点都需要调用一次渲染函数,而Triangle Lists则只有从节点中添加的三角形数量累积到一定数量才渲染,让图形接口一次调用中渲染比较多的三角形,降低GPU和CPU控制权相互转让的时间,降低反复调用渲染函数的时间,同时由于最佳累积量处于1000左右,可以用16位索引,避免了32位索引,降低了传输带宽,充分利用GPU。
6、边界裂缝处理
6.1 基于边界样式的裂缝处理方法
对大规模地形进行细节层次简化时,由于节点的细节层次不同会产生裂缝,如两个相邻的节点,邻近摄像机镜头的节点比另外一个节点可能具有更高分辨率,造成相邻节点细节层次的差异,从而产生裂缝。下图说明了裂缝的产生。
图 21. 多分辨率LOD模型节点间裂缝
图 22. 多分辨率LOD模型细节层次切换顶点跃动
裂缝处理方法从大体上可分为两种,一种是在低分辨率的节点添加一条边,另外一种是在高分辨率的节点删掉一条边。边删除方法通过在产生裂缝的边界处删除顶点及该顶点到节点中心点连线以消除相邻节点细节层次差异带来的裂缝。
图a 裂缝处理前 图b 裂缝处理后
图23. 传统的裂缝消除
上图示意了传统的边界裂缝处理方法,图12-a中两个黑点表示该边界上因相邻节点细节层次级别差异带来插值误差裂缝的顶点,图12-b通过删除这两个顶点,及这两个顶点到节点中心点连线消除了裂缝。使用这种消除裂缝方法,通常是采用Triangle Fans模式,因为该模式可以方便地分别判断各边界上是否存在引起裂缝的顶点,存在的话则忽略该顶点,不存在的话则渲染该顶点。然而这种裂缝消除方法不单不适应我们前面Triangle Lists累积三角形渲染策略,还因为合并了二个带来裂缝的三角形而同时降低了裂缝所在边界及节点中心点区域的精度。
上述这些方法都实现了裂缝的消除,但是都并不能够充分利用Direct3D、OpenGL的硬件渲染能力,无论添加边或者删除边或多或少都添加或删除了三角形,并不能够保证每个节点渲染的三角形数目的一致性,对于相邻节点层次相差超过1时处理并无优势。
本文在上述方法的基础上提出了边界样式方法,在删除边界引起插值误差带来裂缝的顶点的同时,不改变节点中心区域精度。通过实验我们发现,实际的场景中出现裂缝时,边界两边的相邻节点细节层次差别一般不会超过3级,因此,我们预先定义的裂缝的边界样式及处理方法,当场景绘制出现裂缝时,直接与预先定义好到的样式尝试匹配,如果裂缝存在情况已被考虑,则可以直接根据已定义的处理方法改变索引,从而消除裂缝。
图14中,我们以4×4的模板、细节层次差别1级为例,给出了16种可能的边界样式,通过裂缝位置匹配确定裂缝的种类。图中灰色区域的三角形表示节点中在消除裂缝的同时精度(分辨率)不变的三角形,而白色区域的三角形表示存在裂缝的边界。我们通过修改,将裂缝边界处的精度(分辨率)降低了1级,最终达到消除裂缝的效果。
图24.相邻节点细节层次相差1时的16种边界样式
下面两个图中,我们具体给出了裂缝出现的情况和处理方法,包括细节层次差别1级和2级,确定裂缝位置后,根据细节层次差别的不同,确定最终的裂缝处理方案。
a. 相邻节点细节层次相差1时的裂缝消除
b. 相邻节点细节层次相差2时的裂缝消除
图25. 边界样式节点裂缝消除
在5.1中,我们论述过索引缓冲渲染机制,显然,在具体组织边界样式过程中,我们无需删除或添加顶点的数目,只需要在用索引组织顶点的时候,先组织中央区域三角形,再考虑各边界裂缝存在情况,如果存在裂缝,则在组织三角形时忽略某些顶点即能顺利消除边界裂缝。
图26. 边界样式节点裂缝消除
5.3 用插值高程代替实际高程的裂缝消除方法
5.2所提及的方法在边界索引组织时,需要花费一定的时间周期计算和判断边界情况,同时由于三角形的合并,在顶点缓冲中分布着一系列离散的顶点。
本文在相关工作中提到的方法都是在裂缝边界处合并高精度的三角形或者修改高精度三角形的顶点(索引)。这样做有利于保持场景网格的拓扑关系,便于场景的其他绘制时,以三角形为单位的矢量计算。
但如果对光照、地形模型精度等要求不是很高,在地形实时渲染中不需要强调完整的拓扑网格,或者允许面积为零的三角形存在。
本文在此基础上,再提出了一种既不改变顶点缓冲中顶点组织顺序又不改变索引缓冲中索引组织顺序的裂缝消除方法。
图a 裂缝消除前 图b 裂缝消除后
图27. 用插值高程代替实际高程消除裂缝
这种方法分别对存在裂缝的别界顶点用插值高程代替实际高程,如上图a,只需要把A点的高程值(Y坐标值)设为B点的高程值即可实现裂缝的“缝合”。
这种方法保持了每个节点顶点数目和索引数目的一致性,使得顶点缓冲中顶点的顺序尽可能地符合渲染顺序,但是对于各插值处而言,均比边界样式方法多渲染了一个位置重复的顶点,增加了渲染三角形的数目,从渲染量的角度而言增大了GPU流水线的负担,但从组织的角度而言更合理更接近人们的常规组织方式。
通过我们的实验证明,这种方法与基于边界样式的裂缝消除方法,速度比较接近,略慢于边界样式方法,但比传统的方法都要快。
表10. 各种裂缝消除方法对比
裂缝消除方法类型 | 顶点缓冲中顶点分布 | 特点 |
不消除 | 顶点顺序与渲染顺序比较接近 | 无 |
边界裂缝处增加顶点及增加到低层次节点中心点连线 | 无序,按索引组织渲染顶点时,顶点处于顶点缓冲中位置距离大,访问跳跃频繁 | 增加顶点计算量大,GPU渲染吞吐量增大,节点精度增加 |
边界删除一个顶点及该顶点到节点中心点的连线方法 | 顶点顺序与渲染顺序比较接近 | 删除顶点计算量大,渲染量减少,节点精度降低明显 |
边界样式方法 | 跳跃,存在忽略始终没用到的顶点 | 边界判断运算大,渲染量减少,节点精度降低不明显,中心区域精度没变化 |
用插值高程代替实际高程方法 | 顶点顺序与渲染顺序比较接近 | 边界判断运算较小,渲染量大,节点精度降低不明显 |
从上述可以看出,本文5.2,5.3提出的两种方法,在速度上比过往方法没有非常明显的提高,但是前者保证了节点中心精度不变,后者保证了顶点缓冲中顶点顺序与渲染顺序尽可能接近,更易于代码编写和三角形组织。
结果与讨论
我们对多种地理数据进行了实验,如下:
表12. 各种地形数据源
数据集 | 格网大小 | 来源 |
Puget Sound (普及特湾) | 32768×32768 | USGS 1:10m DEM ,1:0.1m高程 |
Grand Canyon (美洲大峡谷) | 32768×16384 | USGS 1:10m DEM ,1:0.1m高程 |
Rockies (落基山脉) | 70400×54400 | Terra地球卫星影像 |
我们在3.0GHz Pentium 4 CPU,1 GB system memory , nVIDIA Geforce FX 6600 GPU with 128M video memory(出厂参数为每秒处理502Million个三角形)环境下进行了实验,实验以640×480×32bit全屏幕模式下,90度视锥宽度环境下进行。
54400×74400落基山脉一部分
32768×16384 Grand Canyon(美洲大峡谷)
图35. 我们策略实时渲染的两个场景效果
我们在带有视锥剔除、多LOD评价因子,约束帧FPS为60的情况下和同类研究作了对比,我们得到88Million三角形每秒的渲染量,进一步接近目前主流显示卡(如NVidia GeForce FX 5900 / 6200 / 6600等,价值约100-150美金,每秒渲染300Million-600Million个三角形,参考附录一)的三角形处理能力。我们还在相同环境下运行了下表后三种方法所附实验程序,下表是详细的对比数据:
表13. 不同方案FPS60下的渲染对比
方案 | 我们同一机器(Nvidia GF FX6600GT)上测得的每秒渲染的三角形数量 | 原论文报告的数据 |
Our approach | 88Million | / |
Geometry Clipmaps (2004) | 55Million | 59Million (Radeon 9800XT) |
Cignoni et (2003) | 59Million | 16Million |
Lindstrom (2002) | 18Million | 2.4Million |
VDPM Hoppe(1998) | 3Million | 0.48Million |
通过上表对比,我们发现,我们策略的FPS略低于Geometry Clipmaps,但是我们的累积渲染策略在同样条件下,每秒渲染了更多的三角形,获得了更高的精度,我们发现在640×480分辨率下,我们比其它方法多渲染的三角形并没有得到明显的效果呈现,部分三角形光栅化后小于1个象素点,并没有明显的视觉精度提高,但是随着我们屏幕分辨率的提高,在1280×1024的分辨率下,我们在稳定的视觉环境下得到了更高的精度,帧速减小带来的高精度渲染是值得,我们发现与其它世界空间误差评价策略相比,我们的策略能够使得更多的三角形在投影变换到屏幕空间后呈现小的象素点,不存在一个三角形光栅化后占有多个屏幕象素的情况。
表14. 不同方案的更新速度
Update step \ Differen schemes | our approach | Geometry Clipmaps |
update chunk block | 3 | / |
Computation of static error | 3 | 3 |
Decompression or Synthesis | / | 3 |
load to video memory (load vertex buffer and index buffer) | 1 | 3 |
Normal map computation | / | 11 |
Total | 7 | 20-11=9 |
应用与展望
本文的这套超大规模场景策略,能够应用在国家安全,精确制导、高分辨率卫星航拍遥感影像可视化,超大规模城市建模衍变仿真、人工植物群、虚拟现实场景漫游、虚拟战场,电子沙盘等领域,有着重要的研究意义和经济价值。
本研究能应用于精确制导模拟,能够监控整个导弹发射,非惯导轨迹飞行等过程,有俯视,镜头跟踪等观察模式。
本研究可以应用于赛博空间、虚拟城市等领域,实现超大规模城市建模衍变仿真,能对城市中多达40000的建筑物、树木、人等场景对象实时渲染,多级道路样式和基于OL-System文法的区域迭代等能够模拟城市从小镇到大都市的发展过程,在城市规划、衍变模拟等有着深远的研究意义。已有辐射状和悉尼状城市等多个案例演示。
本研究可应用于高分辨率卫星、航拍、遥感影像空间数据可视化等方面,支持基于DEM,DOM的海量空间数据,能进行地物标注,支持俯视、轴视等观察模式,已有突尼斯海湾,塔克拉马干沙漠,澳洲大宝礁等多个案例演示。
本研究可应用于地学分析,VRGIS等领域上,能进行多种地学测量,地表区域分析,地形分层显示,地貌、植被属性查询, 无级别比列尺等操作,已有火山口、深邃、山峰,海岸线等多个空间测量,3DGIS操作,地貌科学分析案例演示。
本研究可应用于地学仿真实验、虚拟战场、虚拟军事环境等,代替传统的人工沙盘作业,为地学实验提供快捷准确有效的数据,在短时间内模拟整个大规模场景的变化,不必长时间进行实地观察分析,对地理群体特征进行可视化分析研究,代替部分在现实世界中难以进行或费时、费力、昂贵的地学试验。
本研究可用于飞行模拟、地区观光等领域上,进行景点路线导游,有鸟群跟踪,第一人称漫步等多种漫游模式,已有夏威夷四大岛,Coiba Island等案例演示。
此外,还可应用于大规模人工植物群仿真,三维游戏引擎等方面,根据本文策略开发的原型——World Creative Suite,World Explorer , World Solution SDK已经可以应用上述领域,World Builder能通过分形或Perlin Noise等方法根据分形维度、地表样式、分布序列、道路树木数量等生成与现实地形相近的人工地形。
参考文献
1. A.E.W. Mason & E.H. Blake “A Graphical Representation of the State Spaces of Hierarchical Level-of-Detail Scene Descriptions” IEEE Transactions on Visualization and Computer Graphics, 2001 7(1) 70-73.
2. B. D. Larsen & N. J. Christensen. “Real-time Terrain Rendering using Smooth Hardware Optimized Level of Detail”. WSCG 2003 11(2) 282-289.
3. C. Dachsbacher & M. Stamminger. “Rendering Procedural Terrain by Geometry Image Warping” Eurographics 2004.
4. D.Cline & P.K.Egbert “Terrain decimation through quadtree morphing” IEEE Transactions on Visualization and Computer Graphics 2001 7(1) 62-69.
5. F.Losasso & Hugues.Hoppe “Geometry Clipmaps: Terrain Rendering Using Nested Regular Grids” ACM SIGGRAPH 2004 Proc.
6. H.Hoppe “Smooth view-dependent level-of-detail control and its application to terrain rendering” IEEE Visualization 1998 35-42.
7. J.Levenberg “Fast view-dependent level-of-detail rendering using cached geometry” IEEE Visualization 2002 Proc.
8. P.Lindholm et “A user-programmable vertex engine” ACM SIGGRAPH 2001 Proc, 149-158.
9. M.Duchaineau et “ROAMing terrain: Real-time op-timally adapting meshes” IEEE Visualization 1997 Proc, 81-88.
10. Pajarola “Large scale terrain visualization using the restricted quadtree triangulation” IEEE Visualization 1998 Proc 19-26.
11. P.Lindstrom et “Real-time, continuous level of detail rendering of height fields” ACM SIGGRAPH 1996 Proc, 109-118.
12. P.Lindstrom & V.Pascucci “Terrain simplification simpli-fied: A general framework for view-dependent out-of-core visualization” IEEE Transactions on Visualization and Computer Graphics 2002 8(3), 239-254.
13. P.Lindstrom & V.Pascucci “Visualization of large terrains made easy” IEEE Visualization 2001 Pro 363-370.
14. P.Cignoni et “Planet-Sized Batched Dynamic Adaptive Meshes (P-BDAM)” IEEE Visualization 2003 Proc.
15. 谭兵, 徐青, 马东洋 “用约束四叉树实现地形的实时多分辨率绘”. 计算机辅助设计与图形学学报, 2003 15(3).
16. 谭兵, 徐青, 周杨 “大区域地形可视化技术的研”. 中国图象图形学报, 2003 8(5).
17. 王宏武, 董士海 “一个与视点相关的动态多分辨率地形模型”. 计算机辅助设计与图形学学报 2000 12(8).
附录一:常见GPU处理三角形能力和显存大小
型号 | 每秒处理的三角形数量 | 显存(video memory) |
ATI RADEON X800 XT | 7.8亿(780M) | 256MB/512MB |
ATI RADEON 9800 XT | 4.12亿(412M) | 256M |
ATI RADEON 9700 | 3.25亿(325M) | 128M |
ATI RADEON 9000 | 0.5亿(50M) | 128M/64M |
nVidia GeForce FX 6800 | 6亿(600M) | 256MB/512MB |
nVidia GeForce FX 5950 | 3.56亿(356M) | 128MB/256MB |
nVidia GeForce FX 5900 | 3.38亿(338M) | 128MB/256MB |
nVidia GeForce FX 5600 | 1.13亿(113M) | 256MB |
nVidia GeForce FX 5200 | 8100万(81M) | 128MB |
nVIDIA GeForce 4 MX400 | 3500万(35M) | 128M/64M |
nVIDIA GeForce 2 MX400 | 2000万(20M) | 128M/64M |
nVIDIA GeForce 2 MX200 | 2000万(20M) | 32M |
附录二:Vertex Shader指令
Vertex Shader简单指令:
指令 | 目的操作数 | 源操作数 | 说明 |
ABS | v | v | 求绝对值 |
ADD | v | v, | v |
ARL | a | v | 载入到地址寄存器 |
DP3 | ssss | v, | v |
DP4 | ssss | v, | v |
DPH | ssss | v, | v |
DST | v | v, | v |
EX2 | ssss | s | 计算底数为2 |
EXP | v | s | 计算底数为2 |
FLR | v | v | 计算比 |
FRC | v | v | 计算 |
LG2 | ssss | s | 计算底数为2 |
LIT | v | v | 计算光照计算系数 |
LOG | v | s | 计算底数为2 |
MAD | v | v, | v, |
MAX | v | v, | v |
MIN | v | v, | v |
MOV | v | v | 赋值 |
MUL | v | v, | v |
POW | ssss | s, | s |
RCP | ssss | S | 计算倒数 |
RSQ | ssss | S | 计算平方根的倒数 |
SGE | v | v, | v |
SLT | v | v, | v |
SUB | v | v, | v |
SWZ | v | V | 扩展的分量下标置换 |
XPD | v | v, | v |
Vertex Shader中的复杂指令:
宏 | 参数 | 行为 | 时钟数 |
exp | dest, src1 | 提供精度至少在1/220 的2的幂计算 | 12 |
frc | dest, src1 | 返回每一个输入部分的小数 | 3 |
log | dest, src1 | 提供精度至少在1/220 的log2(x)计算 | 12 |
m3x2 | dest, src1, src2 | 计算输入向量和一个3x2矩阵的乘积 | 2 |
m3x3 | dest, src1, src2 | 计算输入向量和一个3x3矩阵的乘积 | 3 |
m3x4 | dest, src1, src2 | 计算输入向量和一个3x4矩阵的乘积 | 4 |
m4x3 | dest, src1, src2 | 计算输入向量和一个4x3矩阵的乘积 | 3 |
m4x4 | dest, src1, src2 | 计算输入向量和一个4x4矩阵的乘积 | 4 |