2013-05-16 1 views
5

параметров для мул HLSL в (х, у) here указано: сказать, чтоHLSL мула() переменные разъяснения

  • если х является вектором, он рассматривается как вектор-строки.
  • если y - вектор, то он рассматривается как вектор-столбец.

ли это, следовать по смыслу, что:

а.

  • если х является вектором, у рассматривается как row-major matrix
  • , если у представляет собой вектор, х рассматривается как column-major matrix

б.

так ID3DXBaseEffect :: SetMatrix() переходит в row-major matrix, поэтому я хотел бы использовать матрицу переходила в затенении в следующем порядке:

отл. Output.mPosition = mul(Input.mPosition, SetMatrix()value);?

Я только начинаю с шейдеров и пересматриваю свою математическую матрицу. Было бы хорошо, если бы кто-нибудь мог это прояснить.

ответ

8

Да, если x - вектор, то x рассматривается как основной вектор строки, а y рассматривается как строчная матрица; наоборот для столбца мажора так для ряда-мажорного матричной системы:

float4 transformed = mul(position, world); 

и столбцы:

float4 transformed = mul(world, position); 

Из-за способом, что умножение матриц работает, если матрица-столбец из основных то вы должны отправить умножить на вектор-столбец, чтобы получить правильный результат. Если матрица имеет значение «строка-майор», вы должны предварительно умножить на вектор строки.

Так что, действительно, hlsl не волнует, является ли ваша матрица строкой или столбцом, вам нужно применить векторное умножение в правильном порядке, чтобы получить правильный результат.

+0

+1 Спасибо, я предполагаю, что это все о заказе потом. Отличная манера ответа! – dk123

+1

Это не совсем верно. Существует различие между «row-major» (что касается компонентов матрицы заказов, которые хранятся в памяти) и «конвенция векторных строк» ​​(которая представляет собой порядок умножения). Матрица здесь * хранится * в строчном порядке в обоих случаях. В первом случае используется вектор строки, а второй - вектор-столбец (и матрица должна была бы быть построена соответствующим образом для каждого). –

12

№ Термины "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 также использует порядок столбцов, но не дает (насколько мне известно) способ изменить его.

Дальнейшее чтение по этим вопросам:

+0

OpenGL позволяет вам указывать порядок строк/столбцов по одной единице с помощью квалификатора 'layout'. Это не часто полезно, поскольку GL API уже позволяет переносить матричную униформу при их отправке, но может быть полезна для однородных буферов. К сожалению, *** только *** применяется к униформам. Конструктор 'mat4', например, всегда будет принимать свои компоненты в порядке сортировки по столбцу, и нет спецификатора макета или всего, что может в данный момент изменить это поведение. –

+0

Кстати, вы уверены, что 'ID3DXBaseEffect :: SetMatrix()' фактически переносит матрицу перед отправкой ее в HLSL? Если бы это было так, то матрица пришла бы в основном порядке столбца, а затем пост-умножение (вектор-столбец матрицы *) было бы подходящим способом. –

+0

@ AndonM.Coleman Не путайте строку-майор с хранилищем столбцов с вектор-вектором и таблицей-вектором. Это два разных варианта конвенции. Ряд-вектор против столбца-вектора влияет на порядок умножения; row-major vs column-major влияет на хранение матричных компонентов в памяти. Как я уже сказал, порядок хранения по умолчанию в HLSL является основным столбцом, тогда как математическая библиотека D3DX на стороне процессора имеет ряд основных характеристик. Поэтому 'SetMatrix()' должен транспонировать матрицу, независимо от того, используете ли вы пре- или пост-умножение в своем коде. –