diff --git a/include/rasteriser/rasteriser.h b/include/rasteriser/rasteriser.h index 20a70b9..f67b8f6 100644 --- a/include/rasteriser/rasteriser.h +++ b/include/rasteriser/rasteriser.h @@ -14,6 +14,9 @@ typedef struct { i64 idx0; i64 idx1; i64 idx2; + f32 h0; + f32 h1; + f32 h2; colour_t colour; } scene_triangle_t; diff --git a/src/rasteriser/main.c b/src/rasteriser/main.c index 8d8a897..d083ea6 100644 --- a/src/rasteriser/main.c +++ b/src/rasteriser/main.c @@ -53,18 +53,30 @@ int main(void) { } // Triangles scene_triangle_t tris[] = { - (scene_triangle_t){0, 1, 2, (colour_t){.colour = 0xff0000ff}}, - (scene_triangle_t){0, 2, 3, (colour_t){.colour = 0xff0000ff}}, - (scene_triangle_t){4, 0, 3, (colour_t){.colour = 0x00ff00ff}}, - (scene_triangle_t){4, 3, 7, (colour_t){.colour = 0x00ff00ff}}, - (scene_triangle_t){5, 4, 7, (colour_t){.colour = 0x0000ffff}}, - (scene_triangle_t){5, 7, 6, (colour_t){.colour = 0x0000ffff}}, - (scene_triangle_t){1, 5, 6, (colour_t){.colour = 0xffff00ff}}, - (scene_triangle_t){1, 6, 2, (colour_t){.colour = 0xffff00ff}}, - (scene_triangle_t){4, 5, 1, (colour_t){.colour = 0xff00ffff}}, - (scene_triangle_t){4, 1, 0, (colour_t){.colour = 0xff00ffff}}, - (scene_triangle_t){2, 6, 7, (colour_t){.colour = 0x00ffffff}}, - (scene_triangle_t){2, 7, 3, (colour_t){.colour = 0x00ffffff}}, + (scene_triangle_t){0, 1, 2, 1.0f, 1.0f, 1.0f, + (colour_t){.colour = 0xff0000ff}}, + (scene_triangle_t){0, 2, 3, 1.0f, 1.0f, 1.0f, + (colour_t){.colour = 0xff0000ff}}, + (scene_triangle_t){4, 0, 3, 1.0f, 1.0f, 1.0f, + (colour_t){.colour = 0x00ff00ff}}, + (scene_triangle_t){4, 3, 7, 1.0f, 1.0f, 1.0f, + (colour_t){.colour = 0x00ff00ff}}, + (scene_triangle_t){5, 4, 7, 1.0f, 1.0f, 1.0f, + (colour_t){.colour = 0x0000ffff}}, + (scene_triangle_t){5, 7, 6, 1.0f, 1.0f, 1.0f, + (colour_t){.colour = 0x0000ffff}}, + (scene_triangle_t){1, 5, 6, 1.0f, 1.0f, 1.0f, + (colour_t){.colour = 0xffff00ff}}, + (scene_triangle_t){1, 6, 2, 1.0f, 1.0f, 1.0f, + (colour_t){.colour = 0xffff00ff}}, + (scene_triangle_t){4, 5, 1, 1.0f, 1.0f, 1.0f, + (colour_t){.colour = 0xff00ffff}}, + (scene_triangle_t){4, 1, 0, 1.0f, 1.0f, 1.0f, + (colour_t){.colour = 0xff00ffff}}, + (scene_triangle_t){2, 6, 7, 1.0f, 1.0f, 1.0f, + (colour_t){.colour = 0x00ffffff}}, + (scene_triangle_t){2, 7, 3, 1.0f, 1.0f, 1.0f, + (colour_t){.colour = 0x00ffffff}}, }; for (u64 i = 0; i < ARR_LEN(tris); ++i) { list_append(scene_triangle_t, arena, triangles, tris[i]); diff --git a/src/rasteriser/rasteriser.c b/src/rasteriser/rasteriser.c index 60a6041..331ec56 100644 --- a/src/rasteriser/rasteriser.c +++ b/src/rasteriser/rasteriser.c @@ -11,6 +11,11 @@ #include #include +typedef struct { + vec3f_t point; + f32 h; +} segment_intersection_result_t; + internal void render_instance(window_t *wnd, const rasteriser_scene_t *scene, Arena *arena, mat4x4f_t camera_matrix, mat3x4f_t projection_matrix, @@ -29,8 +34,9 @@ internal list_float *interpolate(Arena *arena, i32 i0, f32 d0, i32 i1, f32 d1); internal inline void order_triangle_points(triangle_t *triangle); internal inline bounding_sphere_t get_bounding_sphere(const list_vec3f_t *vertices); -internal inline vec3f_t segment_intersection(const vec3f_t *a, const vec3f_t *b, - const clipping_plane_t *plane); +internal inline segment_intersection_result_t +segment_intersection(const vec3f_t *a, const vec3f_t *b, f32 ha, f32 hb, + const clipping_plane_t *plane); internal inline void copy_triangles(Arena *arena, list_scene_triangle_t *dst, const list_scene_triangle_t *src); internal inline f32 signed_distance(const vec3f_t *vertex, @@ -119,9 +125,9 @@ internal void render_instance(window_t *wnd, const rasteriser_scene_t *scene, .p0 = list_get(projected, triangle.idx0), .p1 = list_get(projected, triangle.idx1), .p2 = list_get(projected, triangle.idx2), - .h0 = 1.0f, - .h1 = 1.0f, - .h2 = 1.0f, + .h0 = triangle.h0, + .h1 = triangle.h1, + .h2 = triangle.h2, .colour = triangle.colour, }; @@ -351,72 +357,106 @@ internal void clip_triangle_against_plane(Arena *arena, model_t *model, vec3f_t *vp; vec3f_t *vn0; vec3f_t *vn1; + f32 *hp; + f32 *hn0; + f32 *hn1; i64 *in0; i64 *in1; if (d0 > 0.0f) { vp = v0; vn0 = v1; vn1 = v2; + hp = &(triangle->h0); + hn0 = &(triangle->h1); + hn1 = &(triangle->h2); in0 = &(triangle->idx1); in1 = &(triangle->idx2); } else if (d1 > 0.0f) { vp = v1; vn0 = v0; vn1 = v2; + hp = &(triangle->h1); + hn0 = &(triangle->h0); + hn1 = &(triangle->h2); in0 = &(triangle->idx0); in1 = &(triangle->idx2); } else { vp = v2; vn0 = v0; vn1 = v1; + hp = &(triangle->h2); + hn0 = &(triangle->h0); + hn1 = &(triangle->h1); in0 = &(triangle->idx0); in1 = &(triangle->idx1); } - list_append(vec3f_t, arena, model->vertices, - segment_intersection(vp, vn0, plane)); - list_append(vec3f_t, arena, model->vertices, - segment_intersection(vp, vn1, plane)); + segment_intersection_result_t r0 = + segment_intersection(vp, vn0, *hp, *hn0, plane); + segment_intersection_result_t r1 = + segment_intersection(vp, vn1, *hp, *hn1, plane); + list_append(vec3f_t, arena, model->vertices, r0.point); + list_append(vec3f_t, arena, model->vertices, r1.point); *in0 = model->vertices->count - 2; *in1 = model->vertices->count - 1; + *hn0 = r0.h; + *hn1 = r1.h; } else { vec3f_t *vn; vec3f_t *vp0; vec3f_t *vp1; + f32 *hn; + f32 *hp0; + f32 *hp1; i64 *in; i64 *ip; if (d0 < 0.0f) { vn = v0; vp0 = v1; vp1 = v2; + hn = &(triangle->h0); + hp0 = &(triangle->h1); + hp1 = &(triangle->h2); in = &(triangle->idx0); ip = &(triangle->idx2); } else if (d1 < 0.0f) { vn = v1; vp0 = v0; vp1 = v2; + hn = &(triangle->h1); + hp0 = &(triangle->h0); + hp1 = &(triangle->h2); in = &(triangle->idx1); ip = &(triangle->idx2); } else { vn = v2; vp0 = v0; vp1 = v1; + hn = &(triangle->h2); + hp0 = &(triangle->h0); + hp1 = &(triangle->h1); in = &(triangle->idx2); ip = &(triangle->idx1); } - list_append(vec3f_t, arena, model->vertices, - segment_intersection(vp0, vn, plane)); - list_append(vec3f_t, arena, model->vertices, - segment_intersection(vp1, vn, plane)); + segment_intersection_result_t r0 = + segment_intersection(vp0, vn, *hp0, *hn, plane); + segment_intersection_result_t r1 = + segment_intersection(vp1, vn, *hp1, *hn, plane); + list_append(vec3f_t, arena, model->vertices, r0.point); + list_append(vec3f_t, arena, model->vertices, r1.point); *in = model->vertices->count - 2; + *hn = r0.h; scene_triangle_t tri = { .idx0 = *in, .idx1 = *ip, .idx2 = model->vertices->count - 1, + .h0 = *hn, + .h1 = *hp1, + .h2 = r1.h, .colour = triangle->colour, }; @@ -489,8 +529,9 @@ get_bounding_sphere(const list_vec3f_t *vertices) { }; } -internal inline vec3f_t segment_intersection(const vec3f_t *a, const vec3f_t *b, - const clipping_plane_t *plane) { +internal inline segment_intersection_result_t +segment_intersection(const vec3f_t *a, const vec3f_t *b, f32 ha, f32 hb, + const clipping_plane_t *plane) { f32 neg_d = plane->distance * -1.0f; f32 na_dot = vec_dot(vec3f_t, plane->normal, *a); vec3f_t ba = vec_sub(vec3f_t, *b, *a); @@ -498,7 +539,10 @@ internal inline vec3f_t segment_intersection(const vec3f_t *a, const vec3f_t *b, f32 t = (neg_d - na_dot) / nba_dot; - return vec_add(vec3f_t, *a, vec_mul_num(vec3f_t, ba, t)); + return (segment_intersection_result_t){ + .point = vec_add(vec3f_t, *a, vec_mul_num(vec3f_t, ba, t)), + .h = ha + t * (hb - ha), + }; } internal inline void copy_triangles(Arena *arena, list_scene_triangle_t *dst,