整理自這兩篇博文
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"
}
...
}
}