140 lines
5.6 KiB
Markdown
140 lines
5.6 KiB
Markdown
|
|
# 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](https://docs.unity3d.com/6000.0/Documentation/ScriptReference/Rendering.RenderPipeline.SubmitRenderRequest.html), inside the render loop of other cameras.
|
||
|
|
|
||
|
|
**Note**: If your project uses the [Universal Render Pipeline](https://docs.unity3d.com/Manual/urp/urp-introduction.html) (URP), the recommended best practice is to use [UniversalRenderPipeline.SingleCameraRequest](https://docs.unity3d.com/Packages/com.unity.render-pipelines.universal@17.2/api/UnityEngine.Rendering.Universal.UniversalRenderPipeline.SingleCameraRequest.html) instead of [StandardRequest](https://docs.unity3d.com/6000.0/Documentation/ScriptReference/Rendering.RenderPipeline.StandardRequest.html), 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.
|
||
|
|
|
||
|
|
```c#
|
||
|
|
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:
|
||
|
|
|
||
|
|
```c#
|
||
|
|
[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:
|
||
|
|
|
||
|
|
```c#
|
||
|
|
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
|
||
|
|
- [Render Requests](User-Render-Requests.md)
|
||
|
|
- [Creating a custom render pipeline](srp-custom.md)
|
||
|
|
|