可視性問題
- 光線追蹤需要消耗更多的內(nèi)存和時(shí)間,但是相比柵格化的模擬效果更好,而在如今計(jì)算機(jī)硬件發(fā)展后,幾乎所有非實(shí)時(shí)渲染器都采用光線追蹤技術(shù),或者采用混合技術(shù).
如何用柵格化解決可視性問題:如何做到吭练?
從屏幕空間轉(zhuǎn)換到標(biāo)準(zhǔn)化設(shè)備坐標(biāo)空間-NDC(normalized device Coordinates),再轉(zhuǎn)換到柵格化坐標(biāo).
- 所有的點(diǎn)最初定義的坐標(biāo)系是屏幕空間(screen space),由位于畫布中心的原點(diǎn)定義.坐標(biāo)系所有的軸都是單位長(zhǎng)度的,因此坐標(biāo)可能為負(fù)數(shù)——如果該點(diǎn)位于畫布左側(cè).
- 柵格空間(raster space)是用像素網(wǎng)格來定義坐標(biāo)系的。其坐標(biāo)原點(diǎn)位于左上角蒿涎,其一個(gè)像素點(diǎn)為一個(gè)單位長(zhǎng)度穿撮,所以其實(shí)際畫布大小由圖片的寬高決定缺脉。
轉(zhuǎn)換方法如下:
- 由于在柵格空間的坐標(biāo)都為正數(shù),所以需要先把P點(diǎn)的原始坐標(biāo)標(biāo)準(zhǔn)化悦穿。即將它們的坐標(biāo)轉(zhuǎn)換為0-1范圍內(nèi)攻礼,這時(shí)候我們稱它們轉(zhuǎn)換到了NDC空間中,這樣再轉(zhuǎn)換到柵格空間就很簡(jiǎn)單了栗柒。
- 當(dāng)轉(zhuǎn)換到NDC空間后礁扮,將標(biāo)準(zhǔn)化后的坐標(biāo)乘以圖像的大小,并將結(jié)果取整瞬沦。
原始坐標(biāo)中P點(diǎn)的范圍取決于屏幕空間中畫布的大小太伊,但是為了簡(jiǎn)便,我們假設(shè)畫布的大小為[-1,1]逛钻,下面是偽代碼
int width = 64, height = 64; // dimension of the image in pixels
Vec3f P = Vec3f(-1, 2, 10);
Vec2f P_proj;
P_proj.x = P.x / P.z; // -0.1
P_proj.y = P.y / P.z; // 0.2
// convert from screen space coordinates to normalized coordinates
Vec2f P_proj_nor;
P_proj_nor.x = (P_proj.x + 1) / 2; // (-0.1 + 1) / 2 = 0.45
P_proj_nor.y = (1 - P_proj.y ) / 2; // (1 - 0.2) / 2 = 0.4
// finally, convert to raster space
Vec2i P_proj_raster;
P_proj_raster.x = (int)(P_proj_nor.x * width);
P_proj_raster.y = (int)(P_proj_nor.y * height);
if (P_proj_raster.x == width) P_proj_raster.x = width - 1;
if (P_proj_raster.y == height) P_proj_raster.y = height - 1;
有幾點(diǎn)需要在代碼中注意:
- 在屏幕空間和NDC空間中點(diǎn)使用的坐標(biāo)為Vec3f或Vec2f類型僚焦,其中點(diǎn)都為小數(shù),而在柵格空間中坐標(biāo)是用vec2i類型整數(shù)表示曙痘。
- 數(shù)組中從下標(biāo)0開始芳悲,所以柵格空間中的點(diǎn)坐標(biāo)不能大于圖像寬度-1,而當(dāng)屏幕空間中的點(diǎn)正好位于1時(shí)有可能發(fā)生這種情況屡江。所以代碼需要檢測(cè)這種特殊情況芭概。
- NDC空間的原點(diǎn)位于左下角赛不,而柵格空間的原點(diǎn)位于左上角惩嘉,所以進(jìn)行轉(zhuǎn)換時(shí)需要反轉(zhuǎn)x軸。
但是我們?yōu)槭裁葱枰@種轉(zhuǎn)換呢踢故?我們需要以下的方法來解決可視性問題:
- 將所有的點(diǎn)投射到屏幕上
-
對(duì)每個(gè)點(diǎn)將其坐標(biāo)從屏幕空間轉(zhuǎn)換到柵格空間中
首先文黎,要如何找到這些點(diǎn)惹苗?我們將組成多邊形物體的三角形拆分為更小的幾何體, 在實(shí)時(shí)API中這被稱為碎片(fragment)
找到點(diǎn)映射到的像素耸峭,并存儲(chǔ)點(diǎn)到眼睛的距離(存放于該像素點(diǎn)的深度表中)
-
- 過程結(jié)束后桩蓉,升序排列每個(gè)像素的深度表,那么深度表的第一個(gè)點(diǎn)就是該像素需要顯示的點(diǎn)劳闹。
表需要被排序院究,因?yàn)樵谕渡鋾r(shí)并不是按照深度順序去進(jìn)行的。
這個(gè)方法有一個(gè)叫深度排序的算法本涕。根據(jù)物體深度排序的概念是所有柵格化算法的基礎(chǔ)业汰。有許多知名的算法例如:
- z-緩沖區(qū)算法(z-buffering),這是最常用的算法菩颖。
- 畫家算法(the Painter algorithm)
- Newell's algorithm
當(dāng)考慮透明度時(shí)
為什么我們需要維護(hù)一個(gè)列表的點(diǎn)呢样漆?只保存最短距離的點(diǎn)就行了?因?yàn)樯鲜鏊惴ㄊ纠豢紤]了非透明物體晦闰。當(dāng)幾個(gè)半透明點(diǎn)投射到同一個(gè)像素時(shí)放祟,我們需要通過深度表記錄,并以特定的算法進(jìn)行合成呻右,這樣才能正常地渲染它們跪妥。
光線追蹤解決可視性問題
我們可以從像素點(diǎn)開始,將其轉(zhuǎn)換為屏幕空間內(nèi)的點(diǎn)(以像素中心計(jì)算坐標(biāo))声滥。然后我們可以從眼睛追蹤一條光線骗奖,讓其經(jīng)過P',射向場(chǎng)景中醒串。如果射線與物體相交执桌,那我們就知道了P點(diǎn)就是對(duì)該像素點(diǎn)可見的點(diǎn)。
注意:光線追蹤和柵格化是殊途同歸的芜赌,它們都基于相同的原理仰挣。不同的是前者是從眼部到物體,后者是從物體到眼部缠沈。
光線追蹤的技術(shù)更為復(fù)雜膘壶,因?yàn)槠湫枰鉀Q光線和物體的相交問題。對(duì)于不同的表面和幾何體屬性都有不同的方法洲愤。
許多年來颓芭,大量的研究用于尋找最有效的方法來計(jì)算光線和最簡(jiǎn)單的三角形的相交,以及NURBS柬赐,隱式平面(implicit surfaces)的相交亡问。然而,一個(gè)可行的做法是,在渲染過程開始前州藕,將所有的幾何體轉(zhuǎn)換為某一種代表性的幾何體束世。這樣渲染時(shí)只需要計(jì)算光線和這種代表性幾何體的相交。由于三角形是一種理想的床玻。
有許多優(yōu)點(diǎn):
- 三角形有許多幾何特性非常適合作為幾何原型毁涉。
- 由于上一點(diǎn),有許多研究用于測(cè)試最佳的光線-三角相交檢測(cè)的算法锈死。最好的算法應(yīng)該是速度最快的贫堰,使用內(nèi)存最少的,并且十分健壯的待牵。
- 從代碼角度來看严嗜,支持一個(gè)過程比編程處理許多幾何體更具有優(yōu)勢(shì)。這樣可以專門設(shè)計(jì)代碼去更好地處理三角形洲敢,尤其是對(duì)加速結(jié)構(gòu)來說漫玄。計(jì)算相交的時(shí)間隨著場(chǎng)景中的幾何體數(shù)量增加而線性遞增。同時(shí)压彭,針對(duì)光線-三角相交的硬件支持也在發(fā)展睦优。
比較柵格化和光線追蹤
利用加速結(jié)構(gòu)(acceleration structure),其將空間分割成一個(gè)個(gè)小的子空間網(wǎng)格壮不。不同的物體就可以根據(jù)它們落入的子空間來分類汗盘。
如果子空間的大小大于物體的平均大小,那么一個(gè)子空間可能包含多個(gè)物體询一。我們不需要去測(cè)試所有的物體隐孽,我們可以先測(cè)試光線是否經(jīng)過給定的子空間。如果經(jīng)過健蕊,我們?cè)贉y(cè)試光線是否和子空間內(nèi)的物體相交菱阵;如果沒有經(jīng)過,那么我們就可以跳過對(duì)該子空間內(nèi)的物體的相交測(cè)試缩功。這樣我們只需要測(cè)試場(chǎng)景內(nèi)幾何體的一個(gè)子集晴及,這大大節(jié)省了時(shí)間。
如果加速結(jié)構(gòu)可以用于加速光線追蹤嫡锌,那么光線追蹤是否比柵格化更優(yōu)秀呢幌绍?可以說是也可以說不是松嘶。使用加速結(jié)構(gòu)引起了許多新問題
- 構(gòu)建該結(jié)構(gòu)需要時(shí)間,這意味著渲染器需要等待構(gòu)建完才能啟動(dòng)卵迂。這大概用不到幾秒鐘靠柑,但是對(duì)于應(yīng)用到實(shí)時(shí)軟件來說凿歼,這幾秒就太久了准颓。
- 加速需要大量的內(nèi)存镣屹,這取決于場(chǎng)景的復(fù)雜程度。但是由于相當(dāng)一部分內(nèi)存被用在加速結(jié)構(gòu)上,用于其他功能的內(nèi)存就更少了茸塞,尤其是用于存儲(chǔ)幾何體的躲庄。在實(shí)際工作中查剖,這意味著使用光線追蹤相比較之下只能渲染更少的幾何體钾虐。
- 找到一個(gè)合適的加速結(jié)構(gòu)是很難的。加速結(jié)構(gòu)的效率取決于場(chǎng)景中物體的分布和物體的各種屬性笋庄。
實(shí)際上效扫,光線追蹤由于某些原因還是相當(dāng)流行的。首先是因?yàn)樗母拍钕喈?dāng)簡(jiǎn)單直砂,雖然柵格化的代碼也長(zhǎng)不到哪里去菌仁。但是光線追蹤的概念更容易去編程實(shí)現(xiàn),并且更貼近于實(shí)現(xiàn)3D場(chǎng)景的自然的想法静暂。而且在柵格化中難以模擬的陰影和反射等在真實(shí)圖像中很重要的特性济丘,在光線追蹤中可以直接進(jìn)行模擬。
柵格化很快洽蛀,但是需要?jiǎng)幽X去支持復(fù)雜的視覺特效摹迷,光線追蹤支持復(fù)雜的視覺特效,但是需要?jiǎng)幽X去讓其變快郊供。(David Luebke - NVIDIA)
總結(jié)
柵格化和光線追蹤各有千秋峡碉,沒有哪個(gè)有壓倒性的優(yōu)勢(shì)。