Version: Unity 6.0 (6000.0)
言語 : 日本語
カスタムシェーダーでの DOTS Instancing プロパティへのアクセス
URP の DOTS インスタンシングシェーダーの例

URP の DOTS インスタンシングシェーダーのベストプラクティス

全ての unity_DOTSInstanceData バッファの最初の 64 バイトは、ゼロに初期化して未使用のままにすることが推奨されます。なぜなら、バッチ作成中に指定されない全てのメタデータ値に対して Unity が使用するデフォルトのメタデータ値が、ゼロであるためです。具体的には、シェーダーが UNITY_ACCESS_DOTS_INSTANCED_PROP マクロからゼロのメタデータ値をロードする場合、インスタンスインデックスが無視されるため、この値はアドレス zero からロードされます。最初の 64 バイト (最大の値型 [float4x4 行列] のサイズ) を確実にゼロにすることで、このようなロードが予測通りにゼロという結果を返すことを確実にできます。そうしないと、アドレスゼロに何があるかによって、シェーダーが、予測不能なものをロードする可能性があります。

DOTS Instancing を使用する場合、Shader Graph や Unity 提供のシェーダーは、変換行列に特殊な規則を使用します。GPU メモリと帯域幅を節約するために、変換行列は、Float を 16 個フルに使用するのではなく 12 個だけ使用して保存されます (4 つの Float は常に一定であるため)。これらのシェーダーは、行列内の各列の x、y、z が順番に格納される形でフォーマットされた Float を想定します。つまり、最初の 3 つの Float は最初の列の x、y、z であり、次の 3 つの Float は 2 番目の列の x、y、z です。行列は各列の w 要素を保存しません。これが影響する変換行列は以下です。

  • unity_ObjectToWorld
  • unity_WorldToObject
  • unity_MatrixPreviousM
  • unity_MatrixPreviousMI

以下のコードサンプルには、通常の 4×4 行列を “Float 12 個” の規則に変換する構造体が含まれています。

struct PackedMatrix
{
    public float c0x;
    public float c0y;
    public float c0z;
    public float c1x;
    public float c1y;
    public float c1z;
    public float c2x;
    public float c2y;
    public float c2z;
    public float c3x;
    public float c3y;
    public float c3z;

    public PackedMatrix(Matrix4x4 m)
    {
        c0x = m.m00;
        c0y = m.m10;
        c0z = m.m20;
        c1x = m.m01;
        c1y = m.m11;
        c1z = m.m21;
        c2x = m.m02;
        c2y = m.m12;
        c2z = m.m22;
        c3x = m.m03;
        c3y = m.m13;
        c3z = m.m23;
    }
}
カスタムシェーダーでの DOTS Instancing プロパティへのアクセス
URP の DOTS インスタンシングシェーダーの例