Implement Z buffer

This commit is contained in:
Abdelrahman Said 2024-08-04 17:53:52 +01:00
parent bd1326d83e
commit f024d51d85
3 changed files with 31 additions and 3 deletions

View File

@ -1,4 +1,5 @@
#include "img.h" #include "img.h"
#include "aliases.h"
#include "mem_arena.h" #include "mem_arena.h"
#include "pam.h" #include "pam.h"
#include "utils.h" #include "utils.h"
@ -6,6 +7,8 @@
#include <stddef.h> #include <stddef.h>
#include <string.h> #include <string.h>
internal u64 calculate_pixel_index(Buffer *buffer, u64 x, u64 y, u64 base_size);
bool _init_buffer(Arena *arena, Buffer *buffer, u64 base_size) { bool _init_buffer(Arena *arena, Buffer *buffer, u64 base_size) {
if (!arena || !buffer || buffer->width == 0 || buffer->height == 0) { if (!arena || !buffer || buffer->width == 0 || buffer->height == 0) {
return false; return false;
@ -17,8 +20,13 @@ bool _init_buffer(Arena *arena, Buffer *buffer, u64 base_size) {
return buffer->buf != NULL; return buffer->buf != NULL;
} }
u8 *_get_pixel(Buffer *buffer, u64 x, u64 y, u64 base_size) {
u64 idx = calculate_pixel_index(buffer, x, y, base_size);
return ((u8 *)(buffer->buf)) + idx;
}
void _set_pixel(Buffer *buffer, u64 x, u64 y, void *value, u64 base_size) { void _set_pixel(Buffer *buffer, u64 x, u64 y, void *value, u64 base_size) {
u64 idx = (y * buffer->width + x) * base_size; u64 idx = calculate_pixel_index(buffer, x, y, base_size);
memcpy(((u8 *)(buffer->buf)) + idx, value, base_size); memcpy(((u8 *)(buffer->buf)) + idx, value, base_size);
} }
@ -65,3 +73,8 @@ void draw_line(Image *img, u64 x0, u64 y0, u64 x1, u64 y1, Colour colour) {
void save_image(const Image *img, const char *filename) { void save_image(const Image *img, const char *filename) {
write_p7_image(img->width, img->height, (u8 *)(img->buf), filename); write_p7_image(img->width, img->height, (u8 *)(img->buf), filename);
} }
internal u64 calculate_pixel_index(Buffer *buffer, u64 x, u64 y,
u64 base_size) {
return (y * buffer->width + x) * base_size;
}

View File

@ -26,12 +26,15 @@ BUF_TYPE(f32, Depth);
#define init_buffer(ARENA, BUF) \ #define init_buffer(ARENA, BUF) \
_init_buffer(ARENA, (Buffer *)BUF, sizeof(*((BUF)->buf))) _init_buffer(ARENA, (Buffer *)BUF, sizeof(*((BUF)->buf)))
#define get_pixel(TYPE, BUF, X, Y) \
(*((TYPE *)(_get_pixel((Buffer *)BUF, X, Y, sizeof(*((BUF)->buf))))))
#define set_pixel(BUF, X, Y, VAL_PTR) \ #define set_pixel(BUF, X, Y, VAL_PTR) \
_set_pixel((Buffer *)BUF, X, Y, VAL_PTR, sizeof(*((BUF)->buf))) _set_pixel((Buffer *)BUF, X, Y, VAL_PTR, sizeof(*((BUF)->buf)))
#define clear_buffer(BUF, VAL_PTR) \ #define clear_buffer(BUF, VAL_PTR) \
_clear_buffer((Buffer *)BUF, VAL_PTR, sizeof(*((BUF)->buf))) _clear_buffer((Buffer *)BUF, VAL_PTR, sizeof(*((BUF)->buf)))
bool _init_buffer(Arena *arena, Buffer *buffer, u64 base_size); bool _init_buffer(Arena *arena, Buffer *buffer, u64 base_size);
u8 *_get_pixel(Buffer *buffer, u64 x, u64 y, u64 base_size);
void _set_pixel(Buffer *buffer, u64 x, u64 y, void *value, u64 base_size); void _set_pixel(Buffer *buffer, u64 x, u64 y, void *value, u64 base_size);
void _clear_buffer(Buffer *buffer, void *value, u64 base_size); void _clear_buffer(Buffer *buffer, void *value, u64 base_size);
void draw_line(Image *img, u64 x0, u64 y0, u64 x1, u64 y1, Colour colour); void draw_line(Image *img, u64 x0, u64 y0, u64 x1, u64 y1, Colour colour);

View File

@ -144,7 +144,7 @@ bool init_render(Arena *arena, Render *render, u64 width, u64 height) {
return false; return false;
} }
f32 inf = INFINITY; f32 inf = -1.0f * INFINITY;
clear_buffer(&(render->depth), &inf); clear_buffer(&(render->depth), &inf);
return true; return true;
@ -215,6 +215,7 @@ internal void render_triangle(const Triangle *triangle, const Model *model,
internal void fill_triangle(Render *render, Vertex vertices[TRIANGLE_VERTICES], internal void fill_triangle(Render *render, Vertex vertices[TRIANGLE_VERTICES],
Colour colour) { Colour colour) {
Image *img = &(render->img); Image *img = &(render->img);
Depth *depth = &(render->depth);
TriangleBBox bbox = get_triangle_bbox(img, vertices); TriangleBBox bbox = get_triangle_bbox(img, vertices);
u64 v0x, v0y, v1x, v1y, v2x, v2y; u64 v0x, v0y, v1x, v1y, v2x, v2y;
@ -230,6 +231,8 @@ internal void fill_triangle(Render *render, Vertex vertices[TRIANGLE_VERTICES],
f32 denom = (f32)d00 * (f32)d11 - (f32)d01 * (f32)d01; f32 denom = (f32)d00 * (f32)d11 - (f32)d01 * (f32)d01;
V2i ap; V2i ap;
V3f coords; V3f coords;
f32 z;
f32 zbuf;
for (u64 y = bbox.y0; y < bbox.y1; ++y) { for (u64 y = bbox.y0; y < bbox.y1; ++y) {
for (u64 x = bbox.x0; x < bbox.x1; ++x) { for (u64 x = bbox.x0; x < bbox.x1; ++x) {
@ -238,9 +241,18 @@ internal void fill_triangle(Render *render, Vertex vertices[TRIANGLE_VERTICES],
if (coords.x < 0.0f || coords.y < 0.0f || coords.z < 0.0f) { if (coords.x < 0.0f || coords.y < 0.0f || coords.z < 0.0f) {
continue; continue;
} }
z = 0.0f;
z += vertices[0].z * coords.x + vertices[1].z * coords.y +
vertices[2].z * coords.z;
zbuf = get_pixel(f32, &(render->depth), x, y);
if (z > zbuf) {
set_pixel(depth, x, y, &z);
set_pixel(img, x, y, &colour); set_pixel(img, x, y, &colour);
} }
} }
}
} }
internal TriangleBBox get_triangle_bbox(const Image *img, internal TriangleBBox get_triangle_bbox(const Image *img,