【Unity】別のカメラから深度、法線、接線を描画するカスタムパス

投稿者: | 2024-03-03

カスタムパスで、メインカメラとは別のカメラからの深度と法線、接線ベクトルをレンダリングするサンプルシーンを詳しく見てみました。

参考:https://github.com/alelievr/HDRP-Custom-Passes?tab=readme-ov-file#depth-capture

カメラ

シーンには2つのカメラがあります。

片方のカメラでは、Cameraコンポーネントが無効になっています。

UI

Canvasに3つのRaw Imageゲームオブジェクトがあります。Raw Imageコンポーネントにはレンダーテクスチャがアタッチされています。

スクリプトも追加されています。スクリプトでは、RectTransformのサイズをレンダーテクスチャに合わせています。

        rt.sizeDelta = new Vector2(debugtexture.width, debugtexture.height) * debugSize;

レンダーテクスチャはProjectウィンドウで右クリックから作成できます。

Nomal・TangentとDepthでは、レンダーテクスチャの設定が違います。

Custom Pass Volume

Custom Pass Volumeコンポーネントでは、独自のカスタムパスが追加されています。カスタムパスには、無効なカメラやレンダーテクスチャがアタッチされています。

カスタムパス

カスタムパスのスクリプトにはExecuteメソッドだけがあります。まず2つ目のカメラのアスペクト比を設定します。レンダーテクスチャのアスペクト比の方が大きいときはそれを使います。

        if (depthTexture != null)
            bakingCamera.aspect = Mathf.Max(bakingCamera.aspect, depthTexture.width / (float)depthTexture.height);
        if (normalTexture != null)
            bakingCamera.aspect = Mathf.Max(bakingCamera.aspect, normalTexture.width / (float)normalTexture.height);
        if (tangentTexture != null)
            bakingCamera.aspect = Mathf.Max(bakingCamera.aspect, tangentTexture.width / (float)tangentTexture.height);

CustomPassContextインスタンスのcullingResultsにカリング結果を表す構造体を入れます。CullingResults構造体には、可視オブジェクトやライトなどの情報が含まれます。

        bakingCamera.TryGetCullingParameters(out var cullingParams);
        cullingParams.cullingOptions = CullingOptions.None;

        // Assign the custom culling result to the context
        // so it'll be used for the following operations
        ctx.cullingResults = ctx.renderContext.Cull(ref cullingParams);

CullingResults構造体を取得するには、ScriptableRenderContext.Cullメソッドを呼びます。引数にカメラから取得したScriptableCullingParametersを渡します。Camera.TryGetCullingParametersメソッドでScriptableCullingParametersを取得できます。

この部分をコメントアウトすると、一部のオブジェクトがレンダーテクスチャに描画されなくなります。

RenderStateBlockをインスタンス化して、デプスステートをオーバーライドします。引数にマスクを渡しています。

        var overrideDepthTest = new RenderStateBlock(RenderStateMask.Depth) { depthState = new DepthState(true, CompareFunction.LessEqual) };

最後に各レンダーテクスチャに深度と法線、接線をレンダリングします。クリアフラッグやカメラのカリングマスク、RenderStateBlockインスタンスを渡しています。

        // Depth
        if (depthTexture != null)
            CustomPassUtils.RenderDepthFromCamera(ctx, bakingCamera, depthTexture, ClearFlag.Depth, bakingCamera.cullingMask, overrideRenderState: overrideDepthTest);

        // Normal
        if (normalTexture != null)
            CustomPassUtils.RenderNormalFromCamera(ctx, bakingCamera, normalTexture, ClearFlag.All, bakingCamera.cullingMask, overrideRenderState: overrideDepthTest);

        // Tangent
        if (tangentTexture != null)
            CustomPassUtils.RenderTangentFromCamera(ctx, bakingCamera, tangentTexture, ClearFlag.All, bakingCamera.cullingMask, overrideRenderState: overrideDepthTest);

これで別のカメラからレンダーテクスチャに描画できます。

参考:
https://github.com/alelievr/HDRP-Custom-Passes?tab=readme-ov-file#depth-capture
https://docs.unity3d.com/ja/2019.4/ScriptReference/Camera.TryGetCullingParameters.html
https://docs.unity3d.com/ja/2019.4/ScriptReference/Rendering.ScriptableCullingParameters.html
https://docs.unity3d.com/ja/2019.4/ScriptReference/Rendering.CullingResults.html
https://docs.unity3d.com/ScriptReference/Rendering.ScriptableRenderContext.Cull.html
https://docs.unity3d.com/ja/2019.4/ScriptReference/Rendering.CullingOptions.html
https://docs.unity3d.com/Packages/com.unity.render-pipelines.high-definition@9.0/api/UnityEngine.Rendering.HighDefinition.CustomPassContext.html

コメントを残す

メールアドレスが公開されることはありません。