Search code examples
openglmatrix2dglslorthographic

OpenGL Orthographic Matrix Isn't Working Properly


I have created a simple 2D area using OpenGL, comprised of tiles. These tiles have been stretched relative to the screen's aspect ratio by default. To fix this I have attempted to use an orthographic projection matrix. Here is how I created it:

public void createProjectionMatrix() {
    float left = 0;
    float right = DisplayManager.getScreenWidth();
    float top = 0;
    float bottom = DisplayManager.getScreenHeight();
    float near = 1;
    float far = -1;

    projectionMatrix.m00 = 2 / (r - l);
    projectionMatrix.m11 = 2 / (t - b);
    projectionMatrix.m22 = -2 / (f - n);
    projectionMatrix.m30 = - (r + l) / (r - l);
    projectionMatrix.m31 = - (t + b) / (t - b);
    projectionMatrix.m32 = - (f + n) / (f - n);
    projectionMatrix.m33 = 1;
}

The problem probably lies here but I just can't find it. I then call this method with the creation of my renderer, store it in a uniform variable and use it in the vertex shader like so:

vec4 worldPosition = transformationMatrix * vec4(position, 0, 1);
gl_Position = projectionMatrix * viewMatrix * worldPosition;

Where projectionMatrix is a mat4 which corresponds to the previously created orthographic projection matrix.

Right now absolutely nothing except for the clear color renders.

EDIT:

The orthographic projection matrix is created and loaded into the shaders right after the renderer's creation and after the shader's creation.

public Renderer() {
    createOrthoMatrix();
    terrainShader.start();
    terrainShader.loadProjectionMatrix(projectionMatrix);
    terrainShader.stop();
    GL11.glEnable(GL13.GL_MULTISAMPLE);
    GL11.glClearColor(0, 0, 0.5f, 1);
}

The rest of the matrices are passed in at each render with the loadUniforms() method.

for(Terrain t : batch) {
    loadUniforms(t, terrainManager, camera, lights);
    GL11.glDrawElements(GL11.GL_TRIANGLES, model.getModel().getVertexCount(), GL11.GL_UNSIGNED_INT, 0);
}

private void loadUniforms(Terrain t, TerrainManager tm, Camera camera, List<Light> lights) {
    Matrix4f matrix = Maths.createTransformationMatrix(t.getPosition(), 0, 0, 0, 1);
    terrainShader.loadTransformationMatrix(matrix);
    terrainShader.loadViewMatrix(camera);
    terrainShader.loadNumberOfRows(tm.getNumberOfRows());
    terrainShader.loadOffset(t.getOffset());
    terrainShader.loadLights(lights);
}

Finally this is what the vertex shader looks like:

#version 400 core

in vec2 position;

uniform mat4 transformationMatrix;
uniform mat4 viewMatrix;
uniform mat4 projectionMatrix;

void main(void) {
vec4 worldPosition = transformationMatrix * vec4(position, 0, 1);
gl_Position = projectionMatrix * viewMatrix * worldPosition;
}

Solution

  • It has been a long and arduous task (if I may sound incompetent myself). But I have found a solution to my problem, there is probably a better way to solve it, but this is how I did it.

    I changed the createProjectionMatrix() to look like

    public void createProjectionMatrix() {
        float width = Display.getWidth();
        float height = Display.getHeight();
        float left = -width;
        float right = width * 1f;
        float top = height * 1f;
        float bottom = -height;
        float near = 0;
        float far = 10;
    
        projectionMatrix.m00 = (2f / (right - left)) * 1000;
        projectionMatrix.m11 = (2f / (top - bottom)) * 1000;
        projectionMatrix.m22 = 2f / (far - near);
        projectionMatrix.m30 = - (right + left) / (right - left);
        projectionMatrix.m31 = - (top + bottom) / (top - bottom);
        projectionMatrix.m32 = -(far + near) / (far - near);
        projectionMatrix.m33 = 1;
    }
    

    Multiplying m00 and m11 by a large number is the only way I am able to see anything besides the clear color. If I remember this correctly, it is because the renderer is rendering at less than a pixel. This idea was presented to me by @NicoSchertler. So thank you very much! The shaders looks the same and now it runs well. If anyone has a less bootleg solution please share it, as I will be glad to see how it was solved. Here is a link that was very helpful to me, OpenGL 3+ with orthographic projection of directional light.