Most of the time, we can pre-multiply matrix Model_View_Projection together as matrix_MVP. Then call mul(matrix_MVP, object_space_position). This can reduce the number of matrix mul required.
On modern GPUs, this is commonly done in the vertex shader, outputting projection space position of a vertex. Then, the hardware will automatically interporlate among the triangle vertices, and do the z-div for you to convert into NDC space.
Most of the time, we can pre-multiply matrix Model_View_Projection together as matrix_MVP. Then call mul(matrix_MVP, object_space_position). This can reduce the number of matrix mul required. On modern GPUs, this is commonly done in the vertex shader, outputting projection space position of a vertex. Then, the hardware will automatically interporlate among the triangle vertices, and do the z-div for you to convert into NDC space.