圖形學隨筆:渲染管線簡略概述
➤ 渲染管線簡略概述
(非嚴謹定義,用於理順渲染管線大致流程)
首先,
宏觀概念
一句話:
渲染管線就是模型(或者說圖形)資訊到最終螢幕的這麼一個過程
,就是渲染管線乾的。需要特別注意的是,在
進入GPU之前,在CPU中的渲染邏輯的預先處理部分也應該包含在渲染管線的流程當中
。
渲染管線並
沒有絕對統一的一個標準
,不過大致的流程都是差不多的,而且隨著技術的發展,
流程也在持續變化
,在比較權威的
Real-time Rendering
這本書中,渲染管線
粗略
分為以下步驟:
Real-time Rendering 渲染管線
對上述的粗略步驟,以
更細的粒度進行劃分渲染管線各個階段
:
這個流程中,
綠色代表該階段可程式設計,其中虛線框代表是可選階段,黃色表示該階段不可程式設計但可以透過引數配置來控制,藍色階段表示完全固定,不可程式設計也不可配置
。
更加詳細的流程如下圖所示(下圖中紫色表示為固定階段):
渲染管線各個階段概述:
(1)應用階段—Appllication Stage:
首先需要注意的是應用階段
發生在CPU中
,可以由
開發人員完全控制
。CPU將需要
渲染的資料
進行一波
預先處理
,並將最終處理的結果,即
渲染圖元(Rendering Primitives)
,連同
渲染的方式,渲染狀態等
必要資訊,一同發往GPU(視訊記憶體)做進一步處理。然後,使用渲染指令指揮GPU開始渲染(
Draw Call
),因為之前向GPU傳送了足夠的資訊,所以渲染指令可以足夠簡單。除此之外,如果要渲染的物件,比如一個網格體,還需要進行諸如碰撞檢測等邏輯處理,這個過程不應算在渲染管線內,是在CPU中處理的。
GPU有很多單獨微小的處理單元,足夠的微小,足夠的簡單,數量也是極多
,所以GPU的計算質量和強度遠遠不如CPU,但是可以同時執行很多很多的小任務。
(2)幾何處理階段—Geometry Processing Stage:
① 頂點著色器(Vertex Shader):可程式設計
,MVP變換的
模型變換
和
檢視變換
就在此階段處理,同時,此階段還能
控制頂點
的一些
屬性
,比如座標變換、計算顏色資訊以及光照資訊等。但需要注意的是
不能新增或刪除頂點
。同時,此階段中,頂點的處理是相對獨立的,頂點之間的聯絡是未知的(或者不處理?),結合GPU的特性,這一階段進行的速度會很快。
② 曲面細分著色器(Tessellation Shader):可程式設計,此階段可選
,透過將曲面進一步劃分為更小的子曲面(增加了更多的頂點),可以讓模型的細節更加的豐富,顯然也是需要更多的資源消耗,這個階段還可進一步劃分為以下三個子階段:
Ⅰ。
Hull-Shader Stage(細分控制)
:此階段是
可程式設計
的,可以指揮GPU如何對頂點進行曲面細分操作,但是還未具體執行細分。
Ⅱ。
Tessellation Stage(細分操作)
:此階段是
不可程式設計
,GPU會根據 Hull-Shader Stage 階段對曲面細分的指令,執行曲面細分,這個階段才是
真正的曲面細分執行階段
。
Ⅲ。
Domain-Shader Stage(細分計算)
:此階段是
可程式設計
的,可以控制計算經過曲面細分後的頂點。
③ 幾何著色器(Geometry Shader):可程式設計,此階段可選
,這個階段,就可以對頂點進行更進一步的操作了,
增加和刪除頂點
,雖然和頂點著色器一樣可以對頂點屬性進行修改,但由於幾何著色器並行呼叫硬體困難,並行程度低(不太理解原因,暫記),所以在對
頂點的屬性修改
上
效率遠弱於頂點著色器
。此階段一個有意思的地方在於它可以把一個或多個頂點轉變為完全不同的基本圖形(或稱為圖元),從而生成比原來多得多的頂點。
④ 投影(Projection):不可程式設計且不可配置,GPU固定實現
,MVP變換的
投影變換
在此階段處理,投影完成後頂點就被約束在裁剪空間了,可進行下一步的裁剪操作。
⑤ 裁剪(Clipping):不可程式設計,但可透過引數控制
,裁剪操作主要是為了將
攝像機檢視之外的頂點剔除
出去,然後將頂點對映到螢幕空間,這是一個三維空間到二維空間的操作,然後經過齊次除法得到歸一化的裝置座標(Normalized Device Coordinates),即通常所說的
NDC
。 二維化後,座標Z軸的值並未被捨棄,而是被記錄到
深度緩衝(Z-Buffer)
,用於後面的階段中計算模型相較於攝像機的先後位置。
⑥ 螢幕對映(Screen Mapping):不可程式設計且不可配置,GPU固定實現
,裁剪階段會將攝像機空間歸一化,所有頂點被壓縮在[-1, 1]的範圍內,物理顯示螢幕的畫素數量顯然是整數個的,所以需要將裁剪階段中得到的X和Y軸座標投影到螢幕上,也就是
視口變換
,變換後為
視窗座標系
。需要注意的是此時Z軸的座標資訊仍然在深度緩衝中,留待後續階段處理。
(3)光柵化階段—Rasterlation Stage:
① 圖元組裝(Primitive Assembly):
此階段是
不可程式設計且不可配置,GPU固定實現
的,此時就需要關心頂點之間的關係了,依據頂點的資料和資訊,將需要連線的頂點連線,組成一個個面。需要注意的是,頂點不一定會連線,單個頂點,或者頂點的連線,也可作為圖元,圖元不一定是一個面。
② 三角形遍歷(Triangle Traversal):
此階段是
不可程式設計且不可配置,GPU固定實現
的,主要判斷三角形覆蓋了哪些螢幕畫素點,如果螢幕上某個畫素點被判斷為被圖元覆蓋,則會生成對應畫素大小的片元,注意此時片元不一定會最終成為畫素,片元也不等於畫素。判斷畫素點是否被圖元覆蓋主要有三種方式:
Standard Rasterization
(判斷中心點若被圖元覆蓋,則生成對應片元);
Outer-conservative Rasterization
(畫素只要被圖元挨著了,就生成對應片元);
Inner-conservative Rasterization
(畫素點需要完全被圖元覆蓋,才生成對應片元)。這一階段還會處理
抗鋸齒(Anti-aliasing)
操作,比如經典的
多重取樣抗鋸齒(MultiSampling Anti-Aliasing,MSAA)
。可以看出,
圖元覆蓋畫素點的判斷,和抗鋸齒沒有直接關係,判斷圖元是否覆蓋畫素點主要還是用來生成片元
。因為畫素點離散性質,會導致不可避免的鋸齒存在,所以才需要抗鋸齒。
③ 片元著色器(Fragment Shader):可程式設計,此階段可選
,也被稱為
畫素著色器(Pixel Shader)
,開發者可根據需要,給片元著色,比如透過三角形重心座標插值計算顏色值,計算陰影,或者直接用紋理覆蓋。需要特別特別注意的是,
片元不等於畫素
,片元可以
理解為預備畫素
,相對於一個畫素而言,片元除了包含基本的RGBA值之外,還包含了更多的資訊,例如法線,紋理座標等等資訊。
片元經過一系列的測試(深度測試,透明度測試等)才有可能被選上而轉變為畫素
,這也是將之稱為預備畫素的原因。如果一個片元被選定作為一個畫素,經過一系列的變換,最終將轉變為包含RGBA值的螢幕畫素。
④ 逐片元操作(Per-Fragment Operations):不可程式設計,但可透過引數控制
,這一階段也被稱為
合併階段(Output-Merger)
,主要就是對片元進行
測試(Test)
以及
合併(Merge)
。測試是可以透過引數配置來控制的,主要有
裁剪測試(Scissor Test)
、
透明度測試(Alpha Test)
、
模板測試(Stencil Test)
以及
深度測試(Depth Test)
這幾種方式。一般情況下,大量的被遮擋的片元會在測試過程中被剔除,最終成為不了畫素,但這些片元卻幾乎參與了整個渲染管線流程,消耗GPU大量資源,所以有
深度測試提前(Early-Z)
技術來最佳化這種情況,不過這個技術會導致透明度測試的衝突,比如A擋住了B,應該將B剔除,但A卻是透明或半透明的,所以B不能被剔除,甚至還需要和半透明的A進行混合,解決這種衝突需要代價,這也是透明度測試導致效能下降的原因。當一個片元經過了測試之後,就可以將其轉變為畫素了(需要注意的是此時畫素已經包含了深度資訊,之前這部分資訊被儲存在深度緩衝裡),在顯示到螢幕這之前,還需要進行
合併操作
,合併主要有兩個方式,完全
不透明的畫素
可直接進行
顏色替換
,而對於
半透明的畫素
還需要進行
混合(Blend)
操作,這個操作是高度可配置的。一切完成之後,片元就會被送往
顏色緩衝區
,此時的片元,就基本等價於畫素了,值得一提的是,GPU會使用一種稱為
雙重緩衝(Double Buffering)
的方式,簡單來說就是算好兩幀的影象,一幀為
前置緩衝(Front Buffer)
,就是當前螢幕顯示的那一幀,逐片元操作完成後生成的畫素會被送往
後置緩衝(Back Buffer)
,這就是另外的那一幀了,後置緩衝會替換掉前置緩衝,螢幕的影象就進入下一幀了。
概念補充:
(1)頂點、圖元、片元和畫素的區別,
簡單描述
:
① 首先,按
生成
的先後順序:
頂點 ⇨ 圖元 ⇨ 片元 ⇨ 畫素
。
②
頂點
,
頂點著色器
,就是一個頂點(或許還有更深層次的意思?)。
③
圖元
,
圖元組裝
時生成,圖元是由頂點組成的,可以是單獨一個點,也可使一條直線,更多的情況下,是一個三角形(或多邊形)。
④
片元
,
三角形遍歷
時,生成被圖元覆蓋的螢幕畫素點對應的片元,圖元在經過光柵化階段後,會被分割為一個個畫素大小的基本單位,即被稱之為片元,片元更像是畫素的資料表示,最終的畫素就是由片元中的資訊生成的。
⑤
畫素
,在
逐片元操作
時,片元經過一些列的測試處理,透過測試後的片元會轉換為畫素,最終呈現在螢幕上的包含RGBA值的最小單元。
(2)
渲染管線每個階段的輸入,是上一個階段的輸出,而執行後的輸出,會作為下一階段的輸入。
(3)總結各階段操作特性:著色器都是可程式設計的,但只有頂點著色器是必須的階段;裁剪和逐片元操作雖不可程式設計,但可以配置;
投影
、螢幕對映、圖元組裝和三角形遍歷都是GPU的固定實現。
點選進入:B站個人主頁
點選進入:知乎個人主頁
點選進入:公眾號話題
微信公眾號搜尋:問塵