Incomplete implementation of back face culling

This commit is contained in:
Abdelrahman Said 2024-07-14 16:02:37 +01:00
parent 5a3b143762
commit 51099ae97e
3 changed files with 77 additions and 6 deletions

View File

@ -22,6 +22,7 @@ typedef struct {
colour_t colour; colour_t colour;
} scene_triangle_t; } scene_triangle_t;
MAKE_LIST_TYPE(u64);
MAKE_LIST_TYPE(f32); MAKE_LIST_TYPE(f32);
MAKE_LIST_TYPE(vec2i_t); MAKE_LIST_TYPE(vec2i_t);
MAKE_LIST_TYPE(vec3f_t); MAKE_LIST_TYPE(vec3f_t);
@ -33,6 +34,8 @@ typedef enum {
RASTERISER_RENDER_WIREFRAME, RASTERISER_RENDER_WIREFRAME,
RASTERISER_RENDER_FILLED, RASTERISER_RENDER_FILLED,
RASTERISER_RENDER_SHADED, RASTERISER_RENDER_SHADED,
COUNT_RASTERISER_RENDER,
} render_type_t; } render_type_t;
typedef struct { typedef struct {

View File

@ -159,6 +159,8 @@ int main(void) {
return EXIT_FAILURE; return EXIT_FAILURE;
} }
render_type_t type = RASTERISER_RENDER_FILLED;
while (running) { while (running) {
while (SDL_PollEvent(&event)) { while (SDL_PollEvent(&event)) {
switch (event.type) { switch (event.type) {
@ -174,6 +176,8 @@ int main(void) {
camera.rotation.y += 1.0f; camera.rotation.y += 1.0f;
} else if (event.key.keysym.sym == SDLK_a) { } else if (event.key.keysym.sym == SDLK_a) {
camera.rotation.y -= 1.0f; camera.rotation.y -= 1.0f;
} else if (event.key.keysym.sym == SDLK_e) {
type = (type + 1) % COUNT_RASTERISER_RENDER;
} }
break; break;
} }
@ -181,7 +185,7 @@ int main(void) {
clear_window(&window, bg); clear_window(&window, bg);
render_scene(&window, frame_arena, &scene, RASTERISER_RENDER_FILLED); render_scene(&window, frame_arena, &scene, type);
swap_buffers(&window); swap_buffers(&window);

View File

@ -11,12 +11,20 @@
#include <string.h> #include <string.h>
#include <sys/mman.h> #include <sys/mman.h>
#define CULL_ENABLED 0
internal void render_instance(window_t *wnd, const rasteriser_scene_t *scene, internal void render_instance(window_t *wnd, const rasteriser_scene_t *scene,
Arena *arena, mat4x4f_t camera_matrix, Arena *arena, mat4x4f_t camera_matrix,
mat3x4f_t projection_matrix, mat3x4f_t projection_matrix,
const instance_t *instance, render_type_t type); const instance_t *instance, render_type_t type);
internal void clip_instance(Arena *arena, model_t *model, internal void clip_instance(Arena *arena, model_t *model,
const rasteriser_scene_t *scene); 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, internal void clip_instance_against_plane(Arena *arena, model_t *model,
const bounding_sphere_t *sphere, const bounding_sphere_t *sphere,
const clipping_plane_t *plane); const clipping_plane_t *plane);
@ -26,6 +34,13 @@ internal void clip_triangle_against_plane(Arena *arena, model_t *model,
i64 triangle_index, i64 triangle_index,
const clipping_plane_t *plane); const clipping_plane_t *plane);
internal list_float *interpolate(Arena *arena, i32 i0, f32 d0, i32 i1, f32 d1); 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 void order_triangle_points(triangle_t *triangle);
internal inline bounding_sphere_t internal inline bounding_sphere_t
get_bounding_sphere(const list_vertex_t *vertices); 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, mat3x4f_t projection_matrix,
const instance_t *instance, render_type_t type) { const instance_t *instance, render_type_t type) {
list_vertex_t *transformed = list_create_with_capacity( list_vertex_t *transformed = list_create_with_capacity(
vertex_t, arena, vertex_t, arena, instance->model->vertices->count + 10);
(instance->model->vertices->count + 10) * sizeof(vertex_t));
list_scene_triangle_t *triangles = list_create_with_capacity( list_scene_triangle_t *triangles = list_create_with_capacity(
scene_triangle_t, arena, scene_triangle_t, arena, instance->model->triangles->count + 10);
(instance->model->triangles->count + 10) * sizeof(scene_triangle_t));
if (!transformed || !triangles) { if (!transformed || !triangles) {
return; return;
} }
@ -94,13 +107,17 @@ internal void render_instance(window_t *wnd, const rasteriser_scene_t *scene,
} }
model_t model = {transformed, triangles}; model_t model = {transformed, triangles};
#if CULL_ENABLED
cull_back_faces(arena, scene, &model);
#endif
clip_instance(arena, &model, scene); clip_instance(arena, &model, scene);
if (is_null_model(&model)) { if (is_null_model(&model)) {
return; return;
} }
list_vec2i_t *projected = list_create_with_capacity( 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) { if (!projected) {
return; return;
} }
@ -151,6 +168,8 @@ internal void render_instance(window_t *wnd, const rasteriser_scene_t *scene,
case RASTERISER_RENDER_SHADED: case RASTERISER_RENDER_SHADED:
draw_shaded_triangle(wnd, arena, tri); draw_shaded_triangle(wnd, arena, tri);
break; 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, internal void clip_instance_against_plane(Arena *arena, model_t *model,
const bounding_sphere_t *sphere, const bounding_sphere_t *sphere,
const clipping_plane_t *plane) { 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; 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) { internal inline void order_triangle_points(triangle_t *triangle) {
if (triangle->p1.y < triangle->p0.y) { if (triangle->p1.y < triangle->p0.y) {
swap(vec2i_t, triangle->p0, triangle->p1); swap(vec2i_t, triangle->p0, triangle->p1);