Introduction to Shaders in Unity

Ever wondered about shaders in Unity? In this tutorial, you’ll learn what shaders are, how to display vertex colors and how to animate within shaders. By Joseph Hocking.

4.7 (25) · 1 Review

Download materials
Save for later
Share

Unity provides a lot of help to game developers, and that includes offering Shaders to make complex VFX and animations easier. You can get pretty far just tinkering with the standard Shaders that come with Unity. However, you can enhance the visuals in your projects by writing custom Shaders.

In this tutorial, you’ll learn:

  • What Shaders are.
  • How to display vertex colors.
  • How to animate within Shaders.

To practice, you’ll be polishing the graphics of a desert island scene using custom Shaders. Download the project files by clicking on the Download Materials button at the top or bottom of this tutorial. The sample project provides models and textures so that you can concentrate on the Shaders.

Note: Some of the models and textures that the begin project uses come from Sharegc.com and Textures.com.

The sample project uses Unity 2019.3, although everything in this tutorial should work in older versions as well.

Note: This is an intermediate-level tutorial, which assumes you already know the basics of how to operate Unity. If you’re new to Unity, start with our Introduction to Unity: Getting Started tutorial.

What Are Shaders?

Computer graphics, especially 3D graphics, use many different kinds of information to construct the visuals: meshes, textures, lights and so on. That information passes to the graphics hardware, which then processes the image and displays it onto the screen.

Rendering is what programmers call the process of generating an image, and Shaders are short programs that render graphics data. That is, a Shader is a program that takes meshes, textures etc. as the input and generates an image as the output.

How computers render graphics

Understanding Types of Shaders

Technically, an individual Shader doesn’t output an entire image, nor do they always do rendering. Rather, there are different types of Shaders that do different things.

The main type is a Pixel Shader, named for the obvious reason that it outputs a pixel. Another common term is Fragment Shader, since each pixel is a fragment of the full image.

Fragment Shaders output a single pixel’s color, which it calculates based on that pixel’s position on a polygon. The program runs over and over, mostly in parallel, to generate all the pixels of all the polygons processed by that Shader. Indeed, being able to process more pixels simultaneously is a major part of how video cards accelerate graphics.

There are also Vertex Shaders, which you use to compute the position of vertices in the image. While the input data is in three dimensions, the computer needs to determine where the vertices appear in two dimensions before it can render the pixels.

You can achieve some interesting visual effects by manipulating the data output by Vertex Shaders, but you won’t cover that in this tutorial.

Compute Shaders don’t actually render anything, but are simply programs that run on video hardware. These Shaders are a recent innovation – indeed, older video hardware may not even support them.

As with Fragment and Vertex Shaders, a Compute Shader is a short program that the graphics card runs in a massively-parallel fashion. Unlike the other Shaders, Compute Shaders don’t output anything visual. Instead, they take advantage of the parallel processing in video cards to do things like cryptocurrency mining. You won’t work with Compute Shaders in this tutorial.

Unity introduces yet another kind of Shader, a Surface Shader. These are Shaders that do lighting calculations for you, and you only need to write code – remember, a Shader is a program – to handle other surface properties, like color and texture.

Surface Shaders are really Fragment and Vertex Shaders under the hood, but Unity generates code to handle lighting. This is handy since lighting calculations are both very complicated and frequently standardized between many different Shaders.

Finally, the graphics data tells the video card which Shader to use through materials. When you inspect a material, you’ll notice a menu at the top. That menu selects which Shader to assign to that material. Thus, when the graphics hardware renders a polygon, it runs the Shader of that polygon’s material.

Selecting from the Shader menu

Alright, enough explanation. It’s time to write some Shaders!

Writing a Custom Shader

If you haven’t already, open the begin project then open RW/Scenes/SampleScene. You’ll see a pre-constructed desert island scene, complete with positioned models that have materials assigned to them.

Desert island scene at the start

The existing scene doesn’t look terrible, but you can improve it in at least two ways: The island has hard, square edges, and the water is completely static.

You can solve both issues with custom Shaders. Before addressing those issues, however, you need to understand how to create Shaders.

To start with, create a Surface Shader asset in the Shaders folder by right-clicking and selecting Create ▸ Shader ▸ Standard Surface Shader. Name it MyFirstShader.

Go to the Materials folder, select cartoon-sand and click the Shader drop-down at the top of the Inspector. Select Custom ▸ MyFirstShader to switch the material to that Shader.

selecting MyFirstShader as the shader for the cartoon-sand material

Nothing much will change in the scene yet because you haven’t changed any of the default Shader code. Nevertheless, the sand material on the island now uses your custom Shader rather than the standard Shader built into Unity.

Looking at the Default Template for a Custom Shader

Double-click the Shader asset to open it in your code editor, and examine the code.

The shader is made up of various sections inside the main Shader block of code.

All the code is inside a Shader block with curly brackets, with the name Custom/MyFirstShader. This simply tells Unity what to show when browsing a material’s Shader menu. Looking at the different sections…

Properties

	Properties {
		_Color ("Color", Color) = (1,1,1,1)
		_MainTex ("Albedo (RGB)", 2D) = "white" {}
		_Glossiness ("Smoothness", Range(0,1)) = 0.5
		_Metallic ("Metallic", Range(0,1)) = 0.0
	}

The Properties block at the top is where you declare the various user-defined properties. These are the values you can edit in the inspector when you select a material.

Going over a single line in detail: First, you see the variable name used within the code. Next, inside parentheses, you define the name you’ll display in the inspector. Also inside the parentheses, you declare what type the property is: a color, a 2D texture or a number range. Finally, after the =, you give the property a default value.