예제 프로그램의 셰이더 코드에서는 'World * View * Projection' 순으로 행렬연산을 수행하는게, 내 프로그램에서는 'Project * View * World' 순으로 연산해야 정상적인 결과가 나왔기 때문이다. 컴퓨터에서 다차원 배열로 행렬을 구성할 때, 행렬을 어떤 순서로 접근할 것인지에 대한 순서가 있다. DirectX에서는 행렬 순서가 row-major(행우선)이고, HLSL에서는 column-major(열우선)이다.
위와 같이 행렬을 접근하는 순서가 다르기 때문에, 사용하는 라이브러리에 명시된 순서를 확인하고 그에 맞게 연산을 하지 않으면 제대로 된 결과가 나오지 않는다. 서로간의 행렬 순서가 달랐기 때문에, DirectX에서는 'World * View * Projection' 순으로 연산하는것을 셰이더(HLSL)에서는 'Projection * View * World'로 연산해야 제대로 된 결과값이 나왔던 것이다. 행렬이 DirectX에서 셰이더 상수로 넘어갈때 자동적으로 row-major에서 column-major로 변환된다. 따라서, 셰이더 코드에서도 DirectX와 똑같은 순서로 연산을 하려면, 상수버퍼의 행렬을 전치행렬로 변환하여 갱신해야 한다.
m_view = DirectX::XMMatrixTranspose(m_view);
m_projection = DirectX::XMMatrixTranspose(m_projection);
d3dDevice->CreateBuffer(&cbd, nullptr, &m_constantBuffer);
예제에서는 Effect Interface를 사용하는데, 아마 내부에서 자동적으로 전치행렬로 변환하는 듯 하다.
내가 짠 코드에서는 Effect Interface를 사용하지도 않고, 전치행렬을 사용하지도 않아서 연산 순서가 뒤바뀌었던 것.
위와 같이 전치행렬로 변환하면, 셰이더 코드에서도 row-major 기준으로 연산을 할 수 있다.
row major
Output.Pos = mul(float4(Input.Pos, 1.0f), matrixWorld);
Output.Pos = mul(Output.Pos, matrixView);
Output.Pos = mul(Output.Pos, matrixProj);
column major
Output.Pos = mul(matrixWorld, float4(Input.Pos, 1.0f));
Output.Pos = mul(matrixView, Output.Pos);
Output.Pos = mul(matrixProj, Output.Pos);
'그래픽스 > DirectX' 카테고리의 다른 글
[Direct X] Constant Buffer(상수 버퍼) 란? (0) | 2023.07.14 |
---|---|
[DX11] 튜토리얼 4 - 3D 공간 (0) | 2023.07.14 |
[DX11] 튜토리얼 2 - 삼각형 렌더링 (0) | 2023.07.12 |
DirectX 렌더 대상 뷰 (RTV) 생성 (0) | 2023.07.12 |
[DX11 물방울책] 챕터 7 - 광원 (0) | 2023.07.11 |