葉 誠,羅 訓
(天津理工大學 計算機科學與工程學院,天津 300384)
現階段場景模型生成技術并不發達,程序員在處理生成模型場景問題上還存在很多情況沒有解決.本研究在游戲引擎的實驗環境下,討論了大規模復雜場景生成階段的一些重要問題,優化了相關算法.本文主要研究大規模復雜場景生成后場景模型的優化,根據模型和攝像機的遠近實時調用不同層級的模型方面進行研究.大型復雜生成場景文件在游戲引擎中的漫游存在著模型渲染上和模型調取的問題,該研究使用了模型加載及其渲染優化技術,優化了場景漫游的工程簡化了制作流程;在模型場景渲染技術上,通過使用一種基于LOD 場景模型的新型算法,解決了大規模復雜場景的實時渲染有許多技術上的難點,主要包括海量地形數據的表示和組織、動態場景的管理以及場景的真實感表現等.即按照生成模型的規模大小,使用模型切割代碼將模型切割成尺寸大小均等的不同尺寸,滿足工程對于場景漫游的要求;相關論文研究了關于大規模地形的快速渲染方法,其思想是將之前分割好的地塊都先簡化為一些不同細節層次的網格模型,存儲在外部存儲介質上.程序根據攝像機距離模型的遠近調取合適的地形塊導入內存,再進行模型的渲染.這種方法的缺陷是增加了很多的步驟,在不同的模型切換時會產生視覺上的卡頓問題.本文對于自動LOD 技術進行探討采用網格簡化算法結合視點的動態LOD 技術,提高了幀率減少了當前占用CPU 進行計算的時間,并且減少了攝像機下的三角形和頂點數從而減少了渲染的工作量.
本文在游戲引擎中使用天津工業大學的生成模型(如圖1)進行漫游,采用不同方法對該工程進行優化處理,提出將LOD 技術和動態網格簡化算法并行計算形成一種新型的自動LOD 構建算法,主要貢獻可以概括為:
(1)將游戲引擎中LOD 技術與動態網格簡化算法并行節省渲染時間.
(2)提出了自動LOD 構建方法只需要使用一套模型就可以應用LOD 技術.

圖1 天津工業大學模型
在大型場景中經常使用的優化算法主要有:LOD技術,遮擋剔除算法,動態加載,本文主要對這LOD 技術和網格簡化算法進行了結合改進從而提出了自動LOD 算法.
LOD 技術,也稱為層次細節技術,是在實時渲染顯示系統中采取的細節省略技術,此技術于1976年由Clark 提出[1].作為目前主要的場景優化方法,它根據物體的重要性、視點的相對速度或者位置等衡量標準,動態改變場景中三維模型的復雜程度,模型距離視點越近,顯示的模型細節越豐富,從而降低了CPU 和GPU需要處理的的頂點數量,提高場景的渲染速度[2].在復雜模型的動態顯示中,當觀察點距離某一物體很近時,該物體的圖像將在屏幕上占據較多的像素點;而當觀察點距離某一物體很遠時,該物體的圖像只能在屏幕上占據很少的像素點.在這種情況下,用大量的面去精確表示該物體是不必要的[3].認為當物體覆蓋屏幕較小區域時,可以使用該物體描述較粗的模型,并給出了一個用于可見面判定算法的幾何層次模型,以便對復雜場景進行快速繪制.LOD 技術在不影響畫面視覺效果的條件下,通過逐次簡化景物的表面細節來減少場景的幾何復雜性,從而提高繪制算法的效率.該技術通常對每一原始多面體模型建立幾個不同精度的幾何模型.與原模型相比,每個模型均保留了一定層次的細節.在繪制時,根據不同的標準選擇適當的層次模型來表示物體.LOD 技術具有廣泛的應用領域.目前在實時圖像通信、交互式可視化、虛擬現實、地形表示、飛行模擬、碰撞檢測、限時圖形繪制等領域都得到了應用,已經成為一項要害技術.很多造型軟件和VR 開發系統都開始支持LOD 模型表示.LOD 生成的一種常用方法是網格簡化.目前常用的網格簡化方式有邊壓縮、面收縮、點聚合和頂點刪除等[4].
遮擋剔除算法利用遮擋剔除(occlusion culling)技術,在游戲引擎中使用遮擋剔除時,會在渲染對象被送進渲染管線之前,將因為遮擋而不會被看到的隱藏對象或隱藏面進行剔除,從而減少了每幀的渲染數據量,提高了渲染性能[5].可見性剔除是提高大規模復雜場景的加速技術之一,目的是減少送入圖形管線的面片數量,降低場景規模增長對圖形系統的負擔[6].對于給定的場景和觀察視點,通過判斷場景中物體的可見性,快速拒絕那些顯然不可見的繪制元素,從而減少送入圖形繪制管線的幾何復雜度[7].在遮擋密集的場景中,性能提升會更加明顯.遮擋剔除是當一個物體被其他物體遮擋住而不在攝像機的可視范圍內時,不對其進行渲染.在3D 圖形計算中并不是一個自動進行的過程,因為在絕大多數情況下離相機最遠的物體首先被渲染,靠近攝像機的物體后渲染,并覆蓋先前渲染的物體(這種重復渲染又叫做“OverDraw”),它不同于視錐剪裁.視錐剪裁只是不渲染攝像機視角范圍外的物體,而對于那些被其他物體遮擋,但是依然在鏡頭范圍內的物體,則不會被視錐剔除.當然當你使用遮擋剔除時,視錐裁剪還是會生效的.由于地形場景一般較為復雜,對CPU 開銷很大.為了降低地形的遮擋剔除過程中CPU的負荷,提出了以GPU 具有遮擋查詢功能為基礎的遮擋剔除算法[8].
在游戲引擎中,如果想使用傳統的LOD 技術(如圖2)就必須先將面數最大的模型分別簡化為幾種面數不同,導出后再放入游戲引擎中使用LOD 技術優化工程.在這種新型的LOD 技術中,動態網格簡化算法采用網格預先簡化的方法事先生成LOD 模型避免了直接使用網格簡化算法所需完成的大量計算,有效地降低了算法的時間開銷.在串行計算環境下,網格簡化算法使得一些較小規模(包含1 05以下量級三角面單元)的網格模型的在交互幀率下的動態LOD 模型構建成為可能.然而在面對大規模網格模型(包含1 05及以上量級三角面單元)時,卻仍無法滿足交互幀率繪制需求.
在動態網格簡化算法使用在大規模復雜模型的時候其時間性能需要有所提升,該理論基于網格的動態LOD 構建方法,并且使用了三維模型的簡化算法,創造出一個新型高效率的自動LOD 算法,如圖3.

圖2 傳統LOD 加載算法處理步驟

圖3 自動LOD 加載算法處理步驟
算法主要具備如下優勢:
(1)適用于較大面數的模型,具備良好的擴展性.
(2)只需要一套模型.
(3)可以自由縮減模型的面數.
自動LOD 加載模型總體流程如圖4所示.

圖4 自動LOD 加載模型流程
為了能夠對模型使用網格簡化選擇三角邊坍縮的辦法實現,可以讓兩個頂點并成一個頂點,如圖5所示.

圖5 三角邊坍縮
要實現邊uv的坍縮需要刪除兩側的面A和B,使用點v來代替點u,需要進行點的連接操作,目標是連接點v和點u的鄰點還要除去點u,點v為點u的坍縮目標.
對于1 個實體模型(具有封閉的邊界,根據邊界可以將空間分為模型內部和模型外部2 部分),1 次坍縮,可以移除2 個三角面,3 條邊和1 個頂點.通過反復的迭代,最終就會使模型簡化到預期的面數.
如果想要刪除掉某個點還要盡量保持原始模型外觀這就需要考慮到坍縮的代價公式如下:

在式(1)中頂點u的三角形被包含于集合Tu里,頂點u和頂點v的三角形被包含于集合Tuv里.
式(1)中需要考慮兩個頂點點u坍縮到點v并且需要將頂點u刪除這一系列操作所花費的代價.首先需要處理的是邊,在網格簡化的流程中,無關緊要的部分是首要剔除的部分.其次應該要注意頂點u附近的曲率,因為只有當點周圍的曲率越平坦,那么這個點也就越不重要.值得關注的是,連個頂點從點u坍縮到點v和從點v坍縮到點u的代價有所不同.
根據上述公式,依賴于針對點與其周圍鄰點坍縮的代價進行計算,再決定以代價最小的鄰點為目標進行坍縮運算.
根據以上的描述,可以將實現分為以下步驟:
(1)遍歷模型上點、邊和面的關系.
(2)計算坍縮代價和坍縮目標,并排序.
(3)通過公式找到坍縮代價最小的頂點,通過衡量相鄰頂點的的坍縮代價和坍縮目標,實時調整有序列表.
(4)再次遍歷頂點,計算設置頂點數量是否小于現頂點數量,如果是則重復第(3)步.
因為在程序運行的時候不能夠實時進行上述步驟,特別是第(2)步,因為全部的頂點被遍歷了很多次,不必要的工作量過于繁重.因此,可以考慮將工作分成離線烘培和運行時這兩個步驟,具體實現步驟如圖6所示.

圖6 實現步驟
離線烘焙會輸出兩個int 數組:permutation和vertex_map.
步驟:
(1)收集頂點信息:主要是頂點位置和index,另外需要初始化兩個列表:包含頂點的三角面列表和頂點的鄰居列表.
(2)收集三角面信息:需要得到模型上所有三角面里所含有的頂點和計算法線(目的是計算曲率).并且不斷更新頂點的三角面列表將新的三角形填入列表,還需要使每個頂點加入另外兩個頂點的鄰居列表中.
(3)通過不斷分析點與該點鄰點的坍縮代價,決定坍縮代價最小的鄰點為最終的目標.
(4)依據坍縮代價對所有的頂點進行排序.
(5)替換坍縮代價最小的頂點:根據坍縮公式設法得到代價最小的點u和它的鄰邊目標點v,讀取包含頂點u的三角面列表,只要哪個三角面里面含有頂點v就刪除該三角面,如果不能遍歷到就將頂點u與頂點v進行交換.再次分析頂點u鄰點的坍縮代價以及坍縮目標,根據最新的信息重新編排列表.
(6)令permutation[u.index]=當前頂點數量,令vertex_map[u.index]=v.index(如果沒有坍縮目標,則賦值為-1).
(7)目前的點數大于0,如果是將返回第(5)步.
permutation保存了每個頂點被移除的倒數次序(1 是最后被移除的,最大的是第一個被移除的),vertex_map保存了每個頂點的坍縮目標的位置.
輸入需要繪制的最大頂點數量n.
步驟:
(1)遍歷三角面.
①獲得當前三角面的三個頂點的index,即idx0、idx1和idx2.
②如果permutation[idx0]=n則idx0=vertex_map[idx0],否則執行第⑤步.
③如果idx0==-1 oridx1==idx0 oridx2==idx0,該三角面不參與繪制.同理映射并判斷idx1 和idx2.
④返回第①步.
⑤當前三角面加入繪制列表.
(2)根據三角面的數據,整理頂點屬性.
值得注意的是,員網格信息將不會被刪除,再程序運行的時候,還能夠再任意的層次細節模型上切換.
如果想要有出色的游戲性能以及更佳的畫面效果,該研究還可繼續改進上述步驟:
(1)最小堆排序:在離線烘培的第(4)步中,應該考慮需刪除點的鄰點的坍縮代價,同時坍縮列表也要隨之更新.因此可以選擇最小優先隊列(最小堆)記住頂點和坍縮代價,根據新的信息重新完善頂點的順序.
(2)刪除不用頂點:需要提高幀率并通過減少攝像機前的三角面和頂點降低渲染壓力,在第(2)步中,需要依靠三角面的數據對Mesh 的頂點數組(還有uv、uv2、colors、normals、tangents、boneWeights等)和三角面數組進行重新排列.
(3)邊界點處理:在處理過程中有兩個問題比較棘手,一種是不閉合的三角面,例如飄帶、披風等.另外一種是兩個墊高點雖然有相同的坐標,但是不同的uv或normal,例如Unity3D 的Sphere 是有一條接縫的.假如這兩種情況不進行參考,在坍縮的過程中,將會出現沒能指出對的坍縮目標來代替原頂點,會發生鏤空和破損的情況.根據上面說的問題,我們在考慮坍縮消耗的問題上,會將這些邊緣點的曲率設為2 (可以在編輯器里調整).
(4)內存優化:如果不想多次重新建立Mesh 的vertices等數組,可以選擇unsafe 的方式來改變數組的大小.
(5)JobSystem:離線烘焙中使用了JobSystem 來加速烘焙.
本論文選取天津工業大學的生成模型場景為例子,驗證過程為自動LOD 算法與遮擋刪除技術,動態加載,普通漫游分別對同一場景隨即視點位置進行渲染,對比各項渲染數據.
FPS (Time per frame and FPS):Frames Per Seconds表示引擎處理和渲染一個游戲幀所花費的時間,該數字主要受到場景中渲染物體數量和GPU 性能的影響,FPS 數值越高,游戲場景的漫游體驗會更加平穩和舒適.
CPU:獲取到當前占用CPU 進行計算的時間絕對值或時間點,如果Unity 主進程處于掛斷或休眠狀態時,CPU time 將會保持不變.
Tris &Verts:攝像機下的所有三角形和頂點這也是主要瓶頸.
圖7中描述了各個算法之間在同一場景下,攝像機前三角面和頂點的數量,三角面與頂點的數量呈反比,數量越大計算機所需要做的工作就越多.

圖7 實驗數據對比
圖8中描述了各個算法之間在同一場景下,幀率和CPU 進行計算的時間,因為FPS 和CPU 的數值與三角面和頂點數量有直接關系,所以提出自動LOD 算法.

圖8 實驗數據對比
文中使用的方法自動LOD 考慮到了之前幾種優化方法的缺點(算法優缺點對比如表1所示),通過使用三角邊坍縮算法,不僅節省了模型導出和導入步驟還節省了大量的內存空間.

表1 算法優缺點對比
針對大型場景漫游提出了新的自動LOD 技術,實驗解決了只使用一套生成模型就可以應用LOD 技術的方法,減少了工作的步驟,對工程中大型生成場景模型的漫游實施了優化處理,不僅提高游戲幀率,而且減少當前占用CPU 進行計算的時間,還節省了不必要的存儲空間,具有一定的參考價值和實際意義.