[PROGRAMMING TIPS] Direct3D 10 to Direct3D 11: Transpose Your Matrices

DirectX - Direct3D

Not a killer tip but if you have to port a Direct3D 9 or Direct3D 10 app to Direct3D 11, I think this tip will be useful. I spent around one hour before finding the solution in the DirectX SDK doc.

When you migrate an app from DX9 to DX10, there ‘s nothing special to do with your transformation matrices:

D3DXMATRIX proj_mat;
D3DXMATRIX view_mat;
D3DXMATRIX model_mat;
MVP = model_mat * view_mat * proj_mat;

shader->effect->SetMatrix(hMVP, &MVP); // DX9

pMVP->SetMatrix((float*)&MVP); //DX10: same thing

Now when you migrate a DX9 or DX10 app to DX11, you have to transpose your transformation matrices before use them in your shaders. In the DX10 SDK doc (Samples and Tutorials > Direct3D 11 > Tutorials > Tutorials 4: 3D Spaces), you can read this:

Also, because matrices are arranged differently in memory in C++ and HLSL, we must transpose the matrices before updating them.

To transpose your matrices, just use D3DXMatrixTranspose():

D3DXMatrixTranspose(&cb->tMVP, &MVP);

where cb is a D3D11 constant buffer, tMVP the transposed matrix and MVP the transformation matrix in DX9/DX10 format.

This operation is absolutely fundamental, otherwise your meshes will look odd:

D3D11 - no matrix transpose
D3D11 – D3D10 matrices used without transpose.

D3D11 - matrix transpose
D3D11 – D3D10 matrices have been transposed.

Actually (if I’m not wrong), Direct3D 11 stores the matrices in the same way than… OpenGL! At last, Direct3D does what OpenGL has always done…

What does it mean?

Simply that matrices you use with OpenGL can be directly used with Direct3D 11, no need anymore to reverse the order of matrices when you need to concat them. Cool!

Maybe the DX team should add this tips in the section “Migrating to Direct3D 11″ 😉

7 thoughts on “[PROGRAMMING TIPS] Direct3D 10 to Direct3D 11: Transpose Your Matrices”

  1. somari

    Wait, wait.
    In GLSL, there’s this:

    mat4 m1;
    mat4 m2; // = transposed m1
    vec4 v;

    m1*v == v*m2;

  2. DrBalthar

    You are aware that there is setMatrixTranspose in D3D Effect?

    And you are also aware that D3DXMATH is replaced with XNAMath?

  3. hint

    No need to transpose your matrices before uploading them to the GPU. You can simply use the row_major keyword in your HLSL code.

  4. Grandmaster B

    Its a myth that OpenGL matrices are transposed in relation to Direct3D 10 and before. Both APIs had the same matrix storage order they just used a different math convention in their documentation – therefore the myth.

    You can easily check that by using glRotate and glTranslate. There was (or is?) also an official statement on opengl.org.

    The one thing that is different is the corrdinate system, while Direct3D uses a left-handed coordinate system, OpenGL uses a right-handed coordinate system, this needs a matrix conversion of the view matrix – for example.

  5. Jeff Stryker

    It’s actually not a myth, and it’s nothing to do with left-handed or right-handed – DX9 can handle either handedness fine. And whether the internal storage is transposed is irrelevant. What matters is that when you take a 16-float chunk of data and send it as a D3DXMATRIX to DX9, and take the same chunk and send it to GL using glUniformMatrix4fv, or in a constant buffer, you have to transpose one of them in order to get the same result from a premultiply operation. As of DX11, you can use the SAME CODE to set up a constant buffer for GL or DX11, and send that buffer to the shader. Then a premultiply will work the same for either.

Comments are closed.