前回、SRP Batcher に対応するために CBUFFER を有効にしてから UnityCG.cginc をインクルードするという内容の記事を書いたんですが、今回はその続きです。

UnityCG.cginc (UnityShaderVariables.cginc) では SRP Batcher に対応するために必要な全てのシェーダー定数を UnityPerDrawCBUFFER に入れていないんです。Unity のブログにも書いてありますが、UnityPerDraw に含めないといけないビルトインのシェーダー定数は次のようになっています。

変数名 UnityCG.cgincを使った場合に宣言される場所 CBUFFER名
float4x4 unity_ObjectToWorld UnityShaderVariables.cginc UnityPerDraw
float4x4 unity_WorldToObject UnityShaderVariables.cginc UnityPerDraw
float4 unity_LODFade UnityShaderVariables.cginc UnityPerDraw
real4 unity_WorldTransformParams UnityShaderVariables.cginc UnityPerDraw
float4 unity_RenderingLayer UnityShaderVariables.cginc UnityPerDraw
real4 unity_SpecCube0_HDR UnityShaderVariables.cginc UnityReflectionProbes
real4 unity_SpecCube1_HDR UnityShaderVariables.cginc UnityReflectionProbes
float4 unity_LightmapST UnityShaderVariables.cginc UnityLightmaps
float4 unity_DynamicLightmapST UnityShaderVariables.cginc UnityLightmaps
real4 unity_SHAr UnityShaderVariables.cginc UnityLighting
real4 unity_SHAg UnityShaderVariables.cginc UnityLighting
real4 unity_SHAb UnityShaderVariables.cginc UnityLighting
real4 unity_SHBr UnityShaderVariables.cginc UnityLighting
real4 unity_SHBg UnityShaderVariables.cginc UnityLighting
real4 unity_SHBb UnityShaderVariables.cginc UnityLighting
real4 unity_SHC UnityShaderVariables.cginc UnityLighting
float4 unity_ProbesOcclusion UnityShaderVariables.cginc UnityLighting
float4 unity_ProbeVolumeParams UnityShaderVariables.cginc UnityProbeVolume
float4x4 unity_ProbeVolumeWorldToObject UnityShaderVariables.cginc UnityProbeVolume
float3 unity_ProbeVolumeSizeInv UnityShaderVariables.cginc UnityProbeVolume
float3 unity_ProbeVolumeMin UnityShaderVariables.cginc UnityProbeVolume
real4 unity_LightData Universal RP のみ N/A
real4 unity_LightIndices[2] Universal RP のみ N/A
float4x4 unity_MatrixPreviousM HDRP のみ N/A
float4x4 unity_MatrixPreviousMI HDRP のみ N/A
float4 unity_MotionVectorsParams HDRP のみ N/A

UnituCG.cginc を使ってしまうと UnityPerDraw に含まれるシェーダー定数は最初の5つのみで、他のシェーダー定数は別の名前の CBUFFER> に含まれてしまいます。シェーダーのコードの中で使っていないシェーダー定数であれば、別の CBUFFER で宣言されていても問題ないので、大抵のシェーダーは SRP Batcher compatible になるんですが、使っている場合は not compatible になってしまいます。
また、表の最後の5つのシェーダー定数は Universal RP や High Definition RP でのみ使われているもので、元々 UnityCG.cginc を使っていたシェーダーには関係ないでしょう。

さて、シェーダーのコードの中で、上記の UnityPerDraw 以外の CBUFFER に含まれるシェーダー定数を必要とする場合、SRP Batcher に対応するためには自分でシェーダー定数を宣言しないといけません。幸い、UnityShaderVariables.cginc はシェーダー定数を宣言するのがメインで、複雑な関数やマクロの定義を含んでいません。なので、UnityShaderVariables.cginc をコピーして必要なシェーダー定数の宣言を UnityPerDraw の中に移動させるのが簡単です。そして、そのファイルをインクルードしてから UnityCG.cginc をインクルードすれば OK です。

例えば、コピーしたファイルを UnityShaderVariablesForSRPBatcher.cginc という名前で保存したとしたら、

という具合になります。enable_cbuffer のプラグマは Unity 2019.3 以降でしか使えないので、それより前のバージョンでは前回の記事を参考にしてください。

ただし、注意点があります。まず、UnityCG.cginc をインクルードしたときに、本物の UnityShaderVariables.cginc がインクルードされないように、

を定義しておく必要があります。これはコピーしたときにこの部分を書き換えていなければ OK です。
次に、

というコメントをファイルのどこかに入れる必要があります。もしこのコメントがないと、Unity Editor がファイルを書き換えて、次のような変更が加えられます。

コメントを入れる代わりに、ファイルの拡張子を UnityEditor が認識できないものにしてもいいですが、その場合 Project ビューに表示されなくなるのでちょっと不便です。また、ファイル名が UnityShaderVariables.cginc のままであれば Unity Editor に書き換えられることはないようです。

あともうひとつ。CGPROGRAM 〜 ENDCG を使うと、自動で UnityShaderVariables.cginc がインクルードされてしまうので、必ず HLSLPROGRAM 〜 ENDHLSL を使います。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

Anti Spam Code *