# Perspective Projection Matrix in OpenGL  Here is a small function to create a perspective projection matrix. This function does not use OpenGL calls to initialize the matrix. This routine is nice because it can be used either with Direct3D (requires a little ogl to d3d matrix conversion – will be posted in another HowTo) or with the upcoming Larrabee too. And this function will be very useful to all coders that will need to produce OpenGL 3.1 compliant code because with OpenGL 3.1, you must have your own matrices functions!

```void BuildPerspProjMat(float *m, float fov, float aspect,
float znear, float zfar)
{
float xymax = znear * tan(fov * PI_OVER_360);
float ymin = -xymax;
float xmin = -xymax;

float width = xymax - xmin;
float height = xymax - ymin;

float depth = zfar - znear;
float q = -(zfar + znear) / depth;
float qn = -2 * (zfar * znear) / depth;

float w = 2 * znear / width;
w = w / aspect;
float h = 2 * znear / height;

m  = w;
m  = 0;
m  = 0;
m  = 0;

m  = 0;
m  = h;
m  = 0;
m  = 0;

m  = 0;
m  = 0;
m = q;
m = -1;

m = 0;
m = 0;
m = qn;
m = 0;
}
```

and here is how to use it in an OpenGL 1 / OpenGL 2 code:

```float m = {0};
float fov=60.0f; // in degrees
float aspect=1.3333f;
float znear=1.0f;
float zfar=1000.0f;
BuildPerspProjMat(m, fov, aspect, znear, zfar);
glMatrixMode(GL_PROJECTION);

// okay we can switch back to modelview mode
// for all other matrices
glMatrixMode(GL_MODELVIEW);
...
```

With a real OpenGL 3.0 code, we must use GLSL shaders and uniform variables to pass and exploit the transformation matrices:

```glUseProgram(shaderId);
glUniformMatrix4fv("projMat", 1, GL_FALSE, m);
RenderObject();
glUseProgram(0);
```

[source]

## 13 thoughts on “Perspective Projection Matrix in OpenGL”

1. luuk

glMatrixMode(GL_PROJECTION);

THese functions are both depricated in OGL 3.0 and up

2. Zenja

You can cut down the number of calculations (and eliminate the multiplactions by -1) but simplifying the terms:
{
const float h = 1.0f/tan(fov*PI_OVER_360);
float neg_depth = zNear-zFar;

m = h / aspect;
m = 0;
m = 0;
m = 0;

m = 0;
m = h;
m = 0;
m = 0;

m = 0;
m = 0;
m = (zFar + zNear)/neg_depth;
m = -1;

m = 0;
m = 0;
m = 2.0f*(zNear*zFar)/neg_depth;
m = 0;
}

3. Damien

The “how to use it” code is confusing; the GL Matrix functions are supposed to be removed in ogl 3.1. Maybe i’m wrong but i think that you must provide the matrix to the shaders using parameters ?!

Regards

4. JeGX Post Author

Luuk and Damien > you’re both right. In a proper GL 3.1 code, we must use a glsl shader to render an object and tranformation matrices must be passed with uniforms. But I wanted to give a simple GL 2 code. I update a bit the post…

Zenja > thanks for the optimization 😉

5. Lars

Thanks for the nice code example.

I have used matrices, in school, in the distant past, but have only
recently started using OpenGL, OpenCV, etc.

Over the past few days I have spent a lot of time trying to
learn about matrices, perspective projection, homogeneous
coordinates, and related topics.

I see that the matrix presented in your code is similar to that
for the perspective projection presented at:
http://www.songho.ca/opengl/gl_projectionmatrix.html
except that your example has it this way:

m = 0;
m = 0;
m = q;
m = -1;

m = 0;
m = 0;
m = qn;
m = 0;

and the other web site does it like this:

m = 0;
m = 0;
m = q;
m = qn;

m = 0;
m = 0;
m = -1;
m = 0;

Why is that?
I think that the answer probably lies in the use of
homogeneous coordinates but I don’t understand it yet.
Can you help me with this?

Thanks,
Lars

6. Sam

@Lars

It looks like the two matrices are the same, just transposed. The third parameter of glUniformMatrix4fv can transpose for you. Assuming you get projMat from the code on this page you can either transpose it like this:

/* c code */
glUniformMatrix4fv(“projMat”, 1, GL_TRUE, m);

gl_Position = projMat * vertex_position;

OR you can choose not to transpose and do your multiplication bass ackwards in the shader.

/* c code */
glUniformMatrix4fv(“projMat”, 1, GL_FALSE, m);

gl_Position = vertex_position * projMat;

OR you could rewrite the projection like in the other website. That way you don’t have to transpose for your shader, you can multiply in mat * vec order, and your matrix is laid out in memory in row major order as God intended.

IMHO the other website uses the superior convention.

-Sam

7. Sam

Oops. The first argument to glUniformMatrix4fv() should be a GLint location, not an actual name.

8. Mr. What

In this example, xmax, ymax are not defined, as used in the 3rd and 4th lines of the function. should they be replaced with xymax?

9. JeGX Post Author

@Mr. What: thanks for pointing out the mistake. Fixed!

10. Pillum

whats the definition of PI_OVER_360`?

11. Neil Kolban

In the code, when I look at the 16 element float array, I can’t tell if the matrix is defined row major or column major. It would be wonderful to see a description of the matrix as a 4 x 4 grid.

12. Andrew

What is the definition of PI_OVER_360?
I’m guessing that is for converting from degrees to radians, and it is meant to represent (2PI / 360).

2pi because pi represents 180 degrees.

Though in another example that same section is written as
(fieldOfView / 360.0f * 3.14159f)
Which suggests it is actually meant to be (PI/360)
Very confusing. I do not get why it would be this.
Would be good if someone could share.

13. Gordon

PI / 360 = PI / 180 * 0.5

So really, its a my concise way of saying:

tan(FOV * 0.5 * PI/180)

So, really what we are doing is taking half the angle of the FOV, converting to radians, and then calculating the tangent.