Unity defines several preprocessor macros when compiling Shader programs.
Macro: | Target platform: |
---|---|
SHADER_API_D3D11 |
Direct3D 11 |
SHADER_API_GLCORE |
Desktop OpenGL “core” (GL 3/4) |
SHADER_API_GLES |
OpenGL ES 2.0 |
SHADER_API_GLES3 |
OpenGL ES 3.0/3.1 |
SHADER_API_METAL |
iOS/Mac Metal |
SHADER_API_VULKAN |
Vulkan |
SHADER_API_D3D11_9X |
Direct3D 11 “feature level 9.x” target for Universal Windows Platform |
SHADER_API_DESKTOP |
Windows, Mac and Linux desktop platforms, WebGLA JavaScript API that renders 2D and 3D graphics in a web browser. The Unity WebGL build option allows Unity to publish content as JavaScript programs which use HTML5 technologies and the WebGL rendering API to run Unity content in a web browser. More info See in Glossary, Stadia |
SHADER_API_MOBILE |
iOS and Android mobile platforms, tvOS |
Additionally, SHADER_TARGET_GLSL
is defined when the target shading language is GLSL (always true for OpenGL/GLES platforms).
SHADER_TARGET
is defined to a numeric value that matches the ShaderA program that runs on the GPU. More info
See in Glossary target compilation model (that is, matching #pragma target
directive). For example, SHADER_TARGET
is 30
when compiling into Shader model 3.0. You can use it in Shader code to do conditional checks. For example:
#if SHADER_TARGET < 30
// less than Shader model 3.0:
// very limited Shader capabilities, do some approximation
#else
// decent capabilities, do a better thing
#endif
UNITY_VERSION
contains the numeric value of the Unity version. For example, UNITY_VERSION
is 202030
for Unity 2020.3.0. This can be used for version comparisons if you need to write Shaders that use different built-in Shader functionality. For example, a #if UNITY_VERSION >= 202000
preprocessor check only passes on versions 2020 or later.
Preprocessor macros SHADER_STAGE_VERTEX
, SHADER_STAGE_FRAGMENT
, SHADER_STAGE_DOMAIN
, SHADER_STAGE_HULL
, SHADER_STAGE_GEOMETRY
, SHADER_STAGE_COMPUTE
are defined when compiling each Shader stage. Typically they are useful when sharing Shader code between pixelThe smallest unit in a computer image. Pixel size depends on your screen resolution. Pixel lighting is calculated at every screen pixel. More info
See in Glossary Shaders and compute Shaders, to handle cases where some things have to be done slightly differently.
Direct use of these platform macros is discouraged, as they don’t always contribute to the future-proofing of your code. For example, if you’re writing a Shader that checks for D3D11, you may want to ensure that, in the future, the check is extended to include Vulkan. Instead, Unity defines several helper macros (in HLSLSupport.cginc
):
Macro: | Use: |
---|---|
UNITY_BRANCH |
Add this before conditional statements to tell the compiler that this should be compiled into an actual branch. Expands to [branch] when on HLSL platforms. |
UNITY_FLATTEN |
Add this before conditional statements to tell the compiler that this should be flattened to avoid an actual branch instruction. Expands to [flatten] when on HLSL platforms. |
UNITY_NO_SCREENSPACE_SHADOWS |
Defined on platforms that do not use cascaded screenspace shadowmaps (mobile platforms). |
UNITY_NO_LINEAR_COLORSPACE |
Defined on platforms that do not support Linear color space (mobile platforms). |
UNITY_NO_RGBM |
Defined on platforms where RGBM compressionA method of storing data that reduces the amount of storage space it requires. See Texture Compression, Animation Compression, Audio Compression, Build Compression. See in Glossary for lightmapsA pre-rendered texture that contains the effects of light sources on static objects in the scene. Lightmaps are overlaid on top of scene geometry to create the effect of lighting. More info See in Glossary is not used (mobile platforms). |
UNITY_NO_DXT5nm |
Defined on platforms that do not use DXT5nm normal-map compression (mobile platforms). |
UNITY_FRAMEBUFFER_FETCH_AVAILABLE |
Defined on platforms where “framebuffer color fetch” functionality can be available (generally iOS platforms - OpenGL ES 2.0, 3.0 and Metal). |
UNITY_USE_RGBA_FOR_POINT_SHADOWS |
Defined on platforms where point light shadowmaps use RGBA Textures with encoded depth (other platforms use single-channel floating point Textures). |
UNITY_ATTEN_CHANNEL |
Defines which channel of light attenuation Texture contains the data; used in per-pixel lighting code. Defined to either ‘r’ or ‘a’. |
UNITY_HALF_TEXEL_OFFSET |
Defined on platforms that need a half-texel offset adjustment in mapping texels to pixels. |
UNITY_UV_STARTS_AT_TOP |
Always defined with value of 1 or 0. A value of 1 is on platforms where Texture V coordinate is 0 at the “top” of the Texture. Direct3D-like platforms use value of 1; OpenGL-like platforms use value of 0. |
UNITY_MIGHT_NOT_HAVE_DEPTH_Texture |
Defined if a platform might emulate shadow maps or depth Textures by manually rendering depth into a Texture. |
UNITY_PROJ_COORD(a) |
Given a 4-component vector, this returns a Texture coordinate suitable for projected Texture reads. On most platforms this returns the given value directly. |
UNITY_NEAR_CLIP_VALUE |
Defined to the value of near clipping planeA plane that limits how far or close a camera can see from its current position. A camera’s viewable range is between the far and near clipping planes. See far clipping plane and near clipping plane. More info See in Glossary. Direct3D-like platforms use 1.0 while OpenGL-like platforms use –1.0. |
UNITY_VPOS_TYPE |
Defines the data type required for pixel position input (VPOS): float2 on D3D9, float4 elsewhere. |
UNITY_CAN_COMPILE_TESSELLATION |
Defined when the Shader compiler “understands” the tessellation Shader HLSL syntax (currently only D3D11). |
UNITY_INITIALIZE_OUTPUT(type,name) |
Initializes the variable name of given type to zero. |
UNITY_COMPILER_HLSL , UNITY_COMPILER_HLSL2GLSL , UNITY_COMPILER_CG
|
Indicates which Shader compiler is being used to compile Shaders. See documentation on Shader compilation for more details. Use this if you run into very specific Shader syntax handling differences between the compilers, and want to write different code for each compiler. |
UNITY_REVERSED_Z
- defined on plaftorms using reverse Z buffer. Stored Z values are in the range 1..0 instead of 0..1.Declaring and sampling shadow maps can be very different depending on the platform. Unity has several macros to help with this:
Macro: | Use: |
---|---|
UNITY_DECLARE_SHADOWMAP(tex) |
Declares a shadowmap Texture variable with name “tex”. |
UNITY_SAMPLE_SHADOW(tex,uv) |
Samples shadowmap Texture “tex” at given “uv” coordinate (XY components are Texture location, Z component is depth to compare with). Returns single float value with the shadow term in 0..1 range. |
UNITY_SAMPLE_SHADOW_PROJ(tex,uv) |
Similar to above, but does a projective shadowmap read. “uv” is a float4, all other components are divided by .w for doing the lookup. |
The format of tex
must be RenderTextureFormat.Shadowmap.
NOTE: Not all graphics cards support shadowmaps. Use SystemInfo.SupportsRenderTextureFormat to check for support.
Direct3D 11 groups all Shader variables into “constant buffers”. Most of Unity’s built-in variables are already grouped, but for variables in your own Shaders it might be more optimal to put them into separate constant buffers depending on expected frequency of updates.
Use CBUFFER_START(name)
and CBUFFER_END
macros for that:
CBUFFER_START(MyRarelyUpdatedVariables)
float4 _SomeGlobalValue;
CBUFFER_END
If you use a GPU compute buffer or graphics buffer to set the value of the variables, make sure the buffer and the constant buffer have matching data layouts on all graphics APIs you build for. See Using constant buffers with GPU buffers for more information.
Note: You can’t add structs to constant buffers.
Usually you would use texture2D
in Shader code to declare a Texture and Sampler pair.
However on some platforms (such as DX11), Textures and Samplers are separate objects,
and maximum possible Sampler count is quite limited. Unity has some macros to declare
Textures without Samplers, and to sample a Texture using a Sampler from another Texture.
Use this if you end up running into Sampler limits, and you know that several of your
Textures can in fact share a Sampler (Samplers define Texture filtering and wrapping modes).
Macro: | Use: |
---|---|
UNITY_DECLARE_TEX2D(name) |
Declares a Texture and Sampler pair. |
UNITY_DECLARE_TEX2D_NOSAMPLER(name) |
Declares a Texture without a Sampler. |
UNITY_DECLARE_TEX2DARRAY(name) |
Declares a Texture array Sampler variable. |
UNITY_SAMPLE_TEX2D(name,uv) |
Sample from a Texture and Sampler pair, using given Texture coordinate. |
UNITY_SAMPLE_TEX2D_SAMPLER( name,samplername,uv) |
Sample from Texture (name), using a Sampler from another Texture (samplername). |
UNITY_SAMPLE_TEX2DARRAY(name,uv) |
Sample from a Texture array with a float3 UV; the z component of the coordinate is array element index. |
UNITY_SAMPLE_TEX2DARRAY_LOD(name,uv,lod) |
Sample from a Texture array with an explicit mipmap level. |
For more information, see documentation on Sampler States.
When Surface ShadersA streamlined way of writing shaders for the Built-in Render Pipeline. More info
See in Glossary are compiled, they generate a lot of code for various passes to do lighting. When compiling each pass, one of the following macros is defined:
Macro: | Use: |
---|---|
UNITY_PASS_FORWARDBASE |
Forward renderingA rendering path that renders each object in one or more passes, depending on lights that affect the object. Lights themselves are also treated differently by Forward Rendering, depending on their settings and intensity. More info See in Glossary base pass (main directional light, lightmaps, SH). |
UNITY_PASS_FORWARDADD |
Forward rendering additive pass (one light per pass). |
UNITY_PASS_DEFERRED |
Deferred shadingA rendering path in the Built-in Render Pipeline that places no limit on the number of Lights that can affect a GameObject. All Lights are evaluated per-pixel, which means that they all interact correctly with normal maps and so on. Additionally, all Lights can have cookies and shadows. More info See in Glossary pass (renders G-buffer). |
UNITY_PASS_SHADOWCASTER |
Shadow caster and depth Texture rendering pass. |
UNITY_SHADER_NO_UPGRADE
allows you to disable Unity from automatically upgrading or modifying your shader file.
Most of the time, Depth Texture are used to render Depth from the CameraA component which creates an image of a particular viewpoint in your scene. The output is either drawn to the screen or captured as a texture. More info
See in Glossary. The UnityCG.cginc include file contains some macros to deal with the above complexity in this case:
Note: On DX11/12 and Metal, the Z buffer range is 1–0 and UNITY_REVERSED_Z is defined. On other platforms, the range is 0–1.
For example, this shader would render depth of its GameObjectsThe fundamental object in Unity scenes, which can represent characters, props, scenery, cameras, waypoints, and more. A GameObject’s functionality is defined by the Components attached to it. More info
See in Glossary:
Shader "Render Depth" {
SubShader {
Tags { "RenderType"="Opaque" }
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct v2f {
float4 pos : SV_POSITION;
float2 depth : TEXCOORD0;
};
v2f vert (appdata_base v) {
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
UNITY_TRANSFER_DEPTH(o.depth);
return o;
}
half4 frag(v2f i) : SV_Target {
UNITY_OUTPUT_DEPTH(i.depth);
}
ENDCG
}
}
}