空間劃分及可見性演算法

2021-06-29 11:52:35 字數 3086 閱讀 6863

最簡單的流水線可見性處理如下:

對每個物體轉換到世界座標,然後進行視椎體剔除,其次是背面消隱,最總通過空間剪裁和光柵化期間的影象空間裁剪得到最終的要繪製的影象。

在場景很簡單,物體很少的情況,上述方法是可行的。但考慮到現代遊戲的場景複雜程度,如果還採用上面的流水線來提出多邊形,就顯得力不從心了,因為這意味著在每次移動攝像機的時候都要對場景中的所有的物體進行視椎體的剔除及背面消隱,而這根本是不肯能的。

因此,就迫切一種方法,能快速的對大部分場景進行剔除操作。進一步說就是,能根據當前視點位置快速得到當前可見的多邊形集合。

而這就需要對空間進行有效的劃分,即對物體要有乙個有效的管理。

常見空間劃分演算法有:

bsp、bhv、octree等

常見的可見性演算法有:

pvs、oc、portal等

下面先對最重要的bsp演算法進行簡單的分析:

bsp樹的原理:使用分割面將空間劃分成凸形子空間構成的二叉樹。

bsp樹的應用:

<1>大規模剔除物體。

<2>碰撞檢測。

<3>可以根據視點的位置很快的確定當前正確的渲染順序(從後到前或從前到後)。(注:現在的遊戲99%都不採用該方法進行渲染)

根據bsp樹的原理,很容易聯想到,如果把多邊形自身作為分割面,則有可能在擁有很多房間或關卡的室內場景遊戲中發揮作用。

具體來說就是以多邊形鍊錶作為輸入提供給空間劃分系統來建立bsp樹。

步驟:<1>選擇第乙個多邊形作為分割面。如果鍊錶中只剩乙個多邊形或沒有多邊形則演算法結束;

<2>判斷下乙個多邊形在分割面的前面還是後面,分別新增到front和back鍊錶中;

<3>遞迴處理front和back鍊錶;

顯示和訪問bsp以根據當前視點獲得正確的繪製順序由於應用不多,在此就不在詳細介紹了。

建立bsp樹對時間是不敏感的,因為將通過某種建模工具生成模型及對應的bsp數並儲存到磁碟中,即建立樹的過程是離線的。

(留個問題以後詳述:什麼工具可以生成bsp,怎麼生成,以什麼格式儲存,在使用時又是如何載入?)

bsp樹的侷限性:只適合半靜態場景,如果多邊形在本超平面內平移,bsp樹是不會改變的,但是如果旋轉多邊形則需要重新生產bsp樹。

下面討論一下bsp在剔除上的應用:

凸形子空間特性和便利的線性時間複雜度使bsp樹非常適合於大規模剔除操作。

下次主要討論:

<1>背面消隱

<2>視景體剔除

先來複習一下背面消隱:

前提為左手座標系,每個三角形都會以一定順序儲存三個頂點,按照這個順序觀察三角形,如果是順時針方向則該面為三角形的正面,另乙個面為三角形的背面。有了該假設,我們就可以計算三角形的面法線了,該法線垂直三角形面並指向三角形的正面。選擇三角形面上的一點為起點,視點為終點構造乙個向量,起名叫做視點向量。根據法線向量和視向量的點積的符號很容易計算該面是否是正面朝向的,即是否可以被消隱。如果啟動了背面消隱則三角形只有一面是可見的,如果要求三角形兩面都可見則應該禁用背面消隱。

禁用背面消隱:g_pd3ddevice->setrenderstate( d3drs_cullmode, d3dcull_none );

通過背面消隱可以消除一部分三角形,但是普通的背面消隱存在侷限性:

<1>由於它沒有考慮觀察向量方向,所以可能會產生誤差。比如,通過普通背面消隱判斷為可見的三角形,由於觀察方向向量會導致三角形實際是不可見的。

<2>在室內環境中有很多面都是雙面可見的,這時普通的背面消隱就失去了存在的意義。

所以必須把觀察向量考慮進來,產生一種新的更嚴格的背面消隱演算法,具體演算法就不在贅述了。

有了上述的背面消隱演算法,結合bsp樹會在視景體剔除中發揮極大作用。因為如果根據背面消隱演算法知道當前分割面相對視點是否可見,如果不可見,並且視點在分割面的背面則可以判斷出,在該分割面前面的所有的面都是不可見的。同理,如果視點在分割面的前面,且該分割面是不可見的,則可判斷在該分割面後面的所有的面都是不可見的。這樣就可以迅速的剔除視椎體以外的大量三角形。

到此為止,簡單的介紹了使用bsp樹對視椎體進行剔除的演算法。但是,到目前為止,插入到渲染列表中的的三角形在實際情形中還是有很多是不可見的,也就是冗餘的。為了剔除這些冗餘三角形,就出現了pvs演算法。

pvs(潛在可見集),可以手動建立,也可以使用工具建立,可以儲存成陣列,也可以儲存成矩陣,也存在很多編碼方式,在此不再贅述。總之是離線建立的。在插入到渲染列表之前在使用pvs來提取冗餘三角形。

portal(入口),是一種實時的pvs,它根據portal的大小對視椎體進行裁剪,根據新的視椎體來確定pvs。具體怎麼實現以後再介紹。

明天再介紹,bhv和8叉樹。

前面討論的bsp和portal大多數情況會被用於室內場景的管理,更確切的說是在充滿分割面的場景中。在室外場景管理中一般會用到bhv(包圍體層次結構)或八叉樹(num_division = 2的一種特殊的bhv)。

關於如何建立bhv及如何遍歷bhv樹利用視椎體進行剔除就不在贅述了。但需要認識到以下幾點:

<1>bhv樹也是需要離線建立的。

<2>層數的限制很自由,至少有以下選擇:

(1)在節點的大小達到特定值時;

(2)在達到特定層數時;

(3)在每個節點包含的多邊形的數目達到特定值時;

<3>8叉樹比較常用,是因為它能很好的模擬3d座標系有8個象限組成的特性。

最後,讓我們來**一下oc(遮掩剔除):

在實際應用中,有時候不想使用有關可見性的靜態解決方案,因為遊戲世界可能頻繁變換,pvs、bsp、bhv都不適合。

可喜的是,我們發現在遊戲中經常會有一些很大的物體,它們會遮掩大部分場景,這就為oc提供了可能性。

oc技術的步驟如下:

<1>遍歷完全位於視椎體內的且可見的所有的物體,選擇n個最近、最大的物體。

<2>將物體投影到螢幕空間,並計算投影區域的面積。從中選擇m個投影面積較大的物體,然後計算每個遮掩物的內接矩形。

<3>將遮掩矩形加入到遮掩體中,然後根據遮掩體對所有多邊形和物體進行檢測,剔除所有被遮掩的物體。

下面是使用oc需要注意的幾點:

<1>可以離線選擇一部分遮掩物,在執行階段根據潛在的遮掩物進行選擇,速度會很快。

<2>一般結合bsp、portal、8叉樹等場景管理,才能使效率很高。

到此為止,關於空間劃分和可見性演算法基本介紹完畢。後面會結合具體引擎,關於該專題進行深入分析,並對以前留下的問題進行闡述。

空間劃分及可見性演算法 三

前面討論的bsp和portal大多數情況會被用於室內場景的管理,更確切的說是在充滿分割面的場景中。在室外場景管理中一般會用到bhv 包圍體層次結構 或八叉樹 num division 2的一種特殊的bhv 關於如何建立bhv及如何遍歷bhv樹利用視椎體進行剔除就不在贅述了。但需要認識到以下幾點 1 ...

C 中 作用域及可見性

作用域是用來表示某個識別符號在什麼範圍內有效,可見性是指識別符號是否可見,可引用。1.作用域 作用域是這樣乙個區域,識別符號在程式的這個區域內是有效的。c 的作用域主要有四種 函式原型作用域 塊作用域 類作用域和檔案作用域。a.函式原型作用域 函式原型大家還記得嗎?比如 void fun int x...

PL SQL變數作用範圍及可見性

在pl sql程式設計中,如果在變數的定義上沒有做到統一的話,可能會隱藏一些危險的錯誤,這樣的原因主要是變數的作用範圍所致。與其它高階語言類似,pl sql的變數作用範圍特點是 變數的作用範圍是在你所引用的程式單元 塊 子程式 包 內。即從宣告變數開始到該塊的結束。乙個變數 標識 只能在你所引用的塊...