0

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;
}
Dylan Deshler
  • 59
  • 1
  • 8
  • `orthoMatrix.m00 = 2 / (r - 1)`? Shouldn't that be [`(r - l)`](https://www.opengl.org/sdk/docs/man2/xhtml/glOrtho.xml) instead? [`1`](https://en.wikipedia.org/wiki/1_%28number%29) != [`l`](https://en.wikipedia.org/wiki/L). – genpfault Jun 23 '15 at 20:24
  • @genpfault Thanks for pointing that out! but the problem is still there – Dylan Deshler Jun 23 '15 at 21:35
  • Time for a [MCVE](http://stackoverflow.com/help/mcve) then. – genpfault Jun 23 '15 at 22:01
  • What's the order of the elements in your matrix struct/class? – Reto Koradi Jun 24 '15 at 02:58
  • @RetoKoradi Not sure what you mean but in the shader I start with the orthographic matrix * view matrix * transformation matrix * vec4(position, 0, 1) – Dylan Deshler Jun 24 '15 at 04:04
  • I was asking about the order of the matrix elements in the struct/class definition. What order are `m00`, `m01`, `m10`, `m11`, etc declared in? – Reto Koradi Jun 24 '15 at 04:12
  • @RetoKoradi They went undefined, which I think sets them to 0, not sure which order. Do you want me to define all of the elements in the matrix? I think the problem is with the matrix, am I setting all of the elements to the correct values? Are left, top, right, bottom, near, and far all correctly declared? – Dylan Deshler Jun 24 '15 at 17:07
  • They're probably initialized by default. But it's impossible to tell without knowing what matrix class you are using. Is it something you wrote yourself? Or are you using some kind of third party library? – Reto Koradi Jun 24 '15 at 17:13
  • 1
    If it rendered fine before, then you should now have a rendering of less than a pixel in size. Try to include a scaling factor in the matrix (multiply `m00` and `m11` by something big (e.g. `100`) to see if that's the case). And you might neet to transpose the matrix (swap columns and rows). That's why @RetoKoradi wanted to see the matrix declaration. – Nico Schertler Jun 24 '15 at 17:24
  • Oh, gotcha it is a matrix4f from the lwjgl library. I import it with `org.lwjgl.util.vector.Matrix4f` – Dylan Deshler Jun 24 '15 at 17:28
  • @NicoSchertler I did `orthoMatrix.m00 = (2 / (right - left)) * 100` and `orthoMatrix.m11 = (2 / (top - bottom)) * 100` but nothing changed. It could be that I need to switch the columns and rows. Not entirely sure how I would do that tho – Dylan Deshler Jun 24 '15 at 17:30
  • Just switch `.m30` to `.m03` etc. – Nico Schertler Jun 24 '15 at 17:31
  • @NicoSchertler Nothing changed, Is it possible that my camera is behind what I'm trying to render? It is initialized as a `Vector2f(1 , 1)` so the z is 0. – Dylan Deshler Jun 24 '15 at 17:36

2 Answers2

0

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.

Community
  • 1
  • 1
Dylan Deshler
  • 59
  • 1
  • 8
0

This will solve your problem with the aspect. Try it out:

public void createProjectionMatrix() {
float srcaspect = 4f / 3f; /* Default aspect ratio to scale ortho, can be other than 4:3 display origin. */
float dstaspect = DisplayManager.getScreenWidth() / DisplayManager.getScreenHeight();
float yscale = (dstaspect < (1f / 1f) ? dstaspect : 1f / 1f) / (1f / 1f);
float scale = 0.5f*(DisplayManager.getScreenHeight());
float top = scale - (scale / yscale);
float bottom = scale + (scale / yscale);
float left = scale - (scale * dstaspect / yscale) - (scale - (scale * srcaspect));
float right = scale + (scale * dstaspect / yscale) - (scale - (scale * srcaspect));
float near = 10;
float far = 1000;

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;
}
PunkSnips
  • 1
  • 1