Unity Shader 基础
Chapter3 Unity Shader 基础
概述
在Unity需要材质(Material)与Unity Shader配合使用来达到满意的效果。
- Unity Shader定义了渲染需要的各种代码(顶点着色器与片元着色器等),属性(使用哪些纹理)和指令(渲染和标签设置),我们通过材质调节这些属性,再赋给相应的模型。
- 材质:配合GameObject的Mesh或者Particle Systems组件来工作。
- Unity Shader:
- Standard Surface Shader:使用了一个包含了标准光照模型的表面着色器模板
- Unlit Shader: 一个不包含光照但是包含雾效的基本顶点/片元着色器
- Image Effect Shader: 为实现屏幕后处理提供基本模板
- Compute Shader: 借助GPU的并行性来进行一些与渲染流水线无关的计算
ShaderLab
一款专门为Unity Shader服务的语言。
Properties 属性
- 语句格式:
Name("display name",PropertyType)=DefaultValue
- 支持的属性类型:
|属性类型|定义语法|
|:——–:|:——–:|
|Int|number|
|Float|number|
|Range(min,max)|number|
|Color|(number,number,number,number)|
|Vector|(number,number,number,number)|
|2D|”defaulttexture”{}|
|Cube|”defaulttexture”{}|
|3D|”defaulttexture”{}|
Unity允许重载默认的材质编辑面板以提供更多的自定义数据类型。 关键词“Custom Shader GUI”
Properties语义块的作用仅仅是为了让这些属性可以出现在材质面板里。
SubShader:表面着色器
语句格式
1
2
3
4
5
6
7
8
9
10
11
12SubShader{
//可选的,标签
[Tags]
//可选的,状态
[RenderSetup]
//一次完整的渲染流程,如果pass的数目过多,会造成渲染性能的下降。
Pass{
}
...
}RenderSetup 状态:关于渲染状态的设置指令
| 状态名称 | 设置指令 |解释|
|:——–:|:——–:|:—-:|
| Cull |Cull Back/Front/Off| 剔除模式:剔除背面/正面/关闭剔除|
|ZTest|ZTest Less Greater/LEqual/GEqual/Equal/NotEqual/Always|设置深度剔除时使用的函数|
|ZWrite|ZWrite On/Off|关闭/开启深度写入|
|Blend|Blend SrcFactor DstFactor|开启并设置混合模式|Tags 标签:希望怎样以及何时渲染这个对象
Tags{"TagName1"="Value1" "TagName2"="Value2"}
| 标签类型 | 说明 |
|——–|——–|
| Queue | 控制渲染顺序,指定该物体属于哪一个渲染队列 |
|RenderType|对着色器进行分类,可以用于着色器替换功能|
|DisableBatching|指明是否对该SubShader使用批处理|
|ForceNoShadowCasting|控制使用该SubShader的物体是否会投射阴影|
|IgnoreProjector|控制使用该SubShader的物体是否受projector(投影仪?)的影响|
|CanUseSpriteAtlas|当该SubShader是用于sprite时,将该标签设为“false”|
|PreviewType|指明材质面板将如何预览该材质。默认材质下,材质将显示为一个球形,我们可以通过将该标签的值设为“Plane”“SkyBox”来改变预览类型|
上述标签可以在SubShader中声明,而不可以在Pass块中声明,Pass块有专属于自己的标签。Pass语义块:
1
2
3
4
5
6Pass{
[Name]
[Tag]
[RenderSetup]
// Other code
}- Name “MyPassName”:定义该Pass的名称,可以使用UsePass命令来直接使用其他unity shader中的Pass,例如:
UsePass "MyShader/MYPASSNAME"
,由于Unity 内部会将所有Pass 名称转换为大写字母的表示,所以在使用UsePass的时候必须使用大写形式的名字。 - RenderSetup:我们可以对Pass设置渲染状态,除上述状态设置以外,我们还可以使用固定管线的着色器。
Tag:
|标签类型|说明|例子|
|—|—-|—|
|LightMode|定义该Pass在Unity渲染流水线中的角色|Tags{“LightMode”=”ForwardBase”}|
|RequireOptions|用于制定当满足某些条件的时候才渲染该Pass,它的值是一个由空格分割的字符串,目前支持的选项:SoftVegetation|Tags{“RequireOptions”=”SoftVegetation”}|特殊的Pass:
UsePass:使用该指令复用其他UnityShader中的Pass。
GrabPass:负责抓取屏幕并将结果存储在一张纹理之中,以用于后续的Pass 处理。
- Name “MyPassName”:定义该Pass的名称,可以使用UsePass命令来直接使用其他unity shader中的Pass,例如:
FallBack
如果上面所有的SubShader在这块显卡上都不能运行,那么就用这个最低级的Shader。
1 | FallBack "name" |
通过一个字符串通知引擎最低级的Shader是哪个,也可以关闭Fallback功能——如果上述的SubShader无法使用,那就不要管它了。
其他语义
- 拓展编辑界面:CustomEditor
- 对命令进行分组:CateGory
UnityShader的形式
ShaderLab语句块:1
2
3
4
5
6
7
8
9
10
11
12
13
14Shader "Myshader"{
Properties{
// 所需的各种属性
}
SubShader{
// 真正意义上的SubShdaer代码会出现在这里
// 表面着色器(Surface Shader)
// 顶点/片元着色器(Vertex/Fragment Shader)
// 固定函数着色器(Fixed Function Shader)
}
SubShader{
// 与上一个Shader类似
}
}
表面着色器
当给Unity提供一个表面着色器的时候,它在背后依旧将其转换为对应的顶点/片元着色器。意义在于Unity为我们处理了很多光照细节,使得我们无需再操心这些事情。
1 | Shader "Custom/Simple Surface Shader"{ |
表面着色器被定义在SubShader语义块中的CGPROGRAM与ENDCG之间。之间的代码使用Cg/HLSL语言编写,它嵌套在ShaderLab语言中。
顶点/片元着色器
顶点/片元着色器的代码需要定义在CGPROGRAM与ENDCG之间,而着色器是写在Pass语义块内,而非SubShader内,这样做来定义每个Pass需要的Shader代码,灵活性更高,同时控制渲染的实现细节。
1 | Shader "Custom/Simple VertexFragment Shader"{ |
固定函数着色器
上面两种UnityShader形式都使用了可编程管线,而对于一些旧的设备不支持可编程管线着色器,此时需要使用固定函数着色器来完成渲染,这些着色器往往只可以完成一些非常简单的效果。
1 | Shader "Tutorial/Basic"{ |
乐乐女神的一些建议:
- 除非有明确的需求必须要使用固定函数着色器,否则请使用可编程管线的着色器。
- 如果想和各种光源打交道,你可能更喜欢表面着色器,但需要小心它在移动平台的性能表现。
- 如果需要使用的光照数目非常少,使用顶点/片元着色器是一个更好的选择。
- 如果有很多自定义的渲染效果,请选择顶点/片元着色器。