劉遙等
摘 要: 在此利用HTML5中的異步加載技術(shù)進(jìn)行地形高程數(shù)據(jù)的加載和調(diào)度,用WebGL技術(shù)中的Three.js引擎進(jìn)行地形繪制,在瀏覽器上實(shí)現(xiàn)了基于離散型LOD的3D大地形實(shí)時(shí)繪制,將異步加載和實(shí)時(shí)繪制動(dòng)態(tài)交替進(jìn)行。實(shí)驗(yàn)表明,該方法消除了因數(shù)據(jù)加載而產(chǎn)生的“卡頓”現(xiàn)象,給用戶更流暢的Web3D體驗(yàn)。
關(guān)鍵詞: 異步加載; WebGL; 大地形; 離散型LOD
中圖分類號(hào): TN911?34 文獻(xiàn)標(biāo)識(shí)碼: A 文章編號(hào): 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技術(shù)和Web技術(shù)的發(fā)展十分迅速,如何在瀏覽器上實(shí)現(xiàn)大規(guī)模的、可實(shí)時(shí)繪制的3D場(chǎng)景成為研究的熱點(diǎn)話題。傳統(tǒng)的Web3D主要有Java Applet、Adobe公司的Flash Player瀏覽器插件和微軟Silverlight技術(shù)。但是,Java Applet不僅需要下載一個(gè)巨大的支持環(huán)境,而且畫面非常粗糙,主要原因是其在圖形渲染時(shí),并沒有直接利用圖形硬件本身的加速功能,因此,顯卡性能的提升對(duì)其三維渲染不起任何作用。Flash Player瀏覽器插件和微軟Silverlight技術(shù)解決了這一問題,利用圖形硬件的加速功能,實(shí)現(xiàn)了高性能的圖形渲染,但這兩種方案也存在一些問題,比如它們是通過瀏覽器插件形式實(shí)現(xiàn)的,這就對(duì)不同的操作系統(tǒng)和瀏覽器版本的插件有不同的要求。
WebGL的出現(xiàn)完美的解決了上述兩個(gè)問題:首先,它通過JavaScript腳本本身實(shí)現(xiàn)Web交互式三維圖形程序的制作,而無需任何瀏覽器插件支持;其次,它利用底層的圖形硬件加速功能進(jìn)行的圖形渲染,是通過統(tǒng)一的、標(biāo)準(zhǔn)的、跨平臺(tái)的OpenGL ES2.0接口實(shí)現(xiàn)的[1]。但是,WebGL技術(shù)只解決了對(duì)地形的快速渲染,不能動(dòng)態(tài)地對(duì)大規(guī)模數(shù)據(jù)進(jìn)行加載。在傳統(tǒng)的繪制中,一般是將外部數(shù)據(jù)通過JSON或者文本形式同步地一次性傳到CPU,將所有數(shù)據(jù)加載完成后再將頂點(diǎn)、紋理等數(shù)據(jù)傳到GPU進(jìn)行繪制,當(dāng)數(shù)據(jù)量過大時(shí),在繪制之前會(huì)有很長(zhǎng)時(shí)間的數(shù)據(jù)加載時(shí)間,在場(chǎng)景中會(huì)出現(xiàn)較長(zhǎng)時(shí)間的“卡頓”現(xiàn)象。為解決傳統(tǒng)方法繪制前下載數(shù)據(jù)時(shí)間過長(zhǎng),并實(shí)現(xiàn)一種一邊加載數(shù)據(jù)一邊繪制場(chǎng)景的效果,本文采用規(guī)則網(wǎng)格進(jìn)行地形數(shù)據(jù)的存儲(chǔ),運(yùn)用HTML5的異步加載技術(shù)對(duì)數(shù)據(jù)進(jìn)行動(dòng)態(tài)的加載和調(diào)度,用WebGL的Three.js引擎繪制,實(shí)現(xiàn)了大規(guī)模地形數(shù)據(jù)的動(dòng)態(tài)加載和離散型LOD場(chǎng)景的實(shí)時(shí)繪制。
1 相關(guān)技術(shù)
1.1 WebGL
WebGL是一組用于在Web頁面繪制3D圖形的繪圖標(biāo)準(zhǔn)接口,繼承自O(shè)penGL ES2.0規(guī)范,因而具有強(qiáng)大的圖形功能。WebGL技術(shù)標(biāo)準(zhǔn)可以為HTML5 Canvas提供硬件3D加速渲染,用于創(chuàng)建復(fù)雜3D結(jié)構(gòu)的網(wǎng)站頁面,這免去了安裝網(wǎng)頁專用渲染插件的麻煩,因而具有良好的跨平臺(tái)移植能力。WebGL已得到了Google Chrome,Safari,F(xiàn)irefox,Opera等瀏覽器的支持[2]。
1.2 Three.js庫(kù)
Three.js是由Ricardo開發(fā),它面向?qū)ο?,以?jiǎn)單、直觀的方式封裝了3D圖形編程中常用的對(duì)象,在開發(fā)中使用了很多圖形引擎的高級(jí)技巧,極大地提高了性能。它將WebGL原生API細(xì)節(jié)抽象化,將3D場(chǎng)景拆解為網(wǎng)格、材質(zhì)和光源等。開發(fā)者可以使用上層的JavaScript對(duì)象和調(diào)用JavaScript函數(shù),并可以使用流行的3D建模軟件導(dǎo)出文本格式的文件,然后使用Three.js加載;也可以使用Three.js自己的JSON格式或者二進(jìn)制格式。
要想使用Three.js把圖形渲染到頁面中,一個(gè)應(yīng)用至少需要執(zhí)行如下步驟:
(1) 創(chuàng)建一個(gè)畫布元素;
(2) 獲取畫布的上下文;
(3) 創(chuàng)建Three.js場(chǎng)景類;
(4) 創(chuàng)建相機(jī)、光照等;
(5) 創(chuàng)建自定義物體,并添加到場(chǎng)景;
(6) 運(yùn)行渲染循環(huán)[3]。
1.3 HTML5異步加載技術(shù)
異步加載技術(shù)是相對(duì)于同步加載技術(shù)而言的。同步模式,又稱阻塞模式,在數(shù)據(jù)完成加載之前會(huì)阻止瀏覽器的后續(xù)處理和解析。
異步加載又叫非阻塞加載,瀏覽器在加載js的同時(shí),還會(huì)進(jìn)行后續(xù)頁面的處理[4]。本文中,使用異步加載技術(shù)進(jìn)行高程數(shù)據(jù)的加載和解析,同時(shí)使用解析完成的高程數(shù)據(jù)動(dòng)態(tài)的構(gòu)建場(chǎng)景樹,這樣,可以在加載多張高度圖的同時(shí)非阻塞地將已加載完成并解析好的高程數(shù)據(jù)動(dòng)態(tài)地構(gòu)建場(chǎng)景樹,以減少因大量數(shù)據(jù)加載而產(chǎn)生的場(chǎng)景“卡頓”現(xiàn)象。
2 實(shí)驗(yàn)步驟
2.1 Web服務(wù)器端的數(shù)據(jù)組織
2.1.1 高程數(shù)據(jù)存儲(chǔ)格式
在GIS中,DEM一般有3種類型的格網(wǎng)數(shù)據(jù):規(guī)則格網(wǎng)RSG和不規(guī)則格網(wǎng)TIN以及兩者的混合結(jié)構(gòu)。其中,規(guī)則網(wǎng)格數(shù)據(jù)結(jié)構(gòu)由于其頂點(diǎn)呈規(guī)則分布,只需要記錄數(shù)據(jù)的基本信息和每個(gè)網(wǎng)格的高程值,結(jié)構(gòu)簡(jiǎn)單、操作方便、便于簡(jiǎn)化,非常適合于大規(guī)模地形數(shù)據(jù)的組織和管理。
本文處理的原始地形數(shù)據(jù)以均勻采樣的地形網(wǎng)格數(shù)據(jù)形式存儲(chǔ),制作一個(gè)JPG格式的高度圖。高度圖是存儲(chǔ)地形高度信息的二維貼圖,它們通常是8位的灰度圖,圖像上的每個(gè)點(diǎn)存儲(chǔ)地形對(duì)應(yīng)位置的高度。它的高度值變化范圍是在0~255之間,其中0(黑色)表示最低高度而255表示最大高度。在實(shí)際中,可以乘以一個(gè)縮放值乘以默認(rèn)高度值,增加其范圍,但會(huì)使兩個(gè)高度之間的誤差增大,也可以使用多個(gè)字節(jié)來表示一個(gè)高度。
JPG格式高度圖的每一個(gè)像素都由R,G,B值和透明度α值4個(gè)值組成,像素的順序從左到右,從上到下,按行存儲(chǔ)。本文實(shí)驗(yàn)中的高度圖用兩個(gè)字節(jié)表示一個(gè)高程值,每個(gè)高程值的范圍為0~65 535,則一個(gè)像素可以表示兩個(gè)高程值,易知:
[H1=256×R+GH2=256×B+α]
2.1.2 地形數(shù)據(jù)的四叉樹表示
建立三維地形網(wǎng)格模型過程中,四叉樹結(jié)構(gòu)是一種常用的數(shù)據(jù)結(jié)構(gòu),由一個(gè)根節(jié)點(diǎn)、若干個(gè)樹枝節(jié)點(diǎn)及葉節(jié)點(diǎn)組成,且每個(gè)節(jié)點(diǎn)上最多只有4棵子樹。四叉樹中的根節(jié)點(diǎn),包含對(duì)應(yīng)地形區(qū)域的4個(gè)頂點(diǎn)的坐標(biāo)和4個(gè)指向其孩子節(jié)點(diǎn)的指針;樹枝節(jié)點(diǎn)不僅包含以上信息。還包含一個(gè)指向其雙親節(jié)點(diǎn)的指針;若這個(gè)節(jié)點(diǎn)是葉子節(jié)點(diǎn),包含4個(gè)頂點(diǎn)的坐標(biāo)和一個(gè)指向其雙親節(jié)點(diǎn)的指針。
采用四叉結(jié)構(gòu)建立地形多分辨率模型的基本過程為將原始地形看作一個(gè)正方形區(qū)域,對(duì)應(yīng)四叉樹結(jié)構(gòu)的根節(jié)點(diǎn),未經(jīng)過任何細(xì)分,其細(xì)節(jié)精度為0,用level = 0表示,如圖1所示;對(duì)節(jié)點(diǎn)進(jìn)行迭代細(xì)分,當(dāng)節(jié)點(diǎn)滿足某個(gè)條件時(shí),將此節(jié)點(diǎn)劃分成4個(gè)相等的正方形,即4個(gè)節(jié)點(diǎn);然后對(duì)4個(gè)子節(jié)點(diǎn)繼續(xù)判斷,如果滿足上述節(jié)點(diǎn),則繼續(xù)細(xì)分,如果不滿足上述條件,則停止細(xì)分,如此迭代,知道最后的節(jié)點(diǎn)數(shù)等于全部DEM數(shù)據(jù)點(diǎn)個(gè)數(shù)或所有節(jié)點(diǎn)已不滿足上述條件。
2.2 LOD地形數(shù)據(jù)的異步加載和動(dòng)態(tài)調(diào)度
由以上內(nèi)容可知,在四叉樹的數(shù)據(jù)結(jié)構(gòu)下,假設(shè)level = 0時(shí)的網(wǎng)格有128×128個(gè)頂點(diǎn),即需要128×128的高度圖來存儲(chǔ)頂點(diǎn)高度,那么level = 1時(shí)就需要4張128×128的高度圖來存儲(chǔ)高度數(shù)據(jù),level= 2時(shí)需要16張,以此類推。當(dāng)精度層級(jí)增長(zhǎng)時(shí),需要加載的高度圖數(shù)據(jù)呈指數(shù)倍增長(zhǎng)。如果等待所有層級(jí)的高度數(shù)據(jù)完全加載完畢之后再繪制,會(huì)使用戶等待時(shí)間過長(zhǎng),當(dāng)數(shù)據(jù)量過大時(shí),還可能使瀏覽器崩潰。
當(dāng)分析這一問題時(shí)發(fā)現(xiàn),在瀏覽器中要構(gòu)建大數(shù)據(jù)量的場(chǎng)景,就要?jiǎng)討B(tài)調(diào)度高程數(shù)據(jù)以逐步構(gòu)建場(chǎng)景樹。最佳流程應(yīng)該是在下載完成一張高度圖并讀取這張高度圖之后就立刻將這張高度圖所對(duì)應(yīng)的網(wǎng)格繪制完畢并加載到場(chǎng)景中,然后等待,直到下一精度層級(jí)的高度圖加載并繪制完成。這種在加載數(shù)據(jù)的同時(shí)依然可以進(jìn)行場(chǎng)景繪制的方式就是異步加載。
在HTML5中提供了異步加載文件的函數(shù)onload(),異步加載一張高度圖數(shù)據(jù)至少需要執(zhí)行以下步驟:
(1) 創(chuàng)建一個(gè)canvas畫布對(duì)象;
(2) 獲取canvas對(duì)象及其上下文;
(3) 創(chuàng)建一個(gè)Image對(duì)象;
(4) 指定需要加載Image對(duì)象的位置;
(5) 執(zhí)行Image對(duì)象的onload(),異步加載高度圖;
(6) 加載完畢后,從canvas上下文中讀取數(shù)據(jù)。
通過異步加載實(shí)現(xiàn)動(dòng)態(tài)構(gòu)建場(chǎng)景樹的程序流程圖如圖2所示。
由圖2可知,在場(chǎng)景初始化階段,只需要將根節(jié)點(diǎn)高度圖異步加載到內(nèi)存中,讀取高度數(shù)據(jù)后,創(chuàng)建根節(jié)點(diǎn),并將根節(jié)點(diǎn)加入場(chǎng)景,然后開始動(dòng)態(tài)地構(gòu)建場(chǎng)景樹。
構(gòu)建場(chǎng)景樹時(shí)要首先判斷4個(gè)子節(jié)點(diǎn)是否已經(jīng)加載,判斷的必要性在于考慮到在未來的程序開發(fā)中有可能遇到以下情況:當(dāng)?shù)匦螖?shù)據(jù)加載過多,而某些地形在距離當(dāng)前視點(diǎn)過遠(yuǎn)或者用戶已經(jīng)長(zhǎng)時(shí)間沒有訪問該地形時(shí),這些數(shù)據(jù)的存在會(huì)給瀏覽器帶來過大的負(fù)擔(dān),需要對(duì)這些數(shù)據(jù)進(jìn)行剔除,所以有可能會(huì)出現(xiàn)某些子節(jié)點(diǎn)曾經(jīng)加載過而現(xiàn)階段已經(jīng)被剔除掉的情況。
當(dāng)判斷完成,找到應(yīng)該加載的節(jié)點(diǎn)后,異步加載所需加載節(jié)點(diǎn)的高度圖,在這里就體現(xiàn)了異步加載的必要性。假如沒有異步加載機(jī)制,就必須等待到當(dāng)前正在加載的高度圖加載完畢之后才能繪制,這樣,由于同步加載的阻塞機(jī)制,會(huì)出現(xiàn)一直在執(zhí)行加載程序而繪制程序一直被阻塞的情況,無法完成加載完成一張高度圖就繪制一個(gè)LOD節(jié)點(diǎn),并且很可能在數(shù)據(jù)量過大時(shí)瀏覽器在繪制第一幀之前瀏覽器就已經(jīng)因不堪重負(fù)而崩潰,從而無法在瀏覽器上看到任何場(chǎng)景。異步加載的作用就在于:首先,GPU繪制當(dāng)前幀的場(chǎng)景時(shí),CPU可以同時(shí)加載場(chǎng)景暫時(shí)還不需要但之后可能需要的高度圖數(shù)據(jù);其次,在每一幀中,可以無阻塞地根據(jù)高度圖的加載進(jìn)度選擇應(yīng)該構(gòu)建的場(chǎng)景節(jié)點(diǎn);另外,在每一幀中,并不是所有數(shù)據(jù)都要繪制,在繪制循環(huán)中可以方便地根據(jù)視點(diǎn)的位置等信息進(jìn)行數(shù)據(jù)的動(dòng)態(tài)剔除,以減少瀏覽器的壓力。
2.3 場(chǎng)景繪制循環(huán)
由圖2可知,在每一幀中,都要執(zhí)行一個(gè)加載函數(shù)和一個(gè)繪制函數(shù),這樣做的目的是實(shí)現(xiàn)CPU和GPU的協(xié)同工作以達(dá)到較好的用戶體驗(yàn)效果。加載函數(shù)的作用是異步的加載高度圖和紋理圖,并在每一對(duì)高度圖和紋理圖加載完成之后分別用一個(gè)標(biāo)志數(shù)以記錄當(dāng)前的加載進(jìn)度。
在繪制函數(shù)中,通過一個(gè)數(shù)組來記錄當(dāng)前已經(jīng)加載進(jìn)場(chǎng)景的物體類,一個(gè)標(biāo)志數(shù)來記錄已加載入場(chǎng)景中的物體個(gè)數(shù)。每一幀的繪制過程為:
(1) 判斷當(dāng)前視點(diǎn)位置;
(2) 遍歷記錄當(dāng)前已經(jīng)加載進(jìn)場(chǎng)景的物體類數(shù)組,根據(jù)當(dāng)前視點(diǎn)位置,判斷應(yīng)該顯示的物體編號(hào),并將應(yīng)該顯示的物體的顯示標(biāo)志設(shè)為true,不應(yīng)該顯示的物體顯示標(biāo)志設(shè)置為false;
(3) 調(diào)用繪制網(wǎng)格的命令,繪制當(dāng)前應(yīng)該顯示在場(chǎng)景中的物體類;
(4) 更新記錄數(shù)組和場(chǎng)景數(shù)據(jù)。
3 實(shí)驗(yàn)及結(jié)果分析
實(shí)驗(yàn)所用的每一張高度圖都是32×64的JPG格式的服務(wù)器端文件,可表示64×64個(gè)高程值。
本文實(shí)驗(yàn)程序是在Google Chrome 33.0.1750.154版本的瀏覽器上開發(fā)完成,硬件條件 Intel(R) Core(TM)2 Quad CPU,3 GB內(nèi)存,顯卡NVIDIA Quadro NVS 290。
試驗(yàn)程序分別做了一個(gè)3層LOD模型,總共需要下載1+4+16=21張高度圖,一個(gè)2層LOD模型,需要加載1+4=5張高度圖,將本文所述的異步加載方法和將傳統(tǒng)的同步加載方法進(jìn)行對(duì)比,通過單步跟蹤,得到數(shù)據(jù)如表1所示。
表1 實(shí)測(cè)對(duì)比數(shù)據(jù)
對(duì)實(shí)測(cè)數(shù)據(jù)及場(chǎng)景變化的描述如下:
(1) 傳統(tǒng)方法在初始化階段有明顯的“卡頓”現(xiàn)象,且沒有場(chǎng)景節(jié)點(diǎn)被繪制出來。
(2) 傳統(tǒng)方法加載完成之后只需要約1~2 f即可全部繪制完成,這一階段的繪制幀率為58~60 f/s。
(3) 異步加載方法在初始化階段只需加載一張圖,約1.5 f,在第2 f末已繪制完成第一層LOD模型,幾乎沒有“卡頓”現(xiàn)象。
(4) 異步方法3層模型從初始化完成到整個(gè)場(chǎng)景繪制完成的過程中需要29 f,幀率有一定的起伏,但總體呈現(xiàn)逐漸加快的趨勢(shì),明顯的可以看到場(chǎng)景中逐步顯現(xiàn)出LOD各個(gè)子節(jié)點(diǎn)。
(5) 異步方法2層LOD模型從初始化完成到場(chǎng)景繪制完成需要7 f,幀率為平穩(wěn)的46 f/s。
(6) 場(chǎng)景繪制完成后,對(duì)場(chǎng)景中的物體進(jìn)行拖拽、旋轉(zhuǎn)操作時(shí),兩層LOD幀率幾乎不變,而3層LOD則由于三角形數(shù)目的增多因此在重繪時(shí)幀率會(huì)有明顯下降。
由以上數(shù)據(jù)可以看出,異步加載方法雖然不能減少?gòu)募虞d到繪制的總時(shí)間,但是可以明顯地減少“卡頓”時(shí)間,并且可以實(shí)現(xiàn)一邊加載高度圖一邊將加載好的數(shù)據(jù)實(shí)時(shí)的繪制出來,給用戶比較流暢自然的Web3D體驗(yàn)。
4 結(jié) 語
本文使用Three.js框架,通過HTML5的異步加載技術(shù)動(dòng)態(tài)地構(gòu)建WebGL大地形場(chǎng)景樹,目標(biāo)在于實(shí)現(xiàn)CPU加載和GPU繪制的相互協(xié)作,給Web用戶更好的3D體驗(yàn)。本文的實(shí)驗(yàn)程序所構(gòu)建出的場(chǎng)景距離比較完美還有以下不足:首先,對(duì)場(chǎng)景中長(zhǎng)期沒有用到的節(jié)點(diǎn)還沒有做到動(dòng)態(tài)剔除,因此,還沒有實(shí)現(xiàn)對(duì)最大數(shù)據(jù)量的平衡控制;其次,在LOD場(chǎng)景控制時(shí)沒有消除因LOD層級(jí)過渡而產(chǎn)生的裂縫,以后,程序可以從這兩方面加以改進(jìn)。
參考文獻(xiàn)
[1] 方強(qiáng).基于WebGL的3D圖形引擎研究與實(shí)現(xiàn)[D].合肥:安徽大學(xué),2013.
[2] CANTOR D, JONES B.WebGL編程指南[M].李強(qiáng),譯.北京:清華大學(xué)出版社,2013.
[3] PARISI T. WebGL up and running [M]. Sebastopol: OReally. 2012: 2?16.
[4] 張亞飛.HTML5和RIA網(wǎng)站設(shè)計(jì)[M].北京:清華大學(xué)出版社,2013.
[5] CHANG K.地理信息系統(tǒng)導(dǎo)論[M].5版.陳建飛,張?bào)懔?,譯.北京:科學(xué)出版社,2010.
[6] ROGERS D F.計(jì)算機(jī)圖形學(xué)算法基礎(chǔ)[M].北京:機(jī)械工業(yè)出版社,2002.
[7] 佚名.three.js教程[EB/OL]. [2010?01?06].http://github.com/tparisi/WebGLBook.