<p>The perspective matrix as written is setup for OpenGL here is one setup for vulkan:</p>
<pre><code>// Radians is just a small wrapper around a float here
mat4 Projection( Radians fovy, flt32 s, flt32 near, flt32 far )
{
   flt32 g = 1.0f / tan(fovy * 0.5f);
   flt32 k = far / (far-near);

   return mat4{
       g/s,  0.0f, 0.0f, 0.0f,
       0.0f, g,    0.0f, 0.0f,
       0.0f, 0.0f, k,    -near * k,
       0.0f, 0.0f, 1.0f, 0.0f };
};
</code></pre>

CC BY-SA 4.0
2023-02-20T15:48:44.643Z
2023-02-20T15:48:44.643Z
pmw1234
<p>Disregard, The issue was found to be an error in Vec3 overloaded division operator used when calculating Normals in Vec3::Normalize(). I will leave the problem up for anyone who wants to study</p>

CC BY-SA 4.0
2023-02-20T13:00:11.520Z
2023-02-20T13:00:11.520Z
Joseph Vargas
<p>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.</p>
<p>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.</p>
<p>A condensed version of my Mat4 class is as follows~</p>
<pre><code>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&amp; Position, const Vec3&amp; Target, const Vec3&amp; 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;
    }
};
</code></pre>

<vulkan><linear-algebra>
Custom LookAt and Perspective Matrix functions not rendering in Vulkan
Joseph Vargas
# Custom LookAt and Perspective Matrix functions not rendering in Vulkan

(Asked by: username_0 on 2023-02-20)

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;
    }
};

```

**Tags:** vulkan, linear-algebra


---

## 2 answers

### Answer by username_1 on 2023-02-20. Score: 1

The perspective matrix as written is setup for OpenGL here is one setup for vulkan:

```
// Radians is just a small wrapper around a float here
mat4 Projection( Radians fovy, flt32 s, flt32 near, flt32 far )
{
   flt32 g = 1.0f / tan(fovy * 0.5f);
   flt32 k = far / (far-near);

   return mat4{
       g/s,  0.0f, 0.0f, 0.0f,
       0.0f, g,    0.0f, 0.0f,
       0.0f, 0.0f, k,    -near * k,
       0.0f, 0.0f, 1.0f, 0.0f };
};

```


---

### Answer by username_0 on 2023-02-20. Score: 0

Disregard, The issue was found to be an error in Vec3 overloaded division operator used when calculating Normals in Vec3::Normalize(). I will leave the problem up for anyone who wants to study


---

