GPU圖形渲染流程

圖形渲染管道被認爲是實時圖形渲染的核心,簡稱爲管道。管道的主要功能是由給定的虛擬攝像機、三維物體、燈源、光照模型、紋理貼圖或其他來產生或渲染一個二維圖像。由此可見,渲染管線是實時渲染技術的底層工具。圖像中物體的位置及形狀是通過它們的幾何描述、環境特徵、以及該環境中虛擬攝像機的擺放位置來決定的。物體的外觀受到了材質屬性、燈源、貼圖以及渲染模式(sharding modles)的影響。
渲染管線分爲三個階段;應用程序階段,幾何階段,光柵化階段
1. 應用程序階段(CPU)
應用程序階段,通過高級編程語言(C、C++、JAVA)進行開發,與CPU、內存打交道,主要任務是識別出潛在可視的網格實例,並把它們及其材質呈交給圖形硬件以供渲染。在該階段的末端將產生幾何體數據,包括頂點座標、法向量、紋理座標、紋理等,通過數據總線傳送到圖形硬件以供渲染(時間瓶頸),進行幾何階段。應用程序階段負責驅動GPU管道,在該階段有三個角色:
1.可見性判別:僅把可見(或至少潛在可見)的物體提交GPU,以免浪費寶貴的資源去渲染看不見的物體。(裁剪?)
2.提交幾何圖元至GPU以供渲染:像DirectX中的渲染調用接口DrawIndexedPrimitive(),該接口把子網格材質對傳送至GPU進行下一步操作,類似的,在OpenGL中的接口glDrawArrays()也有相同功能。另一種提交方法是建立GPU命令表。場景如果需要多步驟渲染,則需要多次提交,所提交的幾何圖元應有適當地排序以優化性能。
3.控制着色器參數以及渲染狀態。
很多經典的算法都是在這個階段中進行的,諸如碰撞檢測、場景圖建立、空間八叉樹更新、視錐裁剪等。
1.1 視錐裁剪
視錐裁剪算法是在應用程序階段執行的。在把場景中的物體提交給GPU進行下一階段操作之前,需要把對最後影像沒有任何貢獻的物體裁剪掉,僅僅把可見的網格數據傳送給GPU。這個建立可見網格實例表的過程即爲可見性判斷。
錐體由虛擬攝像機來定義。虛擬攝像機制定了場景對觀察者可見的部分,即我們將依據哪部分3D場景來創建2D圖像。在世界座標系中,攝像機有一定的位置和方向屬性,定義了可見的空間體積即視錐體。下圖展示一個虛擬攝像機的模型:在這裏插入圖片描述
用幾何術語來講,上述的空間體積是一個平截頭體。在平截頭體剔除裏,三維物體與平截頭體有三種位置關係:
1.三維物體完全位於平截頭體外。
2.三維物體部分位於平截頭體內。
3.三維物體完全位於平截頭體內
對於第一種情況,物體會被排除在渲染表之外。給定一個網格模型,我們可以通過一些簡單的判別測試來判斷網格模型是否位於平截頭體內,這些測試會用到物體的包圍體積(包圍物體的一個球體)及平截頭體的六個平面。把平截頭體六個平面同時往裏縮進物體包圍體積的半徑長度,若球體中所有6個修改後的平面的前方,那麼物體就是完全位於平截頭體內部的(第三種情況),這種情況下三維物體將被保留並進入下一個階段的處理。對於第二種情況,三維物體的三角形單元將被分爲兩個部分,位於視域體內部的將被保留,視域體外的哪部分將被剔除。
1.2 場景圖
現在的遊戲世界能夠達到很大的規模,在多數場景中,大部分的幾何物體處於上文所說的平截頭體之外,如果這些物體的剔除皆使用平截頭體,會造成難以想象的時間資源消耗。因此我們希望能夠設計一種數據結構來解決大場景的裁剪問題,它能夠迅速丟棄大量完全不接近攝像機平截頭體的場景部分,這樣才能進行更加仔細的平截頭體剔除,此數據結構更可以幫助對場景中的幾何物體排序。這種數據結構就是場景圖。場景圖不一定是圖,更多可能是某種樹:四叉樹、八叉樹、BSP樹、kd樹等等。它們的理念在於把三維空間以某種形式劃分爲區域,使不與平截頭體相交的區域儘快丟棄,而無須逐一物體進行平截頭體剔除。
1.3 四叉樹與八叉樹
四叉樹使用遞歸的方式把空間劃分成象限,因此四叉樹每個節點都有四個孩子節點。象限的劃分通常是由軸對稱的平面切割而成,所以每個象限是正方形或長方形的,不過也有一些四叉樹用任意形狀來細分空間。四叉樹這種數據結構出現的目的就是加速平截頭體的裁剪,那麼它是如何辦到的呢?我們從根節點往葉子節點遍歷,如果某個節點區域若位於平截頭體外,則該節點的四個孩子節點區域也是位於平截頭體外,所以我們可以停止遍歷該分支。八叉樹是四叉樹的三維版本,每層遞歸細分都把八叉樹空間劃分爲8個子區域,子區域通常中正方體或者長方體,不過也可以是任意三維區域。
2. 幾何階段(GPU)
幾何階段主要負責頂點座標變換、光照、裁剪、投影以及屏幕映射,該階段基於GPU進行計算,該階段的末尾得到經過變換和投影之後的頂點座標、顏色、以及紋理座標。其主要工作可以概括爲“變換三維頂點座標”和“光照計算”。我們的顯卡信息中通常會有一個標示爲“T&L”的硬件部分,T即是Transform,L即是Lighting。那麼三維頂點座標爲什麼需要變換?如何變換?要知道,我們出入到計算機中的是一系列三維座標點,但我們最終看到的從視點出發觀察到的特定點。我們電腦顯示器是二維的,GPU所需要做的,就是把三維頂點數據經過轉換繪製到二維屏幕上,並讓二維畫面看起來有3D效果。頂點的變換涉及一系列的座標系統,頂點變換過程,就是通過各個變化矩陣,把一個座標系統下的頂點信息,變化到另外一個座標系統上,從而實現3D的頂點數據最終可以在2D屏幕上進行顯示。我們來了解一下變換過程中的各個座標系統。
2.1 座標系統
根據頂點座標變換的順序,主要有如下幾個座標空間:局部座標系(或稱自身座標系、建模座標系)、世界座標系、觀察座標系、視口座標系(屏幕座標系)。
局部座標系
局部座標系用於定義構成物體的三角形單元列表的座標,它描述的是模型文件本身的頂點與頂點值之間的關係,頂點值是在模型建模時得到的。局部座標系與場景中的其他物體沒有任何的參照關係,這也是局部座標系與世界座標系區分的關鍵。在這裏插入圖片描述
世界座標系
構建各種模型時,每個模型都位於其自身的局部座標系中,而無論在現實世界還是在計算機的虛擬空間中,物體都必須和一個固定的座標原點進行參照才能夠確定自己所在的位置,這是世界座標系的實際意義所在。位於局部座標系中的物體通過一個稱爲世界變換的運算過程變換到世界座標系中,該變換通常包括平移、旋轉、以及比例運算,分別用於設定該物體在世界座標系中的位置、方向及模型的大小。這變換過程由一個四階矩陣控制,通常稱爲世界矩陣(world matrix)。在這裏插入圖片描述
另外,光照計算通常也是在世界座標系中進行的,這是因爲光照效果受到了物體之間關係的影響(如距離、是否遮擋、有無相互投影等)。當然,在觀察座標系中也可以得到相同的光照效果,因爲中同一觀察空間中物體之間的相對關係是保存不變的。有一點值得注意,頂點法向量中模型文件中屬於局部座標系描述,中GPU的頂點程序中必須將法向量轉換到世界座標系才能使用。這種轉換同樣是通過一個矩陣,這矩陣是上文所提的世界變化矩陣的逆矩陣。
觀察座標系
在現實世界中,每個人都是通過自己的眼睛來觀察世界,同樣的,在虛擬世界中,虛擬攝像機就是我們的“眼睛”,計算機每次只能從唯一的視角出發來渲染物體。例如當我們玩CS遊戲時,屏幕顯示的內容隨着視點的變化而變化,這是因爲GPU將物體的座標從世界座標系變換到了觀察座標系。實際上所謂的觀察座標系,也就是我們在上文中提到的攝像機的視錐體,它以攝像機爲原點,由攝像機觀察方向、視角、遠近裁剪平面,共同構成一個梯形體的三維空間:在這裏插入圖片描述
近裁剪平面也即是梯形體較小的矩形面,在Directx中,爲了簡化繪製工作,通常將近裁剪平面和投影平面合二爲一。在觀察者座標系中,我們的任務是獲取3D場景的2D表示,這種從N維到N-1維的操作在數學上稱爲投影,實現投影有多種方式,如正投影(也稱平行投影)和透視投影。由於透視投影更加符合人類的視覺習慣,它會產生近大遠小的效果,所以我們採用這種投影來執行視錐中的3維數據到投影平面的投影。Directx中通過一個稱爲投影矩陣來將視域體中的幾何體投影到投影窗口中。
視口座標系(屏幕座標系)
從視點座標系到視口座標系的轉換是通過
視口變換操作
來進行的。視口變換的任務是將頂點座標從投影平面轉換到屏幕的一個矩形區域中,該區域稱爲視口。在遊戲中,視口通常是整個矩形屏幕區域,當然也可以將視口描述爲屏幕的一個子區域,視口的座標是相對於窗口來描述的。
在這裏插入圖片描述
經過一系列座標的轉換,我們輸入計算機的一系列三維座標點已經轉換爲2D屏幕的三維顯示數據。
2.2 圖元裝配
幾何階段處理結束後,送到光柵化階段的是一堆三角形面片,所以幾何階段中需要對頂點進行圖元裝配。所謂的圖元裝配,即根據頂點原始的連接關係,還原出模型的網格結構。網格由頂點和索引組成,在之前的流水線中是對頂點的處理,而在這階段是根據索引將頂點連接中一起,組成線、面單元。然後對超出視口外的三角形進行裁剪(視口裁剪),如果有一個三角形其中一個頂點位於畫面外,另外兩個頂點位於畫面內,我們看到的將是一個四邊形,而這個四邊形又被劃分爲兩個小的三角形。
這裏提到了視口裁剪,實際上裁剪是個很大的概念,裁剪包括了視域裁剪(應用程序階段)、視口裁剪、背面剔除、遮擋剔除(光柵化階段)。背面剔除涉及到三角形的頂點繞序問題。每個多邊形都有兩個側面,我們將其中一個標記爲正面,另一個側面標記爲背面,通常,多邊形的背面是不可見的,通過背面剔除操作可以不對物體的背面進行渲染,減少需要繪製的頂點個數。一般來說我們根據右手定則來決定三角形的法向量,如果法向量朝向視點(三角形頂點順時針繞序)即爲正面,反之爲背面。在Directx3D中,默認頂點排列順序爲順時針的三角形單元是正面朝向。但也可以通過SetRenderState方法來修改剔除方式。
3. 光柵化階段## 標題
管道的最終階段爲合併階段或混合階段,稱之爲光柵運算階段,光柵化的目的是計算出每個像素的顏色值。這個階段把幾何階段送過來的三角形轉化爲片段,並對片段進行着色。片段經過裁剪測試、alpha測試、模板測試、深度測試、融合等處理後,最終和幀緩衝混合。光柵化過程大致如下圖所示:
在這裏插入圖片描述3.1 背面剔除
對於實時交互的圖形應用程序而言,圖形渲染速度和效率是非常重要的。渲染的時候應該儘量減少不必要的操作。剔除是一種通過避免渲染背對觀察者的幾何體面來提高性能的優化措施。所有幾何體都包含正面和反面。剔除基於大多數對象都是封閉的事實;如果你有一個立方體,你不會看到背離你的那一面(總是隻有一面在你的前方),因此我們不需要繪製出背面。因此也被稱做背面剔除。
3.2 alpha測試
紋理的顏色中含有alpha分量,alpha分量主要用於指定像素的透明度。假定我們爲每個像素的alpha分量保留了8位,則該alpha分量的合法區間是[0,255],其中,[0,255]對應透明度[0%,100%]。當像素的alpha值爲0時,該像素是完全透明的。如果像素的alpha值爲128,其透明度就是50%,而alpha值爲255則表示完全不透明。
alpha測試指的是將一個像素點的alpha值和一個固定值比較。如果比較的結果失敗,像素將不會被寫到顯示輸出中。
** 3.3 模板測試**
在說明模板測試之前,我們需要先介紹一下模板緩存。模板緩存與深度測試緩存、後臺緩存(或顏色緩存,最終顯示在屏幕上的緩衝區)的大小(分辨率)完全一致,模板緩存中的像素點與後臺緩存的像素點是一 一對應的。模板緩存允許我們動態地、有針對性地決定是否將某個像素寫入後臺緩存中。模板緩存用與獲得某種特效,如鏡面效果或陰影效果。在實現鏡面效果時,我們在“鏡子”這塊區域中繪製某個特定物體的映像,而使用模板緩存來阻止物體映像在“非鏡子”的區域中進行繪製。爲了進行這種阻止,就需要使用模板測試。判斷是否將某個像素寫入後臺緩存的決策過程,稱爲模板測試。
3.4 深度測試
當兩個物體有前後位置關係時,位於前面的物體會將後面的物體部分或全部遮擋。這時爲了優化考慮,GPU不應該繪製被遮擋的片段,這種行爲稱爲遮擋剔除。爲了更好了解遮擋剔除與深度測試,我們先來看看深度緩存。深度緩存是一個只含有特定像素的深度信息而不含圖像數據的表面。深度緩存爲最終繪製圖像中的每一個像素都保留了一個深度項。所以,當所繪製的圖形的分辨率爲640480時,深度緩存中將有640480個深度項。深度緩存用於計算每個像素的深度值並進行深度測試,深度測試的基本內容是依據深度值讓處於同一位置的不同像素進行競爭,以選出該寫入該位置的像素,距離攝像機最近的像素獲勝,並被寫入深入緩存的對應位置上。這樣做是合理的,因爲距離攝像機最近的像素一定會將位於其後方的像素遮擋。
3.5 alpha融合
融合技術能使我們將當前要進行的光柵化的像素的顏色與先前已經光柵化並處於同一位置的像素的顏色進行合成,即將正在處理的圖元顏色值與存儲中後臺緩存中的像素顏色值進行合成。利用該技術,我們可以獲得各種各樣的效果,尤其是透明效果。不過值得注意的是,爲了場景中繪製透明物體,通常需要對物體按照由後到前的順序進行混合處理,如果按照任意順序進行處理將會產生嚴重的失真。所以在blending(混色)操作之前要來一次Depth test(見下圖)。
3.6 抖動處理
在低位深度的圖象中,由於顏色總數的限制,有些顏色無法顯示出來,爲了模擬出那些顏色以提高顯示效果,廣泛採用了一種稱作抖動處理(dithering)的方法,也稱半色調處(Halftoning)。它是指用交替的點圖案去模擬在圖象中不能使用的顏色的過程。單色圖象是最簡單的格式,一般由黑色和白色組成,在一些單色圖象如黑白照片和有深淺的圖案中,會使用各種灰度,這種圖象常被稱爲灰度圖象(Grayscale Image)。由於人眼會把一個很細緻的黑白相間的圖案解釋成灰色,所以灰度圖象也可使用單色文件格式,數據仍然可以是黑和白**。使用黑色或某一種單色的點獲得連續的該色灰度的過程就是抖動處理。**抖動處理被更多的用在那些低位數彩色圖象文件中,與不採用這種處理相比,它具有更好的顯示效果。經歷了這階段之後,像素的顏色值被寫入幀緩存中。以上內容即爲渲染管道的整個流程。
淺談 GPU圖形固定渲染管線
計算機圖形學入門

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章