Render to a render texture outside the URP rendering loop
Trigger a camera to render to a Render Texture outside of URP rendering loop.
Read time 3 minutesLast updated 17 days ago
To trigger a camera to render to a render texture outside of the Universal Render Pipeline (URP) rendering loop, use the and APIs in a C# script.
SingleCameraRequestSubmitRenderRequestFollow these steps:
-
Create a render request of thetype. For example:
UniversalRenderPipeline.SingleCameraRequestUniversalRenderPipeline.SingleCameraRequest request = new UniversalRenderPipeline.SingleCameraRequest(); -
Check whether the camera supports the render request type, using theAPI. For example, to check the main camera:
RenderPipeline.SupportsRenderRequestCamera mainCamera = Camera.main;if (RenderPipeline.SupportsRenderRequest(mainCamera, request)){ ...} -
Set the target of the camera to aobject, using the
RenderTextureparameter of the render request. For example:destinationrequest.destination = myRenderTexture; -
Render to the render texture using the SubmitRenderRequest API. For example:RenderPipeline.SubmitRenderRequest(mainCamera, request);
To make sure all cameras finish rendering before you render to the render texture, use either of the following approaches:
- A coroutine that waits for the end of the frame. For more information, refer to the WaitForEndOfFrame API.
- A callback. For more information, refer to the RenderPipelineManager.endContextRendering API.
Example
The following example renders multiple cameras to multiple render textures. To use the example, follow these steps:
- In your Unity project, add the code to a new C# script called .
SingleCameraRenderRequest.cs - Add the script to a GameObject in your scene.
- In the Inspector window of the GameObject, assign the cameras and render textures. Make sure the number of cameras is the same as the number of render textures.
- Enter Play mode.
using System.Collections;using System.Collections.Generic;using UnityEngine;using UnityEngine.Rendering;using UnityEngine.Rendering.Universal;public class SingleCameraRenderRequest : MonoBehaviour{ public Camera[] cameras; public RenderTexture[] renderTextures; void Start() { // Make sure all data is valid before you start the component if (cameras == null || cameras.Length == 0 || renderTextures == null || cameras.Length != renderTextures.Length) { Debug.LogError("Invalid setup"); return; } // Start the asynchronous coroutine StartCoroutine(RenderSingleRequestNextFrame()); // Call a method called OnEndContextRendering when a camera finishes rendering RenderPipelineManager.endContextRendering += OnEndContextRendering; } void OnEndContextRendering(ScriptableRenderContext context, List<Camera> cameras) { // Create a log to show cameras have finished rendering Debug.Log("All cameras have finished rendering."); } void OnDestroy() { // End the subscription to the callback RenderPipelineManager.endContextRendering -= OnEndContextRendering; } IEnumerator RenderSingleRequestNextFrame() { // Wait for the main camera to finish rendering yield return new WaitForEndOfFrame(); // Enqueue one render request for each camera SendSingleRenderRequests(); // Wait for the end of the frame yield return new WaitForEndOfFrame(); // Restart the coroutine StartCoroutine(RenderSingleRequestNextFrame()); } void SendSingleRenderRequests() { //Iterates over the cameras array. for (int i = 0; i < cameras.Length; i++) { UniversalRenderPipeline.SingleCameraRequest request = new UniversalRenderPipeline.SingleCameraRequest(); // Check if the active render pipeline supports the render request if (RenderPipeline.SupportsRenderRequest(cameras[i], request)) { // Set the destination of the camera output to the matching RenderTexture request.destination = renderTextures[i]; // Render the camera output to the RenderTexture synchronously RenderPipeline.SubmitRenderRequest(cameras[i], request); // At this point, the RenderTexture in renderTextures[i] contains the scene rendered from the point // of view of the Camera in cameras[i] } } }}