I am calculating the model, view and projection matrices independently to be used in my shader as follows:

gl_Position = projection * view * model * vec4(in_Position, 1.0);

When I try to calculate my camera's view matrix the Z axis is flipped and my camera seems like it is looking backwards.

My program is written in C# using the OpenTK library.

Translation (Working)

I've created a test scene as follows:

enter image description here enter image description here

From my understanding of the OpenGL coordinate system they are positioned correctly.

The model matrix is created using:

Matrix4 translation = Matrix4.CreateTranslation(modelPosition);
Matrix4 model = translation;

The view matrix is created using:

Matrix4 translation = Matrix4.CreateTranslation(-cameraPosition);
Matrix4 view = translation;

Rotation (Not-Working)

I now want to create the camera's rotation matrix. To do this I use the camera's right, up and forward vectors:

// Hard coded example orientation:
// Normally calculated from up and forward
// Similar to look-at camera.
Vector3 r = Vector.UnitX;
Vector3 u = Vector3.UnitY;
Vector3 f = -Vector3.UnitZ;

Matrix4 rot = new Matrix4(
    r.X, r.Y, r.Z, 0,
    u.X, u.Y, u.Z, 0,
    f.X, f.Y, f.Z, 0,
    0.0f, 0.0f, 0.0f, 1.0f);

This results in the following matrix being created:

enter image description here

I know that multiplying by the identity matrix would produce no rotation. This is clearly not the identity matrix and therefore will apply some rotation.

I thought that because this is aligned with the OpenGL coordinate system is should produce no rotation. Is this the wrong way to calculate the rotation matrix?

I then create my view matrix as:

// OpenTK is row-major so the order of operations is reversed:
Matrix4 view = translation * rot;

Rotation almost works now but the -Z/+Z axis has been flipped, with the green cube now appearing closer to the camera. It seems like the camera is looking backwards, especially if I move it around.

My goal is to store the position and orientation of all objects (including the camera) as:

Vector3 position;
Vector3 up;
Vector3 forward;

Apologies for writing such a long question and thank you in advance. I've tried following tutorials/guides from many sites but I keep ending up with something wrong.

Edit: Projection Matrix Set-up

Matrix4 projection = Matrix4.CreatePerspectiveFieldOfView(
    (float)(0.5 * Math.PI),
    (float)display.Width / display.Height,
  • \$\begingroup\$ There is a part of this process that you are currently ignoring. OpenGL does not mandate anything about any of the axes in coordinate spaces prior to clip-space in the programmable pipeline. Clip-space is left-handed, and the only way to achieve this is if your projection matrix flips the Z-axis, given your current view-space setup. Can you show the setup of your projection matrix? \$\endgroup\$ May 27, 2014 at 0:29
  • \$\begingroup\$ I've added the projection matrix set-up to the original post, thanks. \$\endgroup\$
    – Karle
    May 27, 2014 at 0:40
  • \$\begingroup\$ Considering that OpenTK is row-major and the function you are calling shares its name with a D3D function... I would not be surprised if that produces a projection matrix that expects left-handed view-space coordinates (D3D convention). If you call Matrix4.Perspective (...) instead, does anything change? \$\endgroup\$ May 27, 2014 at 0:51
  • \$\begingroup\$ I tried calling Matrix4.Perspective(...) with the same arguments and it produced the same matrix (ignoring very small rounding errors). The documentation marks the method as deprecated. \$\endgroup\$
    – Karle
    May 27, 2014 at 0:56

1 Answer 1


The problem is that constructing the matrix out of the right, up, and forward vectors inherently sets up coordinates in which X points right, Y points up, and Z points forward. The Z axis in this coordinate system points the opposite of the direction it's "supposed" to point (for right-handed view space, as seen in your first diagram).

To fix the problem, you just need to build the view matrix using the camera's right, up, and backward (negative forward) vectors instead.


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .