基于Web服务的大地形实时渲染技术研究

2015-07-09 20:57刘遥等
现代电子技术 2015年8期

刘遥等

摘 要: 在此利用HTML5中的异步加载技术进行地形高程数据的加载和调度,用WebGL技术中的Three.js引擎进行地形绘制,在浏览器上实现了基于离散型LOD的3D大地形实时绘制,将异步加载和实时绘制动态交替进行。实验表明,该方法消除了因数据加载而产生的“卡顿”现象,给用户更流畅的Web3D体验。

关键词: 异步加载; WebGL; 大地形; 离散型LOD

中图分类号: TN911?34 文献标识码: A 文章编号: 1004?373X(2015)08?0080?04

Research on real?time rendering technology of 3D large terrain based on Web service

LIU Yao, HUA Wen?yuan , WANG Yu?mei

(Department of Command and Control System, North China Institute of Computer Technology, Beijing 100086, China)

Abstract: In this paper, the asynchronous loading technology in HTML5 is used for loading and scheduling the terrain elevation data, and the three.js engine in WebGL is adopted for terrain drawing. The real?time 3D large terrain rendering based on discrete LOD was achieved in the browser. Asynchronous loading is alternated with real?time rendering in the entire process. The experiment result shows that this method can eliminate the "pause" phenomenon generated by loading data. It offers for a smoother Web3D experiencefor.

Keywords: asynchronous loading; WebGL; large terrain; discrete LOD

近年来,3D技术和Web技术的发展十分迅速,如何在浏览器上实现大规模的、可实时绘制的3D场景成为研究的热点话题。传统的Web3D主要有Java Applet、Adobe公司的Flash Player浏览器插件和微软Silverlight技术。但是,Java Applet不仅需要下载一个巨大的支持环境,而且画面非常粗糙,主要原因是其在图形渲染时,并没有直接利用图形硬件本身的加速功能,因此,显卡性能的提升对其三维渲染不起任何作用。Flash Player浏览器插件和微软Silverlight技术解决了这一问题,利用图形硬件的加速功能,实现了高性能的图形渲染,但这两种方案也存在一些问题,比如它们是通过浏览器插件形式实现的,这就对不同的操作系统和浏览器版本的插件有不同的要求。

WebGL的出现完美的解决了上述两个问题:首先,它通过JavaScript脚本本身实现Web交互式三维图形程序的制作,而无需任何浏览器插件支持;其次,它利用底层的图形硬件加速功能进行的图形渲染,是通过统一的、标准的、跨平台的OpenGL ES2.0接口实现的[1]。但是,WebGL技术只解决了对地形的快速渲染,不能动态地对大规模数据进行加载。在传统的绘制中,一般是将外部数据通过JSON或者文本形式同步地一次性传到CPU,将所有数据加载完成后再将顶点、纹理等数据传到GPU进行绘制,当数据量过大时,在绘制之前会有很长时间的数据加载时间,在场景中会出现较长时间的“卡顿”现象。为解决传统方法绘制前下载数据时间过长,并实现一种一边加载数据一边绘制场景的效果,本文采用规则网格进行地形数据的存储,运用HTML5的异步加载技术对数据进行动态的加载和调度,用WebGL的Three.js引擎绘制,实现了大规模地形数据的动态加载和离散型LOD场景的实时绘制。

1 相关技术

1.1 WebGL

WebGL是一组用于在Web页面绘制3D图形的绘图标准接口,继承自OpenGL ES2.0规范,因而具有强大的图形功能。WebGL技术标准可以为HTML5 Canvas提供硬件3D加速渲染,用于创建复杂3D结构的网站页面,这免去了安装网页专用渲染插件的麻烦,因而具有良好的跨平台移植能力。WebGL已得到了Google Chrome,Safari,Firefox,Opera等浏览器的支持[2]。

1.2 Three.js库

Three.js是由Ricardo开发,它面向对象,以简单、直观的方式封装了3D图形编程中常用的对象,在开发中使用了很多图形引擎的高级技巧,极大地提高了性能。它将WebGL原生API细节抽象化,将3D场景拆解为网格、材质和光源等。开发者可以使用上层的JavaScript对象和调用JavaScript函数,并可以使用流行的3D建模软件导出文本格式的文件,然后使用Three.js加载;也可以使用Three.js自己的JSON格式或者二进制格式。

要想使用Three.js把图形渲染到页面中,一个应用至少需要执行如下步骤:

(1) 创建一个画布元素;

(2) 获取画布的上下文;

(3) 创建Three.js场景类;

(4) 创建相机、光照等;

(5) 创建自定义物体,并添加到场景;

(6) 运行渲染循环[3]。

1.3 HTML5异步加载技术

异步加载技术是相对于同步加载技术而言的。同步模式,又称阻塞模式,在数据完成加载之前会阻止浏览器的后续处理和解析。

异步加载又叫非阻塞加载,浏览器在加载js的同时,还会进行后续页面的处理[4]。本文中,使用异步加载技术进行高程数据的加载和解析,同时使用解析完成的高程数据动态的构建场景树,这样,可以在加载多张高度图的同时非阻塞地将已加载完成并解析好的高程数据动态地构建场景树,以减少因大量数据加载而产生的场景“卡顿”现象。

2 实验步骤

2.1 Web服务器端的数据组织

2.1.1 高程数据存储格式

在GIS中,DEM一般有3种类型的格网数据:规则格网RSG和不规则格网TIN以及两者的混合结构。其中,规则网格数据结构由于其顶点呈规则分布,只需要记录数据的基本信息和每个网格的高程值,结构简单、操作方便、便于简化,非常适合于大规模地形数据的组织和管理。

本文处理的原始地形数据以均匀采样的地形网格数据形式存储,制作一个JPG格式的高度图。高度图是存储地形高度信息的二维贴图,它们通常是8位的灰度图,图像上的每个点存储地形对应位置的高度。它的高度值变化范围是在0~255之间,其中0(黑色)表示最低高度而255表示最大高度。在实际中,可以乘以一个缩放值乘以默认高度值,增加其范围,但会使两个高度之间的误差增大,也可以使用多个字节来表示一个高度。

JPG格式高度图的每一个像素都由R,G,B值和透明度α值4个值组成,像素的顺序从左到右,从上到下,按行存储。本文实验中的高度图用两个字节表示一个高程值,每个高程值的范围为0~65 535,则一个像素可以表示两个高程值,易知:

[H1=256×R+GH2=256×B+α]

2.1.2 地形数据的四叉树表示

建立三维地形网格模型过程中,四叉树结构是一种常用的数据结构,由一个根节点、若干个树枝节点及叶节点组成,且每个节点上最多只有4棵子树。四叉树中的根节点,包含对应地形区域的4个顶点的坐标和4个指向其孩子节点的指针;树枝节点不仅包含以上信息。还包含一个指向其双亲节点的指针;若这个节点是叶子节点,包含4个顶点的坐标和一个指向其双亲节点的指针。

采用四叉结构建立地形多分辨率模型的基本过程为将原始地形看作一个正方形区域,对应四叉树结构的根节点,未经过任何细分,其细节精度为0,用level = 0表示,如图1所示;对节点进行迭代细分,当节点满足某个条件时,将此节点划分成4个相等的正方形,即4个节点;然后对4个子节点继续判断,如果满足上述节点,则继续细分,如果不满足上述条件,则停止细分,如此迭代,知道最后的节点数等于全部DEM数据点个数或所有节点已不满足上述条件。

2.2 LOD地形数据的异步加载和动态调度

由以上内容可知,在四叉树的数据结构下,假设level = 0时的网格有128×128个顶点,即需要128×128的高度图来存储顶点高度,那么level = 1时就需要4张128×128的高度图来存储高度数据,level= 2时需要16张,以此类推。当精度层级增长时,需要加载的高度图数据呈指数倍增长。如果等待所有层级的高度数据完全加载完毕之后再绘制,会使用户等待时间过长,当数据量过大时,还可能使浏览器崩溃。

当分析这一问题时发现,在浏览器中要构建大数据量的场景,就要动态调度高程数据以逐步构建场景树。最佳流程应该是在下载完成一张高度图并读取这张高度图之后就立刻将这张高度图所对应的网格绘制完毕并加载到场景中,然后等待,直到下一精度层级的高度图加载并绘制完成。这种在加载数据的同时依然可以进行场景绘制的方式就是异步加载。

在HTML5中提供了异步加载文件的函数onload(),异步加载一张高度图数据至少需要执行以下步骤:

(1) 创建一个canvas画布对象;

(2) 获取canvas对象及其上下文;

(3) 创建一个Image对象;

(4) 指定需要加载Image对象的位置;

(5) 执行Image对象的onload(),异步加载高度图;

(6) 加载完毕后,从canvas上下文中读取数据。

通过异步加载实现动态构建场景树的程序流程图如图2所示。

由图2可知,在场景初始化阶段,只需要将根节点高度图异步加载到内存中,读取高度数据后,创建根节点,并将根节点加入场景,然后开始动态地构建场景树。

构建场景树时要首先判断4个子节点是否已经加载,判断的必要性在于考虑到在未来的程序开发中有可能遇到以下情况:当地形数据加载过多,而某些地形在距离当前视点过远或者用户已经长时间没有访问该地形时,这些数据的存在会给浏览器带来过大的负担,需要对这些数据进行剔除,所以有可能会出现某些子节点曾经加载过而现阶段已经被剔除掉的情况。

当判断完成,找到应该加载的节点后,异步加载所需加载节点的高度图,在这里就体现了异步加载的必要性。假如没有异步加载机制,就必须等待到当前正在加载的高度图加载完毕之后才能绘制,这样,由于同步加载的阻塞机制,会出现一直在执行加载程序而绘制程序一直被阻塞的情况,无法完成加载完成一张高度图就绘制一个LOD节点,并且很可能在数据量过大时浏览器在绘制第一帧之前浏览器就已经因不堪重负而崩溃,从而无法在浏览器上看到任何场景。异步加载的作用就在于:首先,GPU绘制当前帧的场景时,CPU可以同时加载场景暂时还不需要但之后可能需要的高度图数据;其次,在每一帧中,可以无阻塞地根据高度图的加载进度选择应该构建的场景节点;另外,在每一帧中,并不是所有数据都要绘制,在绘制循环中可以方便地根据视点的位置等信息进行数据的动态剔除,以减少浏览器的压力。

2.3 场景绘制循环

由图2可知,在每一帧中,都要执行一个加载函数和一个绘制函数,这样做的目的是实现CPU和GPU的协同工作以达到较好的用户体验效果。加载函数的作用是异步的加载高度图和纹理图,并在每一对高度图和纹理图加载完成之后分别用一个标志数以记录当前的加载进度。

在绘制函数中,通过一个数组来记录当前已经加载进场景的物体类,一个标志数来记录已加载入场景中的物体个数。每一帧的绘制过程为:

(1) 判断当前视点位置;

(2) 遍历记录当前已经加载进场景的物体类数组,根据当前视点位置,判断应该显示的物体编号,并将应该显示的物体的显示标志设为true,不应该显示的物体显示标志设置为false;

(3) 调用绘制网格的命令,绘制当前应该显示在场景中的物体类;

(4) 更新记录数组和场景数据。

3 实验及结果分析

实验所用的每一张高度图都是32×64的JPG格式的服务器端文件,可表示64×64个高程值。

本文实验程序是在Google Chrome 33.0.1750.154版本的浏览器上开发完成,硬件条件 Intel(R) Core(TM)2 Quad CPU,3 GB内存,显卡NVIDIA Quadro NVS 290。

试验程序分别做了一个3层LOD模型,总共需要下载1+4+16=21张高度图,一个2层LOD模型,需要加载1+4=5张高度图,将本文所述的异步加载方法和将传统的同步加载方法进行对比,通过单步跟踪,得到数据如表1所示。

表1 实测对比数据

对实测数据及场景变化的描述如下:

(1) 传统方法在初始化阶段有明显的“卡顿”现象,且没有场景节点被绘制出来。

(2) 传统方法加载完成之后只需要约1~2 f即可全部绘制完成,这一阶段的绘制帧率为58~60 f/s。

(3) 异步加载方法在初始化阶段只需加载一张图,约1.5 f,在第2 f末已绘制完成第一层LOD模型,几乎没有“卡顿”现象。

(4) 异步方法3层模型从初始化完成到整个场景绘制完成的过程中需要29 f,帧率有一定的起伏,但总体呈现逐渐加快的趋势,明显的可以看到场景中逐步显现出LOD各个子节点。

(5) 异步方法2层LOD模型从初始化完成到场景绘制完成需要7 f,帧率为平稳的46 f/s。

(6) 场景绘制完成后,对场景中的物体进行拖拽、旋转操作时,两层LOD帧率几乎不变,而3层LOD则由于三角形数目的增多因此在重绘时帧率会有明显下降。

由以上数据可以看出,异步加载方法虽然不能减少从加载到绘制的总时间,但是可以明显地减少“卡顿”时间,并且可以实现一边加载高度图一边将加载好的数据实时的绘制出来,给用户比较流畅自然的Web3D体验。

4 结 语

本文使用Three.js框架,通过HTML5的异步加载技术动态地构建WebGL大地形场景树,目标在于实现CPU加载和GPU绘制的相互协作,给Web用户更好的3D体验。本文的实验程序所构建出的场景距离比较完美还有以下不足:首先,对场景中长期没有用到的节点还没有做到动态剔除,因此,还没有实现对最大数据量的平衡控制;其次,在LOD场景控制时没有消除因LOD层级过渡而产生的裂缝,以后,程序可以从这两方面加以改进。

参考文献

[1] 方强.基于WebGL的3D图形引擎研究与实现[D].合肥:安徽大学,2013.

[2] CANTOR D, JONES B.WebGL编程指南[M].李强,译.北京:清华大学出版社,2013.

[3] PARISI T. WebGL up and running [M]. Sebastopol: OReally. 2012: 2?16.

[4] 张亚飞.HTML5和RIA网站设计[M].北京:清华大学出版社,2013.

[5] CHANG K.地理信息系统导论[M].5版.陈建飞,张筱林,译.北京:科学出版社,2010.

[6] ROGERS D F.计算机图形学算法基础[M].北京:机械工业出版社,2002.

[7] 佚名.three.js教程[EB/OL]. [2010?01?06].http://github.com/tparisi/WebGLBook.