在Unity中,所有的Shader程序都是使用名为“ShaderLab”的声明性语言进行编写的。ShaderLab语法不区分大小写。
1.1 Shader的组织结构
Shader的大致结构如下:
Shader "Name"
{
Properties
{
//开放到材质面板的属性
}
SubShader
{
//顶点-片段着色器或者表面着色器或者固定函数着色器
}
SubShader
{
//更加精简的版本
//为了在旧的图形设备上运行
}
Fallback "Name"
}
- Shader中可以编写多个SubShader,但至少需要一个。在应用程序运行过程中,GPU会先检测第一个SubShader能否正常运行,如果不能正常运行就会在检测第二个,依次类推。
- 假如当前GPG的硬件版本太旧,以至于所有的SubShader都无法正常运行,则执行最后的Fallback命令,运行指定的一个基础着色器。
- 如果编写的是Vertex-Fragment Shader,每个SubShader还会包含一个或多个Pass。如果某个SubShader能够在当前GPU上运行,那么该SubShader内的所有Pass会依次执行,每个Pass的输出结果会以指定的方式与上一步的结果进行混合,最终输出。
- 如果编写的是Surface Shader,着色器的代码也是包含在SubShader中,但是Surface Shader不会在嵌套Pass。系统在编译编译Surface Shader时会自动生成多个对应的Pass,最终编译出来的Shader本质上就是Vertex-Fragment Shader。
1.2 Shader的名称
Shader程序的第一行代码用来声明该Shader的名称以及所在的路径。如:
Shader "Custom/Simple Shader"
Shader选择面板
1.3 Properties
Unity可以通过Properties代码块将不同类型的变量或贴图资源开放给开发者,以便可以在材质面板中调节。
Unity Shader的属性主要分为三大类:数值,颜色和向量,纹理贴图,语法定义如下:
_Name("Display Name",type)=defaultValue[{option}]
(1)_Name:属性的名字。通常在名字的最前加一个下划线,后续在整个Shader中都将使用这个名称来获取该属性。
(2)Display Name:在材质面板中显示出来的名称。
(3)type:属性的类型。
(4)defaultValue:将Shader指定给材质的时候初始化的默认值。
所有类型属性汇总如下:
Properties
{
// 浮点类型
_MyFloat ("Float Property", Float) = 1
// 范围类型
_MyRange ("Range Property", Range(0, 1)) = 0.1
// 颜色类型
// 数值范围是[0,1]
_MyColor ("Color Property", Color) = (1, 1, 1, 1)
//向量类型
_MyVector ("Vector Property", Vector) = (0, 1, 0, 0)
// 2D贴图类型
// 默认值可以为空字符串,也可以是表示颜色的字符串如:"white","black","gray","bump"
// "bump"通常用于法线贴图的默认值
_MyTex ("Texture Property", 2D) = "white" {}
// 立方体贴图类型
// 默认值使用gray(RGBA:0.5,0.5,0.5,0.5)
_MyCube ("Cube Property", Cube) = "" {}
// 3D贴图类型
// 默认值使用gray(RGBA:0.5,0.5,0.5,0.5)
_My3D ("3D Property", 3D) = "" {}
}
不同属性类型的显示样式
在Unity5.0之前的版本,纹理属性可以在花括号内添加属性,用于控制固定函数纹理坐标的生成。但是该功能在Unity5.0及以后版本已经移除,所以直接加上一对空的花括号即可。
虽然Properties在参数调节过程中提供了便利,但是这部分代码在Shader中并不是必须的。如果不需要开放参数,完全可以在Shader中省略Properties这部分代码。
1.4 SubShader
SubShader大致结构如下:
SubShader
{
// 标签
Tags{"TagName1" = "Value1" "TagName2" = "Value2"}
// 渲染状态
Cull Back
pass
{
// 第一个Pass
}
pass
{
// 第二个Pass
}
}
每个SubShader都可以设置一个或多个标签(Tags)和渲染状态(States),然后定义至少一个Pass。在SubShader中设置的渲染状态会影响到该SubShader中所有的Pass,如果想要某些状态不影响其他Pass,可以针对某个Pass单独设置渲染状态,不过需要注意,部分渲染状态在Pass中并不支持。
1.4.1 SubShader的标签
SubShader通过标签来确定什么时候以及如何对物体进行渲染,标签通过键值对的形式进行声明,没有数量限制,语法如下:
Tags{"TagName1" = "Value1" "TagName2" = "Value2"}
1. 渲染队列 Queue
在SubShader中可以使用Queue标签确定物体的渲染顺序,如下Unity预先定义的五中渲染队列:
队列名称 | 描述 | 队列号 |
---|---|---|
Background | 最先执行渲染,一般用来绘制Skybox或者背景 | 1000 |
Geometry | 非透明的几何体通常使用这个队列,当没有声明渲染队列的时候,Unity会默认使用这个队列 | 2000 |
AlphaTest | Alpha Test的几何体都是用这个队列,之所以从Geometry队列单独拆分出来,是因为当所有实体都绘制完之后在绘制Alpha Test会更高效 | 2450 |
Transparent | 在这个队列的几何体按由远及近的顺序进行绘制,所有进行Alpha Blend的几何体都应该使用这个队列,如玻璃材质,粒子特效 | 3000 |
Overlay | 用于叠加渲染的效果,如镜头光晕,放到最后渲染 | 4000 |
也可以自己指定一个队列,如:
Tags { "Queue" = "Geometry + 1" }
也可以在材质面板中进行设置,如图:
2. 渲染类型 RenderType
RenderType标签可以将Shader划分为不同的类别,用于后期进行Shader替换或者产生摄像机的深度纹理。如下:
类别说明 | 描述 |
---|---|
Opaque | 用于普通Shader,如:不透明,自发光,反射,地形Shader |
Transparent | 用于半透明Shader,如:透明,粒子 |
TransparentCutout | 用于透明测试Shader,如:植物叶子 |
Background | 用于Skybox Shader |
Overlay | 用于GUI纹理,Halo,Flare Shader |
TreeOpaque | 用于地形系统中的树干 |
TreeTransparentCutout | 用于地形系统中的树叶 |
TreeBillboard | 用于地形系统中的Billboarded树 |
Grass | 用于地形系统中的草 |
GrassBillboard | 用于地形系统中的Billboarded草 |
3. 禁用批处理 DisableBatching
当使用批处理(Batching)的时候,几何体会被变换到世界空间,模型空间会被丢弃。这会导致某些使用模型空间顶点数据的Shader最终无法实现所希望的效果。而开启DisableBatching(禁用批处理)可以解决这个问题。
禁用批处理标签有三个数值可以使用:
(1)"DisableBatching"="True":总是禁用批处理。
(2)"DisableBatching"="False":不禁用批处理,这是默认值。
(3)"DisableBatching"="LODFading":当LOD效果激活的时候才会禁用批处理,主要用于地形系统上的树。
4. 禁用阴影投射 ForceNoShadowCasting
在游戏中,有很多特效类的物体并不需要对其他物体产生投影,这个时候可以将ForceNoShadowCasting标签设置为True。
5. 忽略投影机 IgnoreProjector
如果不希望物体受到Projector(投影机)的投射,可以将IgnoreProjector标签设置为True。一般半透明的Shader都会开启这个标签。
6. 其他标签
除此之外,Unity还提供了很多不常用的标签,如CanUseSpriteAtlas,PreviewType等。请看Unity官方文档关于SubShader标签这一部分的内容。
1.4.2 Pass的渲染状态
如果想某些Pass的渲染状态不影响到其他Pass,可以在该Pass中单独设置渲染状态。并且这些渲染状态在SubShader中同样被允许使用,但是会影响到该SubShader中所有Pass。
渲染状态 | 数值 | 作用 |
---|---|---|
Cull | Cull Back|Front|Off | 设置多边形的剔除方式,有背面剔除,正面剔除,不剔除,默认为Back |
ZTest | ZTest LEqual|GEqual|Equal|NotEqual|Less|Greater|Always | 设置深度测试的对比方式,默认为LEqual |
ZWrite | ZWrite On|Off | 设置是否写入深度缓存,默认为On |
Blend | Blend sourceBlendMode destBlendMode | 设置渲染图像的混合方式 |
ColorMask | ColorMask RGB|A|0|或者R,G,B,A的任意组合 | 设置颜色通道的写入蒙版,默认模板为RGBA,当设置为0时,则无法写入任何颜色 |
其他低频使用的渲染状态请阅读Unity官方文档里关于Pass的渲染状态这一部分内容。
1.5 Fallback
Fallback在所有SubShader之后进行定义。当所有SubShader都不能在当前显卡上运行的时候,就会运行Fallback定义的Shader。语法如下:
Fallback "name"
最常用于Fallback的Shader为Unity内置的Diffuse。
可以使用Fallback Off或者直接什么都不写,来关闭Fallback功能。
网友评论