Unity ShaderLab语法基础

一、Shader的组织结构

无论选择何种语言编写Shader,无论编写的Shader是何种类型,Unity Shader总是通过ShaderLab语言进行包装并组织结构。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Shader "Name"
{
Properties
{
//开放到材质面板的属性
}
SubShader
{
//顶点-片段着色器
//或者表面着色器
//或者固定函数着色器
}
SubShader
{
//更加精简的版本
//或者表面着色器
//为了在旧的图形设备上运行
}
...
FallBack "Name"
}

·首先最开始定义的是Shader的名称,然后定义开放出来的所有属性

·Shader中可以编写多个子着色器(SubShader),但至少需要一个

·在程序执行过程中,GPU会按顺序检测第一个可以正常运行的着色器,如果都无法执行,则会执行最后的回退(Fallback)命令,运行指定的一个基础着色器

结构图

二、Shader的名称

Shader程序的第一行代码用来声明该Shader的名称以及所在路径。

名称就是指该Shader在选择使用的时候所显示的名称,而路径则是指Shader在材质面板上Shader下拉列表的保存路径。

例如:

1
Shader "Custom/Simple Shader"

![Simple Shader](Simple Shader.png)

三、Properties

Shader编写过程中会经常用到一些不同类型的变量或者贴图等资源,为了添加可调节性,有些变量不会直接写死在程序中,而是将这些变量开放为属性,可供后续修改。

Unity Shader的属性主要分为三大类:数值、颜色和向量、纹理贴图。

属性的定义语法如下:

1
_Name("Display Name",type)=ddefaultValue[{option}]

(1)_Name:属性的名字。

(2)Display Name:在材质面板中显示出来的名称。

(3)type:属性的类型。

(4)defaultValue:将Shader指定给材质的时候初始化的默认值。

1.数值类属性

1
2
name("display name",Float)=number
name("display name",Range(min,max))=numer

Float:任意数值的浮点型数据,在材质面板上作为数字输入框的显示。

Range:一个介于最大值和最小值之间的浮点型数据,在材质面板作为滑动条显示。

2.颜色和向量类属性

1
2
3
4
{
name("display name",Color)=(number,number,number,number)
name("display name",Vector)=(number1,number2,number3,number4)
}

Color:颜色类型的数据,有R、G、B、A四个分量定义,在材质面板上显示为取色器。

Vector:向量类型的属性,是一个四位数组,在材质面板上作显示为四个连续的数值输入框,分别为X、Y、Z、W。

3.纹理贴图类属性

1
2
3
4
5
{
name("display name",2D)="defaulttextrue"{}
name("display name",Cube)="defaulttextrue"{}
name("display name",3D)="defaulttextrue"{}
}

(1)2D属性是纹理属性中最常使用的,漫反射贴图、法线贴图等都属于2D类型。

(2)Cube是立方体纹理,由六个有联系的2D贴图拼成的立方体,主要用作反射,例如SkyBox和Reflection Prob。

(3)3D纹理只能被脚本创建。

4.所有类型属性汇总

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Shader "Custom/Simple Shader"
{
Properties
{
_MyFloat("Float Property",Float)=1 //浮点类型
_MyRange("Range Property",Range(0,1))=0.1 //范围类型
_MyColor("Color Property",Color)=(1,1,1,1) //颜色类型
_MyVector("Vector Property",Vector)=(0,0,0,0) //向量类型
_MyTex("Texture Property",2D)="white"{} //2D贴图类型
_MyCube("Cube Property",Cube)=""{} //立方体贴图类型
_My3D("3D Property",3D)=""{} //3D贴图类型
}
SubShader
{
Pass
{

}
}
Fallback "Diffuse"
}

所有类型属性

四、SubShader

SubShader的大致结构:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
SubShader
{
//标签
Tags{"TagName1"="Value1" "TagName2"="Value2" ...}

//渲染状态
Cull Back
...

Pass
{
//第一个Pass
}
Pass
{
//第二个Pass
}
}

每个SubShader都可以设置一个或者多个标签(Tags)和渲染状态(States),然后定义至少一个Pass。

在SubShader中设置的渲染状态会影响到该SubShader中所有的Pass,如果想要某些状态不影响其他Pass,可以针对某个Pass单独设置渲染状态。

1.SubShader的标签

标签语法:

Tags{"TagName1"="Value1" "TagName2"="Value2" ...}

1.1 渲染队列

在SubShader中可以使用Queue标签确定物体的渲染顺序,Unity预先定义了五中渲染队列。

队列名称 描述 队列号
Background 最先执行渲染,一般用来渲染天空盒Skybox或者背景 1000
Geometry 非透明的几何体通常使用这个队列,当没有声明渲染队列的时候,Unity会默认使用这个队列 2000
AlphaTest Alpha测试的几何体会使用这个队列,之所以从Geometry队列单独拆分出来,是因为当所有实体都绘制完之后在绘制Alpha测试会更高效 2450
Transparent 这个队列的几何体按由远及近的顺序进行绘制,所有进行Alpha混合的结合体都应该使用这个队列,例如玻璃材质、粒子特效等 3000
Overlay 用来叠加渲染的效果,如镜头光晕等,放在最后渲染 4000

自定义队列:

Tags{"Queue"="Geometry+1"}

渲染队列

1.2 渲染类型

RenderType(渲染类型)标签可以将Shader划分为不同的类型,用于后期进行Shader的替换或者产生摄像机的深度纹理。

类型名称 描述
Opaque 用于普通的Shader,例如:不透明、自发光、反射、地形Shader
Transparent 用于半透明Shader,例如:透明、粒子
TransparentCutout 用于透明测试的Shader,例如:植物叶子
Background 用于Skybox Shader
Overlay 用于GUI纹理、Halo、Flare Shader
TreeOpaque 用于地形系统中的树干
TreeTransparentCutout 用于地形系统中的树叶
TreeBillboard 用于地形系统中的Billboard树
Grass 用于地形系统中的草
GrassBillboard 用于地形系统中的Billboard草

1.3 禁用批处理

当使用批处理的时候,几何体会被变换到世界空间,模型空间会被丢弃。开启DisableBatching(禁用批处理)可以解决这个问题。

禁用批处理标签的三个数值:

(1)"DisableBatching"="True":总是禁用批处理。

(2)"DisableBatching"="False":不禁用批处理,这是默认数值。

(3)"DisableBatching"="LODFading":当LOD效果激活的时候才会禁用批处理,主要用于地形系统上的树。

1.4 禁止阴影投射

在游戏中,许多特效类物体不需要产生投影。

使用"ForceNoShadowCasting"(禁止阴影投射)标签来实现效果,将其值设置为True

1.5 忽略Projector

如果不希望物体受到Projector(投影机)的投射,可以添加IgnoreProjector标签值。

2.Pass的渲染状态

渲染状态 数值 作用
Cull Cull Back|Front|Off 设置多边形的剔除方式,又背面剔除、正面剔除、不剔除,默认为Back
ZTest ZTest(Less|Greater|LEqual|GEqual|Equal|NotEqual|Always) 设置深度测试的对比方式,默认为LEqual
ZWrite ZWrite On|Off 设置是否写入深度缓存,默认为On
Blend Blend sourceBlendMode destBlendMode 设置渲染图像的混合方式
ColorMask ColorMask RGB|A|0|或者R、G、B、A的任意组合 设置颜色通道的写入蒙版,默认蒙版为RGBA,当设置为0时,则无法写入任何颜色

五、Fallback

当所有的SubShader都不能在当前显卡上运行时,就会运行Fallback定义的Shader。

语法如下:

Fallback "name"

最常用于Fallback的Shader为Unity内置的Diffuse。