ユニバーサルレンダーパイプライン (URP) レンダリングループ外のレンダーテクスチャにレンダリングするカメラをトリガーするには、C# スクリプトで SubmitRenderRequest API を使用します。
この例では、レンダーリクエストとコールバックを使用して、これらのリクエストの進行状況を監視する方法を示します。コードサンプル全体は、コード例 セクションで確認できます。
カメラのフルスタックを考慮せずに 1 台のカメラをレンダリングするには、UniversalRenderPipeline.SingleCameraRequest API を使用します。以下の手順に従ってください。
SingleCameraRenderRequestExample という C# スクリプトを作成し、以下に示す using ステートメントを追加します。
using System.Collections;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
public class SingleCameraRenderRequestExample : MonoBehaviour
{
}
レンダリング元とレンダリング先のカメラとレンダーテクスチャを格納する配列を作成します。
public class SingleCameraRenderRequestExample : MonoBehaviour
{
public Camera[] cameras;
public RenderTexture[] renderTextures;
}
Start メソッドに、スクリプトの実行に進む前に cameras と 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;
}
}
SingleCameraRenderRequest クラス内で名前 SendSingleRenderRequests と戻り値の型 void を持つメソッドを作成します。
以下に示すように、SendSingleRenderRequests メソッドに cameras 配列を反復する for ループを追加します。
void SendSingleRenderRequests()
{
for (int i = 0; i < cameras.Length; i++)
{
}
}
for ループ内で、UniversalRenderPipeline.SingleCameraRequest 型のレンダーリクエストを request という名前の変数に作成します。次に、アクティブなレンダーパイプラインがこのレンダーリクエストの型をサポートしているかどうかを RenderPipeline.SupportsRenderRequest で確認します。
アクティブなレンダーパイプラインがレンダーリクエストをサポートしている場合は、カメラ出力の宛先を renderTextures 配列の一致するレンダーテクスチャに設定します。次に、レンダーリクエストを RenderPipeline.SubmitRenderRequest で送信します。
void SendSingleRenderRequests()
{
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
// When this is complete, the RenderTexture in renderTextures[i] contains the scene rendered from the point
// of view of the Camera in cameras[i]
RenderPipeline.SubmitRenderRequest(cameras[i], request);
}
}
}
SendSingleRenderRequest メソッドの上に、RenderSingleRequestNextFrame という IEnumerator インターフェースを作成します。
RenderSingleRequestNextFrame 内で、メインカメラがレンダリングを終了するのを待ってから、SendSingleRenderRequest を呼び出します。フレームの終了を待ってから、StartCoroutine でコルーチンの RenderSingleRequestNextFrame を再開します。
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());
}
Start メソッドで、StartCoroutine を使用してコルーチンの RenderSingleRequestNextFrame を呼び出します。
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());
}
エディターで、シーンに空のゲームオブジェクトを作成し、SingleCameraRenderRequestExample.cs を コンポーネント として追加します。
Inspector ウィンドウで、レンダリング元のカメラを cameras リストに追加し、レンダリング先のレンダーテクスチャを renderTextures リストに追加します。
ノート:cameras リスト内のカメラの数と、renderTextures リスト内のレンダーテクスチャの数は同じである必要があります。
これで再生モードを開始すると、追加したカメラが追加したレンダーテクスチャにレンダリングされます。
カメラがレンダリングを終了したタイミングを確認するには、RenderPipelineManager API から任意のコールバックを使用します。
以下の例では、RenderPipelineManager.endContextRendering コールバックを使用します。
using System.Collections.Generic を SingleCameraRenderRequestExample.cs ファイルの先頭に追加します。
Start メソッドの終了時に、endContextRendering コールバックにサブスクライブします。
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;
}
OnEndContextRendering というメソッドを作成します。Unity は、endContextRendering コールバックがトリガーしたときにこのメソッドを実行します。
void OnEndContextRendering(ScriptableRenderContext context, List<Camera> cameras)
{
// Create a log to show cameras have finished rendering
Debug.Log("All cameras have finished rendering.");
}
endContextRendering コールバックから OnEndContextRendering メソッドをサブスクライブ解除するには、SingleCameraRenderRequestExample クラスに OnDestroy メソッドを追加します。
void OnDestroy()
{
// End the subscription to the callback
RenderPipelineManager.endContextRendering -= OnEndContextRendering;
}
このスクリプトは以前と同じように動作しますが、どのカメラがレンダリングを終了したかをコンソールウィンドウに記録します。
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()
{
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]
}
}
}
}