譚德林, 譚 良,2
(1.四川師范大學計算機科學學院四川省可視化計算和虛擬現實重點實驗室,四川成都610101;2.中國科學院計算技術研究所,北京100080)
地形繪制在游戲虛擬場景、地理信息系統、飛行仿真系統、城市規劃、駕駛模擬以及虛擬戰場等虛擬環境中應用廣泛。因此目前國內外關于地形繪制算法的研究相當廣泛?;贚OD的思想,Duchaineau于1996年提出了ROAM地形繪制算法;Lindstrom于1997年提出了動態LOD地形繪制算法;De-Boer于2000年提出了GeoMipMapping地形繪制算法。以上3種算法是地形繪制算法的基礎算法,以后的很多地形繪制算法都是由以上幾種算法發展而來的。如北京大學的王宏武于2000年提出的基于四叉樹的多分辨率地形繪制算法;Levenberg于2002年提出的CABBT算法;浙江大學的陸燕青于2003年提出的基于層次二叉樹的多分辨率頂點繪制算法;J.Bittner于2004年提出的GPU遮擋剔除算法等等。對地形繪制算法的研究,可以人為的把其分為兩個階段,即以CPU為核心的地形繪制算法和以GPU為核心的地形繪制算法。在早期,由于受限于以CPU為核心的圖形處理流水線,該時期的地形繪制算法都是依賴于CPU的地形繪制算法,如ROAM算法、動態 LOD算法和以它們為基礎而改進的地形繪制算法等都屬于以CPU為核心的地形繪制算法;隨著計算機圖形適配器的發展,GPU運算能力被提出并得到廣泛應用,以CPU為核心的地形繪制算法已經不符合當代圖形適配器的圖形處理框架,因此基于GPU的地形繪制算法也相應的被提出,如GeoMipMapping算法或者以GeoMipMapping算法為基礎進行改進后所得到的地形繪制算法。國內對基于GPU的地形繪制算法研究較多,如基于索引模板的Patch-LOD地形繪制算法[1]、基于受限法向錐的誤差計算方法[2]、基于GPU加速的分形地形生成算法[3]、基于地平線遮擋裁剪的層次化可見性計算方法[4]、基于現代GPU的大地形可視化算法[5]、基于頂點紋理的LOD地形渲染算法[6]等。隨著以GPU為核心的地形繪制算法的出現,使地形的繪制不再完全依賴于CPU?;贕PU為核心的地形繪制算法是把地形繪制過程中的地形繪制這部分工作交由GPU來完成。這使得以GPU為核心的地形繪制算法不但能充分的利用當代圖形適配器的圖形處理功能,同時也把CPU從繁瑣的地形繪制算法中解放出來,讓其不用過多的參與地形的繪制。通過進一步解放CPU,使得CPU可以直接去參與系統中其它工作的處理。以 GPU為核心的地形繪制算法是當前圖形適配器下地形繪制算法的主流。
通過對以上各種地形繪制算法的分析可以發現,目前的以GPU為核心的地形繪制算法大多都是以Geomipmapping算法為基礎,或者對其進行改進而得到的。而根據Geomipmapping算法的原理可知,在地形繪制的過程中,需要有紋理加載的過程。通過分析可得,傳統的以GPU為核心的地形繪制算法的紋理加載方法的工作流程[7]如圖1所示。

圖1 傳統的紋理加載原理
由圖1可以看出,傳統的紋理加載方法的基本原理為:首先將紋理源的紋理數據加載到系統內存中,然后再將數據從系統內存拷貝到紋理對象,其整個過程都需要由CPU來對其進行控制。由此可見,傳統的地形繪制算法中的紋理加載方法顯然不符合當前以GPU為核心的地形繪制算法的“進一步把CPU中地形繪制的過程中解放出來以使其能更多的參與到其它工作的處理中去”的思想。因此傳統的紋理加載方法成為了當前圖形適配器下各種以GPU為核心的地形繪制算法的瑕疵。為了解決這個問題,在地形繪制算法中引入了PBO[8]。PBO(pixel buffer object)即像素緩存對象,該對象屬于GPU的緩存的一部分。因為PBO采用了DMA技術,它在紋理數據從PBO復制到紋理對象的過程中無需CPU而是由GPU來控制。因此在紋理加載時應用 PBO,可以進一步的解放CPU;同時由于PBO的DMA技術采用異步方式,因此可以通過使用雙PBO機制來加載紋理。雙PBO的引入,使得紋理數據的加載可以用異步并行的方式完成,這進一步加快了紋理數據的加載速度。
由圖1可知,傳統的紋理加載方法需要CPU來全程控制,這顯然與當前以GPU為核心的地形繪制算法的解放CPU的思想不相符。因此,這里在紋理加載的過程中引入了PBO。基于PBO的紋理加載方法的工作原理流程圖如圖2所示。
從圖2可以看出,引入PBO后,紋理源的像素數據直接被傳到PBO中,這個過程仍需由CPU來進行控制;而當紋理數據從PBO復制到紋理對象的過程中,則是采用PBO的DMA技術來完成的,這個過程則由GPU來對其進行控制。由于在這個過程中不需要CPU對其進行控制,因此這時CPU就可以直接去完成其它的任務而不需要等待像素數據傳遞的結束。

圖2 基于PBO的紋理加載原理
由于DMA技術是采用異步方式來完成的,也就是說,在完成紋理源到PBO的數據傳輸后,可以不需要立刻把PBO中的數據復制到紋理對象?;谶@個原理采用了雙PBO機制,其工作原理為當某一個PBO正在和紋理對象進行關聯操作時,另外一個PBO則和像素源進行新的數據傳輸。通過采用雙PBO機制,使得像素數據傳輸到PBO的操作和從PBO中復制數據到紋理對象并行工作,雙PBO機制的工作原理如圖3所示。

圖3 雙PBO工作原理
由圖3可知,當地形繪制到第n幀時,紋理源在CPU的控制下把像素數據寫入PBO1的同時,PBO2將其中的像素數據復制到紋理對象。在 n+1幀時則 PBO1和 PBO2的工作過程剛好相反。通過使用雙PBO,可以使紋理數據的加載并行處理,這進一步提高了紋理加載的速度。
基于PBO的地形繪制算法是在Geomipmapping地形繪制算法的基礎上引入PBO而得到的。Geomipmapping地形繪制算法也叫幾何誤差算法,它是最早的以GPU為核心的地形繪制算法。以后的很多 GPU友好的地形繪制算法都是在它的基礎上,并對其進行改善優化后形成的。Geomipmapping地形繪制算法的基本思想是對整個地形進行分塊,每一個塊的大小為2n+1。根據每塊離視點的距離,可以把它標識為可見和不可見。如該地形分塊不可見,則直接被裁剪體裁剪掉;如地形塊可見,則根據其離視點的距離,又可分為很多細節層次等級,每個細節層次等級對應不同的紋理圖像。等級越低,離視點越近,其紋理圖像的分辨率也越高;反之等級越高,離視點越遠,其紋理圖像的分辨率也越低。在分塊的層次等級中,0級為分塊的層次等級中最低的,其分辨率卻是最大的,隨著等級的增大,分別率則變小。
基于PBO的地形繪制算法也就是在加載紋理數據時,借助PBO,讓紋理源數據直接進入PBO,然后再通過PBO把紋理數據復制到紋理對象。為此,需要先生成PBO對象,接著把PBO和紋理對象進行綁定。這樣就可以讓紋理源數據直接傳遞到PBO中,然后再將PBO中的數據復制到紋理對象。為了完成以上功能,需要借助opengl擴展庫中的擴展函數來完成。根據不同的參數,可以對PBO進行讀和寫。如當參數為GL_STREAM_DRAW_ARB時,表示將像素從紋理源加載到PBO中,而參數為GL_STREAM_READ_ARB時,表明從PBO中把像素數據進行異步讀出。
同時為了使雙PBO能協調工作,需要對這兩個PBO進行有效控制,這里將通過使用兩個變量來分別標識這兩個PBO。在某一幀時,第一個PBO接受像素數據的讀入,另一個PBO則把其中的像素數據拷貝到紋理對象;而在下一幀,這兩個PBO的功能則剛好進行交換。
圖4為基于PBO的地形繪制算法的體系結構?;赑BO的地形繪制算法的體系結構中,存在著兩條流水線,分別為集合流水線和像素流水線,這兩條流水線將于光柵化器處匯合在一起。在該體系結構中,高程圖生成器用來產生虛擬環境中地形的高度圖,通過高度圖,就可以唯一確定世界坐標系中某一點的高度;幾何處理器是用來對頂點進行幾何變換如平移、旋轉、縮放等;像素流水線則對像素進行相應的操作;顯示列表[9]是用來把圖元信息或者其它的信息作為對象保存到服務器中,這就避免了代價較高的傳輸和重新生成的問題;光柵化器用來負責生成片段或者說那些可能位于幾何對象中的像素;幀緩存[10]位于OpenGL流水線上最后顯示階段像素所在處,幀緩存可以視為二維數組,或opengl使用的存儲區域,它包括了顏色緩存、深度緩存、模板緩存和累積緩存。如圖所示,通過PBO映射,還可以將opengl控制的緩存對象與客戶端地址空間進行內存映射。這樣客戶端可通過函數glMapBufferARB()和glUnmapbufferARB()來修改緩存對象的數據。
在實現基于PBO的地形繪制算法的過程中,可以分為指定PBO擴展的函數指針、創建PBO對象、傳輸像素數據等步驟,如下為其部分代碼實現:
(1)生成雙PBO:


圖4 基于PBO的地形繪制體系結構

(2)把數據從PBO復制到紋理對象:

(3)紋理映射:

(4)解除綁定:

如上代碼的主要實現了生成兩個PBO,把PBO綁定到紋理對象以及讓客戶端地址空間的內存與PBO進行映射已經傳輸完數據后把PBO和紋理對象解除綁定。
基于PBO的地形繪制算法實現的硬件環境為:CPU Pentium?Dual-core CPU,內存為 2GB,顯卡為 nvidia geforce g210M。軟件環境為:Windows7Proffessional32位操作系統下,使用VC++6.0和OpenGL 2.0完成的。在如上開發環境下,渲染了一個高度圖大小1025*1025,窗口大小為1024*768的地形。如圖5所示為渲染結果圖。

圖5 基于PBO的地形
表1所示為渲染不同大小的地形、是否使用PBO以及不同頂點數目時的CPU利用率。
由表1可以看出,使用PBO時CPU利用率比不使用PBO時的CPU利用率要低很多。通過使用PBO,使得在紋理載入時,由PBO復制紋理數據到紋理對象的過程中不需要CPU的控制,以便進一步解放出CPU,使其可以直接去進行其它的工作。

表1 CPU使用率比較
針對當前以 GPU為核心的地形繪制算法以及當前解放CPU和充分的利用GPU的思想,這里以Geomipmapping算法的基礎引入了PBO,提出了基于PBO的地形繪制算法。通過使用PBO,減少了CPU對地形繪制的控制,進一步解放了CPU和使用GPU。同時,由于PBO的DMA技術采用異步方式,所以可以通過雙PBO對象來使得從紋理源傳遞像素到PBO和從PBO復制紋理數據到紋理對象并行進行,這也進一步提高了像素傳遞的速度。由實驗結果可知,基于PBO的地形繪制算法完全符合當前解放CPU并充分利用GPU的地形繪制算法的思想。
[1]皮學賢,楊旭東,李思昆,等.基于索引模板的Patch-LOD地形繪制算法[J].計算機研究與發展,2005,4(增刊):183-187.
[2]李勝.超大規模地形場景的高性能漫游[J].軟件學報,2006,17(3):535-545.
[3]馬淑芳.基于GPU加速的分形地形生成方法[D].大連:大連理工大學,2008.
[4]何旭鋒.大規模復雜場景的加速繪制方法研究與實現[D].成都:電子科技大學,2009.
[5]潘宏偉,李輝,廖昌閣,等.一種基于現代GPU的大地形可視化算法[J].系統仿真學報,2007,19(7):3241-3244.
[6]張桀寧,李帥.一種基于頂點紋理的LOD地形渲染算法[J].系統仿真學報,2008,20(4):1758-1764.
[7]紋理加載方法[EB/OL].http://blog.sina.com.cn/s/blog_4062094 e0100alvt.html,2008.
[8]PBO介紹[EB/OL].http://www.songho.ca/opengl/gl_pbo.html,2007.
[9]段菲.openGL編程基礎[M].3版.北京:清華大學出版社,2008:66-69.
[10]幀緩存[EB/OL].http://blog.sina.com.cn/s/blog_4062094e0100 alvv.html,2008.