Surface Shaders with DX11 / OpenGL Core Tessellation
Vertex and fragment shader examples

Writing vertex and fragment shaders

ShaderLabUnity’s declarative language for writing shaders. More info
See in Glossary
shaders encompass more than just “hardware shaders”. They do many things. They describe properties that are displayed in the Material InspectorA Unity window that displays information about the currently selected GameObject, Asset or Project Settings, alowing you to inspect and edit the values. More info
See in Glossary
, contain multiple shaderA small script that contains the mathematical calculations and algorithms for calculating the Color of each pixel rendered, based on the lighting input and the Material configuration. More info
See in Glossary
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 ShadersUnity’s code generation approach that makes it much easier to write lit shaders than using low level vertex/pixel shader programs. More info
See in Glossary
documentation
. For some examples, take a look at Vertex and Fragment Shader Examples. The rest of this page assumes shaders do not interact with Unity lights (for example special effects, post-processed effects etc.)

Shader programs are written in HLSL 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/HLSL code itself
      
      ENDCG
      // ... the rest of pass setup ...
  }

HLSL snippets

HLSL program snippets are written between CGPROGRAMA block of shader code for controlling shaders using NVIDIA’s Cg (C for graphics) programming language. More info
See in Glossary
and ENDCG keywords, or alternatively between HLSLPROGRAM and ENDHLSL. The latter form does not automatically include HLSLSupport and UnityShaderVariables built-in header files.

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 shaderThe “per-pixel” part of shader code, performed every pixel that an object occupies on-screen. The fragment shader part is usually used to calculate and output the color of each pixel. More info
    See in Glossary
    .
  • #pragma geometry name - compile function name as DX10 geometry shader. Having this option automatically turns on #pragma target 4.0, described below.
  • #pragma hull name - compile function name as DX11 hull shader. Having this option automatically turns on #pragma target 5.0, described below.
  • #pragma domain name - compile function name as DX11 domain shader. Having this option automatically turns on #pragma target 5.0, described below.

Other compilation directives:

  • #pragma target name - which shader target to compile to. See Shader Compilation Targets page for details.
  • #pragma require feature … - fine grained control on which GPU features a shader needs, see Shader Compilation Targets page for details.
  • #pragma only_renderers space separated names - compile shader only for given renderers. By default shaders are compiled for all renderers. See Renderers below 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 below for details.
  • #pragma multi_compile … - for working with multiple shader variants. Unused variants of multi_compile shaders are included in the game build.
  • #pragma multi_compile_local … - similar to multi_compile, but enumerated keywords are local. See Making multiple shader program variants: Keyword limits for more information.
  • #pragma shader_feature … - for working with multiple shader variants. Unused variants of shader_feature shaders are not included in the game build.
  • #pragma shader_feature_local … - similar to shader_feature, but enumerated keywords are local. See Making multiple shader program variants: Keyword limits for more information.
  • #pragma enable_d3d11_debug_symbols - generate debug information for shaders compiled for DirectX 11, this will allow you to debug shaders via Visual Studio 2012 (or higher) Graphics debugger.
  • #pragma hardware_tier_variants renderer name - generate multiple shader hardware variants of each compiled shader, for each hardware tier that could run the selected renderer. See Renderers below for details.
  • #pragma hlslcc_bytecode_disassembly - embed disassembled HLSLcc bytecode into translated shader.
  • #pragma disable_fastmath - enables precise IEEE 754 rules, mostly involving NaN handling (currently only affects Metal platform).
  • #pragma glsl_es2 - When set in a GLSL shader, generate a GLSL ES 1.0(OpenGL ES 2.0), even when the shader target is OpenGL ES 3.
  • #pragma editor_sync_compilation - Force synchronous compilation (affects Editor only).

Each snippet must contain at least a vertex program and a fragment program. Thus #pragma vertex and #pragma fragment directives are required.

Compilation directives that don’t do anything starting with Unity 5.0 and can be safely removed: #pragma glsl, #pragma glsl_no_auto_normalization, #pragma profileoption, #pragma fragmentoption.

Unity only supports #pragma directives in the shader files, and not in the includes.

Rendering platforms

Unity supports several renderingThe process of drawing graphics to the screen (or to a render texture). By default, the main camera in Unity renders its view to the screen. More info
See in Glossary
APIs (e.g. Direct3D 11 and OpenGL), and by default all shader programs are compiled into all supported renderers. You can indicate which renderers to compile to using #pragma only_renderers or #pragma exclude_renderers directives. This is mostly useful in cases where you are explicitly using some shader language features that you know aren’t possible on some platforms. Supported renderer names are:

  • d3d11 - Direct3D 11/12
  • glcore - OpenGL 3.x/4.x
  • gles - OpenGL ES 2.0
  • gles3 - OpenGL ES 3.x
  • metal - iOSApple’s mobile operating system. More info
    See in Glossary
    /Mac Metal
  • vulkan - Vulkan
  • d3d11_9x - Direct3D 11 9.x feature level, as commonly used on WSA platforms
  • xboxone - Xbox One
  • ps4Abbreviation of PlayStation 4
    See in Glossary
    - PlayStation 4
  • n3ds - Nintendo 3DS
  • wiiu - Nintendo Wii U

For example, this line would only compile shader into D3D11 mode:

#pragma only_renderers d3d11

See Also


  • 2018–03–20 Page amended with editorial review
  • Shader #pragma directives added in Unity 2018.1

Did you find this page useful? Please give it a rating:

Surface Shaders with DX11 / OpenGL Core Tessellation
Vertex and fragment shader examples