№ Термины "row-major" и "column-major" относятся исключительно к порядку хранения компонентов матрицы в памяти. Они не имеют ничего общего с порядком умножения матриц и векторов. Фактически, вызов D3D9 HLSL mul
интерпретирует аргументы матрицы как столбца-майора во всех случаях. Вызов ID3DXBaseEffect::SetMatrix()
интерпретирует его матричный аргумент как строковый ряд и переносит за кулисами на ожидаемый столбец размером mul
.
Если у вас есть матрица, отвлеченно выглядит следующим образом:
[ a b c d ]
[ e f g h ]
[ i j k l ]
[ m n o p ]
затем при хранении в строке-мажорных порядка, его памяти выглядит следующим образом:
a b c d e f g h i j k l m n o p
т.е. элементов строки все смежны в памяти.При хранении в столбцах порядка, его память будет выглядеть следующим образом:
a e i m b f j n c g k o d h l p
с элементами столбца всех смежного. Тем не менее, это имеет точно нулевой эффект на , который является элементом, который. Элемент b
по-прежнему находится в первой строке и второй колонке в любом случае. Маркировка элементов не изменилась, только так, как они отображаются в памяти.
Если вы объявляете массив как float matrix[rows][cols]
в C, то вы используете хранилище строк. Однако некоторые другие языки, такие как FORTRAN, используют по умолчанию хранилище столбцов для своих многомерных массивов; и OpenGL также использует хранилище столбцов.
Теперь, полностью отдельно, есть еще один выбор соглашения, который является использование строки-вектора или вектора-столбца. Это не имеет ничего общего с макетом памяти матриц, но это влияет на то, как вы строите свои матрицы и порядок умножения. При использовании векторов строк, вы будете делать вектор-матричного умножения:
[ a b c d ]
[x y z w] * [ e f g h ] = [x*a + y*e + z*i + w*m, ... ]
[ i j k l ]
[ m n o p ]
и если вы используете векторы-столбцы, то вы будете делать умножения матрицы на вектор:
[ a b c d ] [ x ]
[ e f g h ] * [ y ] = [x*a + y*b + z*c + w*d, ... ]
[ i j k l ] [ z ]
[ m n o p ] [ w ]
Это потому, что в строка-векторная математика, вектор действительно является 1 × n-матрицей (одна строка), а в математике-столбце - матрицей n × 1 (один столбец), а правилу о том, какие размеры матриц разрешены умноженное вместе определяет порядок. (Вы не можете умножить матрицу 4 × 4 на матрицу 1 × 4, но вы можете умножить матрицу 4 × 4 на 4 × 1.)
Обратите внимание, что матрица не изменилась между двумя уравнения выше; изменилась только интерпретация вектора.
Таким образом, чтобы вернуться к первоначальному вопросу:
При передаче вектора HLSL-х mul
, он автоматически интерпретирует это «правильно», согласно которому аргумент это. Если вектор находится справа, это вектор строки, и если он слева, это вектор-столбец.
Однако матрица интерпретируется одинаково всегда. Матрица - это матрица, независимо от того, умножается ли она на вектор строки слева или на столбец справа. Вы можете свободно решать, использовать ли в вашем коде математику строк или векторов-столбцов, если вы согласны с этим. HLSL является агностиком в этой точке, хотя математическая библиотека D3DX использует векторы строк.
И получается, что по какой-то причине в D3D9 HLSL mul
всегда ожидает, что матрицы будут храниться в порядке столбцов. Однако математическая библиотека D3DX хранит матрицы в строчном порядке, и, как говорится в документации, ID3DXBaseEffect::SetMatrix()
ожидает его ввода в строчном порядке. Он выполняет транспонирование за кулисами, чтобы подготовить матрицу для использования с mul
.
BTW, D3D11 HLSL по умолчанию имеет порядок столбцов, но позволяет использовать директиву компилятора, чтобы сказать ему, что вместо этого используется порядок строк. Он по-прежнему агностик относительно математики строк-векторов и столбцов-векторов. И OpenGL GLSL также использует порядок столбцов, но не дает (насколько мне известно) способ изменить его.
Дальнейшее чтение по этим вопросам:
+1 Спасибо, я предполагаю, что это все о заказе потом. Отличная манера ответа! – dk123
Это не совсем верно. Существует различие между «row-major» (что касается компонентов матрицы заказов, которые хранятся в памяти) и «конвенция векторных строк» (которая представляет собой порядок умножения). Матрица здесь * хранится * в строчном порядке в обоих случаях. В первом случае используется вектор строки, а второй - вектор-столбец (и матрица должна была бы быть построена соответствующим образом для каждого). –