Getting started
This page walks you through creating a shader, using it in a material and changing it.
Create a shader
- In the Project window, open the folder where you want the shader.
- Select Assets > Create > Shader Script > URP > Lit Shader (or HDRP > Lit Shader in an HDRP project).
- Name the file, for example
MyFirstShader, and press Enter.
The file name becomes the name of the C# class. Use only letters and digits in it: underscores aren't allowed in shader class names.
After Unity compiles the script, a MyFirstShader.shaderscript asset appears next to MyFirstShader.cs. This asset is the shader. Its name in Unity's shader menus is Shader Scripts/MyFirstShader.
Note
The URP and HDRP templates only differ in the optional attributes they list as comments. A shader created from either template works on both render pipelines.
Use it in a material
- Select the MyFirstShader.shaderscript asset.
- Select Assets > Create > Material. The new material uses the shader.
To switch an existing material to the shader, open the Shader dropdown at the top of its Inspector and select Shader Scripts > MyFirstShader.
The Material Inspector shows the same sections as the render pipeline's own Lit shader, with the shader's properties in Surface Inputs.
Anatomy of a shader
Open MyFirstShader.cs. Without the comments, it looks like this:
using Ahilevich.ShaderScript;
[Shader]
public class MyFirstShader : ShaderScript.Lit
{
[DisplayName("Base Map"), MainTexture]
public Texture2D BaseMap { get; } = Texture2D.White;
[Inline, MainColor]
public float4 BaseColor { get; } = new float4(1, 1, 1, 1);
[Range(0, 1)] public float Smoothness { get; } = 0.5f;
[Range(0, 1)] public float Metallic { get; } = 0f;
public override void Vert(VertexInput IN, ref VertexOutput OUT)
{
}
public override void Frag(FragmentInput IN, ref LitFragmentOutput OUT)
{
float2 uv = BaseMap.GetTransformedUV(IN.uv0);
float4 color = BaseMap.Sample(uv) * BaseColor;
OUT.albedo = (half3)color.rgb;
OUT.alpha = color.a;
OUT.smoothness = Smoothness;
OUT.metallic = Metallic;
}
}
[Shader]marks the class as a shader. Without an argument, the shader is namedShader Scripts/<ClassName>; use[Shader("My Shaders/Name")]to choose the name.ShaderScript.Litis the kind of shader. A lit shader describes a surface, and the render pipeline lights it. The other kinds areShaderScript.Unlit, which outputs a final color, andShaderScript.Fullscreen, for post-processing effects.- Properties become material properties. Their type decides the kind of property (
Texture2Dfor a texture,float4for a vector or a color,floatfor a number), their initial value is the default value, and attributes change how they're shown:[Range(0, 1)]draws a slider,[Inline]puts the color on the same line as the texture. Vertruns once for each vertex of the mesh. The empty method keeps the mesh as it is.Fragruns once for each pixel.INholds the data interpolated for the pixel, such as its UVs, position and normal.OUTdescribes the surface: its color (albedo), opacity, smoothness, metalness and more. Fields you don't set keep their defaults.
Shader code uses the types of HLSL, the shading language Unity shaders are written in: float for a number, float2 to float4 for vectors, half3 for a lower-precision vector. Casts like (half3)color.rgb convert between them.
Change the shader
Edit Frag to add a rim of light at the edges of the object:
[Range(0, 5)] public float RimPower { get; } = 3;
[HDR, Color] public float4 RimColor { get; } = new float4(0, 1, 1, 1);
public override void Frag(FragmentInput IN, ref LitFragmentOutput OUT)
{
float2 uv = BaseMap.GetTransformedUV(IN.uv0);
float4 color = BaseMap.Sample(uv) * BaseColor;
float3 viewDir = ShaderApi.GetWorldSpaceNormalizeViewDir(IN.positionWS);
float rim = ShaderLib.FresnelEffect(IN.normalWS, viewDir, RimPower);
OUT.albedo = (half3)color.rgb;
OUT.alpha = color.a;
OUT.smoothness = Smoothness;
OUT.metallic = Metallic;
OUT.emission = RimColor.rgb * rim;
}
Save the file. When Unity finishes compiling, the shader and every material that uses it update, and the material shows the two new properties.
When something goes wrong
- C# errors and Shader Script's own checks appear in your IDE and in the Console as regular compiler errors, for example when the code uses a C# feature that can't run on the GPU. Each has an error code and a message that says what to change. Visual Studio shows Shader Script's checks only when you save or build, unless you change a setting: see Diagnostics.
- Shader compilation errors appear in the Console. Double-click one to open the generated shader code at the failing line.
- The Inspector of the
.shaderscriptasset has two buttons: Open Shader Editor opens the C# file, and View Generated Shader opens the complete shader that Shader Script generated. - If a
.shaderscriptasset is missing, run Tools > Shader Script > Reimport All.
See Diagnostics for the error codes, and Debugging shaders for more.
Next steps
- Learn how shader code gets its data in the section on input and output data.
- Browse the attributes to change the surface: transparency, blending, face culling and more.
- Try the other templates in Assets > Create > Shader Script: Unlit and Fullscreen shaders, and shared code.
- Import the samples: select Shader Script in the Package Manager and open its Samples. Reproduced URP and HDRP Shaders contains exact reproductions of URP's and HDRP's own Lit and Unlit shaders, written with Shader Script: a starting point for your own shaders. They appear under Shader Script Samples in the shader menu.