UnityShader入门精要-3.3 UnityShader的结构

时间:2022-06-01 14:07:50

一个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中的命令进行分组。