UnityShader RenderType&Queue 渲染順序

整理自這兩篇博文

https://blog.csdn.net/u013477973/article/details/80607989?depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1&utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1

https://www.jianshu.com/p/0341f0ab9020

RenderType

在Unity Shader中會經常在SubShader中使用Tags,其中就會涉及RenderType和Queue,如:

SubShader{
    Tags{"RenderType"="Opaque"  "Queue"="Geometry"}
    ...
}     
RenderType
RenderType通常使用的值包括:

Opaque: 用於大多數着色器(法線着色器、自發光着色器、反射着色器以及地形的着色器)。
Transparent:用於半透明着色器(透明着色器、粒子着色器、字體着色器、地形額外通道的着色器)。
TransparentCutout: 蒙皮透明着色器(Transparent Cutout,兩個通道的植被着色器)。
Background: Skybox shaders. 天空盒着色器。
Overlay: GUITexture, Halo, Flare shaders. 光暈着色器、閃光着色器。
TreeOpaque: terrain engine tree bark. 地形引擎中的樹皮。
TreeTransparentCutout: terrain engine tree leaves. 地形引擎中的樹葉。
TreeBillboard: terrain engine billboarded trees. 地形引擎中的廣告牌樹。
Grass: terrain engine grass. 地形引擎中的草。
GrassBillboard: terrain engine billboarded grass. 地形引擎何中的廣告牌草。
這些RenderType的類型名稱實際上是一種約定,用來區別這個Shader要渲染的對象,當然你也可以改成自定義的名稱,只不過需要自己區別場景中不同渲染對象使用的Shader的RenderType的類型名稱不同,也就是說RenderType類型名稱使用自定義的名稱並不會對該Shader的使用和着色效果產生影響。

指定RenderType的名稱,主要是爲了配合使用替代渲染的方法:

Camera.SetReplacementShader("shader","RenderType")  
在使用替代渲染方法時,相機會使用指定的 shader 來代替場景中的其他 shader 對場景進行渲染。比如現在有 shader1:

Shader "shader1"{
    Properties{...}
    SubShader{
    Tags{"RenderType"="Opaque"}
    Pass{...}   
    }
    SubShader{
    Tags{"RenderType"="Transparent"}
    Pass{...}   
    }
}
場景中一部分物體當前使用的是 shader2:

Shader "shader2"{
    Properties{...}
    SubShader{
    Tags{"RenderType"="Opaque"}
    Pass{...}   
    }
}
另一部分使用的是 shader3:

Shader "shader3"{
    Properties{...}
    SubShader{
    Tags{"RenderType"="Transparent"}
    Pass{...}   
    }
}
調用替代渲染的方法:

Camera.SetReplacementShader("shader1","")   
這種情況下,場景中所有的物體就都使用shader1進行渲染(當Shader中包含多個SubShader,在渲染時顯卡根據性能從上到下選擇第一個能支持的shader) 
如果在調用時,第二個參數不爲空字符串,即:

Camera.SetReplacementShader("shader1","RenderType")   
這種情況下,首先在場景中找到標籤中包含該字符串(這裏爲"RenderType")的shader,再去看標籤中的該字符串的值與shader1中包含該字符串的值是否一致,一致的話,替換渲染,否則不渲染;由於shader2中包含"RenderType"="Opaque",而且shader1中的第一個SubShader中包含"RenderType"="Opaque",因此將shader1中的第一個SubShader替換場景中的所有shader2,同理,將shader1中的第二個SubShader替換場景中的所有的shader3。

如果shader1爲:

Shader "shader1"{
    Properties{...}
    SubShader{
    Tags{"RenderType"="Opaque" "A"="On"}
    Pass{...}   
    }
    SubShader{
    Tags{"RenderType"="Transparent"  "A"="Off"}
    Pass{...}   
    }
}   
shader2爲:

Shader "shader2"{
    Properties{...}
    SubShader{
    Tags{"RenderType"="Opaque" "A"="On"}
    Pass{...}   
    }
}  
shader3爲:

Shader "shader3"{
    Properties{...}
    SubShader{
    Tags{"RenderType"="Transparent" "A"="On"}
    Pass{...}   
    }
}      
替代渲染的調用方式爲:

Camera.SetReplacementShader("shader1","A")      
最後的結果是,shader1的第一個SubShader將會替換shader2和shader3

渲染順序和RenderQueue

Unity中的渲染順序自上而下大致分爲三層。 最高層爲Camera層,可以在Camera的depth那裏設置,設置之後,圖形的渲染順序就是先繪製depth低的相機下的物體,再繪製depth高的相機下的物體,也就是說,depth高的相機會覆蓋depth低的相機(具體的覆蓋關係有don't clear, solid color等等幾種)

比Camera層稍低一層的是sorting layer層,隨便找一個可以設置sorting layer的地方,選擇sorting layer,點添加按鈕,就可以看到當前所有的sorting layer,並且可以更改sorting layer的順序,排位靠後的sorting layer會覆蓋排位靠前的sorting layer。設置好sorting layer的相互關係之後,就可以給任何一個繼承於Renderer類,或者有renderer的子類作爲field的對象設置sorting layer了。注意這些sorting layer的遮擋關係是在同一個camera的層級下的。不同camera下的renderer渲染順序以camera的depth爲準。有的component的sorting layer可以直接在unity editor裏面設置,比如Sprite Renderer。有的則需要用代碼來設置,比如設置Particle system的sorting layer,就需要在代碼中取到 ParticleSystem.Renderer.SortingLayer 來進行設置。

比sorting layer再低一層的是sorting order,這個數字指代的是在同一個sorting layer下的渲染順序,用法很明顯就不贅述了。

需要注意不要混淆的是gameobject的layer,和renderer的sorting layer。 gameObject的layer個人理解是一個邏輯上的分層,用於camera的culling mask等。而renderer的sorting layer則用於渲染。只有繼承與renderer或者有renderer作爲filed的component才需要設置sorting layer。

另外需要指出的是,常用的NGUI的widget depth其本質也是一個sorting layer下的sorting order。 NGUI好像用的是一個叫做“UI"的sorting layer。由此大家如果有需要,也可以自己取Hack NGUI的代碼,把NGUI的sorting layer暴露出來供自己定製。

簡單總結一下,決定Unity渲染關係的層級順序是:
Camera
sorting layer
sortingorder

但是這些還不夠,因爲還沒有說到比較讓初學者頭疼的(筆者一開始就很頭疼)RenderQueue ,RenderQueue 其實就是shader中tags中的Queue

 

Tags { "Queue"="Geometry" }

默認情況下,Unity會基於對象距離攝像機的遠近來排序你的對象。因此,當一個對象離攝像機越近,它就會優先繪製在其他更遠的對象上面。對於大多數情況這是有效併合適的,但是在一些特殊情況下,你可能想要自己控制對象的繪製順序。而使用Tags{}塊我們就可以得到這樣的控制。

Unity提供給我們一些默認的渲染隊列,每一個對應一個唯一的值,來指導Unity繪製對象到屏幕上。這些內置的渲染隊列被稱爲Background, Geometry, AlphaTest, GeometryLast,Transparent, Overlay。這些隊列不是隨便創建的,它們是爲了讓我們更容易地編寫Shader並處理實時渲染的。

同時需在SubShader中顯示聲明ZWrite Off,通知Unity我們會重寫物體的渲染深度排序。

Properties Value 渲染隊列描述 說明
Background 1000 This render queue is rendered before any others. 這個隊列通常被最先渲染(比如 天空盒)。
Geometry 2000 Opaque geometry uses this queue. 這是默認的渲染隊列。它被用於絕大多數對象。不透明幾何體使用該隊列。
AlphaTest 2450 Alpha tested geometry uses this queue. 需要開啓透明度測試的物體。Unity5以後從Geometry隊列中拆出來,因爲在所有不透明物體渲染完之後再渲染會比較高效。
GeometryLast 2500 Last render queue that is considered “opaque”. 所有Geometry和AlphaTest隊列的物體渲染完後
Transparent 3000 This render queue is rendered after Geometry and AlphaTest, in back-to-front order. 所有Geometry和AlphaTest隊列的物體渲染完後,再按照從後往前的順序進行渲染,任何使用了透明度混合的物體都應該使用該隊列(例如玻璃和粒子效果)
Overlay 4000 This render queue is meant for overlay effects. 該隊列用於實現一些疊加效果,適合最後渲染的物體(如鏡頭光暈)。

好了,最後給出一個最終的總結:
依次按條件先後順序進行排序渲染處理。先按大項條件排序,後按小項條件排序

1.Camera Depth: 越小越優先
2.RenderQueue 2500以下
    1. Sorting Layer/Order in Layer
           1. 按照Sorting Layer/Order in Layer 設置的值,越小越優先
           2. 無此屬性,等同於 Sorting Layer=default ,Order in Layer=0 參與排序
     2.RenderQueue 越小越優先
     3.RenderQueue 相等,由近到遠排序優先
3.RenderQueue 2500以上
     1. Sorting Layer/Order in Layer
           1. 按照Sorting Layer/Order in Layer 設置的值,越小越優先
           2. 無此屬性,等同於 Sorting Layer=default ,Order in Layer=0 參與排序
     2.RenderQueue 越小越優先
     3.RenderQueue 相等,由遠到近排序優先

說明一下:2500是關鍵值,它是透明跟不透明的分界點,因此我們考慮層級的時候要注意着點:renderqueue > 2500的物體絕對會在renderqueue <= 2500的物體前面,即渲染時renderqueue大的會擋住renderqueue小的,不論它的sortingLayer和sortingOrder怎麼設置都是不起作用的。知道了這點,其他的就很好理解了。當兩個的RenderQueue都在同一側時,在SortingLayer高的絕對會在sortingLayer前面,無視renderqueue跟soringOrder,只有在sortingLayer相同的前提下,soringOrder高的會在sortingOrder低的前面,無視renderqueue。當sortingLayer跟sortingOrder相同時,纔看renderqueue的高低,高的在前面。

UGUI中的ui默認使用的是UI/Default 材質,對應的shader中的渲染隊列是Transparent

Shader "UI/Default"
{
    Properties
    {
       ...
    }

    SubShader
    {
        Tags
        {
            "Queue"="Transparent"
            "IgnoreProjector"="True"
            "RenderType"="Transparent"
            "PreviewType"="Plane"
            "CanUseSpriteAtlas"="True"
        }
        ...
    }
}

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章