一个UnityShader的基础结构如下所示:
Shader "ShaderName"{ Properties{ //属性 } SubShader{ //显卡A使用的子着色器 } SubShader{ //显卡B使用的子着色器 } Fallback "VertexLit" }
Unity在背后根据使用的平台来吧这些结构编译成真正的代码和Shader文件,开发者只需要和UnityShader打交道即可。(Unity编写Shader的语言是ShaderLab)
属性:在Shader中访问它们需要使用每个属性的名字,这些属性的名字通常由一个下划线开始,还需要为属性指定它的类型,还需要指定一个默认值,当第一次把该Shader赋给某个材质的时候,材质面板上显示的就是这些默认值。
属性类型:
标签类型 | 说明 | 例子 |
Queue | 控制渲染顺序,指定该物体属于哪一个渲染队列,通 过这种方式可以保证所有的透明物体可以在所有不透 明物体后面被渲染(详见第8章),我们也可以自定义 使用的渲染队列来控制物体的渲染顺序 |
Tags{"Queue"="Transparent" } |
RenderType | 对着色器进行分类,例如这是一个不透明的着色器, 或是一个透明的着色器等。这可以被用于着色器替换 (ShaderReplacement)功能 |
Tags{"RenderType"="Qpaque"} |
DisableBatching | 一些SubShader在使用Unity的批处理功能时会出现问 题,例如使用了模型空间下的坐标进行定点动画。这时可 以通过该标签来直接指明是否对改SubShader使用批处 理 |
Tags{"DisableBatching"="True"} |
ForceNoShadowCasting | 控制使用该SubShader的物体是否会投射阴影 | Tags{"ForceNoShadowCasting"="True"} |
IgnoreProjector | 如果该标签值为“True”,那么使用该SubShader的物 体将不会受Projectror的影响。通常用于半透明物体 |
Tags{"IgnoreProjector"="True"} |
CanUseSpriteAtlas | 当该SubShader是用于精灵(Sprite)时,将该标签设 为“False” |
Tags{"CanUseSpriteAtlas"="False"} |
PreviewType | 指明材质面板将如何预览该材质。默认情况下,材质 将显示为一个球型,我们可以通过把该标签的值设为 “Plane” "SkyBox" 来改变预览类型 |
Tags{"PreviewType"="Plane"} |
需要注意的是,上述的标签仅可以在SubShader中声明,而不可以在Pass块中声明。Pass块虽然也可以定义标签,但这些标签不同于SubShader的标签类型。这是我们下面要讲到的:
- Pass语义块
Pass语义块包含的语义定义如下:
Pass{ [Name] [Tags] [RenderSetup] //Other code }
首先可以在Pass中定义该Pass的名称,例如:
Name "MyPassName"
通过这个名称可以使用ShaderLab的UsePass命令来直接使用其他的UnityShader中的Pass。例如:
UsePass "MyShader/MYPASSNAME"
这样可以提高代码的复用性。需要注意的是由于Unity内部会把素有的Pass的名称转换成大写字母表示,因此在使用UsePass命令时必须使用大写形式的名字。
其次,我们可以对Pass设置渲染状态。SubShader的状态设置同样适用于Pass.除了上面提到的状态设置外,在Pass中我们还可以使用固定管线的着色器命令。
Pass同样可以设置标签,但它的标签不同于SubShader的标签,这些标签也是用于告诉渲染引擎我们希望怎么样来渲染该物体。下表给出了Pass中使用的标签类型。
标签类型 | 说明 | 例子 |
LightMode | 定义该Pass在Unity的渲染流水线中的角色 | Tags{"LightMode"="ForwardBase"} |
RequireOptions | 用于指定当满足某些条件时才渲染该Pass,它的值是一个 由空格分隔的字符串。目前,Unity支持的选项有: SoftVegetation.在后面的版本中可能会增加更多的选项 |
Tags{"RequireOptions"="SoftVegetation"} |
除了上面普通的Pass定义外,UnityShader还支持一些特殊的Pass,以便进行代码服用或实现更复杂的效果。
- UsePass : 如上文所说,可以使用该命令来服用其他UnityShader中的Pass;
- GrabPass : 该Pass负责抓取屏幕并将结果存储在一张纹理中,以用于后续的Pass处理;
最后留一条路: Fallback
紧跟在各个SubShader语义块后面的,可以是一个Fallback命令。他用于告诉Unity,"如果上面所有的SubShader在这块显卡上都不能运行,那么就使用这个最低级的Shader吧!"
它的语义如下:
Fallback "name" //或者 Falllback off
如上所述,我们可以通过一个字符串来告诉Unity这个“最低级的UnityShader”是谁。我们也可以任性的关闭Fallback功能,但一旦你这么做,你的意思大概就是:“如果一块显卡跑不了上面所有的Shader,那就不要管他了!”
下面给出一个使用Fallback的例子:
Fallback "VertexLit"
事实上,Fallback还会影响阴影的投射。在渲染阴影纹理时,Unity会在每个UnityShader中寻找一个阴影投射的Pass,通常情况下,我们不需要自己专门实现一个Pass, 这是因为Fallback使用 的内置Shader中包含了这样一个通用的Pass。因此,为每个UnityShaer正确的设置Fallback是非常重要的。
除了上述语义,还有一些不常用到的语义。例如,如果我们不满足于Unity内置的属性类型,想要自定义材质面板的编辑界面,就可以使用CustomEditor语义来扩展编辑界面。我们还可以使用Category语义来对UnityShader中的命令进行分组。