# Why negate z when constructing projection matrix OpenGL

Matrix4 ortho(float l, float r, float b, float t, float n, float f) {
return Matrix4(
2/(r-l), 0, 0, -(r+l)/(r-l), //row 0
0, 2/(t-b), 0, -(t+b)/(t-b), //row 1
0, 0, -2/(f-n), -(f+n)/(f-n), //row 2
0, 0, 0, 1 //row 3
);
}


, where r, l, t, b, n, f are right, left, top, bottom, near and far corners of the view box.

Now I tested out this matrix using the default parameters of the view box ortho(-1, 1, -1, 1, -1, 1) to see if I get an identity matrix. However I'm getting:

 1, 0, 0, 0,
0, 1, 0, 0,
0, 0, -1, 0,
0, 0, 0, 1


Basically this will result in z coordinate of every transformed point to be negated.

Is it standard to negate the z coordinate when constructing projection matrix? What could be the purpose behind that?

• In my opinion flipping $Z$ is both confusing and unnecessary. It changes the handedness of the different spaces. It's just an arbitrary decision that was made for OpenGL afaik. Jul 10 '20 at 7:23

What could be the purpose behind that?

Have a look at the first lines and the first image in the Perspective Projection section of this link. For the answer to your question, it is not important that you used an orthographic projection, even though there is also a corresponding section in the link.

The issue is how OpenGL defines its coordinate systems. Quote from the link:

Note that the eye coordinates are defined in the right-handed coordinate system, but NDC uses the left-handed coordinate system. That is, the camera at the origin is looking along -Z axis in eye space, but it is looking along +Z axis in NDC.

So if you transform between them, you need to swap the z-axis. This is the whole purpose behind it, switching the handedness of the coordinate systems.

Is it standard to negate the z coordinate when constructing projection matrix?

Depends on your API and how the coordinate systems are defined. In OpenGL, you need to do this.

I'm assuming your scene is constructed based on right-handed coordinates.

If you are using OpenGL, yes. If you are using Direct3D, no.

The projection matrix maps [-n, -f] into [0, 1]. This weird property comes from the fact that the eye coordinates are right-handed, but the clip space (NDC) uses left-handed coordinates. Hence the implementation of ortho().

Direct3D uses a z-axis that goes outwards the screen. Implementations for Direct3D projection matrices will not produce negated z when coupled with your application.

• Thanks! Just to clarify did you mean to write In OpenGL screen-space (Normalized device coordinate), larger z value means FARTHER points.? I mean if OpenGL uses z-axis that goes inwards the screen. Jul 10 '20 at 16:08
• From this link: "Note that the eye coordinates are defined in the right-handed coordinate system, but NDC uses the left-handed coordinate system. That is, the camera at the origin is looking along -Z axis in eye space, but it is looking along +Z axis in NDC." --- So larger values mean farther away in NDC Jul 12 '20 at 11:00
• So this is not correct: "In OpenGL screen-space (Normalized device coordinate), larger z value means closer points." Jul 12 '20 at 11:40
• I see. I was wrong indeed. The misunderstanding came from my thought that the projection matrix maps [n, f] to [0, 1]. What actually happens is the matrix maps [-n, -f] to [0, 1]. I'll edit the answer accordingly. Thanks. Jul 13 '20 at 2:43