US5L3——Shader变体和关键字
US5L3——Shader变体和关键字
本章代码关键字
1 |
Shader 中的变体
Shader Variant(变体)指的是一个 Shader 的特定配置,通过不同的 关键字(Keywords) 和 设置组合 来实现不同的效果
每一种关键字组合或设置都会生成一个独立的 Shader 变体,最终以二进制形式存储在构建文件中供运行时使用
说人话:Shader 变体就是基于一个 Shader 文件当中的代码,编译生成多个版本的 Shader 它基于关键字来生成各种不同的版本
举例说明:一个 Shader 中有两个关键字,每个关键字有两种状态(启用或禁用),最终生成的变体数量就是 22 = 4
- 变体 1:没有启用任何关键字(默认)。
- 变体 2:启用了 关键字1。
- 变体 3:启用了 关键字2。
- 变体 4:同时启用了 关键字1 和 关键字2
运行时,Unity 会根据具体设置选择与之匹配的变体来使用,Unity 的一些内置功能会隐式的生成变体,比如:
- 光照模式 —— US3S5L6——多种光源综合实现
- 雾效 —— US3S11L5——Unity自带全局雾效
- 渲染管线 —— US1L1——渲染管线概述
等等
局部 Shader 关键字
-
声明方法
声明局部关键字有两种方式
#pragma shader_feature
或#pragma multi_compile
来声明关键词关键词命名规则:通常使用大写字母和下划线分隔(
_大写单词_大写单词...
),比如:_TEST_KEYWORD
-
#pragma shader_feature 关键词1 关键词2 关键词3....
作用:该编译指令声明的关键字,只有关键词启用时才会生成对应 Shader 变体
1
2
3
4
5
6
7
8CGPROGRAM
// 该编译指令声明的关键字,只有关键词启用时才会生成对应 Shader 变体
//...
ENDCG如果没有任何地方显式启用
_TEST_KEYWORD
或_TEST_KEYWORD2
则对应的 Shader 变体将不会生成 -
#pragma multi_compile 关键词1 关键词2 关键词3....
作用:该编译指令声明的关键字,不管是否启用都会生成对应 Shader 变体
1
2
3
4
5
6
7
8CGPROGRAM
// 该编译指令声明的关键字,不管是否启用都会生成对应 Shader 变体
//...
ENDCG
两种声明方式的区别:主要区别在于生成 Shader 变体的数量
-
shader_feature
:编译更快,Shader 文件更小,适用开关功能较少的场景 -
multi_compile
:编译更长,Shader 文件更大,适用需要完整覆盖的功能
-
-
使用方法
关键字使用规则,利用
#if ... #elif ... #else ... #endif
配合使用,判断关键词启用时处理什么逻辑1
2
3
4
5
6
7
....
....
....例如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
fixed4 frag (v2f i) : SV_Target
{
// 用关键字控制颜色
fixed4 col = fixed4(1,1,1,1);
// 如果启用了 _TEST_KEYWORD1 就采样
col = tex2D(_MainTex, i.uv);
// 如果启用了 _TEST_KEYWORD2 就启用雾效
UNITY_APPLY_FOG(i.fogCoord, col);
return col;
}通过 Shader 变体和关键词控制,即可将分支行为变为执行各种情况下的变体
Shader 中利用 C# 代码启用和禁用关键字
Unity Shader 中的关键字是一种用于控制 Shader 变体的机制,允许我们通过启用或者禁用特定功能来动态调整 Shader 的行为
Shader 中的关键字可以分为2种:
-
启用和禁用全局关键字
Unity 自带的关键字,所有 Shader 中共享,
可以在 C# 代码中通过Shader.EnableKeyword("全局关键字名")
和Shader.DisableKeyword("全局关键字名")
来控制关键字的启用和禁用 -
局部关键字只在特定的 Shader 中有效,不会影响其他 Shader
Unity 更推荐使用局部关键字以减少关键字冲突问题,可以在 C# 代码中通过:
-
material.EnableKeyword("局部关键字名")
-
material.DisableKeyword("局部关键字名")
来控制关键字的启用和禁用
-
变体和条件分支的区别
-
条件分支语句会带来逻辑上执行的开销,虽然能够在运行时直接判断,但是会带来对性能的影响
在动态功能选择时条件分支语句更适合
-
变体虽然会增加编译时间并占用更多的内容,但是它的性能高,灵活性强
在静态功能选择时变体更优,也就是只会在材质 Inspector 面板内设置或者创建后只修改一次,而不是在运行时动态修改最好