locked
Perspective projection matrix in D3D11

    Question

  • I am learning the Direct3D tutorial (http://code.msdn.microsoft.com/windowsapps/Direct3D-Tutorial-Sample-08667fb0). In the file 'Main.cpp' of the third example, titled "Lession3.cubes", the code of the lines 596-601 assigns the perspective projection matrix

            m_constantBufferData.projection = float4x4(
                xScale, 0.0f,    0.0f,  0.0f,
                0.0f,   yScale,  0.0f,  0.0f,
                0.0f,   0.0f,   -1.0f, -0.01f,
                0.0f,   0.0f,   -1.0f,  0.0f
                );

    However, according to MSDN (http://msdn.microsoft.com/en-us/library/windows/desktop/bb205350(v=vs.85).aspx), the matrix should be written as

            m_constantBufferData.projection = float4x4(
                xScale, 0.0f,    0.0f,  0.0f,
                0.0f,   yScale,  0.0f,  0.0f,
                0.0f,   0.0f,    1.0f,  1.0f,
                0.0f,   0.0f,  -0.01f,  0.0f
                );
    

    according to the formula of perspective projection matrix

    xScale     0          0               0
    0        yScale       0               0
    0          0       zf/(zf-zn)         1
    0          0     -zn*zf/(zf-zn)     0

    Saturday, June 30, 2012 11:38 AM

Answers

  • When we moved from the 'fixed-function' pipeline of Direct3D to the 'programmable shader' pipeline model, the actual choice of right-hand vs. left-hand -and- row-major vs. column-major was no longer fixed by the API. It's just a matter of preference and consistency with your shaders, constant buffers, and computations.

    Most Direct3D applications still use Left-Handed Coordiantes and Row-Major forms but you can transpose them to column-major when setting them into the constant buffers since the matrix multiply can be done slightly more efficently in HLSL. The actual choice of what the HLSL shader expects depends on the /Zpr vs. /Zpc command-line options (or the D3DCOMPILE_PACK_MATRIX_ROW_MAJOR vs. D3DCOMPILE_PACK_MATRIX_COLUMN_MAJOR compile flags), the #pragma pack_matrix setting, and the use of the row_major / column_major keywords See Matrix Ordering. Remember that RH vs. LH and row vs. column-major are in fact independant choices.

    You'll note that DirectXMath actually has both LH and RH implementation of 'handed' matrix functions. XMMATRIX, XMFLOAT3X3, XMFLOAT4X4, and XMFLOAT4X3 are always 'row-major'. This is covered in the DirectXMath Programmer's Guide and Reference.


    Tuesday, July 3, 2012 11:00 PM

All replies

  • Of course the example is correct but I still fail to figure out why the perspective projection matrix is written as that in the example.
    Saturday, June 30, 2012 11:40 AM
  • Hello,

     

    You can take a look this document

    http://msdn.microsoft.com/en-us/library/windows/desktop/bb147302(v=vs.85).aspx

     

    Best regards,

    Jesse



    Jesse Jiang [MSFT]
    MSDN Community Support | Feedback to us

    Monday, July 2, 2012 11:09 AM
    Moderator
  • Jesse, the document you referred agrees with my proposition, and differs from the example code.
    Monday, July 2, 2012 3:55 PM
  • Part of the confusion is "row-major" vs. "column-major" matrices. I assume the flipped signs end up the third column end up reversing each other.

    You may also consider just using DirectXMath instead of hand-coding these things. XMMatrixPerspectiveLH in particular.


    Monday, July 2, 2012 7:25 PM
  • Hello Chuck, I do some math today and am surprised to find that D3D11 coordinate system (CS) is in sharp contrast to D3D10 CS, and in fact identical to OpenGL CS. It's a right-hand CS and has its camera looking at negative z-axis. The D3D11 vector is column-vector. Whereas in D3D10, everything is opposite. I wonder why does Microsoft make such a big change without documenting it explicitly.
    Tuesday, July 3, 2012 2:46 PM
  • When we moved from the 'fixed-function' pipeline of Direct3D to the 'programmable shader' pipeline model, the actual choice of right-hand vs. left-hand -and- row-major vs. column-major was no longer fixed by the API. It's just a matter of preference and consistency with your shaders, constant buffers, and computations.

    Most Direct3D applications still use Left-Handed Coordiantes and Row-Major forms but you can transpose them to column-major when setting them into the constant buffers since the matrix multiply can be done slightly more efficently in HLSL. The actual choice of what the HLSL shader expects depends on the /Zpr vs. /Zpc command-line options (or the D3DCOMPILE_PACK_MATRIX_ROW_MAJOR vs. D3DCOMPILE_PACK_MATRIX_COLUMN_MAJOR compile flags), the #pragma pack_matrix setting, and the use of the row_major / column_major keywords See Matrix Ordering. Remember that RH vs. LH and row vs. column-major are in fact independant choices.

    You'll note that DirectXMath actually has both LH and RH implementation of 'handed' matrix functions. XMMATRIX, XMFLOAT3X3, XMFLOAT4X4, and XMFLOAT4X3 are always 'row-major'. This is covered in the DirectXMath Programmer's Guide and Reference.


    Tuesday, July 3, 2012 11:00 PM
  • Thank you Chuck.
    Thursday, July 5, 2012 5:01 PM
  • check this link to understand the concept of precpective projection

    http://www.mathdisk.com/pub/safi/worksheets/Perspective_Projection

    Sunday, July 8, 2012 1:43 AM