1、Shader是渲染流水线中的某些特定阶段,如顶点着色器阶段、片元着色器阶段等。
在Unity中,我们需要配合使用材质和Unity Shader才能达到需要的效果,一个常见的流程是:
①创建一个材质
②创建一个Unity Shader,并把它赋给上一步中创建的材质
③把材质赋给要渲染的对象
④在材质面板中调整Unity Shader的属性,以得到满意的效果
在上述过程中,Unity Shader定义了渲染所需的各种代码(如顶点着色器和片元着色器)、属性(如使用哪些纹理等)和指令(渲染和标签设置等),而材质则允许我们调节这些属性,并将其最终赋予相应的模型。
Unity Shader与渲染管线的Shader有很大的不同,一个提供了4种Unity Shader模板供我们选择:
#Standard Surface Shader:表面着色器的实现方法
#Unlit Shader:顶点/片元着色器
#Image Effect Shader:为实现各种屏幕后处理效果提供了一个基本模板
#Compute Shader:利用GPU的并行性进行一些与常规渲染流水线无关的计算
2、ShaderLab
Unity Shader为控制渲染过程提供了一层抽象,所以的Unity Shader都是使用ShaderLab来编写的。
一个Unity Shader的基础结构如下所示:
Shader "ShaderName" {
Properties {
//属性
}
SubShader {
//显卡A使用的子着色器
}
SubShader {
//显卡B使用的子着色器
}
Fallback "VertexLit"
}
3、Unity Shader的结构
①起个名字:Shader "Custom/MyShader" { }:控制Unity Shader在材质面板中的出现位置
②材质和Unity Shader的桥梁:
Properties {
Name("display name",PropertyType)=DefaultValue
Name("display name",PropertyType)=DefaultValue
}
例如,_Int("Int",Int)=2 属性名称、显示的名称、类型、默认值
对于Int、Float、Range这些数字类型的属性,其默认值就是一个单独的数字;
对于Color、Vector类属性,默认值用圆括号包围的一个四维向量;
对于2D、Cube、3D这3类纹理类型,通过一个字符串后跟一个花括号来指定的。
③SubShader
每一个Unity Shader文件可以包含多个SubShader语义块,但最少要有一个。
SubShader {
//可选的
[ Tags ]
//可选的
[ RenderSetup ]
Pass {
}
// Other Passes
}
每个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 | 开启并设置混合模式 |
#SubShader的标签是一个键值对,都是字符串类型,告诉Unity的渲染引擎:怎样以及何时渲染这个对象
标签的结构及标签块支持的标签类型:
Tags { "TagName1"="Value1" "TagName2"="Value2" }
标签类型 | 说明 | 例子 |
Queue | 控制渲染顺序,指定该物体的渲染队列,可保证所以透明的物体在所有不透明物体后被渲染 | Tags{ "Queue"="Transparent" } |
RenderType | 对着色器进行分类,可以被用于着色器替换功能 | Tags{ "RenderType"="Opaque" } |
DisableBatching | 一些SubShader在使用Unity的批处理功能时会出现问题,例如使用了模型空间下的坐标进行顶点动画。这时可以通过该标签来直接指明是否对该SubShader使用批处理 | Tags{ "DisableBatching"="True"} |
ForceNoShadowCasting | 控制使用该SubShader的物体是否会投射阴影 | Tags{ "ForceNoShadowCasting"= "True"} |
IgnoreProjector | 如果该标签值为“True”,那么使用该SubShader的物体将不会受Projector的影响。通常用于半透明的物体 | Tags{ "IgnoreProjector"="True"} |
CanUseSpriteAtlas | 当该SubShader是用于精灵时,该标签设为“False” | Tags{"CanUseSpriteAtlas"="False"} |
PreviewType | 指明材质面板将如何预览该材质。 | Tags{ "PreviewType"="Plane"} |
#Pass语义块
Pass {
[ Name ] //Unity内部会把所有Pass名称转换成大写字母表示,因此使用UsePass命令时必须使用大写形式的名字
[ Tags ]
[ RenderSetup ]
//other code
}
可以使用ShaderLab的UsePass命令来直接使用其他Unity Shader中的Pass,例如:
UsePass "MyShader/MYPASSNAME"
SubShader的状态设置同样适用于Pass
Pass标签不同于SubShader的标签,如:
标签类型 | 说明 | 例子 |
LightMode | 定义该Pass在Unity的渲染流水线的角色 | Tags { "LightMode"="ForwardBase"} |
RequireOptions | 用于指定当满足某些条件时才渲染该Pass,值为空格分隔的字符串 | Tags{ "RequireOptions"="SoftVegetation"} |
④后路,Fallback
如果上面的SubShader在显卡上不能运行,就是要最低级的Shader吧
Fallback "name"
Fallback Off
5、表面着色器是Unity自创的一种着色器代码类型,可以理解为顶点/片元着色器的高一层抽象
Cg/HLSL需要嵌套在CGPROGRAM和ENDCG之间
GLSL需要嵌套在GLSLPROGRAM和ENDGLSL之间