LOD地形渲染技术概述

参考文章
http://blog.sina.com.cn/s/blog_5e3213f30100zxet.html LOD技术简述
http://blog.sina.com.cn/s/blog_458f87120100q9eg.html LOD技术概述
http://my.oschina.net/u/997451/blog/122649 LOD裂缝问题解决方法
http://blog.csdn.net/baozi3026/article/details/5732989 ROAM实时动态LOD地形渲染
http://www.gulu-dev.com/post/2014-11-16-open-world 开放世界大地图使用的技术

LOD基本思想

由于大的地形绘制需要在短时间内处理上亿个三角形,其实时绘制要求仍然是飞行仿真、数字娱乐等虚拟现实应用中的一个难点。尽管近年来硬件技术飞速法阵,显卡的性能指标已经有很大的增长,但是仍旧不能满足大地形的实时绘制要求,比如在进行飞行模拟的时候,要穿越一个km为单位的地形,每个网格都用三角形绘制,则此时就算是再好的显卡在每秒至少24帧的要求下也不能进行实时的处理,所以多分辨率技术(Multi-resolution)就此诞生。

这里写图片描述

这里写图片描述

多分辨率网格简化技术/细节层次模型技术(LOD技术),引入“分而治之”的思想,根据地形的不同复杂程度和人眼观察地形的特点,对地形的不同区域采取不同细节的描述和绘制。采用LOD技术绘制地形,在不降低表现效果的前提下,可以尽量减少三角形的数量,以提高图形绘制效率,实现地形的实时交互可视化,通俗具体讲就是将一块地形划分为无数小块区域,对于离视点越近的区域,或者该区域地形越复杂(起伏大,如山区),绘制的三角形数目越多,地形描述精度越高;对于离视点越远的区域,或者该区域越平坦,绘制的三角形数目越少,地形描述精度越低。总结起来就是“近实远虚”

Lindstrom等人于1996年提出了基于四叉树的连续细节层次模型(Continuous level of Detail)的构建算法,是基于规则格网类的具有代表性的研究成果之一。算法的“连续”特性包含了3个意思:

  1. 帧更新时,地形表面保持连续性,即“时间的连续性”;
  2. 不同分辨率的地形分块之间保持连续性,没有裂缝,即空间连续性;
  3. 算法的实时构网能力很强,以保持较高的屏幕刷新率。

高度数据存储和获取

可以下载专门的高程数据,通过读取文本的方式读进内存然后建立顶点缓存和索引缓存。
更加通用的方法是通过高度图读取实现高度数据存储的。高度图可以用ps或者专业的软件制作。在专门的游戏引擎中有个专门的地形编辑器,直接刷地形。

节点评价系统

为了更好的对顶点进行优化,我们把LOD地形分为若干节点,划分节点的数量与大小就要通过一套节点评价系统来决定。为了使细节可以根据要求来进行细化,所以使用树的方法来实现节点的分割,常用的方法有四叉树和二叉树分割,在本篇文章里使用的是四叉树分割.
这里写图片描述
由于采用四叉树的分割方式,当节点最大限度分割时,其数目应该与地形尺寸相匹配,及(TerrainSize+1)*(TerrainSize+1),这也是为什么要求地形尺寸一定要为2n+1。
为了更加清楚的描述算法的思想,对三维地形有如下的要求:

  • 地形必须是一块正方形区域nxn;
  • 地形顶点数量必须是(2^n+1)X(2^n+1)

一个四叉树节点需要包含顶点信息,顶点的数目与该节点的邻接节点有关,为了方便分割,顶点数目设为9个,结构如图
这里写图片描述
0顶点为中心点,1、2、3、4点为角点,5、6、7、8为边点,顶点和角点是固定的,顶点数量的变动时指边点数量的变动如图
这里写图片描述
想象一下,节点分割的次数越多,地形就越精细,但是计算量也就越大,所以需要针对地形复杂区域的节点进行分割,较为平坦的地形则进行较少的分割。
节点分割的评价系统大致分为两个部分

  • 第一是节点到观察点的距离
  • 第二是计算节点区域复杂度

这里写图片描述
节点离观察点越近分割次数越多,根据第一条评价原则,总结出第一条评价公式:
L/d < C1
L为顶点到观察点的距离,d该节点的长度,C1为自定义的常量,C1的值越大顶点分割次数越多

节点区域地形越复杂,分割的次数就越多,根据第二条评价原则,总结出第二条评价公式:
L/r < C2
首先获取到顶点h0到顶点h4的高度,如果该节点分割则还要获得子节点的高度h5到h8,然后依次比较各高度值,取出最大值Max,与最小值Min,r = Max-Min。

综上所述将评价公式1和评价公式2合并起来:
L/(d×r) < C1×C2
变形得到最终公式:
f = L/(d×r×C1×C2) < 1
当满足f < 1时则判断该节点需继续分割。

对节点判断是否分割之后,我们需要存储这个分割信息标志,我们设一个类型为bool[][]类型的数组变量QuadMat,数组的长度应该与节点的数目一致,即QuadMat[TerrainSize+1][TerrainSize+1],存储方式如图,由下图也可看出为何顶点数目以及其高度数据HeightDate的大小也是(TerrainSize+1)*(TerrainSize+1)。
这里写图片描述

视锥及裁剪

在LOD地形中还有一项很重要的减少绘制顶点的方法,那就是对摄像机之外,那些我们观察不到的区域的顶点进行裁剪。这里说的裁剪并不是D3D里所说的裁剪,而是针对节点划分的控制,对于那些我们无法观察到的节点就将其分割信息设置为false。
这里写图片描述
关于frustum culling这里不赘述。

节点的渲染

这里写图片描述
在节点的每条边上是否有边点主要取决于相邻节点是否进行了分割,然而相邻节点既包括自身友节点(同一父节点分割出的四个节点层次为n)和父节点的友节点(层次为n-1),进行判别的时候也要把这两种情况区分开。如图所示红色区域的节点,蓝色的顶点代表通过判断父节点的友节点而增加的边点,红色的顶点点代表通过判断自身友节点而增加的边点。使用边点的作用在于增加节点面数,以避免邻节的不同层次衔接之间出现接缝。
根据节点中顶点的分布特点,采用扇形绘制三角面,如图,directX3D和OpenGL里面都包括这种绘制方法。(其实也可以用普通二维遍历索引渲染)
这里写图片描述
节点渲染的顺序采用递归的方法深度优先遍历整个四叉树的节点,遍历到子叶就进行渲染,判断该节点是否为子叶的标志就是观察该节点的分割信息为false。

LOD存在的问题及解决方法

裂缝问题

通常我们把节点看做一个四叉树,根据分割层次的不同,节点的尺寸也不同,这样一层一层的分割下去直到分割的极限尺寸
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

裂缝产生的原因是左侧节点在交点B处的高度值来自原始准确数据,而右侧节点的Level比左侧的低,在交点B处的高度值是A和C的平均值。这样,同一点在相邻的两个节点之间的高度差便会产生三角形裂缝。
这里写图片描述
两种技术可以解决裂缝的初级问题
1) 边删除技术
边删除技术在Level较高的节点T型裂缝处删除一条边这样把两个相邻的三角形合并成为了一个。如图中所示,要解决裂缝问题,共需要删除3条边,删除边之后的网格如图所示
这里写图片描述
2) 边插入技术,就是在Level较低的节点内部添加一条边,这样就把一个三角形分割成两个
这里写图片描述

然而,要避免T型裂缝现象,仅仅依靠边删除或者边插入技术是不够的,地形网格还需要满足一个条件:相邻两个节点之间的Level差值不能大于或者等于2.这时候边删除是无能为力的,采用边插入技术将使得算法变得过于复杂,不易实现。

解决办法:当两个相邻节点之间的Level之差大于1的时候,强制把Level较低的节点分裂成4个子节点

另外,cryengine里面的做法是
这里写图片描述
预先在不同level的网格周围都空出一行和一列专门用于连线消除裂缝,如图所示连接。

突起问题

当视点移动的时候,地形网格不断更新,当节点Level发生变化的时候,地形中的某点会由一个高度突然跳变到另一个高度,这种称之为“突起”现象(Poping-up)。在地形漫游系统中,“突起”现象给人 一种不真实的感觉。为消除这种不自然的行为,引入了一种”形变“算法。形变的含义是,当节点从一个Level过渡到另一个Level的时候,其中某点平稳缓慢地从一个高度过渡到另一个高度。形变虽然没有本质上消除地形高度变化,但这种“缓变”往往肉眼难以察觉。
关于解决突起的LOD算法,可以查阅相关论文,比较多。

©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页