【Unity6URP】Camera.Render()ではなくRender Requestを使う

これまで独自のタイミングでレンダリングする必要が出てきたときにCamera.Render()を呼んでたけど、
Unity6URPでは「RenderRequest」という機構が用意されていてこちらを使うのが推奨されているようだ。



【この記事を書いたときの環境】
・ Unity 6.3LTE(6000.3.11f1)
・ Universal Render Pipeline 17.3.0

RenderPipeline.SubmitRenderRequestでレンダリングしてみる

以下のコードは、指定したCameraの描画結果を指定したRenderTextureにレンダリングするコードだ。
RenderPipeline.SubmitRenderRequestでレンダリングする。
レンダリングが正常に実行できるかどうかは、RenderPipeline.SupportsRenderRequestで事前に判定できる。

    private void RenderRequest(Camera cam, RenderTexture renderTexture)
    {
        //UniversalRenderPipeline.SingleCameraRequest request = new UniversalRenderPipeline.SingleCameraRequest()
        RenderPipeline.StandardRequest request = new RenderPipeline.StandardRequest()
        {
            destination = renderTexture   //レンダリング結果を指定したレンダラーテクスチャに設定
        };

        if (RenderPipeline.SupportsRenderRequest(cam, request))
        { //レンダリングが正常に実行できるかどうか
            RenderPipeline.SubmitRenderRequest(cam, request); //cam.SubmitRenderRequest(request); でもOK
        }
    }

RenderRequestには以下の2種類のクラスがあります。
・RenderPipeline.StandardRequest
・UniversalRenderPipeline.SingleCameraRequest

この2つのクラスの挙動の違いを確認するために以下のシーンを用意しました。
▼右側のSphere(球体)はOverlayカメラで描画していて、それ以外の描画はBaseカメラで行っているシーン。

RenderPipeline.StandardRequestを使った場合

RenderPipeline.StandardRequestを使うと、カメラスタックの重ね合わせが終わった状態のレンダリング結果がとれる。
このとき指定するカメラは、BaseカメラでもOverlayカメラでも結果は同じ

RenderPipeline.StandardRequest request = new RenderPipeline.StandardRequest();
RenderPipeline.SubmitRenderRequest(cam, request);

▼Baseカメラ+Overlayカメラの描画を重ね合わせた状態の描画がとれた!

Baseカメラの描画だけレンダリングする

Baseカメラの描画だけをレンダリングしたい場合は、UniversalRenderPipeline.SingleCameraRequestを使う。
このときカメラはBaseカメラを設定すること。

using UnityEngine.Rendering.Universal; //←これが必要なので注意

UniversalRenderPipeline.SingleCameraRequest request = new UniversalRenderPipeline.SingleCameraRequest()
RenderPipeline.SubmitRenderRequest(cam, request);

▼Baseカメラで描画している球以外の描画がとれた!

Overlayカメラの描画だけレンダリングできる?

ここまでで、カメラスタックの重ね合わせが終わった描画結果、Baseカメラのみの描画結果がとれるのはわかったが、
Overlayカメラのみの描画結果はとれないのかな?
UniversalRenderPipeline.SingleCameraRequest でOverlayカメラを指定した場合以下の警告がでて意図した結果にならない。

Only Base cameras can be rendered with standalone RenderSingleCamera. Camera will be skipped.

▼RenderPipeline.StandardRequestと同じ、重ね合わせた描画結果がとれてしまった

おまけ:じゃあどうする?

以下のコードで一瞬だけRenderTypeをBaseに変えてみると想定した画像がとれはした。
ただ公式が正式にサポートしている挙動ではなさそうなのでエディタでデバッグするときのみ等、使う場面は限定したほうがよさそう。

    private void RenderRequest(Camera cam, RenderTexture renderTexture)
    {
        UniversalAdditionalCameraData cameraData = cam.GetUniversalAdditionalCameraData();
        CameraRenderType beforeRenderType = cameraData.renderType;
        if (cameraData.renderType == CameraRenderType.Overlay)
        {
            cameraData.renderType = CameraRenderType.Base; //レンダリングする一瞬だけBaseに変える
        }

        UniversalRenderPipeline.SingleCameraRequest request = new UniversalRenderPipeline.SingleCameraRequest()
        {
            destination = renderTexture //レンダリング結果を指定したレンダラーテクスチャに設定
        };

        if (RenderPipeline.SupportsRenderRequest(cam, request)) //レンダリングが正常に実行できるかどうか
        {
            RenderPipeline.SubmitRenderRequest(cam, request); //cam.SubmitRenderRequest(request); でもOK
        }

        cameraData.renderType = beforeRenderType; //もとに戻す
    }

▼一応、Overlayカメラの描画のみがとれた