프로그램에서 채워진 행렬을 보면 변환 구성 요소가 4, 8 및 12 번째 요소를 차지하는 것을 볼 수 있습니다.
시작하기 전에 이해하는 것이 중요합니다. 이는 행렬이 행 메이저 임을 의미합니다 . 따라서이 질문에 대답하십시오.
내 열 주요 WVP 행렬은 HLSL 호출 mul (vector, matrix)로 정점을 변환하는 데 성공적으로 사용됩니다. 이로 인해 벡터가 행 주요로 처리되어야하므로 수학 라이브러리에서 제공하는 열 주요 행렬은 어떻게 작동합니까?
아주 간단합니다. 행렬이 행을 크게합니다.
많은 사람들이 행 전공 또는 전치 행렬을 사용하므로 행렬이 자연스럽게 그렇게 지향되지 않는다는 사실을 잊어 버립니다. 그래서 그들은 번역 행렬을 다음과 같이 봅니다 :
1 0 0 0
0 1 0 0
0 0 1 0
x y z 1
이것은 바뀐 번역 행렬 입니다. 그것은 일반적인 변환 행렬이 아닙니다. 번역은 4 간다 열 이 아닌 네 번째 행. 때로는 교과서에서 이것을 볼 수도 있습니다.
배열의 행렬이 행인지 열인지를 쉽게 알 수 있습니다. 행이 큰 경우 변환은 3, 7, 11 번째 인덱스에 저장됩니다. 열이 큰 경우 번역은 12, 13 및 14 번째 인덱스에 저장됩니다. 물론 제로 기준 지수.
혼란은 실제로 행 주요 행렬을 사용할 때 열 주요 행렬을 사용하고 있다는 믿음에서 비롯됩니다.
행 대 열 전공은 표기법에 불과하다는 진술은 전적으로 사실입니다. 행렬 곱셈과 행렬 / 벡터 곱셈의 역학은 규칙에 관계없이 동일합니다.
변화의 결과는 결과의 의미입니다.
결국 4x4 매트릭스는 단지 4x4 그리드 숫자입니다. 좌표계 변경을 언급 할 필요 는 없습니다 . 그러나 일단 특정 행렬에 의미 를 부여 하면 이제 저장된 내용과 사용 방법을 알아야합니다.
위에서 보여준 변환 행렬을 보자. 유효한 행렬입니다. 다음 float[16]
두 가지 방법 중 하나로 해당 매트릭스를 저장할 수 있습니다 .
float row_major_t[16] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, x, y, z, 1};
float column_major_t[16] = {1, 0, 0, x, 0, 1, 0, y, 0, 0, 1, z, 0, 0, 0, 1};
그러나 번역이 잘못된 위치에 있기 때문에이 변환 행렬이 잘못되었다고 말했습니다. 필자는 번역 행렬을 작성하는 방법에 대한 표준 규칙과 관련하여 다음과 같이 바뀌 었습니다.
1 0 0 x
0 1 0 y
0 0 1 z
0 0 0 1
이들이 어떻게 저장되는지 봅시다 :
float row_major[16] = {1, 0, 0, x, 0, 1, 0, y, 0, 0, 1, z, 0, 0, 0, 1};
float column_major[16] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, x, y, z, 1};
공지 사항 column_major
입니다 동일 로 row_major_t
. 따라서 적절한 변환 행렬을 가져 와서 열 주요로 저장하면 해당 행렬을 바꾸고 행 주요로 저장하는 것과 같습니다.
그것이 표기법 일 뿐이라는 의미입니다. 메모리 저장과 전치라는 두 가지 규칙이 있습니다. 메모리 스토리지는 열 대 행 메이저이며, 조옮김은 정상 대 조옮김입니다.
행 주요 순서로 생성 된 행렬이있는 경우 해당 행렬과 동등한 열 주요 변환을 변환하여 동일한 효과를 얻을 수 있습니다. 그 반대.
행렬 곱셈은 한 가지 방법으로 만 수행 할 수 있습니다. 두 개의 행렬이 지정된 순서대로 특정 값을 곱하고 결과를 저장합니다. 자, A*B != B*A
하지만, 실제 소스 코드 A*B
에 대한 코드와 동일합니다 B*A
. 둘 다 동일한 코드를 실행하여 출력을 계산합니다.
행렬 곱셈 코드는 행렬이 열 주요 또는 행 주요 순서로 저장되는지 여부를 신경 쓰지 않습니다.
동일 없는 벡터 / 행렬 곱셈라고 할. 그리고 여기에 이유가 있습니다.
벡터 / 행렬 곱셈은 잘못된 것입니다. 할 수 없습니다. 그러나 행렬에 다른 행렬을 곱할 수 있습니다 . 따라서 벡터가 행렬 인 경우 행렬 / 행렬 곱셈을 수행하여 벡터 / 행렬 곱셈을 효과적으로 수행 할 수 있습니다.
4D 벡터는 열 벡터 또는 행 벡터로 간주 될 수 있습니다. 즉, 4D 벡터는 4x1 행렬 (행렬 표기법에서는 행 개수가 먼저 됨) 또는 1x4 행렬로 생각할 수 있습니다.
두 가지 행렬 A와 B가 주어지면 A A*B
의 열 수가 B의 행 수와 동일한 경우에만 정의됩니다. 따라서 A가 4x4 행렬 인 경우 B는 4 개의 행이있는 행렬이어야합니다. 그 안에. 따라서을 수행 할 수 없습니다 A*x
. 여기서 x는 행 벡터 입니다. 마찬가지로 x*A
x가 열 벡터 인 경우 수행 할 수 없습니다 .
이 때문에 대부분의 행렬 수학 라이브러리는 다음과 같은 가정을합니다. 벡터에 행렬을 곱하면 벡터는 실제로 작동 하는 곱셈을 의미합니다.
4D 벡터 x에 대해 다음을 정의합시다. C
열 - 벡터한다 매트릭스 의 형태 x
, 및 R
, 행 벡터한다 매트릭스 형태 x
. 이를 감안할 때, 4x4 행렬 A*C
A에 대해 A에 열-벡터를 곱한 행렬을 나타냅니다 x
. 그리고 R*A
행 벡터 x
에 A를 곱한 행렬을 나타냅니다 .
그러나 우리가 엄격한 행렬 수학을 사용하여 이것을 살펴보면 이것들이 동등하지 않다는 것을 알 수 있습니다 . 와 같을 R*A
수 없습니다A*C
. 행 벡터는 열 벡터와 같지 않기 때문입니다. 그것들은 동일한 행렬이 아니므로 동일한 결과를 생성하지 않습니다.
그러나 한 가지 방식으로 관련되어 있습니다. 사실이다 R != C
. 그러나 여기서 T 는 전치 연산입니다. 두 행렬은 서로 바뀝니다.R = CT
재미있는 사실이 있습니다. 벡터는 행렬로 취급되기 때문에 열 대 행 주요 저장 문제가 있습니다. 문제는 둘 다 똑같이 보인다는 것 입니다. float의 배열은 동일하므로 데이터를 보면 R과 C의 차이점을 알 수 없습니다. 에만 차이를 구별하는 방법은 그들이 사용하는 방법입니다.
두 개의 행렬 A와 B가 있고 A가 행 주요로 저장되고 B가 열 주요로 저장되는 경우, 곱하는 것은 완전히 의미 가 없습니다 . 결과적으로 말도 안됩니다. 글쎄,별로. 수학적으로 얻을 수있는 것은하는 것과 같습니다 . 또는 ; 그것들은 수학적으로 동일합니다.AT*B
A*BT
따라서 행렬 곱셈은 두 행렬 (그리고 벡터 / 행렬 곱셈은 행렬 곱 임일뿐)이 동일한 주요 순서로 저장된 경우에만 의미가 있습니다.
그렇다면 벡터 열 주요 또는 행 주요입니까? 앞에서 언급했듯이 둘 다입니다. 열 행렬로 사용되는 경우에만 열 주요이며 행 행렬로 사용되는 경우 주요 행입니다.
따라서 주요 열인 행렬 A가 있으면 x*A
아무것도 의미하지 않습니다. 다시, 그것은을 의미 하지만 , 그것은 당신이 정말로 원했던 것이 아닙니다. 마찬가지로 행이 큰 경우 곱셈을 바꿉니다 .x*AT
A*x
A
따라서, 벡터 / 행렬 곱셈의 순서는 않는 데이터의 전공 순서에 따라 변화를 (당신은 전치 행렬을 사용하고 있는지 여부).
다음 코드 스 니펫에서 r! = r2를 수행하는 이유
코드가 깨지고 버그가 있기 때문입니다. 수학적으로 . 이 결과를 얻지 못하면 동등성 테스트가 잘못되었거나 (부동 소수점 정밀도 문제) 행렬 곱셈 코드가 손상되었습니다.A * (B * C) == (CT * BT) * AT
pos3! = pos는 왜
말이되지 않기 때문입니다. 사실이 되는 유일한 방법은 if 입니다. 그리고 그것은 대칭 행렬에만 해당됩니다.A * t == AT * t
A == AT