Subshaders使用标签来告诉引擎如何以及何时将其渲染。
语法:
Tags { "TagName1" = "Value1" "TagName2" = "Value2" }
指定TagName1具有Value1的值,TagName2具有Value2的值。标签的数目不受限制。
标签基本上是键值对(key-value pairs)。 在SubShader内部,标签用于确定渲染顺序和子渲染器的其他参数。 请注意,Unity识别的以下标记必须在SubShader节内,而不是Pass!
除了由Unity识别的内置标签,你也可以使用自己的标签,并使用Material.GetTag函数查询它们。
你可以使用队列标签来确定对象的绘制顺序。 Shader决定其对象属于哪个渲染队列,这样所有透明的Shader能保证在所有不透明的Shader后渲染。
有四个预定义的渲染队列,但是在预定义的渲染队列之间可以有更多的队列。
预定义队列为:
Background
:最先被调用的渲染,通常用来渲染背景。
Geometry (default)
:默认值,大多数物体使用此队列,用来渲染不透明的物体。
AlphaTest
:alpha tested的物体使用此队列。 它是与几何一个独立的队列,因为在绘制所有实体后,渲染经过alpha-tested的对象更有效率。
Transparent
:这个渲染队列是在Geometry和AlphaTest之后,以从后往前的顺序渲染的。 任何alpha混合(alpha-blended )(即不写入深度缓冲区depth buffer的Shader)应该在这里。例如玻璃,粒子效果。
Overlay
: 此渲染队列用于叠加效果。 任何最后呈现的东西都应该在这里(例如镜头光晕)。
对于特殊用途,可以使用中间队列。在内部,每个队列由整数索引表示:
Background=1000,Geometry=2000,AlphaTest=2450,Transparent=3000和Overlay=4000.
如果着色器使用这样的队列:
Tags { "Queue" = "Geometry+1" }
这将使对象在所有不透明物体后,但在透明物体之前渲染,作为渲染队列索引将是2001(Geometry+1)。 这在你希望某些物体始终在其他物体集之间绘制的情况下非常有用。 例如,在大多数情况下,透明的水应该在不透明物体之后但在透明物体之前绘制。
队列的值到2500(“Geometry+ 500”)被认为“不透明”,优化对象的绘制顺序以获得最佳性能。 对于“透明物体”考虑较高的渲染队列,并按距离对物体进行排序,从最远的一个开始渲染,并以最近的一个结束。 天空盒在所有不透明和所有透明对象之间绘制。
RenderType
标签将shaders分类为多个预定义组,Unity可以运行时替换符合特定RenderType的所有Shader。
一些渲染特效需要使用一些不同的shaders来渲染场景。比如,一个好的边界提取效果需要由一个记录场景法线信息的纹理才能检测出场景中的朝向变化的地方;其他效果也可能需要一个记录场景深度的纹理等等。要想达到这些效果,我们可能需要使用所有物体的替代Shaders来渲染场景。
Shader更换是从脚本使用 Camera.RenderWithShader 或 Camera.SetReplacementShader 函数来完成的。这两个函数均以一个shader和一个replacementTag作为参数。
工作流程:相机还是像平常一样来渲染场景,物体也还是使用原有的材质,但是他们的真实的shader是在使用时来进行改变:
所以,如果所有shaders都拥有一个渲染类型标签,比如 “Opaque”, “Transparent”, “Background”, “Overlay”,你就可以编写一个含有”RenderType = Solid”的替换着色器来只渲染固体物体。其他标记并不会在该替换着色器中被找到,所以与其对应的物体将不会被渲染。或者,你可以编写拥有不同的”RenderType”标签值的子着色器。所有Unity内置着色器都含有一个”RenderType”标签集。
在Unity内置着色器的shader替换标签
代码示例
在Start()函数中指定替换shaders
void Start() {
camera.SetReplacementShader (EffectShader, "RenderType");
}
这要求EffectShader使用RenderType键。 EffectShader会为每个你想要的RenderType设置键值key-value标签。 Shader中的相应代码:
Shader "EffectShader" {
SubShader {
Tags { "RenderType"="Opaque" }
Pass {
...
}
}
SubShader {
Tags { "RenderType"="SomethingElse" }
Pass {
...
}
}
...
}
SetReplacementShader将查看场景中的所有对象,而不是使用它们的普通shader,使用具有指定键的匹配值的第一个subshader。 在此示例中,其shader具有Rendertype =“Opaque”标记的任何对象将被EffectShader中的第一个SubShader替换,任何具有RenderType =“SomethingElse”shader的对象将使用第二个替换SubShader,因此一个。 任何其shader在替换shader中不具有指定键的匹配标签值的对象将不会被渲染。
相关参考:
Unity官方文档:Rendering with Replaced Shaders
Unity圣典:使用替换着色器来渲染
当使用绘制调用批处理 Draw Call Batching 时,一些e shaders(主要是做对象空间顶点变形的shader)不工作 - 这是因为批处理将所有几何转换为世界空间,因此“对象空间”丢失。
DisableBatching
标签可以用来消除这个问题。 有三个可能的值:
“True”(始终禁用此着色器的批处理)
“False”(不禁用批处理;这是默认值)
“LODFading”(当LOD衰减活动时禁用批处理;主要用于树)。
如果给出了ForceNoShadowCasting
标签并且值为“True”,则使用此subshader渲染的对象将永远不会投射阴影。 当你在透明对象上使用shader替换,并且你不会继承来自另一个subshader的阴影传递时,这是最有用的。
如果给定IgnoreProjector
标记并且值为“True”,则使用此shader的对象不会受到投影机的影响。 这对半透明对象最有用,因为暂时没有对他们产生投影的比较合适的办法,那么直接忽略掉就行了。。
如果shader用于sprite,则将CanUseSpriteAtla
s标记设置为“False”,并且当它们打包到地图集时不会工作(请参阅Sprite Packer)。
PreviewType
指示material inspector预览应如何显示材质。 默认情况下,材质显示为球体,但PreviewType也可以设置为“Plane”(显示为2D)或“Skybox”(将显示为天空盒)。
整篇博客参考Unity官方文档:https://docs.unity3d.com/Manual/SL-SubShaderTags.html