原文写得很好,但是主题格式我不太喜欢,所以我对文章的格式进行了修整,方便自己日后阅读
前言
在前面的章节中我们有讨论过每个 Shader 中都可以有多个 SubShader ,并且在渲染时会找到第一个合适的并执行。那么除了在 SubShader 中定义的 Pass 不同以外,我们还能如何定义 SubShader 呢,我们知道在 SubShader 和 Pass 中都有 Tags 可选参数组,Tags 的作用是告诉引擎如何去渲染我们的对象,语法格式如下:
Tags { "TagName1" = "Value1" "TagName2" = "Value2" }
通过 Tags{} 来表示我们添加了一系列的 参数标识,大括号内可以添加多组 Tag(所以才叫 Tags 嘛),名称(TagName)和值(Value)是成对成对出现的,并且全部用字符串表示。
SubShader Tags
SubShader 中的 Tags 必须放置于 SubShader 中的 Tags 内,具体参数有以下这些:
Queue
渲染队列,指定对象什么时候渲染,每个队列其实都是利用一个整数进行索引的。
有以下取值:
1. Background
值为 1000,此队列的对象最先进行渲染。
2. Geometry
Queue 的默认值,值为 2000,通常用于 不透明对象,比如场景中的物件与角色等。
3. AlphaTest
值为 2450,要么 完全透明 要么 完全不透明,多用于利用贴图来实现边缘透明的效果,也就是美术常说的透贴。
4. Transparent
值为 3000,常用于 半透明对象,渲染时 从后往前 进行渲染,建议需要混合的对象放入此队列。
5. Overlay
值为 4000,此渲染队列用于 叠加 效果。最后渲染的东西应该放在这里(例如镜头光晕等)。
写法示例:
Tags{ "Queue" = "Geometry" }
那是不是只有以上这些固定化的渲染队列了呢?
当然不是,我们还有一种方式可以 自定义渲染队列:
Tags{ "Queue" = "Geometry+1" }
如上所示,可以通过在值后加数字的形式来进行重新指定渲染队列。
渲染队列直接影响性能中的重复绘制,合理的队列可极大的提升渲染效率。在 Unity 中,渲染队列小于 2500 的对象都被认为是 不透明的物体,(如
Background,Geometry,AlphaTest),这些物体是 从前往后 绘制的,而使用其他的队列(如Transparent,Overlay)的物体则是 从后往前 绘制的。这意味着,我们需要尽可能地把物体的队列设置为不透明物体的渲染队列,而尽量避免重复绘制。
RenderType
自带的值有以下这些:
- Opaque
- Transparent
- TransparentCutout
- Background
- Overlay
- TreeOpaque
- TreeTransparentCutout
- TreeBillboard
- Grass
- GrassBillboard
这些名称实际上只是一种内部的约定,用来区别这个 Shader 要渲染的对象是属于什么类别的,你可以想像成是我们把各种不同的物体进行分类一样。当然你也 可以改成自定义的名称,这样并不会影响到 Shader 的效果。
那既然没有什么效果影响,那 RenderType 又有什么作用呢?
它的作用是可以利用 Camera.SetReplacementShader 来更改最终的渲染效果。先说下这条语句的语法:
camera.SetReplacementShader (EffectShader, Tag);
这是 Unity 的脚本 API,需要在 C# 脚本中进行调用。
其中EffectShader是我们需要渲染的 Shader,Tag是用来筛选渲染对象用的。
具体按以下规则执行:
- 使用
SetReplacementShader("shaderA",""),这里Tag为空,表示全部物体 Shader 都替换成shaderA进行渲染。 SetReplacementShader("shaderA","RenderType"),由于这里Tag为RenderType, 所以先查看场景中的 shader 中 是否有RenderType参数,如果有,再看RenderType中的值 是否与shaderA中的RenderType值相等,相等则使用shaderA渲染,否则就不渲染(Game 视图什么也没有)。- 关于
Tag参数并不局限于RenderType,我们同样可以使用SetReplacementShader("shaderA","IgnoreProjector")或是其他任何参数如:SetReplacementShader("shaderA","ABC")等。
用法示例
我们建个脚本,添加如下代码,实现 替换材质开关 功能。
其中 taecg/Overdraw(此 Shader 实现的是类似于 Overdraw 的效果)这个 Shader 中的 Tag 如下:
而我们的物体(这头狼),我们给它 的Shader 中 Tag 如下:
然后,我们同时在场景中添加几个其它的默认几何体(它们都是默认的 StandardShader)。
结果如下:
首先在场景中查找所有的对象,筛选出有 RenderType 标签的对象,此时三个物体都有,然后进一步和 taecg/Overdraw 这个 Shader 进行对比,发现只有狼的值与此相同,所以只渲染狼,并且是以taecg/Overdraw 这个 Shader 来进行渲染。
DisableBatching tag
有的时候,我们会利用 Shader 在模型的顶点本地坐标下做一些位移动画,当此模型有 批处理 时会出现效果不正确的情况,这是因为批处理会将所有几何转换为 世界坐标空间,因此 “本地坐标空间” 将丢失。
"DisableBatching" = "True"
这时我们就可以利用此 Tag 在 Shader 中指定是否受批处理影响,有以下 3 个值可选:
-
False(默认值), 不禁用批处理
-
True,始终禁用此着色器的批处理
-
LODFading,仅当 LOD 激活时禁用批处理
ForceNoShadowCasting tag
是否强制关闭投射阴影,值可为:
- True,强制关闭投射阴影
- False(默认值),不关闭投射阴影
"ForceNoShadowCasting" = "True"
IgnoreProjector tag
是否忽略 Projector 投影器的影响,Projector 是 Unity 中内置的组件,可用于实现 贴花 等功能。
-
True,使对象不受 Projector 影响
-
False(默认值),使对象受 Projector 影响
CanUseSpriteAtlas tag
是否可用于精灵打包图集,意思就是如果某个图片精灵被设置为打包进图集中,那么当此精灵所指定 Shader 中设置为
"CanUseSpriteAtlas" = "False"
时就会使其 无法工作,相应的 UI 上也会有警告提示。
PreviewType tag
此 Tag 决定了材质面板的 预览窗口如何显示模型,默认显示的是球体,当我们把值定义为以下两种情况时会进行相应的变化。此功能仅仅影响的只是材质面板的预览,对 Shader 本身没有什么影响。
- Plane 平面预览
- Skybox 天空盒预览