I am trying to create a custom math library for a renderer. The renderer works when using glm but for educational purposes as well as for the sake of having a custom library to support multiple backends, I am creating my own. Currently focusing on Vulkan. I have written a matrix class. Switching to my own library renders a black screen. Vectors are intuitive for me but trying to understand 4x4 Matrices leaves my brain feeling like mush. From cross examining my code from text books and some open source projects, I don't see what could be wrong.
Is there anything wrong with my calculations? Matrices are in Column major order. Could it possibly be an issue with alignment? I've tried changing the winding order. It's currently Counter Clockwise. Looking for any pointers in the correct direction.
A condensed version of my Mat4 class is as follows~
class Mat4
{
public:
union{
// f32 is a custom float32 typedef
f32 mat[16];
struct
{
Vec4 right;
Vec4 up;
Vec4 forward;
Vec4 position;
};
struct
{
f32 xx, xy, xz, xw;
f32 yx, yy, yz, yw;
f32 zx, zy, zz, zw;
f32 tx, ty, tz, tw;
};
struct
{
f32 r0c0, r1c0, r2c0, r3c0;
f32 r0c1, r1c1, r2c1, r3c1;
f32 r0c2, r1c2, r2c2, r3c2;
f32 r0c3, r1c3, r2c3, r3c3;
};
};
Mat4 LookAtRH(const Vec3& Position, const Vec3& Target, const Vec3& Up)
{
Vec3 const front(Vec3::Normalize(Target - Position));
Vec3 const right(Vec3::Normalize(Vec3::Cross(front, Up)));
Vec3 const up(Vec3::Normalize(Vec3::Cross(right, front)));
Vec3 target(
Vec3::Dot(right, Position),
Vec3::Dot(up, Position),
Vec3::Dot(front, Position)
);
return Mat4(
right.x, up.x, -front.x, 0.0f,
right.y, up.y, -front.y, 0.0f,
right.z, up.z, -front.z, 0.0f,
-target.x, -target.y, target.z, 1.0f
);
}
Mat4 PerspectiveRH(f32 FOV, f32 AspectRatio, f32 Near, f32 Far)
{
// DegToRad: Degrees * (PI/180.f)
f32 half_tan_fov = tanf(Math::DegToRad(FOV) / 2.0f);
Mat4 result;
result.mat[0] = 1.0f / (AspectRatio * half_tan_fov);
result.mat[5] = 1.0f / half_tan_fov;
result.mat[10] = - (Far + Near) / (Far - Near);
result.mat[11] = - 1.0f;
result.mat[14] = -(2.0f * Far * Near) / (Far - Near);
return result;
}
};