Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I need the formula to create a orthographic projection matrix. I am using GLM math libary and DirectX11. The reason I cannot use GLM to create it is because the NDC spaces are different between DX11 and OpenGL, thus I need to manually create one.

I am however using right-handed coordinate system and column-major matrices, just like GLM.

This is my attempt, but I get wrongly images when rendering with it, so it is probably wrong. I am using it for cascading shadow maps, and from the graphics debugger, I probably need to mirror it, but it is just a guess. Any ideas?

Mat4 OrthographicMatrix(const float left, const float right, const float top, const float bottom, const float zNear, const float zFar)
    Mat4 ret(1.0f);

    ret[0][0] = 2.0f / (right - left);
    ret[1][1] = 2.0f / (top - bottom);
    ret[2][2] = 1.0f / (zNear - zFar);
    ret[3][0] = (left + right) / (left - right);
    ret[3][1] = (top + bottom) / (bottom - top);
    ret[3][2] = (zNear) / (zNear - zFar);

    return ret;
share|improve this question
Duplicate of this – Chuck Walbourn Aug 15 '14 at 4:59
Please don't cross post. Only post on the site where your question is most relevant. Please remove one of the posts. – Byte56 Aug 15 '14 at 14:13
up vote 4 down vote accepted

The D3DX function D3DXMatrixOrthoOffCenterRH constructs an orthographic projection matrix based on the top/left/right/bottom coordinates of the view volume. Per the documentation, the formula used is:

2/(r-l)      0            0           0
0            2/(t-b)      0           0
0            0            1/(zn-zf)   0
(l+r)/(l-r)  (t+b)/(b-t)  zn/(zn-zf)  1

where top, left, bottom and right coordinates are represented as t, l, b and r respectively. The minimum and maximum depth values are zn and zf.

Since the math here appears to be the identical to the math for your individual components, you're probably seeing a problem in the storage of those components (resulting in an effective transposition). I'd verify the storage location of your last three components is actually what you need it to be.

(Don't just blindly transpose your storage; it's possible you have two transpose-esque bugs elsewhere cancelling eachother out and you're just adding a third; you'll want to review your matrix storage class carefully as where as everywhere in your basic pipeline that you are expecting right-handed systems and conventions to make sure you're not accidentally doing the wrong thing.)

share|improve this answer

Rather than use the legacy D3DXMath, consider using DirectXMath instead
Plus you get all the source in the header.

This computes the matrix as a row-major, right-handed matrix:

inline XMMATRIX XMMatrixOrthographicOffCenterRH
    float ViewLeft, 
    float ViewRight, 
    float ViewBottom, 
    float ViewTop, 
    float NearZ, 
    float FarZ
    assert(!XMScalarNearEqual(ViewRight, ViewLeft, 0.00001f));
    assert(!XMScalarNearEqual(ViewTop, ViewBottom, 0.00001f));
    assert(!XMScalarNearEqual(FarZ, NearZ, 0.00001f));

#if defined(_XM_NO_INTRINSICS_)

    float ReciprocalWidth = 1.0f / (ViewRight - ViewLeft);
    float ReciprocalHeight = 1.0f / (ViewTop - ViewBottom);
    float fRange = 1.0f / (NearZ-FarZ);

    M.m[0][0] = ReciprocalWidth + ReciprocalWidth;
    M.m[0][1] = 0.0f;
    M.m[0][2] = 0.0f;
    M.m[0][3] = 0.0f;

    M.m[1][0] = 0.0f;
    M.m[1][1] = ReciprocalHeight + ReciprocalHeight;
    M.m[1][2] = 0.0f;
    M.m[1][3] = 0.0f;

    M.m[2][0] = 0.0f;
    M.m[2][1] = 0.0f;
    M.m[2][2] = fRange;
    M.m[2][3] = 0.0f;

    M.r[3] = XMVectorSet(-(ViewLeft + ViewRight) * ReciprocalWidth, 
                         -(ViewTop + ViewBottom) * ReciprocalHeight,
                         fRange * NearZ,
    return M;

You can transpose it to get the column-major version.

share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.