このブログ記事は、Arm の Roberto Lopez Mendez 氏とのコラボレーションのもとで作成されました。Arm のパートナーは最近、Unity のビルトインレンダーパイプラインをベースにしたプロジェクトをユニバーサルレンダーパイプライン(URP)に移植しました。そこで、そこで得た経験を Unityコミュニティと共有することにしました。
URP は、スクリプタブルレンダーパイプライン(SRP)のビルド済み実装です。幅広いプラットフォームで高度に最適化されたグラフィックスを実現する、アーティストに優しいワークフローを提供します。シェーダーグラフやVisual Effect Graph といったツールを使って作業することで、ノンプログラマーでも URP を使ってシェーダーや GPU ベースのエフェクトをオーサリングすることが可能です。
URP はクリエイターにパフォーマンスと品質のバランスが取れた結果を提供し、高品質なビジュアルを持つゲームやアプリケーションを複数のモバイルデバイスに展開しやすくするような機能を多数サポートしています。ビルトインレンダーパイプラインから URP にプロジェクトを移行する場合、シェーダーを変換するためにいくつか手動のステップを完了する必要があります。
このブログでは、URP に変換された Arm プロジェクトについて説明します。このプロジェクトでは、カスタムシェーダーに Dynamic Soft Shadows Based on Local Cubemaps の実装を利用しています。この記事では、ビルトインレンダーパイプラインから URP への自動シェーダー変換、カスタムシェーダー変換、LightMode タグの取り扱い、ポストプロセッシングについて説明します。
ここで説明するものを含め、数多くのヒントが私たちの e ブック「Introduction to the Universal Render Pipeline for advanced Unity creators」に収録されています。経験豊富な Unity 開発者でもテクニカルアーティストでも、同じようにビルトインレンダーパイプラインから URP にプロジェクトを移行するための手順を追って理解することができます。
まず、URP パッケージをプロジェクトに追加します。Window > Package Manager を選択してパッケージマネージャーを開き、パッケージの一覧から Universal RP をインストールします。シェーダーのアップグレードを実行したら、Edit > Render Pipeline > Universal Render Pipeline > Upgrade Project Materials to URPipeline Materials と進みます。これらの手順により、Unity のビルトインシェーダーが自動的に URP シェーダーのセットに変換されるようになります。
ビルトインのシェーダーを URP に変換するための追加のリソースとして、こちらのチュートリアルと、シェーダーのアップグレードに関するドキュメンテーションをご覧ください。このガイドの中の、どのビルトインシェーダーが特定の URP シェーダーに変換されるかを示した大きな表が役に立ちます。お気づきのように、ほとんどすべてのレガシーシェーダーが Universal Render Pipeline/Simple Lit シェーダーに変換されます。
変換処理中に舞台裏で何が起こっているかを理解するための簡単な練習は、レガシーシェーダーと URP シェーダーの両方のソースコードを見ることです。Unity ダウンロードアーカイブからビルトインシェーダーをダウンロードすることから始めます。Windows または Mac のいずれかのダウンロードオプションをクリックし、Built-in shaders を選択します。ファイルを解凍すると、280 以上のシェーダーが異なるフォルダーにグループ化されていることがわかります。
Mobile-Diffuse シェーダーを例にとって説明します。このシェーダーは URP/Simple Lit シェーダーに変換されます。数多くの URP シェーダーを、URP GitHub レポジトリの Shaders フォルダーや、Unity エンジニアの Felipe Lira の GitHub レポジトリ UniversalShaderExamples で見つけることができます。
Arm の開発者は自分たちのプロジェクトに URP テンプレートに含まれるサンプルシーンを使用することにしました。「Drywall panel」という名前のゲームオブジェクトを選択し、シェーダーを URP/Lit から URP/Simple Lit に変更し、さらに Edit オプションでソースコードにアクセスしたのです。
URP SimpleLit.shader と Mobile-Diffuse.shader を比較すると、まず、サブシェーダータグで「RenderPipeline」=「UniversalPipeline」となるキーバリューペアが使用されていることに気がつきます。
「RenderPipeline」という名前のサブシェーダータグは、どのレンダーパイプラインでサブシェーダーを使用するかを Unity に指示します。「UniversalPipeline」の値は、Unity がこのサブシェーダーを URP で使用することを意味します。
レンダーパスのコードを見ると、シェーダーのコードが HLSLPROGRAM/ENDHLSL マクロを使用して区切られていることがわかります。
これらのマクロは、従来の CG シェーダープログラム言語(C for Graphics)が High-Level Shading Language(HLSL)に置き換わったことを示していますが、シェーダーの構文や機能は基本的に同じです。Unity のシェーダーファイルは、シェーダーのプロパティ、サブシェーダー、パスを定義する ShaderLab シンタックスを使って記述します。URP の場合、それらのパスの中のシェーダーコードは HLSL で書かれています。
ShaderLab のほとんどはビルトインレンダーパイプラインと比較して変更されていませんが、2 つのパイプライン間の内部ライティング処理の変更により、そのパイプライン用に書かれたシェーダーは URP によって自動的に無効化されます。つまり、URP では、ビルトインレンダーパイプラインと比較した場合、シェーダーによるライティングの扱いが異なるということです。
ビルトインレンダーパイプラインはオブジェクトに到達するすべての光に対して別々のシェーダーパスを実行しますが、URP は配列を介してライティングとシェーディングのすべてを 1 つのパスで処理します。この違いにより、URP ではライトデータを格納する構造が異なり、シェーディングのライブラリも新たな規約に従って提供されます。
Unity は、GPU でサポートされている最初の SubShader ブロックを使用します。最初の SubShader ブロックが「RenderPipeline」=「UniversalPipeline」タグを持っていない場合、URP で実行されません。その代わり、Unity は次のサブシェーダーを(あれば)実行しようとします。どのサブシェーダーもサポートされていない場合、Unity はよく知られたマゼンタ色のエラーシェーダーをレンダリングします。
サブシェーダーは複数のパスブロックを含むことができますが、それぞれのパスブロックに特定の LightMode をタグ付けする必要があります。URP はシングルパスのフォワードレンダラーを使用しているので、GPU がサポートする最初の「UniversalForward」パスのみがオブジェクトのレンダリングに使用されます。
幸いなことに、シェーダーアップグレーダーはあなたに代わって、Unity のビルトインシェーダーを URP シェーダーに自動的に変換してくれます。しかし、カスタムシェーダーはどうでしょうか。
カスタムシェーダーは、URP にアップグレードする際に追加作業が必要です。最初のステップとしては、.cgincのインクルードファイルを同等のHLSLに置き換えることが必要です。
.cginc | HLSL |
---|---|
UnityCG.cginc | GitHub リンク |
AutoLight.cginc | GitHub リンク GitHub リンク |
ビルトインシェーダー関数はシェーダーコーディングの基本です。時間を節約できるだけでなく、よく使われる計算の実装を最適化することができます。このインクルードファイルを例にとってみましょう。プラットフォーム固有の機能に関連するいくつかの組み込み関数、一般的な数学関数、テクスチャユーティリティ、テクスチャフォーマットのサンプリング、深度エンコード/デコード、空間変換、地形/ブラシハイトマップのエンコード/デコード、および雑多なユーティリティが含まれています。
e ブック「Introduction to the Universal Render Pipeline for advanced Unity creators」に、ビルトインシェーダーと URP シェーダーの両方における変換関連の関数とプリプロセッサーマクロの参照表が掲載されています。
LightMode タグは、ライティングパイプラインにおけるパス の役割を定義します。ビルトインレンダーパイプラインでは、ライティングと相互作用する必要があるほとんどのシェーダーは、必要なすべての詳細が処理されたサーフェスシェーダーとして記述されています。しかし、カスタムのビルトインシェーダーでは、LightMode タグを使用して、ライティングパイプラインでパスがどのように考慮されるかを指定する必要があります。
下の表は、ビルトインレンダーパイプラインで使用される LightMode タグと URP が期待するタグの対応関係を示しています。いくつかのレガシーなビルトインレンダーパイプラインのタグは、URP ではまったくサポートされていません。
同時に、URPには、ビルトインレンダーパイプラインに対応するものがないタグも存在します。
ビルトイン(詳しくはこちら ) | 説明 | URP(詳しくはこちら) |
---|---|---|
Always | 常にレンダリングされ、ライティングは適用されない | Not supported |
ForwardBase | アンビエントライト、メインのディレクショナルライト、頂点/SH ライト、ライトマップを適用したフォワードレンダリングで使用。 | UniversalForward |
ForwardAdd | フォワードレンダリングで使用、ピクセル単位の加算ライト適用、ライトごとに 1 パス | UniversalForward |
Deferred | デファードシェーディングで使用され、G バッファをレンダリングする。 | UniversalGBuffer |
ShadowCaster | オブジェクトの深度をシャドウマップまたは深度テクスチャにレンダリングします。 | ShadowCaster |
MotionVectors | オブジェクト単位のモーションベクトルを計算するために使用します。 | MotionVectors |
- | URP はこのタグ値をフォワードレンダリングパスで使用します。パスはオブジェクトのジオメトリをレンダリングし、すべての光の寄与を評価します。 | UniversalForwardOnly |
- | URP はこのタグ値を 2D レンダラーで使用します。パスはオブジェクトをレンダリングし、2D ライトの寄与を評価します。 | Universal2D |
- | カメラの視点からの深度情報のみを深度テクスチャにレンダリングするパスです。 | DepthOnly |
Meta | このパスは Unity エディターでライトマップをベイクするときのみ実行されます。Unity はプレイヤーをビルドするときにシェーダーからこのパスを削除します。 | Meta |
- | このタグの値は、オブジェクトのレンダリング時に追加のパスを描画するために使用されます。フォワードレンダリングパスとデファードレンダリングパスのどちらでも有効です。 URP は、パスに LightMode タグがない場合、このタグ値をデフォルト値として使用します。 | SRPDefaultUnlit |
URPは、現時点ではリプレイスメントシェーダーをサポートしていません。Dynamic Soft Shadows Based on Local Cubemaps プロジェクトは、もともとビルトインレンダーパイプライン用に書かれたもので、下の写真のチェスの駒をレンダリングするのに、シンプルな Custom/ctShadowMap シェーダーで置き換えるシェーダーを使用します。
ライトの位置にシャドウカメラが置かれています。これはシェーダーを使って、チェスの駒のジオメトリをテクスチャにレンダリングします。出来上がったテクスチャを後でチェス盤に投影して、チェスの駒の影を表現しています。
ただし、URP でリプレイスメントシェーダーを使用する方法もあります。チェスの駒の影がどのようにうまく描かれているかを示す、こちらのプロセスをご覧ください(より詳細な情報は、Unity Asset Store で共有されているプロジェクトの Readme ファイルに記載されています)。
使用できるポストプロセッシングエフェクトは、どのレンダーパイプラインを使うかに依存します。ビルトインレンダーパイプラインのポストプロセッシングは、URP のポストプロセッシングと互換性がありません。ここで便利な比較を示します。
ビルトイン | URP |
---|---|
ポストプロセッシングソリューションはデフォルトでは含まれていません。ポストプロセッシングエフェクトを活用するには、パッケージマネージャーを使用して、Post-Processing Version 2 パッケージ(別名 Post-Processing Stack V2(PPv2))をダウンロードしてください。 | 独自のポストプロセッシングソリューションが含まれており、URP テンプレートを使用してプロジェクトを作成する際に Unity がそのソリューションをインストールします。URP ポストプロセッシングドキュメンテーションを参照してください。 ポストプロセッシングエフェクトを活用するには、統合された Volume システム(Post-Processing V3/PPv3)をご利用ください。ブルーム、色収差、被写界深度、色調補正、トーンマッピング、ビネットなどのエフェクトが含まれます。 |
Unity 2019.3 向けに URP を開発する際、統合されたポストプロセッシングスタックが実装され、パイプラインにいくつかのパフォーマンス改善をもたらしました。更新されたスタックは、カメラモーションブラーや Volume フレームワークなどの新しいエフェクトに対応するためのものでもありました。
ただし、PPv3 はカスタムのポストプロセッシングエフェクトに対応していないため、Unity 2019.4 LTS でのみフォールバックとして PPv2 への対応が残っています。Unity 2019.4 LTS でカスタムのエフェクトが必要な場合、インストールされているならば、統合ソリューションからポストプロセッシングの Feature Set を Post-Processing V2 に設定してください。
モバイルでは、これらのエフェクトに多くのフレーム時間を割かれるため、ポストプロセッシングは高価な処理となります。モバイルデバイスで URP を使う場合は、以下のモバイル向きのエフェクトの利用を検討してください。
SRP の導入により、C# スクリプトでレンダリング コマンドをスケジュールし、設定することができるようになったため、これは Unity における最大の変革の 1 つとなりました。URP は、スケーラブルなグラフィックスを効率的に作成し、スムーズなパフォーマンスを実現するように設計されており、ハイエンドデバイスでは最高品質のグラフィックスを、ローエンドデバイスでは最適化されたパフォーマンスを確保します。
この記事で紹介した表は、利用可能な HLSL シェーダー関数、マクロなどのほんの一例です。また、リンクされているインクルードには、他にも便利な機能がたくさんあります。Unity のインストールフォルダーにある CG インクルードなどを調べることで、HLSL で何ができるかを明確に把握し、独自のコンパクトなシェーダーを書くことができます。
これらのリソースをチェックした後、皆さんのシェーダーを URP に移植することが、それほど困難なことではないと思っていただけることを願っています。ご自身の体験やご質問は、URP フォーラムまでお気軽にお寄せください。