【Unity】URPでDeferred Renderingの概要を学んでサクッと使う

UnityのUniversal Render Pipeline(URP)でDeferred Renderingの概要を学び、簡単に使うところまでをまとめました。

Unity 2021.2.0b7(ベータ版時点の情報です)
Universal RP 12.0.0

はじめに

URP 12.0.0ではレンダリングパスとして、Forwardに加えてDeferredが選択できるようになりました。

本記事ではこのDeferredレンダリングについて、その概要と基本的な使い方をまとめます。
URPの基礎知識については以下にまとめていますので、必要に応じて参照してください。

light11.hatenadiary.com

Forward RenderingとDeferred Rendering

Deferredが入るまでレンダリングパスはForwardだけでした。
Forward Renderingでは、描画対象の各メッシュに対して頂点シェーダで座標変換し、フラグメントシェーダでライティング計算をします。

f:id:halya_11:20210820185147p:plain:w700
Forward Rendering

Deferred Renderingにおいても、まずは描画対象を頂点シェーダとフラグメントシェーダで処理します。
ただしこのとき、Forward Renderingと異なりフラグメントシェーダでライティング計算を行いません。
その代わり、ライティング計算に必要な情報だけをG-Bufferrs(Geometry Buffers)と呼ばれる複数のレンダーターゲットに描き込みます。
具体的にはアルベド、ワールド空間の法線、反射率などといった情報です(設定により異なります)。

f:id:halya_11:20210820185842p:plain:w700
G-Buffer

さてこの時点では上図の通りまだ最終的なレンダリング結果は得られていません。
Deferred Renderingでは、こうして作ったG-Bufferを使って最後にまとめてライティング計算をします。

f:id:halya_11:20210820190748p:plain:w700
Deferred Rendering

URPにおけるForward Renderingとの違い

次にURPにおけるForward RenderingとDeferred Renderingの違いをまとめます。

リアルタイムライトが多数使える

まずDeferred Renderingの大きな特徴として1つのオブジェクトに適用可能なリアルタイムライトの数が多いという点が挙げられます。

URPの場合、Forward Renderingでは1つのオブジェクトに対して反映されるリアルタイムライトの数は9個までです。
これに対してDeferred Renderingでは反映可能なリアルタイムライトの数に制限はありません。

またForward Renderingのように頂点ライティングを併用したりはしないため、クオリティも高いと言えます。

ただし広範囲に影響を与えるリアルタイムライトが多数存在するほど処理負荷は大きくなるので注意が必要です。

半透明描画はForwardパスが使われる

Deferred Renderingはその仕組み上、半透明のオブジェクトを処理できません。
これはG-Bufferパスでジオメトリ情報を二次元のテクスチャに描き込んでしまうことによりオブジェクト同士の重なりの情報が失われるためです。

URPではレンダリングパスをDeferredに設定した場合、半透明のオブジェクトはForwardと同じ方法で処理されます。
したがって半透明のオブジェクトに関しては、前述のライティング面での優位性は失われると言えます。

MSAAが使えない

URPのDeferred RenderingではMSAAは使えません。

これはDeferred RenderingでMSAAを適用しようとすると非常に非効率的な実装となってしまうためです。
詳しくは以下の資料がわかりやすいのでこちらを参照してください。

なぜなにリアルタイムレンダリング

Camera Stackingとの組み合わせ

URPのCamera StackingとDeferredを組み合わせたときにも注意が必要です。
この場合、ベースカメラのみがDeferred Renderingパスで描画されます。
オーバーレイカメラに映ったオブジェクトはForward Renderingパスで描画されます。

要件

URPのDeferred Renderingを使うにはシェーダモデル4.5以上である必要があります。

これはつまり以下の条件を満たすものとなります。

OpenGL ES 3.1 capabilities (DX11 SM5.0 on D3D platforms, just without tessellation shaders). Not supported on DX11 before SM5.0, OpenGL before 4.3 (i.e. Mac), OpenGL ES 2.0/3.0. Supported on DX11+ SM5.0, OpenGL 4.3+, OpenGL ES 3.1, Metal, Vulkan, PS4/XB1 consoles. Has compute shaders, random access texture writes, atomics and so on. No geometry or tessellation shaders. Unity - Manual: Shader compilation: targeting shader models and GPU features より

モバイルでもまあまあいけそうですが、使う前に対応端末を踏まえて調査する必要がありそうです。

設定方法

さて前置きが長くなりましたが、実際にURPでDeferred Renderingを使う方法をまとめます。

と言っても設定は簡単で、Universal Renderer DataのRendering PathをDeferredに変更するだけです。

f:id:halya_11:20210820184347p:plain
Deferredを選択

一点認識すべき設定として、上記の設定を行うとAccurate G-buffer normalsという設定項目が出現します。

f:id:halya_11:20210820195020p:plain
Accurate G-buffer normals

これはG-Bufferに法線情報を格納する方式を設定するためのものです。
チェックを外した状態だと、滑らかなサーフェスがカメラに近づいたときにアーティファクトが発生します。

f:id:halya_11:20210820195224p:plain Deferred Rendering Path in URP | Universal RP | 12.0.0より

チェックをつけると正確な法線情報が格納されアーティファクトはなくなります。
ただしその分処理負荷がかかり、特にモバイルではチェックを外しておいた方が良さそうです。

参考

docs.unity3d.com

docs.unity3d.com