可程式設計圖形硬體的迅猛發展,讓高質量實時體渲染圖形成為可能,火焰,煙霧,大氣效果,雲的渲染變得越來越快,這篇文章既包含科學領域應用,如醫療成像,也包含一些遊戲
中的特效應用。
1。體資料
離散的體資料可以想象成一堆3維的立方體,也可以稱其為體素,每個體素代表乙個體空間,其實將體素想象成連續3維訊號的取樣更加恰當,這個取樣在空間表現為乙個點。取樣
理論告訴我們,如果我們以乙個原始訊號最高頻率兩倍或以上的取樣頻率對原始訊號進行取樣的話,那麼我們就能使用取樣資料完美重建原始訊號。但現實中進行完美重建原始信
號存在兩個難點:
a.理想重建要求使用乙個sinc函式對原始訊號在空間域上進行進行卷積(因為sinc函式是乙個理想低通濾波器),注意sinc函式是定義在整個空間域上的,意味著重建時所有取樣
點必須參與到每次計算,計算量上難以承受。
b.現實中的訊號並不是帶限的,就是說並沒有乙個最高頻率,比如從黑色變化到白色,屬於階躍訊號,變化到頻域,其最高頻率無窮大,so不存在乙個最高取樣頻率。(訊號處理
的一些基本概念在「球諧光照」有提到)
現實一點,一般用箱式濾波器和蓬式濾波器代替sinc濾波器(其實在通訊領域這兩個濾波器效果非常差),蓬式濾波器說的草根點其實就是線形插值,三維空間中的線形插值當然
就是三線形插值trilinear,箱式的表現形式就是就近點取樣,效果差得很在這裡不做討論。
俗易懂。體渲染比較麻煩的就是乙個亮度積分,沿投射光線對體素發射亮度的衰減函式進行的積分,實時圖形學目前不可能做完美的符號積分,so轉換成簡單的黎曼和(就是類似
矩形近似)。直接體渲染我們現在一般不會用,所以我不會詳細注釋,在此只是稍微解釋下ray-casting的原理。
ray-casting:光線投射是乙個影象空間的直接體渲染演算法,其體渲染積分的數學計算非常的簡單,對需要成像的影象空間,視點投射一根光線穿過影象的畫素,沿這這根光線,
離散的體資料會等間距的被再次取樣(為什麼是再次取樣,因為得到這些資料我們就已經採了一次原始訊號了,忘了?)當然是用線行取樣(學名蓬式濾波),任何乙個取樣點周
圍必定會有8個體資料,然後利用取樣點到他們的距離在他們之間進行線形插值,插完得到乙個標量,利用這個標量值,找到這個取樣點所對應的 emission 和 在這個空間位置上
對應的衰減值,其實就是rgba。體渲染積分也就用前序後者後序的alpha混合在近似處理了。
shear-warp:錯切-變形演算法。該演算法由g.g.cameron和p.lacroute等人 提出,原理是將三維資料場的投影變換分解為三維資料場的錯切(shear)變換和二維圖象的變形(warp)
兩步 來實現,從而將三維空間的重取樣過程轉換為二維平面的重取樣過程,大大減少了計算量。這是目前被認為速度 最快的一種體繪製演算法。其原理就是對體素進行錯切變換,
然後體素取樣方式得以以正交投影形式完成,而後基礎平面上得到的畫素結果會變換到視平面,而透視投影則在錯且基礎上再進行縮放就ok了。
footpring / splatting:足跡表法(潑墨)。另一種經典的體繪製演算法,原理我也不清楚,呵呵。
3。基於gpu的體渲染
體渲染中最基本的操作就是體素的取樣,另外乙個重要的操作就使體素的合成,這兩個操作目前都可以利用現代圖形硬體進行加速,紋理對映本質上來講就是對取樣點的顏色進行查值,而將取樣點進行混合則很容易在畫素片斷階段完成,現在的問題就是我們怎樣獲得與光線投射演算法相同的結果。現代圖形硬體只能渲染多邊形,所以我們要利用硬體加速直接體渲染,必須建立「**幾何體」,體素取樣座標通過**幾何體上紋理座標插值獲得,在通過後續alpha混合這些**幾何體片斷來完成體素的混合。體資料本來是儲存在3d或者2d中。
**幾何體最常用的形式就是一組視平面平行的平面。3d紋理座標通過內部插值產生,但這只適用於3d紋理。如果體素以一坨2d紋理呈現,該怎麼辦呢?我們必須用一組 物體對齊 的幾何體來作為「**幾何體」,問題就來了,2d紋理只能在本紋理空間內進行取樣,一般會沿體素資料的3個主軸儲存3個片組,這樣的目的主要是為了防止光柵化0個畫素。
4。光線投射演算法實現
基於幾何體片的體渲染有很多優點,比如:紋理快取與光柵化單元之間頻寬很高;內建高效取樣器;高效能的光柵化單元。但也有幾個缺點:幾何體片的方位和數量直接由體素資料所決定,幾何體複雜度受原始資料影響很大;輸出敏感度差,乙個好的圖形演算法應該是高度輸出敏感的,而在影象空間處理更能達到這個目標,實際上光柵化做了極大的無用功,應用中大概只有0.2%到4%的畫素片斷影響最終的影象,因為大部分的體渲染程式關注的是按邊界部分區域可視,或者是只顯然制定材質的部分,因此其實大部分畫素片斷其實都是設定成了全透明的。而傳統的光線投射能完美解決這些問題,光線投射的每條光線能獨立選擇步長,能決定光線投射的距離等等。這章的主要目標就是讓這些傳統的cpu實現演算法在gpu上實現。首先光線投射演算法表現出最本質的並行性(因為光線與光線之間基本沒啥關係),這種並行效能很自然的被我們對映到現代gpu體系中,比如將每根光線的操作對映到畫素上,這樣就能用gpu的畫素著色器部分來加速光線投射演算法了,另外體資料也可以儲存在紋理中,這樣就可以利用gpu的高頻寬來訪問他們。但在此之前,我們必須解決兩個基本問題,第一就是gpu沒有迴圈指令(現在好像有了),而沿光線遍歷是在cpu上是個迴圈,第二個是條件break,就是在特定條件下終止遍歷。
5。均勻柵格的光線投射
均勻柵格的幾何造型和拓撲結構都很簡單明瞭,現在直入主題,我們將討論gpu-based ray-casting的最重要的兩個要素:體資料的儲存於畫素片斷的處理。gpu可以高效的訪問紋理資料,因此我們將體資料以3d紋理的形式儲存與視訊記憶體中,另外,光線投射還需要一些額外的輔助資料,因為光線和畫素是以一一對應關係,所以我們可以將這些資料儲存在乙個2d紋理中,通常只有乙個1維的光線引數儲存在中間紋理中,他就是入射點把體資料的距離,在遍歷光線的過程中,這個值是需要不斷更新的,但目前dx和gl都不支援同時讀寫紋理,這裡就需要乙個變通的方法,我們會使用兩張紋理,第一張儲存的這次需要的取樣距離,這張紋理是允許讀取操作的,另一張則允許寫入操作,在每次迭代後,這兩張紋理互換角色,紋理寫入可以通過渲染到紋理來完成,非常高效。渲染過程主要有三個步驟:a.光線引數的初始化;b.光線遍歷亮度衰減積分;c.測試是否終止遍歷。均勻柵格的體渲染一般使用的是體包圍盒作為**幾何體,首先我們必須確定光線進入體資料的位置,然後這個位置到相機位置的距離寫入紋理,作為中間資料送入下乙個pass,如何終止遍歷呢?首先如果遍歷到乙個完全不透明的地方,這根光線遍歷就可以終止了,或者超出了體資料的範圍,但gpu不提供乙個條件退出指令,實際上我們使用深度測試來完成這個功能,以一種方式設定z值,讓gpu在進入丟棄掉z test失敗的畫素,當然當所有光線都終止時,我們需要完成本幀渲染,也就是結束應用程式迴圈pass渲染。其中就有使用early z-test做法,在光線遍歷進入前就丟棄畫素的。
離屏渲染學習筆記
opengl中,gpu螢幕渲染有以下兩種方式 意為當前螢幕渲染,指的是gpu的渲染操作是在當前用於顯示的螢幕緩衝區中進行。意為離屏渲染,指的是gpu在當前螢幕緩衝區以外新開闢乙個緩衝區進行渲染操作。相比於當前螢幕渲染,離屏渲染的代價是很高的,主要體現在兩個方面 要想進行離屏渲染,首先要建立乙個新的緩...
離屏渲染學習筆記
may 6th,2015 opengl中,gpu螢幕渲染有以下兩種方式 意為當前螢幕渲染,指的是gpu的渲染操作是在當前用於顯示的螢幕緩衝區中進行。意為離屏渲染,指的是gpu在當前螢幕緩衝區以外新開闢乙個緩衝區進行渲染操作。相比於當前螢幕渲染,離屏渲染的代價是很高的,主要體現在兩個方面 要想進行離屏...
unity 渲染線段 學習筆記
線段物件 private gameobject linerendergameobject 線段渲染器 private linerenderer mylinerenderer 設定線段的個數,乙個曲線由幾條線段組成 private int linelength 4 分別記錄4個點,通過這4個三維世界中...