前回、SRP Batcher に対応するために CBUFFER
を有効にしてから UnityCG.cginc をインクルードするという内容の記事を書いたんですが、今回はその続きです。
UnityCG.cginc (UnityShaderVariables.cginc) では SRP Batcher に対応するために必要な全てのシェーダー定数を UnityPerDraw
の CBUFFER
に入れていないんです。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 という名前で保存したとしたら、
1 2 3 4 5 6 |
HLSLPROGRAM #pragma enable_cbuffer #include "UnityShaderVariablesForSRPBatcher.cginc" #include "UnityCG.cginc" : ENDHLSL |
という具合になります。enable_cbuffer
のプラグマは Unity 2019.3 以降でしか使えないので、それより前のバージョンでは前回の記事を参考にしてください。
ただし、注意点があります。まず、UnityCG.cginc をインクルードしたときに、本物の UnityShaderVariables.cginc がインクルードされないように、
1 |
#define UNITY_SHADER_VARIABLES_INCLUDED |
を定義しておく必要があります。これはコピーしたときにこの部分を書き換えていなければ OK です。
次に、
1 |
// UNITY_SHADER_NO_UPGRADE |
というコメントをファイルのどこかに入れる必要があります。もしこのコメントがないと、Unity Editor がファイルを書き換えて、次のような変更が加えられます。
1 2 3 4 5 6 7 |
// Upgrade NOTE: commented out 'float3 _WorldSpaceCameraPos', a built-in variable // Upgrade NOTE: commented out 'float4 unity_DynamicLightmapST', a built-in variable // Upgrade NOTE: commented out 'float4 unity_LightmapST', a built-in variable // Upgrade NOTE: commented out 'float4 unity_ShadowFadeCenterAndType', a built-in variable // Upgrade NOTE: commented out UNITY_DECLARE_TEX2D unity_DynamicLightmap, a built-in variable // Upgrade NOTE: replaced 'glstate_matrix_projection' with 'UNITY_MATRIX_P' // Upgrade NOTE: replaced 'glstate_matrix_transpose_modelview0' with 'UNITY_MATRIX_T_MV' |
コメントを入れる代わりに、ファイルの拡張子を UnityEditor が認識できないものにしてもいいですが、その場合 Project ビューに表示されなくなるのでちょっと不便です。また、ファイル名が UnityShaderVariables.cginc のままであれば Unity Editor に書き換えられることはないようです。
あともうひとつ。CGPROGRAM 〜 ENDCG
を使うと、自動で UnityShaderVariables.cginc がインクルードされてしまうので、必ず HLSLPROGRAM 〜 ENDHLSL
を使います。