Problem getting the projection matrix right

Started by
12 comments, last by klaush 13 years, 7 months ago
Hello guys,

I'm having a really hard time moving away from all OpenGL 3.x deprecated functions. Currently I'm trying to get my own projection-, model- and view-matrices to my shaders. While there were no problems implementing any of the (for me) all new rendering architecture, it seems like I can't get the projection matrix right, not even if I use the gluPerspective/glFrustum code. No matter which calculation I use (there are numerous on the web), I end up with my object being either too small, too wide (as if I used the wrong aspect ratio) or both.
Here is how I currently calculate the projection matrix:
void initPerspective(double zNear, double zFar, double aspect){    double fw, fh;    fh = Math.tan(fov / 360 * Math.PI) * zNear;    fw = fh * aspect;    initFrustum(-fw, fw, -fh, fh, zNear, zFar);}void initFrustum(double left, double right, double bottom, double top,                 float zNear, float zFar){  projectionMatrix.m00 = (float) (2 * zNear / (right - left));  projectionMatrix.m02 = (float) ((right + left) / (right - left));  projectionMatrix.m11 = (float) (2 * zNear / (top - bottom));  projectionMatrix.m12 = (float) ((top + bottom) / (top - bottom));  projectionMatrix.m22 = (float) (-(zFar + zNear) / (zFar - zNear));  projectionMatrix.m23 = (float) (-2 * zFar * zNear / (zFar - zNear));  projectionMatrix.m32 = -1;  projectionMatrix.invert();}

The above code produces (surprinsingly ;)) the exact same matrix as gluPerspective does (I've compared them). However, not only is my object only 1/10 of its size, it is also too wide, as if it was scaled by 1.5 in width.
One more thing noteworthy, before the matrix is actually used in my shader, I put it to column major order.

Thanks for reading.

Klaus

Edit:
Almost forgot the shader code:
// fragment shader#version 150in vec3 ex_Color;out vec4 out_FragColor;void main(void){    out_FragColor = vec4(ex_Color, 1.0);}// vertex shader#version 150uniform mat4 uni_ProjMat;uniform mat4 uni_ViewMat;uniform mat4 uni_ModelMat;in vec3 in_Vertex;in vec3 in_Color;out vec3 ex_Color;void main(void){    mat4 trans = uni_ProjMat * uni_ViewMat * uni_ModelMat;    //mat4 trans = uni_ViewMat * uni_ModelMat;    //mat4 trans = uni_ModelMat;    gl_Position = trans * vec4(in_Vertex, 1.0);    ex_Color = in_Color;}
Advertisement
Maybe your aspect ratio input is wrong or swapped around.
Thanks for your reply, unfortunately the method call seems to be correct.

int width = 800;int height = 600;initProjectionMatrix(0.01f, 1000.0f, (float) width / height, 60.0f);
I'm a little bit confused. You say your problem is "moving away from deprecated functions", so I'm assuming that at some point in the history of your project this was working correctly? You said that it looks wrong even if you use the gluPerspective code. Are you saying that if you just flat out use gluPerspective code it doesn't look right?

If gluPerspective did work for you at some point, and your matrix is giving you the exact same results as gluPerspective did, then logically there has to be something else wrong that isn't in your projection matrix.

Quote:
One more thing noteworthy, before the matrix is actually used in my shader, I put it to column major order.

This scares me slightly, you could be correct but I'm not aware of any reason why you'd have to change the order of the matrix to use it in the shader. Whatever you get from gluPerspective should be fine for the shader.

[size=2]My Projects:
[size=2]Portfolio Map for Android - Free Visual Portfolio Tracker
[size=2]Electron Flux for Android - Free Puzzle/Logic Game
Nevermind the part about the order of the matrix. All I did was calculate the matrix (with above code), invert it, and send it to my shader. I did not actually try to use the gluPerspective matrix in my shader, all I did was compare the two matrices. Are there any obvious errors in my matrix calculation? Is the order of the matrix operations in the shader correct? Thanks!
I think I had a similar problem before and it was that I had a line similar to this: (float)width / height

It ended up being rounded to a whole number anyway. I cast both width and height to a float and like magic...
Quote:All I did was calculate the matrix (with above code), invert it, and send it to my shader.
Do you mean invert, or transpose? ('Cause if you're inverting the projection matrix, that could definitely cause problems.)

If you mean transpose, are you sure the transpose is necessary? Have you tried it without it?
The aspect ratio is definately correct, since height is implicitely cast to float as well (I checked its value).
I did not transpose the matrix. I did however invert it, if I don't the object disappears completely. Heres the thing. I'vegot a projection matrix now which seems to be working (compared it with an object rendered in immediate mode, applying the same transformations). However, the matrix produces is not the same gluPerspective produces, and I have to invert it, otherwise the object appears to be way too close. I'm totally confused now, heres the code I'm using now:

projectionMatrix.setIdentity();double yMax = zNear * Math.tan(fov * Math.PI / 360.0);double yMin = -yMax;double xMax = yMax / aspect;double xMin = yMin / aspect;projectionMatrix.m00 = (float) ((2.0 * zNear) / (xMax - xMin));projectionMatrix.m11 = (float) ((2.0 * zNear) / (yMax - yMin));projectionMatrix.m20 = (float) ((xMax + xMin) / (xMax - xMin));projectionMatrix.m21 = (float) ((yMax + yMin) / (yMax - yMin));projectionMatrix.m22 = (float) (-1.0 * (zFar + zNear) / (zFar - zNear));projectionMatrix.m23 = (float) ((-2.0 * zFar * zNear) / (zFar - zNear));projectionMatrix.m32 = (float) -1.0f;projectionMatrix.invert();


The matrix object is then stored in column major order (just like OpenGL likes it) and sent to the shader. But as I said, the matrix is nothing like the one I get when using glGetFloatv to retrieve the projection matrix created by gluPerspective, the scene appears to be displayed correctly though :(.

Edit:
About transposing it. I did try to transpose it, which did not change anything, which confused me even more.
You shouldn't be inverting the projection matrix. I would start by removing that line, and then working from there to solve your problem.

With the inversion removed, does your matrix match what's generated by the OpenGL utility functions?
Without inverting my matrix, this is what I send to my shader:

[2.309401, 0.0, 0.0, 0.0, 0.0, 1.7320508, 0.0, 0.0, 0.0, 0.0, -1.00002, -1.0, 0.0, 0.0, -0.020000199, 1.0]


The gluPerspective matrix i get when using glGetFloatv is:

[1.299038, 0.0, 0.0, 0.0, 0.0, 1.7320508, 0.0, 0.0, 0.0, 0.0, -1.00002, -1.0, 0.0, 0.0, -0.0200002, 0.0]


However, when not inverting my own matrix my object appears way too large. When I additionally set the last element to 0.0 (just like the gluPerspective matrix) I see nothing. When I use the array I got from glGetFloatv using the gluPerspective function, I see nothing either. When I invert that matrix, my object is way too small.

This topic is closed to new replies.

Advertisement