耿 肖 韩志伟 廖 峰
(西南交通大学电气工程学院 成都 610031)
基于Unity引擎的地形块动态调度算法研究*
耿肖韩志伟廖峰
(西南交通大学电气工程学院成都610031)
针对基于Unity引擎的三维场景仿真中大地形加载过程中内存占用量大的问题,从模型资源加载角度设计一种地形块动态调度算法。以视点位置在地形平面投影为中心,加载其周边地形块,在视点移动过程中,根据其在地形平面投影映射的地形块行、列值变化,更新当前视点周边地形块队列,并计算需加载区域和需卸载区域,进而实现地形块的动态加载和卸载。最后依托Unity的内存管理机制,设计具体程序并实现地形块动态调度和内存优化。实验结果表明:该方法与直接进行大地形加载相比,能明显减少三维仿真中地形资源的内存占用量,并且大幅度提升帧率,在三维场景仿真中应用效果良好。
地形块; 动态调度; 视点位置; 内存管理; 三维仿真
Class NumberTP391
三维地形仿真一直是虚拟现实、三维游戏、虚拟仿真等领域的研究热点,它直接影响整个系统的真实感和沉浸感。为了提高地形漫游的实时性和计算机的渲染效率,国内外学者不断地改进相关技术。目前,主要从两个方面解决大规模地形渲染问题[1~2]。一是通过数据简化减少绘制的三角面数量:具有代表性的有四叉树算法、ROAM算法。二是通过对地形进行分块设计合理的组织体系,减少一次性载入量。文献[3]通过数据库动态存储分块数据并选择合适分块大小,采用动态LOD加快地形生成速度;文献[4]采用分页方法对地形进行管理。很多学者将二者结合来提高地形渲染效率,文献[5]提出一种基于线性四叉树的分块层次细节实时渲染算法,通过降采样减少高程数据存储量,并定义调度准则,最后有效地降低了CPU处理时间和GPU渲染批次。文献[6]通过构建多分辨率地形块,根据视点位置在地形平面投影进行块调度,根据视点高度更改块层次。文献[7]也是将地形分块,根据视锥在地形平面的投影判断地形可见范围,同时采用一种基于视点运动的外推算法,对视点位置和方向进行预测,提前预加载进入视锥的地形数据,从而有效减少渲染速率变化。
上述方法大多从DEM(Digital Elevation Model)数据入手实现地形的可视化,数据量大,实现过程较为复杂而且不利于地形编辑。游戏引擎的出现使得三维仿真中地形的构建更加便捷。故本文针对Unity引擎中构建地形块简单、快捷的优势,结合其内存管理机制,从模型资源载入的角度,设计了一种地形块的动态调度算法。该算法将地形资源分块以行、列值进行标记,通过视点在地形平面的投影确定当前地形块行、列值,计算当前需加载地形块列表。在摄像机移动过程中,计算地形块列表更新,动态加载需调入的地形块,并卸载需调出的地形块。最后通过实验对比其与一次性加载时计算机内存占用、载入时间等数据情况,验证了该算法的高效性。
Unity引擎是由Unity Technologies公司开发的跨平台的专业游戏引擎,其广泛的平台支持和丰富的插件支持使其在游戏开发、虚拟现实、培训仿真等领域具有广泛应用[8]。
2.1Unity地形构建方法
目前获取真实地形的主要方法有两种[9]:一是从数字高程读取,该方法数据量大,适合复杂地形研究。二是从卫星图提取,该方法操作容易、速度较快,但精度要求较低。在虚拟三维场景仿真中,地形作为辅助对象存在,需占用较少资源,故本文采取第二种方式。
Unity中构建地形的方式有多种,可直接通过自带地形工具绘制或建模软件获取,也可通过插件利用卫星地图获取。本文利用Terrain Composer插件工具获取卫星地图中指定区域的地形数据和纹理特征,并且切割地形块,导入Unity能够直接生成地形块资源和地形纹理资源。此外Unity地形组件支持LOD(Levels of Detail),从而大大减少了从DEM数据构建LOD和划分地形块的工作量,构建地形便捷、高效。其获取地形分块的网格模型如图1所示。
图1 Terrain Composer获取真实地形的网格模型
2.2Unity资源管理方式
在Unity引擎中资源文件和场景文件是不同的,资源文件作为程序依赖项主要存放于硬盘中,场景文件则在当前程序运行时被加载至内存。预设(prefab)是联系二者的重要概念,它是游戏对象及其组件的集合,具有继承、重载等属性,极大地方便了资源的重复利用。预设作为一种资源集合引用,可以通过在场景中创建或者销毁预设来实现对资源的动态管理。而地形作为资源文件的一种,可以通过预设进行管理,在场景需要时加载指定地形块至场景,同时卸载不必要的地形块。在Unity引擎中,创建和销毁资源的方式有多种,方式不同,其对内存的占用的影响也不同,3.2节中将详细分析Unity内存管理机制并从内存管理层面确定本文地形块动态调度具体实现方法。
在三维场景仿真中,地形作为仿真背景能够极大地提高场景的真实度,但是存在于地形之上的被仿真对象(例如变电站培训仿真中的变电站)才是仿真重点,因此地形在程序中占用的计算机资源应该尽量小。本文针对Unity中构建地形的快捷性,采用基于视点(摄像机)位置的地形块调度策略[10],以视点位置为中心,动态调度摄像机周边地形块,从而实现场景漫游中地形资源的优化。
3.1基于视点位置的地形块更新
通过Terrain Composer工具构建地形时已经对大地形进行地形分割,而且具备自动LOD,所以可以对地形块进行、行列值标记区分。而Unity加载资源时以资源名称作为索引值,因此可以用二维数组保存地形块名称,然后通过视点位置在X、Z平面(即地形平面)的投影判断当前地形块范围,进行地形块的动态调度。以图2为例,其中(2,2)地形块为摄像机初始所在位置,其周边8块地形块(图中浅色区域)在初始化时均加载至内存,在漫游过程中,加载摄像机移动方向前方的地形块,卸载超出摄像机周边范围的地形块。若摄像机向右移动进入地形块(3,2)则加载即将进入视野的(4,1)、(4,2)、(4,3)地形块,卸载远离摄像机运动方向的(1,1)、(1,2)、(1,3)地形块。在此过程中加载至场景中的地形块数量始终保持不变,从而维持计算机内存占用的平稳。
图2 视点位置在地形平面坐标系映射关系
摄影机在地形平面中投影位置的计算方法随地形块在世界坐标系中位置不同而不同。若以地形中心为世界坐标系中心,则图2中的摄像机位置映射关系可用式(1)表示。
(1)
其中CamNum_X为摄像机映射至地形平面所在地形块行值;CamPos.x为摄像机在世界坐标系中X轴分量;TerrainSize为地形块大小;N为地形块数组维度。摄像机在地形平面的Z方向映射计算方法与之类似。
通过视点位置的映射,易知当前视点所在地形块行、列值及其周边地形块,进而可以通过地形数组中地形块名称来动态加载或卸载地形资源,实现动态调度。
3.2动态调度下内存管理
在Unity中,将资源文件加载至场景中显示物体对象(含网格、贴图、材质等信息)有多种方式,不同的调用方式在内存的占用过程也不一致。Unity中内存管理机制如图3所示[11~12]。
其中加载预设的方式有三种[13],一是静态引用,声明公有变量,然后在Inspector窗口中给变量赋值,之后实例化(Instantiate);二是采用Resources.Load(),Load之后进行实例化;三是采用AssetBundle.Load(),然后进行实例化。其中前两种加载方式在Load过程中只加载网格(Mesh)信息,在实例化过程中才会加载材质(Material)和贴图(Texture),而第三种加载方式在Load过程中就会直接加载预设全部依赖资源,在实例化过程中只是进行克隆操作。
图3 Unity动态加载过程内存管理机制
由图3可以看出在资源的销毁过程中,Destory()函数只是销毁实例化过程中对资源的引用或复制,并没有释放已加载至内存的纹理、材质等资源,所以其释放资源有限。UnloadAsset(obj)释放区域中指定的资源。UnloadUnusedAssets()会卸载当前所有没有被占用的资源。
通过上述分析可知在漫游时采用AssetBundle()加载方式能同时加载预设的纹理、材质信息,此方法能够避免卡帧现象。卸载时使用Destory()函数销毁物体对象后,在地形块卸载完成后调用UnloadUnusedAssets()函数将未被占用的纹理、贴图资源彻底卸载以实现内存回收。至此,在场景漫游中,地形资源的计算机占用率始终维持在较低水平。
3.3地形块动态调度算法实现
针对上述内存管理机制,设计了如图4所示的地形块动态调度算法。该算法以摄像机位置为中心,通过对地形资源进行预设实例化和预设销毁完成内存管理。其具体算法过程如下:
Step1.程序初始化时根据摄像机初始位置加载其周围九个地形块,并将载入地形块名称存入当前地形块列表CurrentTerrainList(保存当前已加载地形块名称)。
Step2.程序进入帧更新,获取当前摄像机位置计算其映射地形块,若未发生变化则不处理,否则进入地形块动态调度。
Step3.根据变化后的摄像机所映射的地形块行、列值,计算当前摄像机周边地形块名称,将其存入字符串列表RefreshTerrainList(保存帧更新后地形块名称)。
图4 地形块动态调度算法流程
Step4.由帧更新前后的地形块列表差值计算需要加载和卸载的地形块。
Step5.采用AssetBundle.Load()方法加载新的地形块;采用Destory()函数销毁场景对象,并在完成后调用UnloadUnusedAssets()回收内存。
Step6.完成调度后,将RefreshTerrainList赋值给CurrentTerrainList,即更新当前地形块列表。
Step7.程序是否结束,若结束则退出程序,否则进入下一帧循环。
其中,结合图2知,列表RefreshTerrainList与CurrentTerrainList的差集则代表需要加载的新的地形块,而CurrentTerrainList与RefreshTerrainList的差集则代表需要卸载的地形块。完成地形块的动态加载和卸载之后,执行UnloadUnusedAssets()函数释放地形块的纹理、材质等内存资源,并更新当前地形块列表,由此则完成整个地形块的调度过程,程序进入下一帧循环。在整个帧循环过程中,内存中地形块的数量维持不变,从而实现对内存中地形块内存占用的管理。
4.1地形块动态调度实例验证
本文以81(9*9)块940*940大小的地形块进行验证(如图5(a)所示,其中地形块周围数字为其行列值)。切割完成后地形块共包含jpg格式纹理贴图81张,地形模型81个。若以地形中心为世界坐标系中心,初始时摄像机的x、z坐标为0,则初始化时加载的地形块为(4,4)及其周边八块地形,在摄像机移动的过程中,地形块始终随着摄像机移动而动态加载和卸载,实时进行地形块动态调度,以保证摄像机所在地形块始终处于中心位置。图5(b)为动态调度过程中摄像机水平向右移动过程中当前地形块变化过程,摄像机由地形块(4,4)进入地形块(4,5),内存中地形块完成动态调度。图5(c)为电力杆塔巡视场景,其中计算机配置为Core i3 CPU,主频2.27GHz,2G内存,ATI 5400 512M显卡,Unity版本为5.0。在场景漫游中,帧率达到60帧/秒,地形调度过程流畅。
图5 地形块动态调度算法实例
4.2地形块动态调度过程中的性能分析
针对上述实验,本文在程序内存占用、帧率等方面进行实测数据分析,以量化该动态调度算法对计算机性能的影响。采用一次性加载方式与采用动态调度算法加载地形方式的主要计算机性能指标如表1所示(计算机配置同4.1)。
表1 两种加载方式主要性能指标对比
由上表可见,本实验中采用动态调度之后,程序中的纹理内存占用、网格内存占用以及总内存占用均大大降低,而且帧率提升一倍。由性能分析器的内存占用曲线(图6所示)可以看出,在进行动态调度时,地形块的加载和卸载过程占用时间很短,而且内存始终维持在稳定水平。随着地形面积的增大,该算法的优势将更加明显。
图6 地形块动态调度过程中内存占用过程
三维引擎的出现极大地方便了游戏开发和虚拟仿真开发人员,而Unity凭借其强大的功能特性、跨平台支持和可视化开发环境等优势在三维引擎中迅速占据一席之地。本文针对Unity引擎中大场景漫游地形一次性加载内存占用量大的问题,详细分析了其内存管理机制,从模型资源加载的角度设计了一种有针对性的地形块动态调度算法。该算法在本文中具有以下特点: 1) 从模型资源的角度入手加载地形,使地形资源与其他仿真对象加载方式相同,同时避免了对DEM数据的大量处理工作,实现方式便捷高效: 2) 以视点位置为中心进行地形块动态调度,在大场景漫游过程能够保持流畅浏览同时降低计算机性能消耗: 3) 详细解析了内存中地形加载和卸载过程,对于控制仿真对象的资源占用和优化有重要作用。实验证明该算法能维持地形资源的内存消耗在较低水平,同时显著提升帧率。目前该算法已经应用在牵引供电系统三维培训仿真中应用并取得良好效果。
[1] 韩敏,汤松涛,李洋.大规模地形实时可视化算法[J].计算机工程,2008,34(13):270-272.
HAN Min, TANG Songtao, LI Yang. Real-time Visualization Algorithm of Large-scale Terrain[J]. Computer Engineering,2008,34(13):270-272.
[2] 宋力兵,龚华军,王新华.基于改进的约束四叉树LOD全球地形实时绘制[J].计算机与数字工程,2013,41(10):1668-1671.
SONG Libing, GONG Huajun, WANG Xinhua. Global Terrain Real-Time Rendering Based On Improved Constraint Quad-Tree and Level of Detail Algorithm[J]. Computer & Digital Engineering,2013,41(10):1668-1671.
[3] 李玉娟,谭同德.三维场景中大规模地形地貌的生成[J].计算机应用与软件,2013,11:131-135.
LI Yujuan, TAN Tongde. The Generation of Lager-scale Terrain and Topography in 3D Scene[J]. Computer Applications and Software,2013,11:131-135.
[4] Zhou Z, Cai B, Zhang D, et al. Paged cache based massive terrain dataset Real-Time rendering algorithm[C]//Information Engineering and Computer Science, 2009. ICIECS 2009. International Conference on. IEEE,2009:1-4.
[5] 李钦,戴树岭,赵永嘉,等.分块LOD大规模地形实时渲染算法[J].计算机辅助设计与图形学学报,2013,25(5):708-713.
LI Qin, DAI Shuling, ZHAO Yongjia, et al. A Block LOD Real-time Rendering Algorithm foe Large Scale Terrain[J]. Journal of Computer-Aided Design & Computer Graphics,2013,25(5):708-713.
[6] 姜昱明,胡曼丽.地形漫游中数据块调度算法研究[J].计算机工程与设计,2007,28(15):3743-3745.JIANG Yuming, HU Manli. Research on Block Scheduling Algor-ithm for Terrain Walkthrough[J]. Computer Engineering and Design,2007,28(15):3743-3745.
[7] 王响,雷小永,戴树岭.基于视点预测的大规模地形的实时渲染[J].系统仿真学报,2013,6:1202-1206.
WANG Xiang, LEI Xiaoyong, DAI Shuling. Real Time Rendering of Large Scale Terrain Based on Viewport Prediction[J]. Journal of System Simulation,2013,6:1202-1206.
[8] Unity Technologies. Unity4.x从入门到精通[M].第1版.北京:中国铁道出版社,2013.
Unity Technologies. Unity4.x From Entry to Master[M]. 1st Edition. Beijing: China Railway Publishing House,2013.
[9] 石敏,王俊铮,魏家辉.真实感三维虚拟场景构建与漫游方法[J].系统仿真学报,2014,9:1969-1974,1979.
SHI Mi, WANG Junzheng, WEI Jiahui. Virtual Scene Contruction and Roaming[J]. Journal of System Simulation,2014,9:1969-1974,1979.
[10] 王朋,刘惠义,杨战军.基于Geometry Clipmap的大规模地形绘制算法[J].计算机与数字工程,2015,43(5):887-891.
WANG Peng, LIU Huiyi, YANG Zhanjun. A Large Scale Terrain Rendering Algorithm Based on Geometry Climap[J]. Computer & Digital Engineering,2015,43(5):887-891.
[11] Hog.全面理解Unity加载和内存管理[EB/OL]. (2012-10-11) [2016-02-03]. http://game.cee-ger.com/forum/read.php?tid=4394#info.
Hog. Comprehensive Understanding of Unity Loading and Memory Management[EB/OL]. (2012-10-11) [2016-02-03]. http://game.cee-ger.com/forum/read.php?tid=4394#info.
[12] Hog.全面理解Unity加载和内存管理机制之二:进一步深入和细节[EB/OL]. (2012-10-15) [2016-02-03]. http://game.ceeger.com/forum/read.php?ti=4466.
Hog. Fully Understand the Unity Loading and Memory Management Mechanism of the Two: Further in Depth and Detail[EB/OL]. (2012-10-15) [2016-02-03]. http://game.ceeger.com/forum/read.php?ti=4466.
[13] Tnqiang. Unity内存申请和释放[EB/OL]. (2014-07-01) [2016-02-03]. http://www.jianshu.co-m/p/b37ee8cea04c.
Tnqiang. Unity Memory Application and Release[EB/OL]. (2014-07-01) [2016-02-03]. http://www.jianshu.co-m/p/b37ee8cea04c.
Dynamic Scheduling Algorithm of Terrain Blocks Based on Unity Engine
GENG XiaoHAN ZhiweiLIAO Feng
(School of Electrical Engineering, Southwest Jiaotong University, Chengdu610031)
In order to solve the problem that the utilization rate of memory was high when large-scale terrain blocks were loaded in the process of 3D simulation based on Unity, a dynamic scheduling algorithm of terrain blocks was proposed in this paper. The projection of the viewpoint in the terrain flat was chosen as the center of the current terrain, and the terrain blocks surrounding it were loaded. When the viewpoint was moving, according to the change of the coordinate of its projection point in the terrain flat, the area of the terrain blocks needing to be loaded and unloaded were calculated. In this paper, the dynamic scheduling algorithm of terrain blocks was realized based on the memory management strategy of Unity. The experiment results showed that the algorithm can effectively reduce the memory usage in terrain loading and increase the frame rate of the 3D simulation.
terrain blocks, dynamic scheduling, viewpoint position, memory management, three-dimensional simulation
2016年3月8日,
2016年4月17日
国家自然科学基金(编号:51407147)资助。
耿肖,男,硕士研究生,研究方向:牵引供电系统三维建模与仿真。韩志伟,男,博士,讲师,研究方向:计算智能理论在铁路和电力系统中的应用。廖峰,男,硕士研究生,研究方向:牵引供电系统三维仿真。
TP391DOI:10.3969/j.issn.1672-9722.2016.09.001