Unity Shader 基础
shader和材质
基本流程
- 创建材质
- 创建unity shader,并赋给创建的材质
- 将材质赋给要渲染的对象
- 在材质面板调整Unity Shader属性。
Unity Shader 模板:
- standard surface shader:包含了标准光照模型的表面着色器模板
- unlit shader:不含光照的基本顶点/片元着色器
- image effect shader:实现屏幕后处理效果基本模板
ShaderLab
unity shader 基本结构
- Properties{} 属性
- SubShader{} 显卡使用的子着色器
- Fallback “”
Properties{} 属性
- 每个属性有名字,通常由下划线开始
- 显示的名称,出现在材质面板上的名字
- 类型
- 属性格式: 名字 (“显示名字”,属性类型) = 初始值
即使我们没在Properties中定义属性,也可以在CG语言中定义属性。在Properties中定义属性是为了在编辑器中可以显示。
SubShader{}
- 每一个Unity Shader文件中可以包含多个SubShader{},但最少要有一个。
- Unity需要加载这个Unity Shader时,会扫描所有SubShader{},选择第一个可以在目标平台中运行的SubShader{}。如果都不支持,Unity就会使用在Fallback语义定义的Unity Shader。
- SubShader基本结构
Subshader {
//可选的
[Tags]
//可选的
[RenderSetup]
Pass{
}
//Other Passes
}
- 每个Pass定义一次完整的渲染流程,数量过多会导致性能下降。
状态设置
状态名称 | 设置指令 | 解释 |
---|---|---|
Cull | Cull Back\Front\Off | 设置剔除模式:剔除背面\正面\关闭剔除 |
ZTest | ZTest Less Greater\LEqual\GEqual\Equal\NotEqual\Always | 设置深度测试时使用的函数 |
ZWrite | ZWrite On\Off | 开启\关闭深度写入 |
Blend | Blend SrcFactor DstFactor | 开启关闭设置混合模式 |
SubShader标签
- 是一个键值对,键和值都是字符串。
- 告诉Unity渲染引擎,我希望怎样以及何时渲染这个对象。
以上标签仅可在SubShader中声明,而不可以在Pass块中声明。Pass块虽然可以定义标签,但是标签类型不同于SubShader中的标签。
Pass语句块
Pass {
[Name]
[Tags]
[RenderSetup]
//Other code
}
- 我们可以定义该Pass的名称
Name “MyPassName”
通过这个名称,我们可以使用UsePass来直接使用其他Unity Shader中的Pass。
UsePass “MyShader/MYPASSNAME”
ps:Unity内部会把pass名称转化成大写字母 - Pass标签列表:
- UsePass:可以使用该命令来服用其他Unity Shader中的Pass;
- GrabPass:该Pass负责抓取屏幕并将结果存储在一张纹理中,以用于后续的Pass处理。
Fallback
紧跟在SubShader语句块后面,它用于告诉Unity,如果所有SubShader语句块在这块显卡上都不能运行,就是用这个最低级的Shader。
Fallback "name"
//或者
Fallback Off
Fallback Off即如果所有SubShader都无法运行,那就不要管它了。
Unity Shader形式
Unity Shader最重要的任务还是指定各种着色器所需的代码。这些着色器代码可以写在SubShader语义块中(表面着色器做法),也可以写在Pass语义块中(顶点/片元着色器和固定函数着色器做法)。
表面着色器(Surface shader)
- 由Unity自己创造的一种着色器,是对顶点/片元着色器的进一步抽象,它需要的代码量很少,Unity在背后做了很多工作,但是渲染代价比较大。它存在的价值就是Unity帮我们处理了很多光照细节。
- 表面着色器被定义在CGPROGRAM和ENDCG中,并且不再pass语义块中,表面着色器并不在意你使用了多少个pass,unity会在背后进行处理。
- CGPROGRAM和ENDCG中间的代码是使用CG/HLSL编写的。
顶点/片元着色器
- 在Unity中我们可以使用CG/HLSL语言来编写顶点/片元着色器,他们更加复杂,但是灵活度也更高。
- 顶点/片元着色器是定义在pass语义块中的,虽然我们需要编写更多的代码,但我们可以控制渲染的细节。
固定函数着色器
- 大部分设备都支持上面两种中的可编程管线,某些较旧的设备,不支持可编程管线着色器,我们需要使用固定函数着色器。
- 代码只相当于一些渲染设置,并且也是被定义在Pass语义块中,但它不是使用CG/HLSL编写,而是完全使用ShaderLab编写。
选择哪种渲染形式
- 如果想和各种光源打交道,使用表面着色器,但要小心在移动平台上的效果。
- 如果光线较少,可以使用顶点/片元着色器。
- 如果想实现很多自定义的渲染效果,那么选择顶点/片元着色器。