レンダーループとは、1 つのフレーム内で行われるすべてのレンダリング操作を意味します。このページでは、Unity のスクリプタブルレンダーパイプラインに基づいたカスタムレンダーパイプラインで、シンプルなレンダーループを作成する方法を説明します。
このページのコード例は、スクリプタブルレンダーパイプラインを使用する際の基本原則を示しています。この情報は、独自のカスタムスクリプタブルレンダーパイプラインを構築する際や、Unity にあらかじめ用意されているスクリプタブルレンダーパイプラインがどのように動作するかを理解するために利用できます。
レンダーループのコードを書き始める前に、プロジェクトの準備をする必要があります。
その手順は以下の通りです。
In the Scriptable Render Pipeline, you use the LightMode Pass tag in a Unity shader to determine how to draw geometry. For more information on assigning Pass tags to Unity shaders, see ShaderLab: assigning tags to a Pass.
This task shows you how to create a very simple unlit Unity shader with a LightMode Pass tag value of ExampleLightModeTag
.
// This is a simple unlit Unity shader that is compatible with a custom Scriptable Render Pipeline.
// It applies a hardcoded color, and demonstrates the use of the LightMode Pass tag.
// It is not compatible with SRP Batcher.
Shader "Examples/SimpleUnlitColor"
{
SubShader
{
Pass
{
// The value of the LightMode Pass tag must match the ShaderTagId in ScriptableRenderContext.DrawRenderers
Tags { "LightMode" = "ExampleLightModeTag"}
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
float4x4 unity_MatrixVP;
float4x4 unity_ObjectToWorld;
struct Attributes
{
float4 positionOS : POSITION;
};
struct Varyings
{
float4 positionCS : SV_POSITION;
};
Varyings vert (Attributes IN)
{
Varyings OUT;
float4 worldPos = mul(unity_ObjectToWorld, IN.positionOS);
OUT.positionCS = mul(unity_MatrixVP, worldPos);
return OUT;
}
float4 frag (Varyings IN) : SV_TARGET
{
return float4(0.5,1,0.5,1);
}
ENDHLSL
}
}
}
In order to test that your render loop works, you must create something to render. This task shows you how to put GameObjects in your scene that use the SRP-compatible Unity shader that you created in the previous task.
準備の最終段階では、カスタム SRP に必要な基本的なソースファイルを作成し、Unity にカスタム SRP を使ったレンダリングを開始するように指示します。
RenderPipeline
を継承したクラスと互換性のあるレンダーパイプラインアセットを作成します。単純なレンダーループの基本的な操作は次のとおりです。
消去とは、最後のフレームで描画されたものを取り除くことです。レンダリングターゲットは通常スクリーンですが、テクスチャにレンダリングして「ピクチャーインピクチャー」効果を出すこともできます。これらの例では、Unity のデフォルト動作であるスクリーンへのレンダリング方法を示しています。
スクリプタブルレンダーパイプラインでレンダーターゲットを消去するには、以下を行います。
CommandBuffer
を Clear
コマンドで設定します。CommandBuffer
を ScriptableRenderContext
のコマンドキューに加えます。これを行うには、ScriptableRenderContext.ExecuteCommandBuffer を呼び出します。ScriptableRenderContext
のコマンドキューを実行するように指示します。これを行うには、ScriptableRenderContext.Submit を呼び出します。他のスクリプタブルレンダーパイプラインの操作と同様に、このコードのエントリーポイントとして、RenderPipeline.Render メソッドを使用します。以下のサンプルコードは、その方法を示しています。
/*
これは、カスタムのスクリプタブルレンダーパイプラインの簡略化された例です。
基本的なレンダーループがどのように機能するかを示しています。
最も効率的なランタイムパフォーマンスというよりは、最も明確なワークフローを示しています。
*/
using UnityEngine;
using UnityEngine.Rendering;
public class ExampleRenderPipeline : RenderPipeline {
public ExampleRenderPipeline() {
}
protected override void Render (ScriptableRenderContext context, Camera[] cameras) {
// 現在のレンダーターゲットを消去するコマンドを作成してスケジューリングします
var cmd = new CommandBuffer();
cmd.ClearRenderTarget(true, true, Color.black);
context.ExecuteCommandBuffer(cmd);
cmd.Release();
// スケジュールされたすべてのコマンドを実行するようにグラフィックス API に指示します
context.Submit();
}
}
カリングとは、カメラに映らないジオメトリをフィルタリングする処理です。
スクリプタブルレンダーパイプラインでカリングを行うには、以下を行います。
ScriptableCullingParameters
構造体の値を手動で更新します。CullingResults
構造体に格納します。このサンプルコードは、上の例を拡張したもので、レンダーターゲットをクリアしてからカリング操作を行う方法を示しています。
/*
これは、カスタムのスクリプタブルレンダーパイプラインの簡略化された例です。
基本的なレンダーループがどのように機能するかを示しています。
最も効率的なランタイムパフォーマンスというよりは、最も明確なワークフローを示しています。
*/
using UnityEngine;
using UnityEngine.Rendering;
public class ExampleRenderPipeline : RenderPipeline {
public ExampleRenderPipeline() {
}
protected override void Render (ScriptableRenderContext context, Camera[] cameras) {
// コマンドを作成してスケジューリングし、現在のレンダーターゲットを消去します。
var cmd = new CommandBuffer();
cmd.ClearRenderTarget(true, true, Color.black);
context.ExecuteCommandBuffer(cmd);
cmd.Release();
// すべてのカメラに繰り返します
foreach (Camera camera in cameras)
{
// 使用しているカメラからカリングパラメーターを取得します。
camera.TryGetCullingParameters(out var cullingParameters);
// カリングパラメーターを使ってカリング操作を行い、結果を保存します。
var cullingResults = context.Cull(ref cullingParameters);
}
// すべてのスケジュールされたコマンドを行うよう、グラフィックス API に指示します。
context.Submit();
}
}
描画とは、指定した設定で指定した 1 組のジオメトリを描画するようにグラフィックス API に指示するプロセスです。
SRP で描画するには、以下を行います。
CullingResults
構造体に格納します。このサンプルコードでは、上の例を基に、レンダーターゲットの消去、カリング操作の実行、その結果のジオメトリの描画を行います。
/*
これは、カスタムのスクリプタブルレンダーパイプラインの簡略化された例です。
これは、基本的なレンダーループがどのように機能するかを示しています。 最も効率的なランタイムパフォーマンスというよりは、最も明確なワークフローを示しています。
*/
using UnityEngine;
using UnityEngine.Rendering;
public class ExampleRenderPipeline : RenderPipeline {
public ExampleRenderPipeline() {
}
protected override void Render (ScriptableRenderContext context, Camera[] cameras) {
// 現在のレンダーターゲットを消去するコマンドを作成してスケジューリングします
var cmd = new CommandBuffer();
cmd.ClearRenderTarget(true, true, Color.black);
context.ExecuteCommandBuffer(cmd);
cmd.Release();
// すべてのカメラに繰り返します
foreach (Camera camera in cameras)
{
// 現在のカメラからカリングパラメーターを取得します
camera.TryGetCullingParameters(out var cullingParameters);
// カリングパラメーターを使用してカリング操作を実行し、結果を保存します
var cullingResults = context.Cull(ref cullingParameters);
// 現在のカメラに基づいて、ビルトインのシェーダー変数の値を更新します
context.SetupCameraProperties(camera);
// LightMode パスタグの値に基づいて、 Unity に描画するジオメトリを指示します
ShaderTagId shaderTagId = new ShaderTagId("ExampleLightModeTag");
//現在のカメラに基づいて、Unity にジオメトリを並べ替える方法を指示します
var sortingSettings = new SortingSettings(camera);
// どのジオメトリを描画するかとその描画方法を説明する DrawingSettings 構造体を作成します
DrawingSettings drawingSettings = new DrawingSettings(shaderTagId, sortingSettings);
// カリング結果をフィルタリングする方法を Unity に指示し、描画するジオメトリをさらに指定します
// FilteringSettings.defaultValue を使用して、フィルタリングなしを指定します
FilteringSettings filteringSettings = FilteringSettings.defaultValue;
// 定義した設定に基づいて、ジオメトリを描画するコマンドをスケジューリングします
context.DrawRenderers(cullingResults, ref drawingSettings, ref filteringSettings);
// 必要に応じて、スカイボックスを描画するコマンドをスケジューリングします
if (camera.clearFlags == CameraClearFlags.Skybox && RenderSettings.skybox != null)
{
context.DrawSkybox(camera);
}
// スケジュールされたすべてのコマンドを実行するようにグラフィックス API に指示します
context.Submit();
}
}
}