Writing shader programs

Reference Manual > ShaderLab Reference > Writing shader programs

ShaderLab shaders encompass more than just "hardware shaders". They do many things. They describe properties that are displayed in the Material Inspector, contain multiple shader implementations for different graphics hardware, configure fixed function hardware state and so on. The actual programmable shaders - like vertex and fragment programs - are just a part of the whole ShaderLab's "shader" concept. Take a look at shader tutorial for a basic introduction. Here we'll call the low-level hardware shaders shader programs.

Shader programs are written in either Cg or GLSL language, by embedding "snippets" in the shader text, somewhere inside the Pass command. They usually look like this:

  Pass {
      // ... the usual pass state setup ...

      CGPROGRAM
      // compilation directives for this snippet, e.g.:
      #pragma vertex vert
      #pragma fragment frag

      // the Cg code itself

      ENDCG
      // ... the rest of pass setup ...
  }

Cg snippets

Cg program snippets are written between CGPROGRAM and ENDCG.

At the start of the snippet compilation directives can be given as #pragma statements. Directives recognized by Unity are:

  • #pragma vertex name - indicates that function name is a vertex program.
  • #pragma fragment name - indicates that function name is a fragment program.
  • #pragma fragmentoption option - adds option to the compiled OpenGL fragment program. See the ARB fragment program specification for a list of allowed options. This directive has no effect on vertex programs or programs that are compiled to non-OpenGL targets.
  • #pragma multi_compile_builtin - for pixel-lit shaders; this will tell Unity to compile dozens of permutations of this shader program to support all light types and all shadowing options.
  • #pragma multi_compile_builtin_noshadows - for pixel-lit shaders that don't receive shadows; this will tell Unity to compile several permutations of this shader program to support all light types. This is faster to compile than the multi_compile_builtin pragma, and the resulting shader is smaller.
  • #pragma target name - which shader target to compile to. See shader targets for details.

Each snippet must contain a vertex program, a fragment program, or both. Thus a #pragma vertex or #pragma fragment directive is required, or both.

Shader targets

By default, Unity compiles vertex programs into a shader model 1.1 equivalent, and fragment programs into a shader model 2.0 equivalent. Using #pragma target allows shaders to be compiled into other capability levels. Currently these targets are supported:

  • #pragma target default - compile to default target:
    • Vertex shader 1.1 and pixel shader 2.0 on Direct3D 9.
    • ARB_vertex_program with 128 instruction limit and ARB_fragment_program with 96 instruction limit (32 texture + 64 arithmetic), and 16 temporary register limit.
  • #pragma target 3.0 - compile to shader model 3.0:
    • Vertex shader 3.0 and pixel shader 3.0 on Direct3D 9.
    • ARB_vertex_program with no instruction limit and ARB_fragment_program with 1024 instruction limit (512 texture + 512 arithmetic), and 32 temporary register limit.
    When compiling to 3.0 target, both vertex and fragment programs need to be present.

GLSL snippets

Use of GLSL shader programs is only recommended for testing. GLSL language is specific to OpenGL, whereas using Cg will compile shaders to both Direct3D and OpenGL.

See GLSL Shader Programs page for details.

Subsections