Files
Bombaleila/Library/PackageCache/com.unity.render-pipelines.core@04ab0eefa0c3/Documentation~/render-graph-write-render-pass.md
2026-03-03 00:39:30 +05:00

5.9 KiB

Write a render pass using the render graph system in SRP Core

Write a render pass using the render graph system, after you use the BeginRecording API to start recording render graph commands.

Note: This section is about creating a custom render pipeline. To use the render graph system in a prebuilt Unity pipeline, refer to either Render graph system in URP or Render graph system in HDRP.

Prerequisites

To add a render pass, you must first create a render graph instance and start recording. For more information, refer to Write a render pipeline with render graph.

Write a render pass

  1. Create a class or struct that declares the resources the render pass uses. For example:

    class PassData
    {
        public TextureHandle cameraTarget;
        public TextureHandle sourceTexture;
    }
    

    Ensure that you declare only the variables that the render pass uses. Adding unnecessary variables can reduce performance.

  2. Declare the render pass, for example using the AddRasterRenderPass method.

    using (var builder = myRenderGraph.AddRasterRenderPass<PassData>("Example render pass", out var passData))
    {
    }
    

    The builder variable is an instance of the IRasterRenderGraphBuilder interface. This variable is the entry point for configuring the information related to the render pass.

  3. Set the resources that the render pass uses. For example:

    using (var builder = myRenderGraph.AddRasterRenderPass<PassData>("Example render pass", out var passData))
    {
        ...
    
        // Set the source texture as the camera target.
        passData.cameraTarget = myRenderGraph.ImportBackbuffer(BuiltinRenderTextureType.CameraTarget, cameraTargetProperties);
    
        // Set the destination texture as a temporary texture.
        passData.sourceTexture = myRenderGraph.CreateTexture(textureProperties);
    
    }
    
    

    For more information, refer to Resources in the render graph system.

  4. Declare the inputs of the render pass using the UseTexture API, but don't add commands to command buffers. This is the recording stage.

    builder.UseTexture(passData.cameraTarget, AccessFlags.Read);
    
  5. Declare the output of the render pass using the SetRenderAttachment API. For example:

    builder.SetRenderAttachment(passData.sourceTexture, 0, AccessFlags.Write);
    
  6. To add commands, declare a rendering function using the SetRenderFunc API. Use a static method or a static lambda method. This is the execution stage. For example:

    builder.SetRenderFunc(static (PassData passData, RasterGraphContext context) =>
    {
        context.cmd.ClearRenderTarget(true, true, Color.blue); 
    });
    

Example

The following example sets a temporary texture as the input and the camera target as the output, then clears the camera target to blue. To use the example, add it to a custom render pipeline after the BeginRecording API. For more information, refer to Write a render pipeline with render graph.

This code example is simplified. It demonstrates the clearest workflow, rather than the most efficient runtime performance.

using (var builder = myRenderGraph.AddRasterRenderPass<PassData>("Example render pass", out var passData))
{

    RenderTargetInfo cameraTargetProperties = new RenderTargetInfo
    {
        width = cameraToRender.pixelWidth,
        height = cameraToRender.pixelHeight,
        volumeDepth = 1,
        msaaSamples = 1,
        format = GraphicsFormat.R8G8B8A8_UNorm
    };            
    passData.cameraTarget = myRenderGraph.ImportBackbuffer(BuiltinRenderTextureType.CameraTarget, cameraTargetProperties);            

    var textureProperties = new TextureDesc(Vector2.one)
    {
        colorFormat = GraphicsFormat.R8G8B8A8_UNorm,
        width = cameraTargetProperties.width,
        height = cameraTargetProperties.height,
        clearBuffer = true,
        clearColor = Color.red,
        name = "My temporary texture"
    };
    
    passData.sourceTexture = myRenderGraph.CreateTexture(textureProperties);

    passData.material = new Material(Shader.Find("Unlit/Texture")); 

    builder.UseTexture(passData.sourceTexture, AccessFlags.Read);
    builder.SetRenderAttachment(passData.cameraTarget, 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 passData, RasterGraphContext context) =>
    {
        // Create a quad mesh
        Mesh mesh = new Mesh();

        Vector3[] vertices = new Vector3[4]
        {
            new Vector3(0, 0, 0),
            new Vector3(1f, 0, 0),
            new Vector3(0, 1f, 0),
            new Vector3(1f, 1f, 0)
        };
        mesh.vertices = vertices;

        int[] triangles = new int[6]
        {
            0, 2, 1,
            2, 3, 1
        };
        mesh.triangles = triangles;

        context.cmd.ClearRenderTarget(true, true, Color.blue); 

        // Pass the source texture to the shader
        passData.material.SetTexture("_MainTex", passData.sourceTexture);

        // Create a transformation matrix for the quad
        Matrix4x4 trs = Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(0, 0, 0), Vector3.one);

        // Draw the quad onto the camera target, using the shader and the source texture
        context.cmd.DrawMesh(mesh, trs, passData.material, 0);
    });
}