Writing vertex and fragment shaders
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.
If you want to write shaders that interact with lighting, take a look at Surface Shaders documentation. The rest of this page will assume shaders that do not interact with Unity lights (e.g. special effects, Image Effects etc.)
Shader programs are written in Cg / HLSL language, by embedding "snippets" in the shader text, somewhere inside the Pass command. They usually look like this:
// ... the usual pass state setup ...
// compilation directives for this snippet, e.g.:
#pragma vertex vert
#pragma fragment frag
// the Cg code itself
// ... the rest of pass setup ...
Cg program snippets are written between CGPROGRAM and ENDCG.
At the start of the snippet compilation directives can be given as #pragma statements. Directives indicating which shader functions to compile:
- #pragma vertex name - compile function name as the vertex shader.
- #pragma fragment name - compile function name as the fragment shader.
- #pragma geometry name - compile function name as DX10 geometry shader. Having this option automatically turns on #pragma target 4.0, see below.
- #pragma hull name - compile function name as DX11 hull shader. Having this option automatically turns on #pragma target 5.0, see below.
- #pragma domain name - compile function name as DX11 domain shader. Having this option automatically turns on #pragma target 5.0, see below.
Other compilation directives:
- #pragma target name - which shader target to compile to. See shader targets for details.
- #pragma only_renderers space separated names - compile shader only for given renderers. By default shaders are compiled for all renderers. See renderers for details.
- #pragma exclude_renderers space separated names - do not compile shader for given renderers. By default shaders are compiled for all renderers. See renderers for details.
- #pragma glsl - when compiling shaders for desktop OpenGL platforms, convert Cg/HLSL into GLSL (instead of default setting which is ARB vertex/fragment programs). Use this to enable derivative instructions, texture sampling with explicit LOD levels, etc.
- #pragma glsl_no_auto_normalization - when compiling shaders for mobile GLSL (iOS/Android), turn off automatic normalization of normal & tangent vectors. By default, normals and tangents are normalized in the vertex shader on iOS/Android platforms.
- #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.
Each snippet must contain a vertex program, a fragment program, or both. Thus a #pragma vertex or #pragma fragment directive is required, or both.
By default, Unity compiles shaders into roughly shader model 2.0 equivalent. Using #pragma target allows shaders to be compiled into other capability levels. Currently these targets are supported:
- #pragma target 2.0 (default) - roughly shader model 2.0
- Shader Model 2.0 on Direct3D 9.
- ARB_vertex_program with 256 instruction limit and ARB_fragment_program with 96 instruction limit (32 texture + 64 arithmetic), 16 temporary registers and 4 texture indirections.
- #pragma target 3.0 - compile to shader model 3.0:
When compiling to 3.0 or larger target, both vertex and fragment programs need to be present.
- Shader Model 3.0 on Direct3D 9.
- ARB_vertex_program with no instruction limit and ARB_fragment_program with 1024 instruction limit (512 texture + 512 arithmetic), 32 temporary registers and 4 texture indirections. It is possible to override these limits using #pragma profileoption directive. E.g.
#pragma profileoption MaxTexIndirections=256 raises texture indirections limit to 256. Note that some shader model 3.0 features, like derivative instructions, aren't supported by ARB_vertex_program/ARB_fragment_program. You can use #pragma glsl to translate to GLSL instead which has fewer restrictions.
- #pragma target 4.0 - compile to DX10 shader model 4.0. This target is currently only supported by DirectX 11 renderer.
- #pragma target 5.0 - compile to DX11 shader model 5.0. This target is currently only supported by DirectX 11 renderer.
Unity supports several rendering APIs (e.g. Direct3D 9 and OpenGL), and by default all shader programs are compiled into for supported renderers. You can indicate which renderers to compile to using #pragma only_renderers or #pragma exclude_renderers directives. This is useful if you know you will only target Mac OS X (where there's no Direct3D), or only Windows (where Unity defaults to D3D), or if some particular shader is only possible in one renderer and not others. Currently supported renderer names are:
- d3d9 - Direct3D 9.
- d3d11 - Direct3D 11.
- opengl - OpenGL.
- gles - OpenGL ES 2.0.
- xbox360 - Xbox 360.
- ps3 - PlayStation 3.
- flash - Flash.
For example, this line would only compile shader into D3D9 mode:
#pragma only_renderers d3d9
Page last updated: 2012-11-16