-
Notifications
You must be signed in to change notification settings - Fork 4
Perspective and Orthographic projections
Because this IceShard targets newer graphics API's, like Vulkan and DX11/DX12, the perspective and orthographic projections are prepared to handle these cases.
We work in a right-handed coordinate system with column-major matrices. The resulting NDC volume is defined by the following ranges:
- For X:
-1 <= x' <= 1 - For Y:
-1 <= y' <= 1 - For Z:
0 <= z' <= 1
The below calculations represent the math that should be applied to components of a point P to get a projected point P'.
The comments provide additional information, where the part of the equation should be stored in a matrix representation.
The z component results negative, this is achieved by subtracting the far_plane from near_plane.
x' =
x * 2 * near_plane / (right - left) + // stored in column 0, row 0 (x axis, x component)
z * (right + left) / (right - left) // stored in column 2, row 0 (z axis, x component)
y' =
y * 2 * near_plane / (top - bottom) + // stored in column 1, row 1 (y axis, y component)
z * (top + bottom) / (top - bottom) // stored in column 2, row 1 (z axis, y component)
z' =
z * far_plane / (near_plane - far_plane) + // stored in column 2, row 2 (z axis, z component)
w * (near_plane * far_plane) / (near_plane - far_plane) // stored in column 3, row 2 (w axis, z component)
w' = z * -1.f // stored in column 2, row 3 (z axis, w component)
The current implementation in IceShard:
ice::math::mat<4, 4, f32> result{ };
result.v[0][0] = 2.f * near_plane / (right - left);
result.v[1][1] = 2.f * near_plane / (top - bottom);
result.v[2][0] = (right + left) / (right - left);
result.v[2][1] = (top + bottom) / (top - bottom);
result.v[2][2] = far_plane / (near_plane - far_plane);
result.v[2][3] = -1.f;
result.v[3][2] = (near_plane * far_plane) / (near_plane - far_plane);
The below calculations represent the math that should be applied to components of a point P to get a projected point P'.
The comments provide additional information, where the part of the equation should be stored in a matrix representation.
The z component results negative, this is achieved by subtracting the far_plane from near_plane.
x' =
x * 2 * (right - left) + // stored in column 0, row 0 (x axis, x component)
w * -(right + left) / (right - left) // stored in column 3, row 0 (w axis, x component)
y' =
y * 2 / (top - bottom) + // stored in column 1, row 1 (y axis, y component)
w * -(top + bottom) / (top - bottom) // stored in column 3, row 1 (w axis, y component)
z' =
z * 1 / (near_plane - far_plane) + // stored in column 2, row 2 (z axis, z component)
w * near_plane / (near_plane - far_plane) // stored in column 3, row 2 (w axis, z component)
w' = w // stored in column 3, row 3 (w axis, w component)
The current implementation in IceShard:
ice::math::mat<4, 4, f32> result{ };
result.v[0][0] = 2.f / (right - left);
result.v[1][1] = 2.f / (bottom - top);
result.v[2][2] = 1.f / (near_plane - far_plane);
result.v[3][0] = -(right + left) / (right - left);
result.v[3][1] = -(bottom + top) / (bottom - top);
result.v[3][2] = near_plane / (near_plane - far_plane);
result.v[3][3] = 1.f;