Shader編程學習筆記(二)—— Shader和渲染管線


Shader和渲染管線

 

什么是Shader

  Shader,中文翻譯即着色器,是一種較為短小的程序片段,用於告訴圖形硬件如何計算和輸出圖像,過去由匯編語言來編寫,現在也可以使用高級語言來編寫。一句話概括:Shader是可編程圖形管線的算法片段。
  它主要分為兩類:Vertex Shader和Fragment Shader。

 

什么是渲染管線

  渲染管線也稱為渲染流水線,是顯示芯片內部處理圖形信號相互獨立的並行處理單元。一個流水線是一序列可以並行和按照固定順序進行的階段。就像一個在同一時間內,不同階段不同的汽車一起制造的裝配線,傳統的圖形硬件流水線以流水的方式處理大量的頂點、幾何圖元和片段。

  注意理解的是這里有一個前后關系,前一個階段的輸入會到后一個階段去輸出。比如在頂點程序當中,頂點程序計算的數據就會作為片段程序再進一步加工的材料。

  為了更形象地理解渲染管線,來看一下下面的插圖。

  最上面的是【3D應用或者游戲】,【3D應用或者游戲】會直接調用【3D應用接口】,也就是OpenGL或者DirectX等。OpenGL和DirectX是方便應用程序去進行硬件訪問和調用的中間層。如果沒有它們,我們需要為硬件去編寫一個非常復雜的專門針對硬件的驅動程序。

  再接下來就是【CPU和GPU的分界線】,在此之上都是CPU的操作,以下進行GPU運算。

  GPU的運算是從左到右依次進行,最開始【GPU前端模塊】到【圖元裝配】這中間如果在過去T&L流水線的過程當中是由硬件設計好的運算過程,也就是集成的,它不能夠進行編程控制。當圖形硬件具有了可編程能力之后,我們就可以在這個階段使用【頂點着色器】進行編寫運算邏輯,用於取代過去直接集成在硬件當中的運算。在這個階段完成之后,會到【光柵化以及插值】階段。

  光柵化就是把計算機顯卡當中運算的數據進行一個細分,用於去適配屏幕上具體的每一個像素的顯示,但是光柵化並不等同於像素顯示,像素顯示最終反映的是顏色,而光柵化過后得到的結果是【幀緩存】,在這個過程當中,我們可以插入【片段着色器】,這個部分就可以使用可編程化運算。所以【片段着色器】的目標是為屏幕上最終要顯示的每一個像素去計算它最后需要什么樣的顏色。

  對於Unity來說,以上過程可以通過下圖來解釋。

  最上面【Geometry】是幾何模型,幾何模型進入【Unity】,可以理解為把幾何模型Mesh、網格等數據交給Unity,Unity導入后就通過Unity引擎去調用【Grphics APU】圖形API,調用圖形API的過程就是在驅動GPU進行處理運算。

  進入GPU運算首先進行的是【Vertex Processor】頂點處理器,這個部分就需要我們使用【Vertex Shader】頂點着色器,頂點着色器運算的結果會交給【Pixel Processor】像素處理器,也就是片段處理器,在這個部分我需要為像素處理編寫【Pixel Shader】像素着色器程序,這部分計算完后就輸出了最終我們可以用於在屏幕上的顏色信息,我們把它叫做【Frame Buffer】幀緩沖。幀緩沖存儲的是計算機依次顯示所要的數據,但也不僅僅是這些數據,它還有其他的附加信息,比如深度值等。

  下面是Unity官方手冊中的一張渲染管線圖示

  渲染管道線中最左邊的這個部分中Transform指的是模型的空間變換,主要針對的是頂點的空間幾何變換;TexGen即Texture Generator,表示的是紋理坐標的生成,主要用於在頂點當中去取得紋理坐標,再轉換為UV取值的范圍;Lighting指的是光照。因此這個部分就是過去就是T&L幾何變換光照流水線,當圖形硬件具有了可編程能力后,這個固定的模塊就被【Vertex Shader】頂點着色器代替了。

  在頂點着色器處理過后,Unity就進入【Culling & Depth Test】裁剪和深度測試過程。裁剪和深度測試描述的是如果一個物體在攝像機前展示,它向着攝像機的面會被觀察到,它背對着攝像機的面不會被觀察到,在這樣的情況下,為了減少GPU處理數據量就進行了一個裁剪(Culling),把看不見的面直接剔除,不需要去處理的這些面所涉及的頂點數據,從而加速圖形處理。第二個方面深度測試(Depth Test),指的是攝像機有一個特性,在計算機當中沒有無限這個概念,計算機處理的數據都是離散化的,它有一個范圍,當超過最近和最遠這個范圍的這部分會被剔除。

  接下來就進入到紋理采樣(Texturing)和霧化處理(Fog)階段。在這階段實際上就是在進行光柵化處理,描述的就是如何在屏幕上顯示每一個像素的顏色。這里需要去紋理采樣,一張貼圖有很多數據,我們去采集紋理上某一點的顏色值,這個就叫做紋理采樣。霧化就是根據最后計算的數據后需不需要進行一個霧化處理,近處的很清晰,遠處的有種朦朧感,這個部分就是片段着色器可編程的能力范圍。

  之后還需要【Alpha Test】,指的是去繪制那些半透明的或全透明的物體。經過【Alpha Test】之后還需要進行【Blending】處理,這階段會混合最終的圖像。

  以上介紹的是渲染管線的流程,要把握的主要的過程就是我們可編程能力是兩個部分,一個就是幾何變換和光照使用的頂點着色器部分,另一個就是關於如何去采樣,去計算顏色以及霧化處理等使用的片段着色器部分。

  這里需要注意的是Unity優化當中有一個主要部分就是減少Draw Call的調用,Draw Call就指的是應用程序去調用圖形硬件GPU去進行渲染的調度過程。應用程序需要准備很多的數據,包括頂點數據、矩陣、向量等數據,都需要通過應用程序傳遞給GPU,這樣個調度過程CPU必須要去收集數據以后才產生一個API的調用,這個過程的消耗是高昂的,如果反復地啟動這個調用,那么就僅僅收集和傳遞參數這樣的過程相當耗時耗力,就會造成了應用程序或游戲運行的瓶頸。因此要盡量減少Draw Call,盡量減少CPU對GPU這樣的調用。

 

Shader和材質、貼圖的關系

  Shader(着色器)實際上就是一小段程序,它負責將輸入的頂點數據以指定的方式和輸入的貼圖或者顏色等組合起來,然后輸出。繪圖單元可以依據這個輸出來將圖像繪制到屏幕上。輸入的貼圖或者顏色等,加上對應的Shader,以及對Shader的特定的參數設置,將這些內容(Shader及輸入參數)打包存儲在一起,得到的就是一個Material(材質),之后,我們便可以將材質賦予三維物體來進行渲染(輸出)了。

  材質好比引擎最終使用的商品,Shader好比是生產這種商品的加工方法,而貼圖就是原材料。

 

總結

  Shader是圖形可編程方案的程序片段。主要分為頂點着色器和片段着色器。

  渲染管線是一種計算機從數據到最終圖形成像的形象描述。

  材質可以理解為商品,Shader是加工這種商品的方法,而貼圖是加工過程中需要的材料。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM