Volumetric Light Scattering as a Custom Renderer Feature in URP

Learn how to create your own custom rendering features with Unity’s Universal Render Pipeline by adding some volumetric light scattering to a small animated scene. By Ignacio del Barrio.

4.7 (9) · 2 Reviews

Download materials
Save for later
Share

One of the most effective ways to make your scenes look absolutely stunning is to add a volumetric lighting effect. Here, you’ll learn how you can easily achieve this stunning effect yourself by harnessing the power of Unity’s Universal Render Pipeline (URP).

If you’re new to Unity development, check out our Getting Started in Unity and Introduction to Shaders in Unity tutorials.

Note: This tutorial assumes that you’re already comfortable working with Unity, C# programming and shaders. An understanding of vector algebra is helpful, but you can still learn a lot without it.

Getting Started

Download the materials for the project using the Download Materials button at the top or bottom of this tutorial. Once you’ve done that, unzip the package and open the starter folder inside Unity.

Next, look at the contents of RW in the Project window:

The Project window

Here’s a quick breakdown of what each folder contains:

  • Animations: Animations for the player character.
  • Materials: Materials to use for the player and environment.
  • Models: Models for the environment and the player.
  • Scenes: The sample scene where you’ll work.
  • Scripts: A bunch of scripts for the sample project.
  • Settings: Assets for Universal Render Pipeline settings.
  • Shaders: An empty folder where your shaders will go.
  • Textures: Textures for the player and debugging.

Don’t worry too much about the contents of all these folders; you’ll mostly work with Scripts and Shaders.

Now, open the Sunset God Rays scene inside RW/Scenes. Look at the scene view and click Play to try the game:

Playing the starter project

You’ll see an overview of the game level. Use the A and D keys to move the player left and right. Jump by pressing Space.

Your goal in this tutorial is to learn how to improve the visuals of the game with some cool volumetric effects, making it more interesting and engaging. Your first step is to understand what volumetric lighting is and how to implement it.

Volumetric Light Scattering

In the real world, light doesn’t travel in a vacuum, where nothing exists between you and the object you are looking at. Unless, of course, you’re in space. :]

In real-time rendering, this is known as the effect of participating media on light transport. The most common phenomenon is fog.

Real-life photograph of crepuscular rays

When the density of particles in the air is high enough, objects that partially occlude a light source will cast shadows on those particles in the form of light beams or rays.

In game design, these are known as god rays or light shafts. This effect lets you enhance the realism and polish of your scenes, making everything look simply beautiful. :]

Next, you’ll look at how to achieve this effect in your Unity games.

Using the Screen Space Method

While not physically accurate, the screen space method is quite simple. First, you render the light source color, then you paint all the objects in your scene black. You do this in an off-screen texture called an occluders map. It looks like this:

Occluders map example

After that, you apply radial blur to the image in post-processing. Starting from the light source center, you take multiple color samples along a vector that goes from the light origin toward the current pixel you’re evaluating. You set the final color of this pixel to the weighted sum of these samples.

An overview of how to sample pixels

Finally, you overlay this image on top of the original color image.

Each step of the screen space method

Now that you understand the process, you’ll see how to apply this concept to your own game.

Creating a Custom Renderer Feature

The Universal Render Pipeline provides a script template to create features. Now you’ll create your very own custom renderer feature.

Inside RW/Scripts, select Create ▸ Rendering ▸ Universal Render Pipeline ▸ Renderer Feature and name the feature VolumetricLightScattering.

Next, double-click VolumetricLightScattering.cs to launch the code editor. You’ll see the following:

How the renderer feature class appears in the editor

This is your renderer feature class. It’s derived from the base abstract class, ScriptableRendererFeature, which enables you to inject render passes into the renderer and execute them upon different events.

ScriptableRendererFeatures are composed of one or many ScriptableRenderPasses. By default, Unity provides you with an empty pass named CustomRenderPass. You’ll learn about the details of this class when you write your custom pass. For now, focus on VolumetricLightScattering.

Unity calls a few methods in a predetermined order as the script runs:

  • Create(): Called when the feature first loads. You’ll use it to create and configure all ScriptableRenderPass instances.
  • AddRenderPasses(): Called every frame, once per camera. You’ll use it to inject your ScriptableRenderPass instances into the ScriptableRenderer.

First, you’ll define some settings to configure this feature. Start by adding the following class above VolumetricLightScattering:

[System.Serializable]
public class VolumetricLightScatteringSettings
{
    [Header("Properties")]
    [Range(0.1f, 1f)]
    public float resolutionScale = 0.5f;

    [Range(0.0f, 1.0f)]
    public float intensity = 1.0f;

    [Range(0.0f, 1.0f)]
    public float blurWidth = 0.85f;
}

VolumetricLightScatteringSettings is a data container for the following feature settings:

  • resolutionScale: Configures the size of your off-screen texture.
  • intensity: Manages the brightness of the light rays you’re generating.
  • blurWidth: The radius of the blur you use when you combine the pixel colors.
Note: You add System.Serializable at the top of the class to make the attributes editable through the inspector.

Next, declare an instance of the settings by adding the following line above Create():

public VolumetricLightScatteringSettings settings = 
    new VolumetricLightScatteringSettings();

This is all you need to get your custom renderer feature ready to use. Save your script and switch to Unity.

Adding the Render Feature to the Forward Renderer

Now that you have a spiffy new renderer feature, you need to add it to the forward renderer.

To do this, find RW/Settings in the Project window and select ForwardRenderer.

The forward renderer inspector

In the Inspector window, select Add Renderer Feature ▸ Volumetric Light Scattering.

Adding the Volumetric Light Scattering feature to the forward renderer

The renderer now uses your renderer feature. Click Settings to show the properties you just defined.

Now, click Play and… you’ll see that nothing has changed. This is because the feature’s render pass doesn’t do anything yet.

Note: If you don’t see the settings in the inspector, try reloading VolumetricLightScattering.cs. Right-click on the script and select Reimport. Go back to the forward renderer — the settings should be visible now.