arenos-nexus/Arenos Nexus/Library/PackageCache/com.unity.render-pipelines.core@f2c863af5658/Documentation~/in-loop-render-requests.md
Daniel 2e704cae70 init
Init Commit Unity
2025-09-25 22:01:28 +02:00

5.6 KiB

Render from another camera inside a camera's rendering loop

Render from cameras nested inside the render loop of other cameras.

Attach the provided script to a GameObject with a Camera component to nest multiple cameras, that are rendering with RenderPipeline.SubmitRenderRequest, inside the render loop of other cameras.

Note: If your project uses the Universal Render Pipeline (URP), the recommended best practice is to use UniversalRenderPipeline.SingleCameraRequest instead of StandardRequest, to make sure you only render the camera provided to the RenderRequest API instead of the full stack of cameras.

Attach the script to nest

Follow these steps:

  1. Create a new C# script.

  2. Add the using statements shown below and the RequireComponent attribute with the Camera type.

    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.Rendering;
    
    [RequireComponent(typeof(Camera))]
    public class InLoopRenderRequest : MonoBehaviour
    {
    
    }
    
  3. Add a property with the type Camera to the InLoopRenderRequest class.

  4. Add a property with the type RenderTexture for each callback the camera uses, as shown below:

    [RequireComponent(typeof(Camera))]
    public class InLoopRenderRequest : MonoBehaviour
    {
        public Camera renderRequestCamera;
    
        public RenderTexture onBeginCameraRendering;
        public RenderTexture onBeginContextRendering;
        public RenderTexture onEndCameraRendering;
        public RenderTexture onEndContextRendering;
    }
    

Full code example

The following is an example of the finalized code which you attach to the secondary camera:

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;

[RequireComponent(typeof(Camera))]
public class InLoopRenderRequest : MonoBehaviour
{
    // Add a reference to the secondary camera that will render the textures
    // It's recommended to disable the secondary camera.
    public Camera renderRequestCamera;

    // Add references to the Render Textures that will contain the rendered image from the secondary camera.
    public RenderTexture onBeginCameraRendering;
    public RenderTexture onBeginContextRendering;
    public RenderTexture onEndCameraRendering;
    public RenderTexture onEndContextRendering;

    void OnEnable()
    {
        // Subscribe to the RenderPipelineManager callbacks
        RenderPipelineManager.beginCameraRendering += OnBeginCameraRender;
        RenderPipelineManager.beginContextRendering += OnBeginContextRendering;
        RenderPipelineManager.endCameraRendering += OnEndCameraRender;
        RenderPipelineManager.endContextRendering += OnEndContextRendering;
    }

    public void OnDisable()
    {
        // Unsubscribe to the callbacks from RenderPipelineManager when we disable the component
        RenderPipelineManager.beginCameraRendering -= OnBeginCameraRender;
        RenderPipelineManager.beginContextRendering -= OnBeginContextRendering;
        RenderPipelineManager.endCameraRendering -= OnEndCameraRender;
        RenderPipelineManager.endContextRendering -= OnEndContextRendering;
    }

    void SubmitStandardRenderRequest(RenderTexture rt, Camera cam)
    {
        RenderPipeline.StandardRequest request = new();

        // Check that the Scriptable Render Pipeline (SRP) we're using supports the given render data.
        if (RenderPipeline.SupportsRenderRequest(cam, request))
        {
            // Set the request RenderTexture
            request.destination = rt;

            // Render the camera output to the RenderTexture synchronously
            // When this is complete, the RenderTexture in renderTextures[i] contains the scene rendered from the point of view of the secondary cameras
            RenderPipeline.SubmitRenderRequest(cam, request);
        }
    }

    // StandardRequest and UniversalRenderPipeline.SingleCameraRequest also trigger RenderPipelineManager callbacks.
    // Check that the callbacks are from the GameObject's Camera component to avoid a recursive rendering of the same camera.
    private void OnBeginContextRendering(ScriptableRenderContext ctx, List<Camera> cams)
    {
        if (cams.Contains(GetComponent<Camera>()))
        {
            SubmitStandardRenderRequest(onBeginContextRendering, renderRequestCamera);
        }
    }

    private void OnEndContextRendering(ScriptableRenderContext ctx, List<Camera> cams)
    {
        if (cams.Contains(GetComponent<Camera>()))
        {
            SubmitStandardRenderRequest(onEndContextRendering, renderRequestCamera);
        }
    }

    private void OnBeginCameraRender(ScriptableRenderContext ctx, Camera cam)
    {
        if (cam == GetComponent<Camera>())
        {
            SubmitStandardRenderRequest(onBeginCameraRendering, renderRequestCamera);
        }
    }

    private void OnEndCameraRender(ScriptableRenderContext ctx, Camera cam)
    {
        if (cam == GetComponent<Camera>())
        {
            SubmitStandardRenderRequest(onEndCameraRendering, renderRequestCamera);
        }
    }
}

Additional resources