全ての 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_ObjectToWorldunity_WorldToObjectunity_MatrixPreviousMunity_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;
}
}