Version: Unity 6.5 Alpha (6000.5)
Language : English
Custom rendering and post-processing for 2D in URP
2D injection points reference in URP

Add a 2D custom render pass to the frame rendering loop in URP

A custom render pass is a way to change how the Universal Render PipelineA series of operations that take the contents of a Scene, and displays them on a screen. Unity lets you choose from pre-built render pipelines, or write your own. More info
See in Glossary
(URP) renders a sceneA Scene contains the environments and menus of your game. Think of each unique Scene file as a unique level. In each Scene, you place your environments, obstacles, and decorations, essentially designing and building your game in pieces. More info
See in Glossary
or the objects within a 2D scene. A custom render pass contains your own rendering code, which you insert into the rendering pipeline at an injection point.

To add a custom render pass in a 2D project, refer to the documentation for 3D projects in Custom render pass workflow in URP.

In a 2D project, make the following changes:

  1. When you write a render pass, use the ScriptableRenderPass2D class instead of the ScriptableRenderPass class.
  2. When you inject a render pass using a Scriptable Renderer Feature, use the ScriptableRendererFeature2D class instead of the ScriptableRendererFeature class.
  3. To inject the render pass, use the renderPassEvent2D property to set a RenderPassEvent2D, instead of the renderPassEvent property. For a list of 2D injection points, refer to Injection points reference for 2D in URP.

To access the texture resources used by the URP 2D renderer, including the active 2D light and shadow textures, use the Universal2DResourceData API. For more information, refer to Frame data in the render graph system in URP.

Example

The following 2D Scriptable Renderer Feature contains an example render pass that creates a texture and clears it to yellow. For more information about adding the render pass to the render pipeline, refer to Add a Renderer Feature to a URP Renderer.

Use the Frame Debugger to check the texture the render pass adds.

using UnityEngine;
using UnityEngine.Rendering.Universal;
using UnityEngine.Rendering.RenderGraphModule;
using UnityEngine.Rendering;

// Create a 2D Scriptable Renderer Feature
public class CreateYellowTextureFeature2D : ScriptableRendererFeature2D
{
    CreateYellowTexture customPass;

    public override void Create()
    {
        customPass = new CreateYellowTexture();

        // Inject the render pass at a 2D injection point
        injectionPoint2D = RenderPassEvent2D.AfterRenderingPostProcessing;
        customPass.renderPassEvent2D = injectionPoint2D;
        customPass.renderPassSortingLayerID = sortingLayerID;
    }

    public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
    {
        renderer.EnqueuePass(customPass);
    }

    // Create a 2D render pass
    class CreateYellowTexture : ScriptableRenderPass2D
    {
        class PassData
        {
            public TextureHandle cameraColorTexture;
        }

        public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameContext)
        {
            using (var builder = renderGraph.AddRasterRenderPass<PassData>("Create yellow texture", out var passData))
            {
                // Get the frame data
                UniversalResourceData frameData = frameContext.Get<UniversalResourceData>();

                // Create texture properties that match the screen size
                TextureDesc textureDesc = frameData.activeColorTexture.GetDescriptor(renderGraph);
                textureDesc.msaaSamples = MSAASamples.None;

                // Create a temporary texture
                passData.cameraColorTexture = renderGraph.CreateTexture(textureDesc);

                // Set the texture as the render target
                builder.SetRenderAttachment(passData.cameraColorTexture, 0, AccessFlags.Write);
    
                // Make sure the render graph system keeps the render pass, even if it's not used in the final frame.
                // Don't use this in production code, because it prevents the render graph system from removing the render pass if it's not needed.
                builder.AllowPassCulling(false);

                builder.SetRenderFunc(static (PassData data, RasterGraphContext context) => ExecutePass(data, context));
            }
        }

        static void ExecutePass(PassData data, RasterGraphContext context)
        {          
            // Clear the render target to yellow
            context.cmd.ClearRenderTarget(true, true, Color.yellow);            
        }
    }

}

Additional resources

Custom rendering and post-processing for 2D in URP
2D injection points reference in URP