1. 程式人生 > >Unity ShaderLab開發實戰(二)渲染路徑

Unity ShaderLab開發實戰(二)渲染路徑

       渲染路徑決定了光照如何應用在Shader中,需要為每個Pass指定要使用的渲染路徑,這樣光照計算才可以被正確進行。Unity--Edit--Project Setting--Player--Other Setting--Rendering Path裡可以設定,也可以在相機的渲染路徑設定中覆蓋Project Setting中的設定。三種(前向渲染路徑(Forward Rendering Path),延遲渲染路徑(Deferred Rendering Path,5.X版本後有兩種),頂點照明渲染路徑(Vertex Lit Rendering Path))。eg:

        Pass

        {

             Tags { "LightMode" = "ForwardBase" }

       }

       LightMode標籤支援的渲染路徑設定選項:

       為一個Pass設定了前向渲染路徑的標籤,會告訴Unity把光照屬性按前向渲染的流程準備好,然後可以通過提供的內建光照變數訪問這些屬性。如果沒設定,那麼取到的光照變數可能有問題。

一、前向渲染路徑:

        原理:每進行一次完整的前向渲染,會渲染該物件的渲染圖元,並計算顏色緩衝區和深度緩衝區的資訊。深度緩衝決定片元是否可見,如果可見則更新顏色緩衝區的顏色值。如果一個物體在多個逐畫素光源的影響區域內,則該物體需要執行多個Pass。每個Pass計算一個逐畫素光源的光照結果,幀緩衝中將這些結果混合成最終的顏色。如果N個物品M個光源則有N*M個Pass。

       Unity中前向渲染路徑有三種處理光照的方式:逐頂點,逐畫素,球諧函式(SH)處理。決定光源使用哪種處理模式的是這個Light的型別和渲染模式(Important)設定。具體:

       1、場景中最亮的平行光逐畫素處理。

       2、RenderMode為Not Important的逐頂點或者SH處理。

       3、RenderMode設定為Important表示逐畫素光源。

       4、如果上面得到最終的逐畫素光源數量小於Quality Setting中的逐畫素光源數量,則會有更多的光源以逐畫素的方式渲染。

       前向渲染有兩種Pass:Base Pass和Additional Pass。兩種Pass如下,摘自《Unity Shader入門精要》

      Blend One One:Additional Pass開啟和設定了混合模式,因為希望與上次的光照結果在幀快取中疊加,而不是覆蓋。

      一個Shader通常一個Base Pass和一個Additional Pass, 一個Bass Pass通常只會執行一次,Additional Pass有可能多次呼叫。除了第一個Pixel平行光之外,每個其他Pixel光源都會在—個單獨的Additional Pass內被執行,也就是說場景中的Pixel光源數為n,則Additional Pass會被執行n-1次,是上個結果的疊加。

       可以使用UnityCGcginc中的shade4PointLights函式在ForwardBase中計算Vertex光源的照明。對於Pixel光源,必須使用
_WorldspaceLightPos0和_LightColor0來計算。

       前向渲染可以使用的內建光照變數:

       前向渲染可以使用的內建光照函式:

二、頂點照明渲染路徑(前向渲染路徑的一個子集,Unity5中已經基本不用了)

三、延遲渲染路徑

       很明顯,前向渲染有效率問題,多個Pass時有很多重複計算。

        延遲渲染有兩個Pass,用了額外的緩衝區:G緩衝,儲存了表面的一些資訊(法線,位置,材質屬性等)。第一個Pass不進行任何光照計算,只計算哪些片元可見,可見的話就把它的相關資訊放在G緩衝區中。第二個Pass,利用G緩衝區的片元資訊進行真正的光照計算。效率不依賴於光源和場景複雜度,依賴於螢幕空間大小。所以,延遲渲染適合場景中光源多時,但是不能處理半透明物體,對顯示卡也有要求。

     Unity中有兩種延遲渲染,一種是5之前的,一種是新的。

 

實戰:

        1.當shader中存在多個不同渲染路徑的pass時,怎麼辦?

        Unity在Defend渲染路徑下,會找在Defend渲染模式下的Pass,不會執行其他的Pass,如果沒找到,再找Forward模式的Pass,返回,如果沒找,再找VertexLit模式下的Pass;在Forward渲染模式下,先找Forward模式的Pass,返回,如果沒找,再找VertexLit模式下的Pass。所以只會執行一個渲染路徑下的Pass,不會同時執行多個不同渲染路徑下的Pass。

         2.Always Pass是按照在程式碼中的位置先後執行的。