Implement perspective projection

This commit is contained in:
Abdelrahman Said 2024-08-11 17:58:38 +01:00
parent 34d0d17b76
commit b4210da399
2 changed files with 32 additions and 1 deletions

View File

@ -39,7 +39,8 @@ int main(void) {
} }
clear_buffer(&(render.img), &bg); clear_buffer(&(render.img), &bg);
render_model(&obj, &render, teal, RENDER_TYPE_SHADED, COLOUR_TYPE_FIXED); render_model(&obj, &render, teal, RENDER_TYPE_SHADED, COLOUR_TYPE_FIXED,
PROJECTION_TYPE_PERSPECTIVE);
save_image(&(render.img), "result.pam"); save_image(&(render.img), "result.pam");
wapp_mem_arena_destroy(&arena); wapp_mem_arena_destroy(&arena);

View File

@ -35,6 +35,19 @@
.y = V1.z * V2.x - V1.x * V2.z, \ .y = V1.z * V2.x - V1.x * V2.z, \
.z = V1.x * V2.y - V1.y * V2.x, \ .z = V1.x * V2.y - V1.y * V2.x, \
}) })
#define mat4x4_mul_vec4(MAT, V) \
((V4f){ \
.x = MAT.row0.x * V.x + MAT.row0.y * V.y + MAT.row0.z * V.z + \
MAT.row0.w * V.w, \
.y = MAT.row1.x * V.x + MAT.row1.y * V.y + MAT.row1.z * V.z + \
MAT.row1.w * V.w, \
.z = MAT.row2.x * V.x + MAT.row2.y * V.y + MAT.row2.z * V.z + \
MAT.row2.w * V.w, \
.w = MAT.row3.x * V.x + MAT.row3.y * V.y + MAT.row3.z * V.z + \
MAT.row3.w * V.w, \
})
#define project_vec4(V) ((V3f){.x = V.x / V.w, .y = V.y / V.w, .z = V.z / V.w})
#define vec3_to_vertex(V) ((Vertex){.x = V.x, .y = V.y, .z = V.z})
typedef struct triangle_bbox TriangleBBox; typedef struct triangle_bbox TriangleBBox;
struct triangle_bbox { struct triangle_bbox {
@ -235,6 +248,23 @@ internal void render_triangle(const Triangle *triangle, const Model *model,
list_get(model->texture_coordinates, triangle->tx2), list_get(model->texture_coordinates, triangle->tx2),
}; };
if (projection == PROJECTION_TYPE_PERSPECTIVE) {
// Basic perspective projection
V4f vertex;
V3f projected;
for (u64 i = 0; i < TRIANGLE_VERTICES; ++i) {
vertex = (V4f){
.x = vertices[i].x,
.y = vertices[i].y,
.z = vertices[i].z,
.w = 1.0f,
};
vertex = mat4x4_mul_vec4(g_cam_matrix, vertex);
projected = project_vec4(vertex);
vertices[i] = vec3_to_vertex(projected);
}
}
if (type == RENDER_TYPE_WIREFRAME) { if (type == RENDER_TYPE_WIREFRAME) {
Vertex v0, v1; Vertex v0, v1;
u64 x0, y0, x1, y1; u64 x0, y0, x1, y1;