Version: 2021.1
Shader variants
Using shader keywords with C# scripts

Shader keywords

You can create shadersA program that runs on the GPU. More info
See in Glossary
that share some common code, but have different functionality when a given keyword is enabled or disabled.

Internally, shader keywords work by creating shader variants. Before you use shader keywords, it is important to understand how shader variants work, and the potential impact on performance and workflow. For information on this topic, see Shader variantsA verion of a shader program that Unity generates according to a specific combination of shader keywords and their status. A Shader object can contain multiple shader variants. More info
See in Glossary
.

Declaring shader keywords

You declare shader keywords in sets. A set contains mutually exclusive keywords.

For example, the following set contains three keywords:

  • COLOR_RED
  • COLOR_GREEN
  • COLOR_BLUE

Internally, shader keywords use #define preprocessor directives. When you declare a set of shader keywords, Unity compiles shader variants with matching #define directives.

Note: In Shader Graph, the terminology is different: a set of keywords is called a Keyword, and the keywords in a set are called states. Internally, the functionality is the same: Unity compiles them in the same way, you work with them the same way with C# scriptsA piece of code that allows you to create your own Components, trigger game events, modify Component properties over time and respond to user input in any way you like. More info
See in Glossary
, and so on.

The number of keywords that you declare and the way that you declare these keywords has a significant impact on the number of shader variants that Unity compiles, which in turn can have a significant effect on the performance of your project and application. For more information, see Shader variants.

To declare keywords in hand-coded shaders, see Declaring and using shader keywords in HLSL. To declare keywords in Shader Graph shaders, see Keywords.

Declaring keywords with local or global scope

When you declare a set of keywords, you choose whether the keywords in the set have local or global scope.

Global and local keywords are separate: global keywords affect the whole project, and local keywords are specific to an individual shader.

Unless you are planning to enable keywords for multiple shaders at the same time, you should generally declare keywords with local scope.

To set this value in hand-coded shaders, see Declaring and using shader keywords in HLSL. To set this value in Shader Graph shaders, see Keywords. For information on enabling and disabling local and global shader keywords, see Using shader keywords with C# scripts.

Note: If there are global and local keywords with the same name, Unity prioritises the local keyword.

Warning: If a material has a local keyword enabled, and its shader changes to one that is no longer declared, Unity creates a new global keyword.

Definition type: “multi compile” or “shader feature”

When you declare a set of keywords, you choose the technique that Unity uses to define them. This affects the number of shader variants that Unity compiles.

  • “multi compile” declares a set of keywords.

    Unity compiles shader variants for all keywords in the set.
  • “shader feature” declares a set of keywords, and also instructs the compiler to compile variants where none of these keywords are enabled.

    Unity examines the state of your project at build time, and only compiles variants for keywords that are in use. A keyword is in use if a material that is included in the build has that keyword enabled.

Which option is best depends on how you use the keywords. If you use the keywords to configure materials in your project and do not change their value from C# scripts at runtime, then you should use “shader feature” to reduce the number of shader keywords and variants in your project. If you enable and disable keywords at runtime using C# scripts, then you should use “multi compile” to prevent variants being stripped in error. For more information on shader stripping, see Stripping shader variants.

To set this value in hand-coded shaders, see Declaring and using shader keywords in HLSL. To set this value in Shader Graph shaders, see Keywords.

Stage-specific keywords

By default, Unity generates keyword variants for each stage of your shader. For example, if your shader contains a vertex stage and a fragment stage, Unity generates variants for every keyword combination for both the vertex and the fragment shader programs. If a set of keywords is only used in one of those stages, this results in identical variants for the other stage. Unity automatically identifies and deduplicates identical variants so that they do not increase build size, but they still result in wasted compilation time, increased shader loading times, and increased runtime memory usage.

To avoid this problem, when you declare a set of keywords in a hand-coded shader, you can instruct Unity to compile them only for a given shader stage.

Note: You are responsible for ensuring that the keywords are only used in the specified shader stages.

Graphics API support

Unity does not fully support the use of stage-specific keyword directives for the following graphics APIs:

  • OpenGL and Vulkan: At compile time, Unity automatically converts all stage-specific keyword directives to regular keyword directives.
  • Metal: any keyword targeting vertex stages also affects tessellation stages, and vice versa.

To set this value in hand-coded shaders, see Declaring and using shader keywords in HLSL. You cannot change this value in Shader Graph; by default, all keywords affect all stages.

Conditional compilation using shader keywords

You can mark sections of your shader source file so that Unity only includes that functionality in variants that are used when a given keyword is enabled.

The way that you do this is different in hand-coded shaders and in Shader Graph. For instructions for hand-coded shaders, see Defining and using shader keywords. For instructions for Shader Graph, see Shader Graph: Keyword Node.

Enabling and disabling shader keywords

You can enable or disable shader keywords. When you enable or disable a shader keyword, Unity uses the appropriate shader variant for rendering.

There are two ways to enable and disable shader keywords:

Unity’s predefined shader keywords

Unity uses predefined sets of shader keywords to enable common functionality. It adds the following sets of shader keywords at compile time:

  • By default, Unity adds this set of keywords to all graphics shader programs: STEREO_INSTANCING_ON, STEREO_MULTIVIEW_ON, STEREO_CUBEMAP_RENDER_ON, UNITY_SINGLE_PASS_STEREO. You can strip these keywords using an Editor script. For more information, see Stripping shader variants using Editor scripts.
  • By default, Unity adds this set of keywords to the Standard Shader: LIGHTMAP_ON, DIRLIGHTMAP_COMBINED, DYNAMICLIGHTMAP_ON, LIGHTMAP_SHADOW_MIXING, SHADOWS_SHADOWMASK. You can strip these keywords using the Graphics settings window.
  • In the Built-in Render PipelineA series of operations that take the contents of a Scene, and displays them on a screen. Unity lets you choose from pre-built render pipelines, or write your own. More info
    See in Glossary
    , if your project uses tier settings that differ from each other, Unity adds this set of keywords to all graphics shaders: UNITY_HARDWARE_TIER1, UNITY_HARDWARE_TIER2, UNITY_HARDWARE_TIER3. For more information, see Graphics tiers: Graphics tiers and shader variants.

Shader keyword limits

There is a limit of 384 global shader keywords, and Unity uses around 60 of them internally (therefore lowering the available number). Each individual shader has a limit of 64 local keywords.

Every keyword declared in the shader source file and its dependenciesIn the context of the Package Manager, a dependency is a specific package version (expressed in the form package_name@package_version) that a project or another package requires in order to work. Projects and packages use the dependencies attribute in their manifests to define the set of packages they require. For projects, these are considered direct dependencies; for packages, these are indirect, or transitive, dependencies. More info
See in Glossary
count towards these limits. Dependencies include Passes that the shader includes using UsePass, and fallbacks.

If Unity encounters a shader keyword with the same name multiple times, it only counts towards the limit once.

Shader variants
Using shader keywords with C# scripts