I'm implementing a 3D graphics app for fun.
To create an orthographic camera following the "theory", you need to have a view projection Matrix implemented in this way:
ViewProjectionMatrix = ProjectionMatrix * _viewMatrix;
But when doing this, objects get skewed when the camera is rotated on the Z axis (translation works well).
If I do this instead:
ViewProjectionMatrix = _viewMatrix * ProjectionMatrix
That fixes the problem (Rotation and Translation work well), going against the theory of how to implement this matrix, what I'm doing wrong?
**This is what I tried: ** My implementation uses OpenGL (via Silk.Net bindings), C# .NET 7, and System.Numerics for matrices and vectors.
I'm calculating the Orthographic camera (Projection Matrix) like this:
float aspectRatio = (float)_window.Width / (float)_window.Height;
float left = -aspectRatio;
float right = aspectRatio;
float bottom = -1f;
float top = 1f;
float nearPlane = -1f;
float farPlane = 1;
ProjectionMatrix = Matrix4x4.CreateOrthographicOffCenter(left, right, bottom, top, nearPlane, farPlane);
Then, I'm calculating the view matrix as the inverse of the camera Model Matrix:
float radiansZ = _angleZ * MathF.PI / 180f;
Matrix4x4 cameraModelMatrix =
Matrix4x4.CreateTranslation(_position) *
Matrix4x4.CreateRotationZ(_angleZ);
Matrix4x4.Invert(
cameraModelMatrix, out _viewMatrix); // _viewMatrix is the inverse of cameraModelMatrix
ViewProjectionMatrix = ProjectionMatrix * _viewMatrix; // here is my problem :(
These are pictures of the different outputs:
Using ViewProjectionMatrix = ProjectionMatrix * _viewMatrix (Theory Correct, Result Wrong) Image: Using ViewProjectionMatrix = ProjectionMatrix * _viewMatrix
Using ViewProjectionMatrix = _viewMatrix * ProjectionMatrix (Theory Wrong, Result Correct) Image: Using ViewProjectionMatrix = _viewMatrix * ProjectionMatrix
System.Numerics is Column-Major, so when passing the Matrix to the uniform, I use transponse = false.
*** Extra Tests ***
I did this just to check problems with multiplication:
Matrix4x4 A = new Matrix4x4(
1, 2, 3, 4,
5, 6, 7, 8,
9, 10, 11, 12,
13, 14, 15, 16
);
Matrix4x4 B = new Matrix4x4(
17, 18, 19, 20,
21, 22, 23, 24,
25, 26, 27, 28,
29, 30, 31, 32
);
Debug.Info("A: {0}",A);
Debug.Info("B: {0}", B);
Debug.Info("A * B: {0}", A * B);
Debug.Info("B * A: {0}", B * A);
This outputs the following:
A: { {M11:1 M12:2 M13:3 M14:4} {M21:5 M22:6 M23:7 M24:8} {M31:9 M32:10 M33:11 M34:12} {M41:13 M42:14 M43:15 M44:16} }
B: { {M11:17 M12:18 M13:19 M14:20} {M21:21 M22:22 M23:23 M24:24} {M31:25 M32:26 M33:27 M34:28} {M41:29 M42:30 M43:31 M44:32} }
A * B: { {M11:250 M12:260 M13:270 M14:280} {M21:618 M22:644 M23:670 M24:696} {M31:986 M32:1028 M33:1070 M34:1112} {M41:1354 M42:1412 M43:1470 M44:1528} }
B * A: { {M11:538 M12:612 M13:686 M14:760} {M21:650 M22:740 M23:830 M24:920} {M31:762 M32:868 M33:974 M34:1080} {M41:874 M42:996 M43:1118 M44:1240} }
This looks expected from a mathematical perspective.