Рекомендуемые методы для DOTS Создание экземпляров шейдеров в URP
Наилучшим решением является инициализация первых 64 байт всех буферов unity_DOTSInstanceData на нуль и оставление их неиспользуемыми. Это потому, что значение метаданных по умолчанию, которое Unity использует для всех значений метаданных, не указанных во время создания пакета, равняется нулю. В частности, когда шейдер загружает нулевое значение метаданных из макроса UNITY_ACCESS_DOTS_INSTANCED_PROP, шейдер загружает это значение с адреса zero, поскольку индекс экземпляра будет игнорироваться. Обеспечение того, чтобы первые 64 байта, которые являются размером наибольшего типа значения (матрица float4x4), были нулевыми, гарантирует, что такие загрузки предсказуемо возвращают результат нулевым. В противном случае шейдер может загрузить что-то непредсказуемое, в зависимости от того, что оказывается расположенным на нулевом адресе.
При использовании DOTS Instancing, Shader Graphs и Shaders, которые предоставляет Unity, используют специальную конвенцию для трансформационных матриц. Чтобы сэкономить GPU память и пропускную способность, они хранят эти матрицы, используя только 12 плавающих знаков вместо полных 16, потому что четыре плавающих знака всегда постоянны. Эти шейдеры ожидают, что плавающие знаки будут форматированы таким образом, что x, y и z каждого столбца матрицы будут храниться в порядке. Другими словами, первые три плавающих знака являются x, y и z первого столбца, следующие три плавающих знака являются x, y и z второго столбца и так далее. Матрицы не хранят элемент w каждого столбца. Трансформационные матрицы, на которые это влияет:
unity_ObjectToWorldunity_WorldToObjectunity_MatrixPreviousMunity_MatrixPreviousMI
В следующем примере кода есть структура, преобразующая обычные матрицы четыре на четыре в соглашение из 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;
}
}