Unity を検索

ビルトインシェーダーをユニバーサルレンダーパイプラインへ移行する

2022年9月2日 カテゴリ: テクノロジー | 16 分 で読めます
Migrating to the Universal Render Pipeline (URP) blog, hero
Migrating to the Universal Render Pipeline (URP) blog, hero

このブログ記事は、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 タグの取り扱い、ポストプロセッシングについて説明します。

Introduction to the Universal Render Pipeline for advanced Unity creators e-book

ここで説明するものを含め、数多くのヒントが私たちの e ブック「Introduction to the Universal Render Pipeline for advanced Unity creators」に収録されています。経験豊富な Unity 開発者でもテクニカルアーティストでも、同じようにビルトインレンダーパイプラインから URP にプロジェクトを移行するための手順を追って理解することができます。

シェーダーを 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 シェーダーのソースコードの比較

変換処理中に舞台裏で何が起こっているかを理解するための簡単な練習は、レガシーシェーダーと 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に置き換えることが必要です。

.cgincHLSL
UnityCG.cgincGitHub リンク
AutoLight.cgincGitHub リンク
GitHub リンク

その他の便利な HLSL インクルード

ビルトインシェーダー関数はシェーダーコーディングの基本です。時間を節約できるだけでなく、よく使われる計算の実装を最適化することができます。このインクルードファイルを例にとってみましょう。プラットフォーム固有の機能に関連するいくつかの組み込み関数、一般的な数学関数、テクスチャユーティリティ、テクスチャフォーマットのサンプリング、深度エンコード/デコード、空間変換、地形/ブラシハイトマップのエンコード/デコード、および雑多なユーティリティが含まれています。

e ブック「Introduction to the Universal Render Pipeline for advanced Unity creators」に、ビルトインシェーダーと URP シェーダーの両方における変換関連の関数とプリプロセッサーマクロの参照表が掲載されています。

シェーダーを URP に移植する:上級者向けステップ

LightMode タグ

LightMode タグは、ライティングパイプラインにおけるパス の役割を定義します。ビルトインレンダーパイプラインでは、ライティングと相互作用する必要があるほとんどのシェーダーは、必要なすべての詳細が処理されたサーフェスシェーダーとして記述されています。しかし、カスタムのビルトインシェーダーでは、LightMode タグを使用して、ライティングパイプラインでパスがどのように考慮されるかを指定する必要があります。

下の表は、ビルトインレンダーパイプラインで使用される LightMode タグと URP が期待するタグの対応関係を示しています。いくつかのレガシーなビルトインレンダーパイプラインのタグは、URP ではまったくサポートされていません。

  • MotionVectors
  • PrepassBase
  • PrepassFinal
  • Vertex 
  • VertexLMRGBM
  • VertexLM

同時に、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 シェーダーで置き換えるシェーダーを使用します。

ライトの位置にシャドウカメラが置かれています。これはシェーダーを使って、チェスの駒のジオメトリをテクスチャにレンダリングします。出来上がったテクスチャを後でチェス盤に投影して、チェスの駒の影を表現しています。

The left side of the image shows chess pieces rendered to a texture with the replacement shader. And, on the right, projected shadows use the rendered texture.
左の画像は、チェスの駒をリプレイスメントシェーダーでテクスチャにレンダリングしたもの。右の画像は、投影された影がレンダリングされたテクスチャを使用しているところを示している。

ただし、URP でリプレイスメントシェーダーを使用する方法もあります。チェスの駒の影がどのようにうまく描かれているかを示す、こちらのプロセスをご覧ください(より詳細な情報は、Unity Asset Store で共有されているプロジェクトの Readme ファイルに記載されています)。

  1. Project ウィンドウで右クリックし、新しい URP Renderer アセットを作成します。次に、Create > Rendering > Universal Render Pipeline > Forward Renderer を選択し、例えば Camera Replacement Renderer などの名前を付けます。
  2. Camera Replacement Renderer アセットをクリックして、プロパティを編集します。 新しい URP Renderer アセット
  3. Opaque Layer MaskTransparent Layer Mask の両方を Nothing に設定することでフィルタリングを変更することができます。これは、通常のカメラレンダリングを無効にします(そうしないと、すべてが 2 回レンダリングされます)。
  4. Add Renderer Feature をクリックし、Render Objects (Experimental) を選択します。
  5. 新しく作成された New Render Objects (Render Objects) をクリックし、名前を変更します。いくつかのオプションが表示されますが、そのうち、
    • Filters > Layer Mask をレンダリングしたいレイヤーに設定します。
    • Overrides > Material をリプレイスメントシェーダーを使用しているマテリアルに設定します。
  6. Assets/Settings/UniversalRP-HighQuality.asset を選択し、+ をクリックして新しいレンダラーを追加し、作成した Camera Replacement Renderer アセットをドラッグアンドドロップします。 UniversalRP-HighQuality.asset
  7. リプレイスメントシェーダーを使用していたカメラを選択し、Renderer を Camera Replacement Renderer に設定した新しい URP Renderer アセットに設定します。 リプレイスメントシェーダーを使用したカメラ

ポストプロセッシング

使用できるポストプロセッシングエフェクトは、どのレンダーパイプラインを使うかに依存します。ビルトインレンダーパイプラインのポストプロセッシングは、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 SetPost-Processing V2 に設定してください。

モバイルでは、これらのエフェクトに多くのフレーム時間を割かれるため、ポストプロセッシングは高価な処理となります。モバイルデバイスで URP を使う場合は、以下のモバイル向きのエフェクトの利用を検討してください。

  • ブルーム(高品質フィルタリング無効時)
  • 色収差
  • カラーグレーディング
  • レンズの歪み
  • ビネット

今すぐシェーダーの移植を始める

SRP の導入により、C# スクリプトでレンダリング コマンドをスケジュールし、設定することができるようになったため、これは Unity における最大の変革の 1 つとなりました。URP は、スケーラブルなグラフィックスを効率的に作成し、スムーズなパフォーマンスを実現するように設計されており、ハイエンドデバイスでは最高品質のグラフィックスを、ローエンドデバイスでは最適化されたパフォーマンスを確保します。

この記事で紹介した表は、利用可能な HLSL シェーダー関数、マクロなどのほんの一例です。また、リンクされているインクルードには、他にも便利な機能がたくさんあります。Unity のインストールフォルダーにある CG インクルードなどを調べることで、HLSL で何ができるかを明確に把握し、独自のコンパクトなシェーダーを書くことができます。

これらのリソースをチェックした後、皆さんのシェーダーを URP に移植することが、それほど困難なことではないと思っていただけることを願っています。ご自身の体験やご質問は、URP フォーラムまでお気軽にお寄せください。

2022年9月2日 カテゴリ: テクノロジー | 16 分 で読めます
関連する投稿