Varied shader variants
While writing your shader, the pieces of code that you want to be able to enable/disable need to be placed between the following directives, where MY_MACRO
is user-defined.
#if MY_MACRO
// ... some optional code ...
#endif
Then, you need to let Unity know that these pieces of code exist using the directive #pragma multi_compile
. In our case, we would do
#pragma multi_compile __ MY_MACRO
So, what happens next? Now, Unity will compile two shaders for you. One without the MY_MACRO
piece of code (specified by the __
int the #pragma
) and other with the piece of code (specified by the MY_MACRO
in the #pragma
).
You can now select what shader to use at runtime by enabling/disabling the macro MY_MACRO
using either Material.EnableKeyword()/.DisableKeyword()
(per material) or Shader.EnableKeyword()/.DisableKeyword()
(globally).
How multi_compile works
To produce a shader variant with no preprocessor macro defined, add a name that is just underscores (__
). This is a common technique to avoid using up two keywords, because there is a limit on how many you can use in a project (see later section on Keyword limits). For example:
#pragma multi_compile __ FOO_ON
This directive produces two shader variants: one with nothing defined (__
), and one with FOO_ON
defined.
Difference between shader_feature and multi_compile
shader_feature
is very similar to multi_compile
. The only difference is that Unity does not include unused variants of shader_feature
shaders in the final build. For this reason, you should use shader_feature
for keywords that are set from the Materials, while multi_compile
is better for keywords that are set from code globally.
Additionally, there is a shorthand notation with just one keyword:
#pragma shader_feature FANCY_STUFF
Which is just a shortcut for #pragma shader_feature _ FANCY_STUFF
. It expands into two shader variants (first one without the define; second one with it).