diff --git a/include/rasteriser/rasteriser.h b/include/rasteriser/rasteriser.h index 012a4ea..3e994f7 100644 --- a/include/rasteriser/rasteriser.h +++ b/include/rasteriser/rasteriser.h @@ -22,6 +22,7 @@ typedef struct { colour_t colour; } scene_triangle_t; +MAKE_LIST_TYPE(u64); MAKE_LIST_TYPE(f32); MAKE_LIST_TYPE(vec2i_t); MAKE_LIST_TYPE(vec3f_t); @@ -33,6 +34,8 @@ typedef enum { RASTERISER_RENDER_WIREFRAME, RASTERISER_RENDER_FILLED, RASTERISER_RENDER_SHADED, + + COUNT_RASTERISER_RENDER, } render_type_t; typedef struct { diff --git a/src/rasteriser/main.c b/src/rasteriser/main.c index 10b2d5f..7233bc6 100644 --- a/src/rasteriser/main.c +++ b/src/rasteriser/main.c @@ -159,6 +159,8 @@ int main(void) { return EXIT_FAILURE; } + render_type_t type = RASTERISER_RENDER_FILLED; + while (running) { while (SDL_PollEvent(&event)) { switch (event.type) { @@ -174,6 +176,8 @@ int main(void) { camera.rotation.y += 1.0f; } else if (event.key.keysym.sym == SDLK_a) { camera.rotation.y -= 1.0f; + } else if (event.key.keysym.sym == SDLK_e) { + type = (type + 1) % COUNT_RASTERISER_RENDER; } break; } @@ -181,7 +185,7 @@ int main(void) { clear_window(&window, bg); - render_scene(&window, frame_arena, &scene, RASTERISER_RENDER_FILLED); + render_scene(&window, frame_arena, &scene, type); swap_buffers(&window); diff --git a/src/rasteriser/rasteriser.c b/src/rasteriser/rasteriser.c index 09d2578..778c9c6 100644 --- a/src/rasteriser/rasteriser.c +++ b/src/rasteriser/rasteriser.c @@ -11,12 +11,20 @@ #include <string.h> #include <sys/mman.h> +#define CULL_ENABLED 0 + internal void render_instance(window_t *wnd, const rasteriser_scene_t *scene, Arena *arena, mat4x4f_t camera_matrix, mat3x4f_t projection_matrix, const instance_t *instance, render_type_t type); internal void clip_instance(Arena *arena, model_t *model, const rasteriser_scene_t *scene); + +#if CULL_ENABLED +internal void cull_back_faces(Arena *arena, const rasteriser_scene_t *scene, + model_t *model); +#endif + internal void clip_instance_against_plane(Arena *arena, model_t *model, const bounding_sphere_t *sphere, const clipping_plane_t *plane); @@ -26,6 +34,13 @@ internal void clip_triangle_against_plane(Arena *arena, model_t *model, i64 triangle_index, const clipping_plane_t *plane); internal list_float *interpolate(Arena *arena, i32 i0, f32 d0, i32 i1, f32 d1); + +#if CULL_ENABLED +internal inline vec3f_t +calculate_triangle_normal(const model_t *model, + const scene_triangle_t *triangle); +#endif + internal inline void order_triangle_points(triangle_t *triangle); internal inline bounding_sphere_t get_bounding_sphere(const list_vertex_t *vertices); @@ -57,11 +72,9 @@ internal void render_instance(window_t *wnd, const rasteriser_scene_t *scene, mat3x4f_t projection_matrix, const instance_t *instance, render_type_t type) { list_vertex_t *transformed = list_create_with_capacity( - vertex_t, arena, - (instance->model->vertices->count + 10) * sizeof(vertex_t)); + vertex_t, arena, instance->model->vertices->count + 10); list_scene_triangle_t *triangles = list_create_with_capacity( - scene_triangle_t, arena, - (instance->model->triangles->count + 10) * sizeof(scene_triangle_t)); + scene_triangle_t, arena, instance->model->triangles->count + 10); if (!transformed || !triangles) { return; } @@ -94,13 +107,17 @@ internal void render_instance(window_t *wnd, const rasteriser_scene_t *scene, } model_t model = {transformed, triangles}; +#if CULL_ENABLED + cull_back_faces(arena, scene, &model); +#endif + clip_instance(arena, &model, scene); if (is_null_model(&model)) { return; } list_vec2i_t *projected = list_create_with_capacity( - vec2i_t, arena, instance->model->vertices->count * sizeof(vec2i_t)); + vec2i_t, arena, instance->model->vertices->count); if (!projected) { return; } @@ -151,6 +168,8 @@ internal void render_instance(window_t *wnd, const rasteriser_scene_t *scene, case RASTERISER_RENDER_SHADED: draw_shaded_triangle(wnd, arena, tri); break; + default: + return; } } } @@ -390,6 +409,36 @@ internal void clip_instance(Arena *arena, model_t *model, } } +#if CULL_ENABLED +internal void cull_back_faces(Arena *arena, const rasteriser_scene_t *scene, + model_t *model) { + list_uint64_t *to_remove = + list_create_with_capacity(u64, arena, model->triangles->count); + vec3f_t normal; + scene_triangle_t triangle; + vertex_t v0; + vec3f_t viewing_vector; + f32 dot_product; + + for (u64 i = 0; i < model->triangles->count; ++i) { + triangle = list_get(model->triangles, i); + v0 = list_get(model->vertices, triangle.idx0); + normal = calculate_triangle_normal(model, &triangle); + viewing_vector = vec_sub(vec3f_t, v0.position, scene->camera->position); + dot_product = vec_dot(vec3f_t, normal, viewing_vector); + + if (dot_product <= 0.0f) { + list_append(u64, arena, to_remove, i); + } + } + + for (u64 i = 0; i < to_remove->count; ++i) { + u64 idx = list_get(to_remove, i); + list_remove(model->triangles, idx); + } +} +#endif + internal void clip_instance_against_plane(Arena *arena, model_t *model, const bounding_sphere_t *sphere, const clipping_plane_t *plane) { @@ -536,6 +585,21 @@ internal list_float *interpolate(Arena *arena, i32 i0, f32 d0, i32 i1, f32 d1) { return values; } +#if CULL_ENABLED +internal inline vec3f_t +calculate_triangle_normal(const model_t *model, + const scene_triangle_t *triangle) { + vertex_t v0 = list_get(model->vertices, triangle->idx0); + vertex_t v1 = list_get(model->vertices, triangle->idx1); + vertex_t v2 = list_get(model->vertices, triangle->idx2); + + vec3f_t ba = vec_sub(vec3f_t, v1.position, v0.position); + vec3f_t ca = vec_sub(vec3f_t, v2.position, v0.position); + + return vec_cross(vec3f_t, ba, ca); +} +#endif + internal inline void order_triangle_points(triangle_t *triangle) { if (triangle->p1.y < triangle->p0.y) { swap(vec2i_t, triangle->p0, triangle->p1);