Unity Shader學習-1.渲染流水線【轉】

Unity Shader學習-1.渲染流水線

先了解一下什么是流水線:(下面是百度百科的定義)

流水線:流水線又稱為裝配線,一種工業上的生產方式,指每一個生產單位只專注處理某一個片段的工作,以提高工作效率及產量

一、什么是渲染流水線

1.概念

渲染流水線的概念與上面說到的流水線的概念也是一致的,其主要任務是輸入一個三維場景,然后輸出一個二維的圖像。這個過程是由CPU和GPU一起完成的。

2.渲染流水線的三個階段

渲染流水線可以分為三個階段:應用階段、幾何階段、光柵化階段

image

a.應用階段(CPU處理)

這一階段是由開發者主導的,在這一階段中開發都有3個主要的任務:

首先,需要準備好場景數據(攝相機位置、視錐體、模型和光源等)

接著,還需要做粗粒度的剔除工作

最后,需要設置好每個模型的渲染狀態(使用的材質、使用的紋理、使用的Shader等)

這一階段最重要的輸出是渲染所需的幾何信息,即渲染圖元,渲染圖元可以是點、線、三角面等。

b.幾何階段(GPU處理)

幾何階段主要用于處理所有和我們繪制的幾何相關的事情。幾何階段負責和每個渲染圖元打交道,進行逐頂點、逐多邊形的操作。這個階段可以進一步分成更小的流水線階段。

幾何階段的一個重要任務就是把頂點坐標變換到屏幕空間中,再交給光柵器進行處理。

總結:輸入的渲染圖元->屏幕空間的二維頂點坐標、每個頂點對應深度、著色等信息

c.光柵化階段(GPU處理)

將會使用上一個階段傳遞的數據來產生屏幕上的像素,并渲染出最終的圖像。主要任務是決定每個渲染圖元中的哪些像素應該被繪制在屏幕上。

3.CPU與GPU之間的通信

渲染流水線的起點是CPU,即應用階段。應用階段可以分為下面3個階段:

1.把數據加載到顯存中

2.設置渲染狀態

3.調用Draw Call

1.數據加載到顯存中

基本步驟就是紋理、網格等數據從硬盤加載到系統內存再加載到顯存。數據加載到顯存后系統內存中的數據就可以被移除了,但是對于一些數據來說CPU需要訪問他們,例如用于碰撞檢測用的網格數據,這些數據則會被保留。

2.設置渲染狀態

渲染狀態指的是場景中的網格是如何被渲染的,例如使用哪個Vertex Shader或者哪個Fragment Shader、光源屬性、材質等。

3.調用Draw Call

Draw Call指的是一個命令,發起方為CPU,接收方為GPU。當給定了一個Draw Call時,GPU會根據渲染狀態(例如材質、紋理、著色器等)和所有輸入的頂點數據進行計算,最終輸出成在屏幕上的像素。這個計算的過程就是GPU流水線。

4.GPU流水線

當GPU收到CPU發送過來的Draw Call指令后,會進行一系列的流水線操作,最終把圖元渲染到屏幕上。對于幾何階段和光柵化階段其實現的載體是GPU,而開發者對這兩個階段的實現細節無法完全控制。而GPU流水線可以細分成不同的流水線階段

image

(1)頂點著色器:

從圖中可以看到GPU的流水線接收頂點數據作為輸入,接著頂點數據被傳遞給頂點著色器。頂點著色器的處理單元是頂點,輸入進來的每個頂點都會調用一次頂點著色器。(頂點著色器本身不可以創建或銷毀任何頂點,并無法得到頂點與頂點之間的關系)

頂點著色器是完全可編程的,它主要完成的工作有:坐標變換和逐頂點光照。

坐標變換:就是對頂點的坐標進行某種變換—把頂點坐標從模型空間轉換到齊次裁剪空間。我們可以通過坐標變換來模擬水面、面料等。

(2)曲面細分著色器:

是一個可選的著色器,主要用于細分圖元。

(3)幾何著色器:

是一個可選的著色器,可用于執行逐圖元的著色操作,或者被用于產生更多的圖元。

(4)裁剪:

這一階段是可配置的。目的是把那些不在視野內的頂點裁剪掉,并剔除某些三角形圖元的面片。

一個圖元與攝像機視野的關系有3種:完全在視野內、部分在視野內、完全在視野外。

完全在視野內的圖元會繼續傳遞給下一個流水線階段

完全在視野外的圖元不會繼續向下傳遞

部分在視野內的圖元需要做裁剪處理

和頂點著色器不同的是,這一步是不可編程的。我們無法通過編程來控制裁剪的過程,而是硬件上的固定操作。

(5)屏幕映射:

這一階段是可配置和編程的,負責把每個圖元的坐標(三維坐標系)轉換成屏幕坐標(二維坐標系)

。這一步輸入的坐標仍然是三維坐標系下的坐標。屏幕映射得到的屏幕坐標決定了這個頂點對應屏幕上哪個像素以及距離這個像素的距離。

注意:OpenGL把屏幕的左下角當成最小的窗口坐標值,而DirectX則定義屏幕的左上角為最小的窗口坐標值。(就不能統一一下嗎。)

image

這樣的差異會給開發者造成不少的坑,如果你發現開發過程中得的圖像是倒轉的,那可能是因為這個問題。

(6)三角形設置:(開始進入光柵化階段)

中文名 光柵化

釋 義: 將圖轉化為一個個柵格組成的圖象

過 程: 把頂點數據轉換為片元的過程

特 點: 每個元素對應幀緩沖區中的一像素

上一階段我們可以得到的數據是屏幕坐標系下的頂點位置以及和它們相關的其他信息,如深度值、法線方向、視角方向等。

光柵化階段的目標:1.計算每個圖元覆蓋了哪些像素 2.為這些像素計算它們的顏色

三角形設置作為光柵化的第一個階段,會計算出光柵化一個三角網格所需要的信息。上一階段的輸出是三角網格的頂點,如果我們想得到整個三角網格的覆蓋情況,就必須計算每條邊上的像素坐標而得到三角形邊界的表示方式。這樣一個得到三角形邊界表示方式的過程就是三角形設置。

(7)三角形遍歷:

這一階段會檢查每個像素是否被一個三角風格所覆蓋。如果覆蓋的話,就會生成一個片元,這樣一個查找哪些像素被三角形覆蓋的過程就是三角形遍歷。

上一階段得到的三角網格的表示形式會在這一階段用來判斷一個三角網格覆蓋了哪些像素,并使用三角網格的3個頂點信息對整個覆蓋區域的像素進行插值。這一階段輸出的是片元的序列。

注意:一個片元并不是真正意義上的像素,而是包含了很多狀態的集合,這些狀態用于計算每個像素的最終顏色。這些狀態包括了屏幕坐標、深度信息,及從幾何階段輸出的頂點信息,如法線和紋理坐標等。

(8)片元著色器:

片元著色器的輸入就是上一階段對頂點信息插值得到的結果,更具體點說,是根據從頂點著色器中輸出的數據插值得到的。而這一階段的輸出是一個或者多個顏色值。這一階段可以完成很多重要的渲染技術,如紋理采樣,但是它的局限在于,它僅可以影響單個片元。

(9)逐片元操作:(渲染流水線最后一步)

這一階段的目的是:合并。那么是合并哪些數據呢?

這一階段的幾個主要任務:

決定每個片元的可見性。這涉及了深度測試、模板測試等

如果一個片元通過了所有的測試,那么就要把這個片元的顏色值和已經存儲在顏色緩沖區中的顏色進行合并,或者說是混合。

這一階段是可編程的,我們可以設置每一步的細節。

可見性:

這一階段顏色首先要解決每個片元的可見性問題,每個片元需要進行以下的測試,如果在中間任何一個階段沒通過測試的都將被舍棄。

image

模板測試:

如果開啟了模板測試,GPU會首先讀取模板緩沖區中該片元位置的模板值,然后將該值和讀取到的參考值(可以開發者自己指定)進行比較,開發者可以設定成小于時舍棄或者大于等于時舍棄該片元。模板測試通常用于限制渲染的區域,另外模板測試還有別的高級用法,如渲染陰影,輪廓渲染。

深度測試:

如果一個片元幸運的通過了模板測試,那么就會進行深度測試,如果開啟了深度深度,GPU就會把該片的深度值和已經存在于深度緩沖區中的深度值進行比較,這個比較函數也是由開發者設定的,可以選擇大于此值時舍棄也可以選擇小于等于此值時舍棄。但通常這個比較函數是小于等于的關系,這是因為我們我們總想只顯示出離攝像機最近的物體,而那些被其他物體遮擋的片元就不需要出現在屏幕上。和模板測試不同的是,如果一個片元沒有通過深度測試,他就沒有權利修改深度緩沖區中的值。而如果通過了測試,開發者可以通開啟/關閉深度寫入來決定是否要利用這個片元的深度值覆蓋緩沖區中的值。

混合:

對于不透明物體,開發者可以關閉混合操作,這樣片元著色器計算得到的顏色值就會直接覆蓋掉顏色緩沖區中的像素值。但對于半透明的物體,我們就需要開啟混合操作來讓這個物體看起來是半透明的。混合操作是高度可配置的,開發者可以選擇開啟/關閉混合功能。如果開啟了,GPU會取出源顏色和目標顏色,將兩種顏色進行混合。源顏色是指片元著色器得到的顏色值,而目標顏色則是已經存在于顏色緩沖區中的顏色值。

透明度測試會導致性能下降的原因:如果我們在片元著色器中進行了透明度測試,而這個片元沒有通過透明度測試,我們會在著色器中調用API(例如clip操作)來手動將其舍棄掉。這就會導致GPU無法提前執行各種測試。所以現代的GPU會判斷片元著色器中的操作是否和提前測試發生沖突。如果有沖突,就會禁用提前測試。但這樣會導致更多的片元需要進行處理了,因為性能會下降

二、關鍵詞答疑

1.OpenGL和DirectX

開發者直接訪問GPU是一件非常麻煩的事情,可能需要與各種寄存器、顯存打交道,而圖像編程接口在這些硬件的基礎上實現了一層抽象。

而OpenGL和DirectX就是這些圖像應用編程接口,他們之間江湖恩怨,可以去看這篇文章。這些接口架起了上層應用程序與底層GPU的溝通橋梁。上層應用程序向這些接口渲染命令,而這些接口會依次向顯示驅動發送渲染命令,而顯卡驅動會把這些命令翻譯成GPU能聽懂的語言來讓他們進行工作。

2.HLSL、GLSL和CG

這三個指的都是著色器的編程語言。

HLSL:High Level Shading Language,DirectX的著色器語言,由微軟控制著色器的編譯,就算使用了不同的硬件,其編譯結果也是一樣的,其使用的平臺比較局限,幾乎都是微軟自己的產品,如Windows、Xbox 360等

GLSL:OpenGL Shading Language,OpenGL的著色器語言,優點在于其跨平臺性,可以在Windows、Mac、Linux甚至移動平臺使用,這種跨平臺性是由于OpenGL沒有提供著色器編譯器,而是由顯卡驅動來完成著色器的編譯工作的。即只要顯示驅動支持對GLSL的編譯它就可以運行。

CG:C for Graphics,NVIDIA的著色器語言,實現了真正意義上的跨平臺,它會根據平臺不同,編譯成相應的中間語言。

3.Draw Call

Draw Call本身的意義很簡單,就是CPU調用圖像編程接口。

1.CPU和GPU是如何實現并行工作的?

主要的解決方案是命令緩沖區,命令緩沖區包含了一個命令隊列,由CPU向其中添加命令,而由GPU從中讀取命令,添加和讀取的過程是獨立的。這樣使得CPU和GPU可以相互獨立工作。當CPU需要渲染對象時,則向命令緩沖區中添加命令,而當GPU完成上一次渲染任務后,它就可以從命令隊列中取出一個命令并執行它。

2.為什么Draw Call多了會影響幀率?

在每次調用Draw Call之間,CPU需要向GPU發送很多內容,包括數據、狀態和命令。CPU需要完成很多工作,例如檢查渲染狀態等。而一旦CPU完成了這些準備工作,GPU就可以開始本次的渲染。GPU渲染的速度是比較CPU提交指令的速度要快很多的。所以性能的瓶頸會出現在CPU身上,如果Draw Call的數量太多,CPU就會把大量的時間花費在提交Draw Call上,造成CPU過載。

3.如何減少Draw Call?

主要的解決方案是批處理(Batch),把眾多小的合并Draw Call合并成一個Draw Call,當然不是所有情況都能合并的。我們可以對網格進行合并,但是合并的過程是比較消耗時間的,因此批處理技術更適合于靜態的網格。

合并需要注意的點:

避免使用大量很小的網格,當不可避免的要使用這些這么小的網格時,考慮是否可以合并他們。

避免使用過多的材質,因為相同的材質會方便我們進行合并

4.什么是固定函數的流水線?

簡稱固定管線,通常是指在舊GPU上實現的渲染流水線。開發者沒有對流水線完全控制權,只有一些配置操作,配置操作只有開和關

作者:ZeroTryTryTry
鏈接:http://www.lxweimin.com/p/297ca72fed0a
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯系作者獲得授權并注明出處。

?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,401評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,011評論 3 413
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,263評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,543評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,323評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,874評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,968評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,095評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,605評論 1 331
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,551評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,720評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,242評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,961評論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,358評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,612評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,330評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,690評論 2 370

推薦閱讀更多精彩內容

  • Unity Shader學習-1.渲染流水線 先了解一下什么是流水線:(下面是百度百科的定義) 流水線:流水線又稱...
    ZeroTryTryTry閱讀 5,507評論 2 17
  • 渲染流水線的工作任務 根據一個三維場景,生成一張二維圖像從一系列的頂點數據、紋理等信息出發,將這些信息轉換為一張人...
    全新的飯閱讀 523評論 0 1
  • 概念渲染流水線 應用階段 由CPU實現,在這個階段,開發者占有絕對的控制權。 此階段實現3個任務: 1 準備好場景...
    TALY閱讀 787評論 0 0
  • 轉載自VR設計云課堂[http://www.lxweimin.com/u/c7ffdc4b379e]Unity S...
    水月凡閱讀 1,029評論 0 0
  • 本周五,我們的童話劇演出。是的,沒錯,就是周五12月1日。 9個葫蘆娃,除了一個有經驗的其余的都毫無演出經驗。所以...
    馭帥閱讀 248評論 0 0