AOV
AOV (Arbitrary Output Variable、任意の出力変数) は HDRP カメラ が生成できる追加画像です。ピクセルごとに追加情報を出力でき、後から構図に利用したり、追加の画像処理 (例えばノイズ除去など) に使うことができます。
以下は AOV の3例です。左から順に、各ピクセルのアルベド、法線、そしてオブジェクト ID となります。
HDRP では、次の方法で AOV にアクセスおよび設定できます。
- HDRP コンポジターツール を使用する。
- Unity Recorder および AOV Recorder パッケージを使用する。
- スクリプティング API を使用し、シーン中の HDRP カメラのいずれかでカスタム AOV リクエストを設定する。
最初の2つのオプションでは、UI における AOV の選択肢が限られますが、3つ目のオプションは HDRP カメラが出力できるデータに柔軟性があります。
マテリアルプロパティー AOV
以下は AOV API でアクセス可能なマテリアルプロパティーのリストです。
マテリアルプロパティー | 説明 |
---|---|
Normal | 法線を出力します。 |
Albedo | アルベドを出力します。 |
Smoothness | サーフェスのスムースネスを出力します。 |
Ambient Occlusion | アンビエントオクルージョンを出力します (N/A for AxF)。ノート: アンビエントオクルージョン、この出力は アンビエントオクルージョンオーバーライド からのレイトレーシング/スクリーンスペースアンビエントオクルージョンを含みません。シーン中のマテリアルからのアンビエントオクルージョンのみを含みます。 |
Specular | スペキュラーを出力します。 |
Alpha | アルファを出力します (ピクセルカバレッジ)。 |
AOV を使ったライティング選択
AOV を使い ライト の選択リストからコントリビューションを出力したり、またはライトのある特定のコンポーネントのみを出力することができます。
ライティングプロパティー | 説明 |
---|---|
DiffuseOnly | ディフューズライトのみをレンダリングします (直接および間接)。 |
SpecularOnly | スペキュラーライトのみをレンダリングします (直接および間接)。 |
DirectDiffuseOnly | 直接ディフューズライトのみをレンダリングします。 |
DirectSpecularOnly | 直接スペキュラーライトのみをレンダリングします。 |
IndirectDiffuseOnly | 間接ディフューズライトのみをレンダリング。 |
ReflectionOnly | リフレクションのみをレンダリングします。 |
RefractionOnly | 屈折のみをレンダリングします。 |
EmissiveOnly | エミッシブライトのみをレンダリングします。 |
カスタムパス AOV
最後に、AOV を使い カスタムパス の結果を出力できます。特に、すべてのカスタムパス射出点でアクティブなカスタムパスの累計結果を出力することができます。これは、シーンゲームオブジェクトのオブジェクト ID などといった、カスタムパスが演算する任意情報の出力に便利です。
スクリプティング API 例
以下のスクリプト例では、HDRP カメラからアルベド AOV を出力し、その結果のフレームを .png 画像の一連としてディスクに保存します。スクリプト例を使うには、HDRP カメラに添付して再生モードを入力します。
UnityEngine の使用;
UnityEngine.Rendering の使用;
UnityEngine.Rendering.HighDefinition の使用;
UnityEngine.Rendering.HighDefinition.Attributes の使用;
public class AovRecorder : MonoBehaviour
{
RTHandle m_TmpRT; //AOV をレンダリングするために使用される RTHandle
Texture2D m_ReadBackTexture;
int m_Frames = 0;
// 最初のフレーム更新前にスタートが呼び出される
void Start()
{
var camera = gameObject.GetComponent<Camera>();
if (camera != null)
{
var hdAdditionalCameraData = gameObject.GetComponent<HDAdditionalCameraData>();
if (hdAdditionalCameraData != null)
{
// 新しい AOV リクエストを初期化する
var aovRequest = AOVRequest.NewDefault();
AOVBuffers[] aovBuffers = null;
CustomPassAOVBuffers[] customPassAovBuffers = null;
// 面アルベドを含む AOV をリクエストする
aovRequest.SetFullscreenOutput(MaterialSharedProperty.Albedo);
aovBuffers = new[] { AOVBuffers.Color };
// 中間結果を保存する RTHandle を割り当てる
m_TmpRT = RTHandles.Alloc(camera.pixelWidth, camera.pixelHeight);
// リクエストを新しい AOVRequestBuilder に追加する
var aovRequestBuilder = new AOVRequestBuilder();
aovRequestBuilder.Add(aovRequest,
bufferId => m_TmpRT,
null,
aovBuffers,
customPassAovBuffers,
bufferId => m_TmpRT,
(cmd, textures, customPassTextures, properties) =>
{
// AOV データを読み返しディスクに書き込むためにコールバックする
if (textures.Count > 0)
{
m_ReadBackTexture = m_ReadBackTexture ?? new Texture2D(camera.pixelWidth, camera.pixelHeight, TextureFormat.RGBAFloat, false);
RenderTexture.active = textures[0].rt;
m_ReadBackTexture.ReadPixels(new Rect(0, 0, camera.pixelWidth, camera.pixelHeight), 0, 0, false);
m_ReadBackTexture.Apply();
RenderTexture.active = null;
byte[] bytes = m_ReadBackTexture.EncodeToPNG();
System.IO.File.WriteAllBytes($"output_{m_Frames++}.png", bytes);
}
});
// 今度は AOV リクエストの構築をする
var aovRequestDataCollection = aovRequestBuilder.Build();
// 最後にカメラにリクエストを設定する
hdAdditionalCameraData.SetAOVRequests(aovRequestDataCollection);
}
}
}
}