Universal Render Pipeline(URP)乗り換えハマりポイントまとめ

公開:2021/02/19
更新:2021/02/19
6 min読了の目安(約5500字TECH技術記事

概要

Built-in Render PipelineからUniversal Render Pipeline(以下URP)への乗り換えでわかりにくかったところなどをまとめてみます

環境は、Unity2020.1.15f1 > Unity2020.2.3f1 + URP10.2.2です

インストール

とりあえずこちらのドキュメントに沿っていけばオッケーです
Installing the Universal Render Pipeline into an existing Project

ざっくり次のような感じです

  1. PostProcessing Stack v2を使ってたら削除
    URPにほぼ同様の機能が内包されているので事前に消しておく
  2. PacakgeManagerでURPをインストール
  3. 設定ファイルを作成
  4. Graphicsセッテイングで3.のファイルを指定

乗り換え

Unity組み込みシェーダーの置換

Upgrading your Shaders
かわりのシェーダーとマテリアルの変換コマンドが用意されています

OnRenderObject()内でCamera.current==nullになる

仕様のようです
RenderPipelineManager.beginCameraRenderingイベントでカメラを覚えておく方法で対応できます

Camera currentCamera;

void OnEnable()
{
    RenderPipelineManager.beginCameraRendering += OnBeginCameraRendering;
}

void OnDisable()
{
    RenderPipelineManager.beginCameraRendering -= OnBeginCameraRendering;
}

void OnBeginCameraRendering(ScriptableRenderContext context, Camera camera)
{
    currentCamera = camera;
}

void OnRenderObject()
{
    if ((currentCamera == null) || (currentCamera.cullingMask & (1 << gameObject.layer)) == 0)
    {
        return;
    }

    ~処理~
}

https://forum.unity.com/threads/camera-current-returns-null-when-calling-it-in-onwillrenderobject-with-universalrp.929880/

OnPreCull(),OnPreRender(),OnPostRender()非サポート

カメラにアタッチされているコンポーネント用のイベントが呼ばれなくなりました
シビアなケースでなければ上記OnRenderObject()のケース同様、RenderPipelineManagerのイベントで代用出来そうです

OnRenderImage()非サポート

カメラアタッチイベントなのでOnRenderImage()もサポートされなくなったのですが簡単な代用方法がなさそうです

Render Featureという自作のレンダリングパスを追加する機能があるので、これを利用するのがよさそうです

https://forum.unity.com/threads/replacing-onrenderimage-graphics-blit-in-urp.857278/

カメラを重ねる方法が変更

カメラの絵を重ねて描画する方法が変わっています
カメラのCleaflags=Depth Only/Don't ClearにしてDepthの数値で処理順を調整して重ねていましたが、これらのパラメータがインスペクタ上に表示されなくなり出来なくなっています

URPではかわりにCamera Stacking機能を使います

上になるカメラのRenderTypeOverlayにして

下になるカメラ(RenderTypeBase)のStackに追加します

これで重ねて描画されます
いままでのDepth管理だと重なり順がわかりづらかったのでこれはいいですね

DepthバッファのクリアはOverlayにしたカメラのRendering > ClearDepthで指定できます

Shader乗り換え

UnityCG.cginc > Core.hlsl

UnityCG.cgincの代わりにCore.hlslをincludeします
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"

CGPROGRAM > HLSLPROGRAM

CGPROGRAM / ENDCGではなくHLSLPROGRAM / ENDHLSLを使うのが推奨されています

そもそもこの違いは、HLSLSupport.cgincUnityShaderVariables.cgincが自動的にincludeされるかどうかだけのようです(前者だとされる)

これらのファイルで定義されている関数がURPの定義と衝突することがあるのでHLSLPROGRAM推奨とのことです

NOTE: HLSL language is the preferred language for URP shaders.
NOTE: URP supports the CG language. If you add the CGPROGRAM/ENDCGPROGRAM block in a shader, Unity includes shaders from the Built-in Render Pipeline library automatically. If you include shaders from the SRP shader library, some SRP shader macros and functions might conflict with the Built-in Render Pipeline shader functions. Shaders with the CGPROGRAM block are not SRP Batcher compatible.

https://docs.unity3d.com/Packages/com.unity.render-pipelines.universal@10.3/manual/writing-shaders-urp-basic-unlit-structure.html

ビルドイン関数名変更

Core.hlslでは、ビルトイン関数がなくなったり名前が変わっていたりします

UnityObjectToClipPos()がないのがよくひっかかるところかと思います

URPの座標系変換関数は次のファイルで定義されています(Core.hlsl経由でincludeされます)
Packages/com.unity.render-pipelines.universal/ShaderLibrary/SpaceTransforms.hlsl

float3 TransformObjectToWorld(float3 positionOS)
float3 TransformWorldToObject(float3 positionWS)
float3 TransformWorldToView(float3 positionWS)
float4 TransformObjectToHClip(float3 positionOS)

など

UnityObjectToClipPos()のかわりはTransformObjectToHClip()になります

とは言いつつ結構そのまま動く

手元の環境では特になにも書き換えなくてもそのまま動くシェーダーも結構多くありました
(ライティングまわりを全然触っていなかったからかな、という気もします)
乗り換え作業としては、エラーが出たところだけHLSLPROGRAM,Core.hlsl形式に書き換えていくというのも全然ありだと思います

機能比較表

公式にBuilt-in Render Pipelineとの比較表が公開されています
上記以外にもいろいろあるので乗り換えの際には一度目を通してみるのをおすすめします

https://docs.unity3d.com/Packages/com.unity.render-pipelines.universal@10.3/manual/universalrp-builtin-feature-comparison.html

個人的にはProjector非対応なのが痛いです
そのうち自前実装しなくちゃいけなくなりそうな気がします

参考

http://tips.hecomi.com/entry/2019/10/27/152520