什么是UnityShader

​ Unity Shader实际上指的就是一个ShaderLab文件。以.shader作为后缀的一种文件。在Unity shader里面,我们可以做的事情远多于一个传统意义上的Shader。

​ 在传统的shader中,我们仅可以编写特定类型的Shader,例如顶点着色器,片元着色器等。在Unity Shader中,我们可以在同一个文件里面同时包含需要的顶点着色器和片元着色器代码。

​ 在传统shader中,我们无法设置一些渲染设置,例如是否开启混合,深度测试等,这些是开发者在另外的代码中自行设置的。而Unity shader中,我们通过一行特定的指令就可以完成这些设置。

​ 在传统shader中,我们需要编写冗长的代码设置着色器的输入和输出,要小心的处理这些输入输出的位置对应关系等。而在Unity shader中,我们只需要在特定语句块中声明一些属性,就可以依靠材质来方便的改变这些属性。而对于模型自带的数据(如顶点,纹理坐标,法线等),Unity Shader也提供了直接访问的方法,不需要开发者自行编码来传给着色器。

UnityShader语法

语句结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
Shader "Unlit/Shader文件名字"
{
Properties
{
//写在此处的所有变量都会显示在unity里显示出来
_MainTex(变量一般都在前面加个_)("外部显示名称", 类型) = "默认值"()
}
//若同时写了多个SubShader,在加载Shader是会选择第一个能在目标平台运行的Shader块,若都不可以运行,则会使用默认的Fallback的Shader。
SubShader
{
//标签,可选
Tags
{
//所有类型都以 key = value 的形式出现
//Tags可以在每个Pass通道里定义,若有全局的Tags则使用全局的,没有使用自己的
}
//可选,渲染设置,也可以定义在Pass通道里,例如:
Cull off(正反两面都渲染)/back(切掉后只渲染正面)/front(切掉后之渲染后面) //裁剪,选择渲染哪个面,默认渲染正面
ZText Always/Less Greater/LEqual/GEqual/Equeal/NotEqual //深度测试,默认小于等于
Zwrite off/on //深度写入
Blend SrcFator DstFactor //混合
LOD 100 //不同情况下使用不同的LOD,达到性能提升
}

//必须写
//同时可以拥有多个pass通道,一般不建议使用多个pass通道,会影响性能
Pass
{
Name "名称" //pass通道的名称,可以在别的pass中直接use + 名称(必须全大写)来直接使用该Pass通道里的内容,不需要重复写。
Tags
{
//以下部分定义只能再pass中写
"LightMode"="ForwardBase" //定义该Pass通道再unity渲染流水中的角色。
"RequireOptions"="SoftVegetation" //只有满足此处设定的值时,才渲染该Pass通道,可定以多个Value,使用空格隔开。
}

//CG语言所写的代码,只要是顶点片元着 色器
CGPROGRAM //以此开始

ENDCG //以此结束
}

Fallback "Legacy Shaders/Transparent/VertexLit" Fallback off //当上面的Shader运行不了的使用下面的Shader渲染
}

Fallback函数非常重要。

属性快内的定义

1
2
3
4
5
6
7
8
9
定义在Properties中
_Int("Int",Int) = 1 整型
_Float("Float",Float) = 1.5 浮点型
_Range("Ranger",range(0,0,2,0)) = 1.0 范围值类型
_Color("Color",Color) = (0,0,0,0) 颜色
_Vector("Vector",Vector) = (1,4,3,8) 用在矩阵,在有多个Int时
_Cube("Cube",Cube) = "white"{} 天空盒,用于代替直接创建天空盒
_3D("3D",3D) = "black"{} 3D类型,不常用
_MainTex(变量一般都在前面加个_)("名字", 类型) = "默认值"() 2D图片类型

Tags标签内定义

1
2
3
4
5
6
7
"Queue"="Transparent"//渲染顺序(透明值的渲染顺序)
"RenderType"="Opaque"//着色器替换功能
"DisableBatching"="True(False)"//是否进行合批
"ForceNoShadowCasting" = "True(False)"//是否投射阴影
"IgnoreProject"="True(False)"//受不受Projector的影响
"CanUseSpriteAltas"="False(true)"//是否用于图片的Shader,通常用于UI
"PreviewType"="plane"//用作Shader面板的类型

SufaceShader

​ 与Unlit Shader结构相似,只是在SubShader中没有Pass通道,而是直接写CGPROGRAM ENDCG语块。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Shader "Unlit/Shader文件名字"
{
Properties
{
与Unlit Shader相似
}
SubShader
{
Tags {}
LOD 200

#pragma

#pragma

CGPROGRAM

void surf(参数){
surface语句块,输入输出
}

ENDCG
}
}

全局操作

​ 当使用脚本去控制Shader中的某些值时,该值不可以在Properties中定义。例如,在写积雪效果时,想用脚本去控制积雪的大小,此时若Properties定义的有积雪强度的值,则在脚本中的控制并不会生效。