An overview of shaders in Unity

URP, HDRP, Built-In, ... . What does it all mean?

What are shaders and why do we need them?

On the basic level, you have two types of processors in your device, the CPU and the GPU.

One is the CPU which is your jack-of-all-trades. It can do everything decently but it does not excel in anything in particular.

The second one is the GPU which specializes in graphics processing and is the core of what people know as the graphics card.

Since the GPU is very different from the CPU it requires a special set of instructions. Simply put, a shader is a list of such instructions (code) that runs on your graphics card.

You may have heard of things like DirectX, OpenGL (ES), Vulkan, and Metal. These are competing instruction sets that certain graphics cards support. Shaders use them to talk to the GPU. Think of them as dialects in a language. All of them talk English but they differ in the details.

To create instructions for the GPU we use programming languages known as shading languages. The most common ones are GLSL (OpenSource), HLSL (Microsoft), and Metal (Apple). If you open a .shader file in Unity then you will see that it contains shader code (among some other things).

If you want to brush up on your shader knowledge then the Shader Core Concepts Manual might be a good starting point.

URP, HDRP, SRP - What do all these abbreviations mean?

Over time Unity has built multiple ways of converting your code to graphics on your monitor. These are called "render pipelines".

When it comes to Unity and render pipelines then there is no shortage of acronyms. The most common ones are Buillt-In, Legacy, BiRP, BiRP, LWRP, URP, HDRP, SRP, SRPs, CRP, and CRPs. Some of them are exchangeable, others are not.

Built-In: the old(est) render pipeline

The oldest render pipeline is the "Built-In Render Pipeline". This is the one that is shipped with every version of Unity from 3 up to 2023.

It is known by many names: Built-In, Legacy, BiRP or BIRP (for Built-In Render Pipeline), Standard Renderer.

Some call this the "Standard Render Pipeline" and occasionally it is abbreviated as SRP. This causes a lot of confusion since Unity defined the term SRP as an acronym for "Scriptable Render Pipeline" not "Standard Render Pipeline" [4].

If you create a new Unity project and you do not choose URP or HDRP then Built-In is what you will get.

SRP(s): Scriptable Render Pipeline(s)

In 2018 Unity introduced a new set of render pipelines. Their main feature was that things that were unchangeable in the old Built-In renderer could now be changed via code, hence the name Scriptable Render Pipelines (short SRPs).

The SRP framework offers some base code to build upon. Anyone can make his or her own render pipeline. Such a customized pipeline would then be called a Custom Render Pipeline (CRP).

However, not many people do that because Unity offers two premade scriptable render pipelines. Namely the Universal Render Pipeline (URP) and the High Definition Render Pipeline (HDRP). So URP and HDRP are both SRPs but they are not considered CRPs because they have been made by Unity itself.

HINT: A common source of confusion with the new SRPs are post-processing effects. Both URP and HDRP come with their own post-processing effects included. You must not install the "Post Processing Stack v2" package. Using the v2 effects will not work in URP or HDRP.

URP: Universal Render Pipeline (formerly LWRP)

In its first incarnation, the Universal Render Pipeline (URP) was called the Light-Weight Render Pipeline (LWRP). Sometimes you will still stumble upon the term LWRP.

The URP is to be the new default renderer for Unity with a nice balance between graphical fidelity and performance. If you are developing for mobile devices then this is the way to go.

HINT: If a tutorial mentions the LWRP be aware that it may be outdated. The URP has developed quite a bit since then. A lot of features have been added. For example, URP now supports motion blur and screen space ambient occlusion (SSAO). Something that LWRP did not.

Image Source: Screenshot from the BoatAttack URP Demo [5]

HDRP: High Definition Render Pipeline

The High Definition Render Pipeline (HDRP) is the AAA render pipeline. It features physically based rendering (PBR) and focuses on render quality.

Image Source: Screenshot from the Terrain demo [6]

How are shaders defined in Unity?

To create a shader in Unity you use a file ending with ".shader". The language used inside that file is a Unity-specific creation called ShaderLab. However, the actual shader programming in Unity is done in HLSL.

With ShaderLab you can describe everything a shader needs in one file. Unity calls these ShaderObjects. A ShaderObject does not only contain the shader code, it also contains additional information like what parameters to expose and how to display them in the editor.

What is a Surface Shader?

First off, you can use Surface Shaders only in the Built-In render pipeline!

If all the different shader languages and standards give you a headache then you are not alone. Programming a shader that runs on every hardware is a nightmare.

That's why Unity did wrap it all up in one unified programming interface called Surface Shaders.

By using surface shaders you don't have to think about all the different graphics APIs, hardware, and render passes. However, they come with a downside. They are less versatile and you have a little less control over what exactly is happening.

Why we can not use Surface Shaders for URP or HDRP

When Unity introduced the Scriptable-Render-Pipelines (SRPs) in 2018 they were meant to eventually replace the old Built-In render pipeline. However, that did not really work. The community did not appreciate the switch and the Built-In renderer is still alive and kicking.

A look into the asset store statistics tells us that the Built-In renderer will not be gone anytime soon. It's still widely supported.


*Stats based on 84,720 assets analyzed on April 14th, 2023

For the SRPs Unity recommends creating shaders with Shader Graph. You can think of Shader Graph as a visual scripting tool for generating shader code.

The thing is, URP and HDRP do not support SurfaceShaders but Shader Graph supports* them all.

  Built-In URP HDRP
Surface Shaders Yes No No
Shader Graph Yes* Yes* Yes*

*Shader Graph does support the Built-In render pipeline with version 12.0 and up (Unity 2021.2+) [1].

How to write a Surface Shader for the Built-In render pipeline

If you search for Unity shaders online you will still find a lot of surface shader code but also some shader code that does not use surface shaders (vertex, fragment). Mixing vertex and fragment shaders with surface shaders is not a thing. It can cause a lot of frustration as shaders tend to fail silently.

If you try to mix surface with vertex shaders then you will get an error like this:

Shader error in 'Custom/NewSurfaceShader': CGPROGRAM cannot contain #pragma surface as well as other programs

Here is an example of a very minimal surface shader:

Shader "Example/SurfaceShader" {
	SubShader {
		Tags { "RenderType" = "Opaque" }
		CGPROGRAM
		#pragma surface surf Lambert
		struct Input {
			float4 color : COLOR;
		};
		void surf (Input IN, inout SurfaceOutput o) {
			o.Albedo = 1;
		}
		ENDCG
	}
	Fallback "Diffuse"
}

The key part here is this line:

#pragma surface ...

It follows the syntax of "#pragma surface <surface function> <lighting model> <optional parameters>" and tells Unity to compile the function with the given name (usually "surf") as a surface shader.

How to write a Vertex & Fragment Shader for the Built-In render pipeline

The alternative to surface shaders is vertex and fragment shaders. These are more flexible but a bit more cumbersome to write than surface shaders.

Here is an example of a very minimal shader:

Shader "Example/VertexShader"
{
    SubShader
    {
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
            };

            struct v2f
            {
                float4 vertex : SV_POSITION;
            };

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                return o;
            }

            fixed4 frag () : SV_Target
            {
                return fixed4(1,0,0,0);
            }
            ENDCG
        }
    }
}

Notice there is a #pramga vertex and #pragma fragment but no #pragma surface.

If you chose to write your own shader then you should make use of the many custom functions Unity has made (see #include "UnityCG.cginc"). Sadly those are not really documented.

Here is a list of handy links concerning shader programming in Unity:

How to write shaders for URP or HDRP

The SRPs do not support surface shaders and thus writing code for them is quite cumbersome. The decision to not support surface shaders has been criticized heavily by the community [2].

Shader Graph

Unity recommends using Shader Graph instead of writing your own shader code. Shader Graph is a visual, node-based creator for shaders.

Shader Graph is installed through the package manager. If you are using URP or HDRP in your project then you already have it installed automatically.

Here is an example of a very simple Shader Graph shader:

The Built-In render pipeline is supported since Shader Graph 12.0 (Unity 2021.2).

Since URP and HDRP depend on Shader Graph Unity has decided to keep their versions in sync:

Alternatives to Shader Graph

An overview of Shader Graph alternatives

Since there is no surface shader support for the SRPs we have to look for alternatives. The table below lists some possible solutions. As you can see, each one has its drawbacks (*).

  Built-In URP HDRP
Surface Shaders & Vertex / Fragment Shaders Yes No No
Shader Graph Yes* Yes Yes
Block Shaders ➔ No Yes* Yes*
Handmade Shaders  ➔
Yes* Yes* Yes*
Better Shaders* ➔ Yes* Yes* Yes*
Amplify Shaders*  ➔
Yes* Yes* Yes*

*Shader Graph Built-In support starts with version 12.0 (Unity 2021+) [1]. Shader graphs are not as flexible as code.
*As of now it is unknown when Block Shaders will be done. Supporting Built-In is not planned.
*Handwritten shaders can achieve everything you need. They are a lot of work and require some expertise.
*Better Shaders is a script-based paid product by a third party [7].
*Amplify Shaders is a node-based paid product by a third party [8].

Block Shaders: The official (yet unfinished) alternative

In October 2022 Unity announced Block Shaders as a new way of writing shader code [3]. This was probably done in response to the rather negative feedback concerning dropping support for Surface Shaders in the SRPs [2]. From what is known Block Shaders will support all SRPs but not the Built-In render pipeline.

When Block Shaders will be production ready is unknown. There is a public roadmap that you can check for updates.

Handmade Shaders: The cumbersome alternative

If you are proficient in shader programming and the Unity Shader Library then writing shaders by hand may be an option.

If you want to take a look at the code generated by Shader Graph then you can use the "View Generate Shader" option.

However, a lot of code is generated, even for the simplest shader. One reason for that is that all the render passes are spelled out in one file. In the past, the Surface Shader system created them behind the scenes.

Hint: A nice shortcut for mirroring what shader graph nodes do is to check out the Shader Graph Node Library in the manual. The code for each node is listed on the library pages. For example, here are two functions of the Blend Node:

If you really want to write your own custom shader for one of the SRP then here is a worthy read in the Unity forum. It dives into how it can be done.

Better Shaders: The script asset alternative

 
Disclosure: This text may contain affiliate links, which means we may receive a commission if you click a link and purchase something that we have recommended. While clicking these links won't cost you any money, they will help fund this project! The links are created by Unity and Partnerize (Unity's affiliate partner).

Better Shaders is what Surface Shaders would have been if Unity had ported them to the new render pipelines.

The caveat is that is a paid asset by a third-party developer, albeit a well-known one with a history of supporting assets for a long time.

If you want to try before you buy then there is a free version. It is a bit outdated and only for personal use but for evaluation purposes, it should suffice.

Amplify Shader Editor: The graph asset alternative

 
Disclosure: This text may contain affiliate links, which means we may receive a commission if you click a link and purchase something that we have recommended. While clicking these links won't cost you any money, they will help fund this project! The links are created by Unity and Partnerize (Unity's affiliate partner).

Amplify Shader Editor is a graph-based solution like Shader Graph. It supports all render pipelines and has a long-standing history of excellent support and performance.

Asset Recommendations

I hope you liked the article. Here are some asset recommendations. If you buy one of them then some of the money earned will go to this project. Thank you.

Disclosure: This text may contain affiliate links, which means we may receive a commission if you click a link and purchase something that we have recommended. While clicking these links won't cost you any money, they will help fund this project! The links are created by Unity and Partnerize (Unity's affiliate partner).

Sources

  1. Forum Post: https://forum.unity.com/threads/does-shader-graph-support-built-in-rendering.529739/#post-7776870
    Changelog: https://docs.unity3d.com/Packages/com.unity.shadergraph@13.1/changelog/CHANGELOG.html#1200---2021-01-11
  2. Forum Post about Surface  Shaders for SRPs: https://forum.unity.com/threads/srp-surface-shaders.847999/
  3. Forum Post about Shader Blocks: https://forum.unity.com/threads/block-shaders-surface-shaders-for-srps-and-more-public-demo-now-available.1350497/, Shader Blocks Introduction Google Doc: https://docs.google.com/document/d/1GAq6wCAbqLiRDaJR6zLmRlRg4AFIZkli49bM80cN09s/edit, Shader Blocks Roadmap: https://portal.productboard.com/8ufdwj59ehtmsvxenjumxo82/c/1375-block-shaders-surface-shaders-replacement?utm_medium=social&utm_source=portal_share 
  4. Scriptable Render Pipelines Docs: https://docs.unity3d.com/Manual/ScriptableRenderPipeline.html
  5. URP Screenshot from the BoatAttack demo project: https://github.com/Verasl/BoatAttack
  6. HDRP Screenshot from the Unity HDRP Terrain Demo project: https://assetstore.unity.com/packages/3d/environments/unity-terrain-hdrp-demo-scene-213198
  7. Better Shaders is a paid Asset by Json Booth: https://assetstore.unity.com/packages/tools/visual-scripting/better-shaders-2022-standard-urp-hdrp-244057?aid=1100lqC54&pubref=gamedevthings
  8. Amplify Shaders is a paid Asset by Amplify Creations: https://assetstore.unity.com/packages/tools/visual-scripting/amplify-shader-editor-68570?aid=1100lqC54&pubref=gamedevthings