在使用shader时,可能会遇到这样的情况:某个shader的绝大部分代码适用于所有的情况,但是有少部分内容需要根据具体的情况采用不同的代码。此时会需要保持shader的大部分代码固定不变,得到对少部分代码做轻微的改动的shader变体。multi_compile
用于产生多种不同的shader变体。multi_compile
会根据不同的情况,使用不同的预处理器指令,多次编译shader代码。
multi compile
在ShaderLab中使用下边的方式定义multi_compile,然后即可在材质面板(配合TOGGLE
)或者代码中控制开启或禁用该关键字(Shader
或Material
的EnableKeyword
和DisableKeyword
方法):
1 |
一个示例:
1 |
将会产生两个shader变体,分别是定义了FANCY_STUFF_OFF
和FANCY_STUFF_ON
。在运行时,会根据材质或shader激活的关键字来启用其中之一。如果二者均未被激活则启用第一个(off
)。也可以定义大于两个的关键字,如:
1 |
将会产生4个shader变体。
当一个关键字全部由下划线组成时,则会生成一个不包含任何预定义宏的变体,如:
1 |
将会生成两个shader变体,其中一个不包含预定义宏,另一个包含FOO_ON
。这种用法通常是配合shader_feature
(后边提到)使用,以减少使用的关键字数量,Unity中支持使用的关键字的数量是有限的。
shader feature
与multi_compile
功能相似。需要注意的是,对于shader_feature
,在游戏中没有使用的关键字,在构建游戏时不会生成对应的shader变体。也就是说如果是在运行时才用代码去开启和关闭关键字(Enable/DisableKeyword)的话,需要使用multi_compile
。
在使用shader_feature
时,有一种简便写法,即当只有一个关键字时,以下的两种写法是等效的:
1 |
multi compile的组合
一个示例:
1 |
会生成6种变体,分别是A+D
、B+D
、C+D
、A+E
、B+E
和C+E
。
内置multi compile与忽略
multi_compile_fwdbase
:编译ForwardBase
(forward rendering base)所需的所有变体。这些变体用于处理不同的lightmap类型,及主方向光是否产生阴影。multi_compile_fwdadd
:编译ForwardAdd
(forward rendering additive)所需的所有变体。这些变体用于处理方向光、聚光灯及点光源类型,以及使用剪影(cookie textures)的变体。multi_compile_fwdadd_fullshadows
:和上边的相同,还包括了实时阴影的光照。multi_compile_fog
:用于处理不同类型的雾的变体(off
/linear
/exp
/exp2
)。
绝大多数内置的快捷操作会产生很多的shader变体。如有需要可以使用#pragma skip_variants
来忽略其中的部分变体,如:
1 |
|
Shader GUI
Toggle
在编辑器UI上绘制Toggle,并且将其与multi_compile
关联。定义float属性,标为Toggle
,与其关联的multi_compile
的关键字是属性名的全大写形式加上_ON
,如:
1 | [Toggle] _Maskable ("Maskable?", Float) = 1 |
或者直接指明:
1 | [Toggle(_MASKABLE_ON)] _Maskable ("Maskable?", Float) = 1 |
shader中直接使用:
1 |
|
自定义GUI
要使用自定义的GUI,需要在shader的末尾指定:
1 | Shader "TestShader" |
定义的自定义GUI类,主要是需要覆写OnGUI
方法:
1 | using UnityEditor; |
REFERENCE
http://docs.unity3d.com/Manual/SL-MultipleProgramVariants.html
https://docs.unity3d.com/Manual/SL-CustomShaderGUI.html
https://docs.unity3d.com/ScriptReference/MaterialPropertyDrawer.html