渲染管线概论
什么是渲染管線
渲染管線(渲染流水線)是將三維場景模型轉換到屏幕像素空間輸出的過程。圖形渲染管線主要包括兩個功能:一是將物體3D坐標轉變為屏幕空間2D坐標,二是為屏幕每個像素點進行著色。
渲染管線的流程
渲染管線的一般流程如下圖所示。分別是:頂點數據的輸入、頂點著色器、曲面細分過程、幾何著色器、圖元組裝、裁剪剔除、光柵化、片段著色器以及混合測試。
此外還可以抽象為4個階段
應用階段:由CPU主要負責的階段,且完全由開發人員掌控。CPU將決定遞給GPU什么樣的數據(目標場景的燈光、模型),有時候還會對這些數據進行處理(將攝像機不可見的元素被**剔除(culling)**出去),并且告訴GPU這些數據的渲染狀態(譬如紋理、材質、著色器等)。
這一階段最重要的輸出是渲染所需的幾何信息,即渲染圖元(通俗來講可以是點、線、面等)
幾何階段:負責大部分多邊形操作和頂點操作,將三維空間的數據轉換為二維空間的數據。
光柵化階段:決定每個渲染圖元中哪些像素應該被繪制在屏幕上,它需要對上一階段得到的逐頂點數據進行插值
像素處理階段:給每一個像素正確配色,最后繪制出整幅圖像
應用程序階段在CPU端完成,后面的所有階段都是在GPU端完成(所以又稱GPU渲染管線)
特點
渲染管線的一個特點就是每個階段都會把前一個階段的輸出作為該階段的輸入。
例如,片段著色器會將光柵化后的片段(以及片段的數據塊)作為輸入進行光照計算。除了圖元組裝和光柵化幾個階段是由硬件自動完成之外,管線的其他階段管線都是可編程/可配置的。
各個階段的功能
應用階段
渲染管線的起點是CPU,CPU與GPU的通信即上文的應用階段
(1)把數據加載到顯存:將數據加載到顯存中能使GPU更快的訪問這些數據,當把數據加載到顯存后,便可以釋放了數據,但一些數據仍需留在內存中,如CPU需要網格數據進行碰撞檢測。
(2)設置渲染狀態:渲染狀態的一個通俗解釋就是,定義了場景中的網格是怎樣被渲染的。例如,使用哪個頂點著色器/片段著色器、光源屬性、材質等。如果不設置渲染狀態,那所有的網格將使用同一種渲染,顯然這是不希望得到的結果。
(3)調用Draw Call:當所有的數據準備好后,CPU就需要調用一個渲染指令告訴GPU,按照上述設置進行渲染,這個渲染命令就是Draw Call。Draw Call命令僅僅指向被渲染的圖元列表,而不包含任何材質信息
在實際的渲染中,GPU的渲染速度往往超過了CPU提交命令的速度,這導致渲染中大部分時間都消耗在了CPU提交Draw Call上。有一種解決這種問題的方法是使用批處理(Batching),即把要渲染的模型合并在一起提交給GPU
GPU渲染管線
綠色表示開發者可以完全編程控制的部分,虛線外框表示此階段不是必需的,黃色表示開發者無法完全控制的部分(但可以進行一些配置),紫色表示開發者無法控制的階段(已經由GPU固定實現)
幾何階段
頂點著色器
頂點著色器的處理單位是頂點,但是每次處理都是獨立的,因此無法創建或銷毀任何一個頂點,也不能得到與其他頂點的關系
頂點著色器主要功能是進行坐標變換。將輸入的局部坐標變換到世界坐標、觀察坐標和裁剪坐標。
雖然我們也會在頂點著色器進行光照計算(稱作高洛德著色),然后經過光柵化插值得到各個片段的顏色,但這種得到的光照比較不自然,所以一般在片段著色器進行光照計算
曲面細分著色器
曲面細分是利用鑲嵌化處理技術對三角面進行細分,以此來增加物體表面的三角面的數量,是渲染管線一個可選的階段
幾何著色器
在這個階段,開發者可以控制GPU對頂點進行增刪改操作
投影
GPU將頂點從攝像機觀察空間轉換到裁剪空間(又被稱為齊次裁剪空間),為之后的剔除過程以及投射到二維平面做準備。
常見的投影方式有透視投影與正交投影。
在三維中原有的三個分量x、y、z上又額外增加了w=1分量,使得可以通過矩陣乘的方式為三維坐標實現平移的效果。
裁剪
只有當圖元部分或全部位于視椎體內時,我們才會將它送到流水線的下個階段,也就是光柵化階段。對于部分位于視椎體的圖元,位于外部的頂點將被裁剪掉,而且在視椎體與線段的交界處產生新的頂點。
在把不需要的頂點裁剪掉后,GPU需要把頂點映射到屏幕空間,這是一個從三維空間轉換到二維空間的操作。
-
對于透視裁剪空間,GPU需要對裁剪空間中的頂點執行齊次除法(將齊次坐標系中的w分量除x、y、z分量),得到頂點的歸一化的設備坐標(NDC)
通過透視除法后,我們得到了NDC坐標,獲得NDC坐標是為了實現屏幕坐標的轉換與硬件無關。
-
正交裁剪空間只需要把w分量去掉即可。
此時頂點的x、y坐標接近于在屏幕上所處的位置了,此時z分量不會被丟棄而是被寫入了深度緩沖(z-buffer)
屏幕映射
屏幕映射的任務就是將每個圖元的x、y值變換到屏幕坐標系,對于z坐標不做任何處理(實際上屏幕坐標系和z坐標一起構成窗口坐標系),這些值會被一起傳遞到光柵化階段
一般來說,屏幕坐標是2D的概念,只用于表示屏幕XY坐標,而窗口坐標是2.5D的概念,它還帶有深度信息,也就是經過變換后的Z軸的信息。
使用齊次坐標的意義,其實就是為了正確記錄下投影變換前(觀察空間)中物體的深度信息,也就是Z坐標的值。
光柵化階段
光柵化會確定圖元所覆蓋的片段,利用頂點屬性插值得到片段的屬性信息,然后送到片段著色器進行顏色計算,我們這里需要注意到片段是像素的候選者,只有通過后續的測試,片段才會成為最終顯示的像素點。
三角形設置(Triangle Setup)
這個過程做的工作就是把頂點數據收集并組裝為簡單的基本體(線、點或三角形)
三角形遍歷(Triangle Traversal)
這個過程將檢驗屏幕上的某個像素是否被一個三角形網格所覆蓋,被覆蓋的區域將生成一個片元(Fragment)
片元不是真正意義上的像素,而是包含了很多種狀態的集合(譬如屏幕坐標、深度、法線、紋理等)
而片元的劃分依據(像素塊被覆蓋到何種程度才被劃分)不管怎么樣都會產生鋸齒,這就有許多抗鋸齒的采樣方式(比如MSAA)
片段著色器
片元著色器的輸入是上一個階段對頂點信息進行插值的結果(是根據從頂點著色器輸出的數據插值得到的),而它的輸出是像素顏色值
這個階段我們能進行很多渲染技術,比如根據頂點法線或者UV計算顏色,接受陰影或者是進行紋理采樣(紋理坐標是通過前述階段的頂點數據插值得到的)
逐片元計算
對每個片元進行操作,將它們的顏色以某種形式合并,得到最終在屏幕上像素顯示的顏色。主要的工作有兩個:對片元進行測試(Test)并進行合并(Merge)。
裁切測試
在裁剪測試中,允許程序員開設一個裁剪框,只有在裁剪框內的片元才會被顯示出來,在裁剪框外的片元皆被剔除。
模板測試
模板測試通常用來限制渲染的區域,渲染陰影,輪廓渲染等
在模板測試中,GPU將讀取片元的模板值與模板緩沖區的模板值進行比較,比較函數由開發者指定,如果比較不通過,這個片元將被舍棄
深度測試
現實生活中,近的物體會遮擋住遠處的物體,深度緩沖就是用來實現這種效果的。
GPU將讀取片元的深度值(就是我們前面留下來的坐標z分量)與緩沖區的深度值進行比較,和模板測試一樣,如何渲染物體之間的遮擋關系也是自定義的(可以讓GPU把沒有被遮擋的部分隱藏了,讓被遮擋的部分顯示出來的。)
大量的被遮擋片元直到深度測試階段才會被剔除,而在此之前它們同樣地被計算,這占用了GPU大量的資源。
因此有種優化技術是將深度測試提前(Early-Z)。但這帶來了與透明度測試的沖突,例如某個片元甲雖然遮擋了另一個片元乙,但甲卻是透明的,GPU應當渲染的是片元乙,這就產生了矛盾,這就是透明度測試會導致性能下降的原因
合并
一個片元通過了所有測試,片元顏色就會被送到顏色緩沖區,到達了合并環節
合并有兩種主要的方式,一種是直接進行顏色的替換,另一種是根據不透明度進行混合(Blend)
如果開啟了混合,GPU會取出片元著色器得到的顏色(源顏色)和顏色緩沖區存在的顏色(目標顏色),之后按照設定的函數進行混合,可以設定透明度通道進行相加,相減還是相乘。
最后GPU會使用雙重緩沖(Double Buffering)的策略,即屏幕上顯示前置緩沖(Front Buffer),而渲染好的顏色先被送入后置緩沖(Back Buffer),再替換前置緩沖,以此避免在屏幕上顯示正在光柵化的圖元
渲染管線中的坐標系變換
- 我們從建模工具得到的是物體的局部坐標(Local Coordinate),
- 局部坐標通過模型矩陣Model變換到世界坐標(World Coordinate),
? 光照計算一般都是在世界空間進行的,所以輸入的頂點坐標需要通過乘以模型矩陣變換到世界空間。在模型變換時,通常還需要將法線變換到世界空間中,對于法線變換不能簡單的使用模型變換矩陣來變換法線,對于包含非均勻縮放的變換,需要求解模型變換的逆轉置矩陣
-
世界坐標通過觀察矩陣View變換到觀察坐標(View Coordinate),
虛擬攝像機定義了我們的觀察空間。虛擬攝像機的位置是坐標的原點,觀察方向沿著Z軸的負方向。我們可以通過攝像機的位置(EyePosition)、觀察目標點(FocusPosition)和向上的方向向量(UpDirection)來構建觀察矩陣。
-
觀察坐標經過投影矩陣Projection變換到裁剪坐標(Clip Coordinate),
? 裁剪空間的目標是能夠方便的對圖元進行裁剪,這塊空間是由視錐體決定的,視錐體外為看不到的區域,也就是被裁剪的部分。當時不同的視錐體有不同的處理過程,而且透視投影判斷點是否在視錐體內比較麻煩,通過一個投影矩陣將頂點轉換到裁剪空間中是一種通用、方便的方式。——常見的投影矩陣有透視投影和正交投影
? 投影矩陣并沒有真正的進行投影工作,而是為投影做準備,真正的投影發生在齊次除法過程中,這發生在屏幕空間映射階段
-
裁剪坐標經過透射除法(Perspective Division)得到標準設備空間(Normalized Device Coordinates,NDC),
-
NDC坐標通過視口變換(Viewport Transformation)變換到窗口坐標進行顯示
總結
- 上一篇: Subplot函数
- 下一篇: Java使用Calendar月操作(时间