redonkulasman
redonkulasman

Reputation: 45

OpenGL: Orthographic Projection

I am trying to have a orthographic projection to use for my GUI rendering. When i draw a mesh using just my regular transform matrix I get what I would expect but when I use my orthographic projection I get nothing at all. My perspective projection works fine as well. My ortho matrix:

public Matrix4f initOrthographic(float left, float right, float bottom, float top, float near, float far)
{
    m[0][0] = 2.0f / (right - left);    m[0][1] = 0;                        m[0][2] = 0;                    m[0][3] = (left + right) / (left - right);
    m[1][0] = 0;                        m[1][1] = 2.0f / (top - bottom);    m[1][2] = 0;                    m[1][3] = (bottom + top) / (bottom - top);
    m[2][0] = 0;                        m[2][1] = 0;                        m[2][2] = 2.0f / (near - far);  m[2][3] = (far + near) / (far - near);
    m[3][0] = 0;                        m[3][1] = 0;                        m[3][2] = 0;                    m[3][3] = 1;

    return this;
}

I can not for the life of me find out what is wrong. I am multiplying this matrix by the regular transform and then multiplying that matrix by the vertex position in the shader. Any Ideas? I can post more code/information if needed.

I think i just found the issue. I had top at 0 and bottom at 720, when i flip these values to 720 top and 0 bottom it works just fine. The only thing is I would like for the top left corner to be (0, 0). Is there any way I can do this or am i stuck with the bottom left being (0, 0)?

Upvotes: 0

Views: 1039

Answers (1)

kamshi
kamshi

Reputation: 615

My orthogonal matrix looks quite different from yours:

      2.0f / (right - left)                          0                                    0                      0
                0                          2.0f / (top - bottom)                          0                      0
                0                                    0                           2.0f / (zFar - zNear)           0
-(right + left) / (right - left)     -(top + bottom) / (top - bottom)    -(zFar + zNear) / (zFar - zNear)        1

Important is how you store the values. If you would use a single float array for your matrix, you would store it like this:

float orthoMat[] =
{
    2.0f / (right - left),
    0,
    0,
    0,

    0,
    2.0f / (top - bottom),
    0,
    0,

    0,
    0,
    2.0f / (zFar - zNear),
    0,

    -(right + left) / (right - left),
    -(top + bottom) / (top - bottom),
    -(zFar + zNear) / (zFar - zNear),
    1
};

This is the layout that OpenGL expects you to pass to the shader. This is the column-major convention. DirectX uses row-major convention. So basically my matrix can be read left-to-right, next row, left-to-right, while your matrix should be read top-to-bottom, next column, top-to-bottom. If you transpose your matrix, you get almost the same matrix as me. There are however some differences between our matrices, even when transposed:

In your code

- m[2][2] should be 2.0f / (zFar - zNear)
- m[0][3], m[1][3] and m[2][3] should be negative

As long as you fix these issues with your matrix and ensure the correct order of elements when passing the matrix to the shader, you can still use your matrix implementation. Just remember that elements 12, 13 and 14 store the translation. If you are confused by all this row-major/column-major stuff, read this short article about it which explains it really well. I highly recommend it.

Upvotes: 2

Related Questions