マルチフレームレンダリングと蓄積
パストレーシング や蓄積 (accumulation) モーションブラーといった、いくつかのレンダリング技術は、複数の中間サブフレームからの情報を組み合わせて、最終的な "コンバージド" フレームを作成します。各中間サブフレームは多少異なる時点と一致し、物理ベースで蓄積モーションブラーを効果的に演算し、オブジェクトの回転、デフォーメーション、マテリアル、またはライティングの変更を計算に入れます。
High Definition Render Pipeline (HDRP) はスクリプティング API を提供してくれるため、サブフレームの作成およびマルチフレームレンダリングエフェクトの収束を制御できます。特に API を使うと、中間サブフレーム (サンプル) の数とそれぞれと一致する時点を制御できます。さらに、シャッタープロファイルを使い、各サブフレームのウェイトを制御できます。シャッタープロファイルは、実際のカメラがシャッターを開閉するスピードを示します。
API はパストレーシングされた動画の録画に特に便利です。通常シーンを編集する際、パストレーシングのコンバージェンスはシーンが変わるたびに再起動し、アーティストが即時に変更を可視化できるような対話型編集ワークフローを提供します。
次の画像はマルチフレームレコーディング API を使って録画された、パストレーシングと蓄積モーションブラーを含む回転するゲームオブジェクトです。
API 概要
レコーディング API は HDRP で利用可能であり、呼び出しが3つあります:
- BeginRecording: マルチフレームレンダリングを開始したいときに呼び出します。
- PrepareNewSubFrame: 新しいサブフレームをレンダリングする前に呼び出します。
- EndRecording: マルチフレームレンダリングを停止したいときに呼び出します。
すべてのパラメーターを受け付ける呼び出しは BeginRecording のみです。パラメーターについては以下で解説します:
パラメーター | 説明 |
---|---|
Samples | 累積するサブフレームの数です。このパラメーターは ボリューム 内のパストレーシングサンプル数をオーバーライドします。 |
ShutterInterval | 2つの連続したフレーム間でシャッターが開く数です。値が0の場合は、インスタントシャッター (モーションブラーなし) に、値が1の場合は2つのフレーム間に (時間) のギャップがなくなります。 |
ShutterProfile | シャッターインターバル中にシャッターポジションを特定するアニメーションカーブです。代わりにシャッターが完全に開く時間とシャッターが閉まり始める時を指定することもできます。 |
下のスクリプト例では、API コールの使用方法を解説します。
スクリプティング API 例
次の例では、スクリプト内でマルチフレームレンダリング API の使用して、パストレーシングおよびまたは蓄積モーションブラーで収束されたアニメーションシーケンスを正しく録画する方法を解説します。シーンにスクリプトをカメラに添付し、コンポーネントのコンテクストメニューから「レコーディング開始」と「レコーディング停止」アクションをクリックして使います。
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.HighDefinition;
public class FrameManager : MonoBehaviour
{
// 蓄積に使われるサンプル数。
public int samples = 128;
[Range(0.0f, 1.0f)]
public float shutterInterval = 1.0f;
// シャッターが完全に開いているときのシャッターインターバルの時間
[Range(0.0f, 1.0f)]
public float shutterFullyOpen = 0.25f;
// シャッターが閉じ始めるときのシャッターインターバルの時間。
[Range(0.0f, 1.0f)]
public float shutterBeginsClosing = 0.75f;
bool m_Recording = false;
int m_Iteration = 0;
int m_RecordedFrames = 0;
[ContextMenu("Start Recording")]
void BeginMultiframeRendering()
{
RenderPipelineManager.beginFrameRendering += PrepareSubFrameCallBack;
HDRenderPipeline renderPipeline = RenderPipelineManager.currentPipeline as HDRenderPipeline;
renderPipeline.BeginRecording(samples, shutterInterval, shutterFullyOpen, shutterBeginsClosing);
m_Recording = true;
m_Iteration = 0;
m_RecordedFrames = 0;
}
[ContextMenu("Stop Recording")]
void StopMultiframeRendering()
{
RenderPipelineManager.beginFrameRendering -= PrepareSubFrameCallBack;
HDRenderPipeline renderPipeline = RenderPipelineManager.currentPipeline as HDRenderPipeline;
renderPipeline?.EndRecording();
m_Recording = false;
}
void PrepareSubFrameCallBack(ScriptableRenderContext cntx, Camera[] cams)
{
HDRenderPipeline renderPipeline = RenderPipelineManager.currentPipeline as HDRenderPipeline;
if (renderPipeline != null && m_Recording)
{
renderPipeline.PrepareNewSubFrame();
m_Iteration++;
}
if (m_Recording && m_Iteration % samples == 0)
{
ScreenCapture.CaptureScreenshot($"frame_{m_RecordedFrames++}.png");
}
}
void OnDestroy()
{
if (m_Recording)
{
StopMultiframeRendering();
}
}
void OnValidate()
{
// シャッターが完全に開いてからしばらく後に (前でなく) シャッターが閉じ始めることを確認する
shutterBeginsClosing = Mathf.Max(shutterFullyOpen, shutterBeginsClosing);
}
}
シャッタープロファイル
BeginRecording の呼び出しでは、カメラのシャッターの開閉速度を特定できます。カメラのシャッター速度は、いわゆる“シャッターフレーム” を定義します。次の画像は、異なるシャッタープロファイルが、左から右に動く青いスフィアにかかったモーションブラーの外観にどのように影響するかを実演します。
すべてのケースにおいて、スフィアのスピードは同じです。唯一の違いはシャッタープロファイルです。プロファイル図表の水平軸は時間を示し、垂直軸はシャッターが開くことを示します。
開く、閉じるのパラメーターを (0,1)、(1,1)、(0.25, 0.75) にそれぞれ設定すると、アニメーションカーブを使わずに最初の3つのプロファイルを簡単に定義できます。
この例では、ゆっくりと開くプロファイルが、モーションブラーにモーショントレイルが生じることがわかります。これは、アーティストにとってはより望ましいかもしれません。反対に、開閉がスムーズなプロファイルは、ゆっくりと開くまたは一様なプロファイルに比べてよりスムーズなアニメーションが作成できます。
制限
マルチフレームレンダリング API はシーンの Time.timeScale
を内部変更します。つまり:
- カメラごとに異なる蓄積モーションブラーを持つことはできません。
- フレームごとに既にこのパラメータを修正するプロジェクトにこの機能は使えません。