Start implementing drawing order
This commit is contained in:
parent
77edf714bb
commit
f6848b5f4f
1
compile
1
compile
@ -12,6 +12,7 @@ RAYTRACER_SRC="src/window/*.c \
|
||||
src/raytracer/*.c \
|
||||
src/math/*.c \
|
||||
src/camera/*.c \
|
||||
$WAPP_SRC \
|
||||
"
|
||||
|
||||
RASTERISER_SRC="src/window/*.c \
|
||||
|
@ -31,7 +31,8 @@ MAKE_LIST_TYPE(scene_triangle_t);
|
||||
|
||||
typedef enum {
|
||||
RASTERISER_RENDER_WIREFRAME,
|
||||
RASTERISER_RENDER_SOLID,
|
||||
RASTERISER_RENDER_FILLED,
|
||||
RASTERISER_RENDER_SHADED,
|
||||
} render_type_t;
|
||||
|
||||
typedef struct {
|
||||
@ -46,6 +47,9 @@ typedef struct {
|
||||
f32 h0;
|
||||
f32 h1;
|
||||
f32 h2;
|
||||
f32 z0;
|
||||
f32 z1;
|
||||
f32 z2;
|
||||
colour_t colour;
|
||||
} triangle_t;
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
#define WINDOW_H
|
||||
|
||||
#include "aliases.h"
|
||||
#include "mem_arena.h"
|
||||
#include "vector/vec.h"
|
||||
#include <SDL2/SDL_video.h>
|
||||
#include <stdbool.h>
|
||||
@ -29,13 +30,17 @@ typedef struct {
|
||||
SDL_Window *window;
|
||||
SDL_Surface *front_buffer;
|
||||
SDL_Surface *back_buffer;
|
||||
f32 *z_buffer;
|
||||
} window_t;
|
||||
|
||||
bool init_window(window_t *wnd, u32 width, u32 height, const char *title);
|
||||
bool init_window(Arena *arena, window_t *wnd, u32 width, u32 height,
|
||||
const char *title);
|
||||
void close_window(window_t *wnd);
|
||||
|
||||
void clear_window(window_t *wnd, colour_t colour);
|
||||
void set_pixel(window_t *wnd, i32 x, i32 y, colour_t colour);
|
||||
void set_z_pixel(window_t *wnd, i32 x, i32 y, f32 value);
|
||||
f32 get_z_pixel(const window_t *wnd, i32 x, i32 y);
|
||||
void swap_buffers(window_t *wnd);
|
||||
|
||||
vec3f_t window_to_viewport(const window_t *wnd, i32 x, i32 y, vec3f_t viewport);
|
||||
|
@ -20,12 +20,6 @@ int main(void) {
|
||||
};
|
||||
vec3f_t viewport = {.x = 1.0f, .y = 1.0f, .z = 1.0f};
|
||||
|
||||
window_t window = {0};
|
||||
|
||||
if (!init_window(&window, 800, 800, "CG From Scratch Rasteriser")) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
Arena *arena = NULL;
|
||||
u64 main_arena_capacity = 64ull * 1024ull * 1024ull * 1024ull;
|
||||
if (!wapp_mem_arena_init(&arena, main_arena_capacity, WAPP_MEM_ALLOC_RESERVE,
|
||||
@ -33,6 +27,12 @@ int main(void) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
window_t window = {0};
|
||||
|
||||
if (!init_window(arena, &window, 800, 800, "CG From Scratch Rasteriser")) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
list_vertex_t *vertices = list_create(vertex_t, arena);
|
||||
if (!vertices) {
|
||||
return EXIT_FAILURE;
|
||||
@ -181,7 +181,7 @@ int main(void) {
|
||||
|
||||
clear_window(&window, bg);
|
||||
|
||||
render_scene(&window, frame_arena, &scene, RASTERISER_RENDER_SOLID);
|
||||
render_scene(&window, frame_arena, &scene, RASTERISER_RENDER_FILLED);
|
||||
|
||||
swap_buffers(&window);
|
||||
|
||||
|
@ -121,16 +121,23 @@ internal void render_instance(window_t *wnd, const rasteriser_scene_t *scene,
|
||||
list_append(vec2i_t, arena, projected, point);
|
||||
}
|
||||
|
||||
vertex_t v0, v1, v2;
|
||||
for (u64 i = 0; i < triangles->count; ++i) {
|
||||
scene_triangle_t triangle = list_get(triangles, i);
|
||||
v0 = list_get(transformed, triangle.idx0);
|
||||
v1 = list_get(transformed, triangle.idx1);
|
||||
v2 = list_get(transformed, triangle.idx2);
|
||||
|
||||
triangle_t tri = {
|
||||
.p0 = list_get(projected, triangle.idx0),
|
||||
.p1 = list_get(projected, triangle.idx1),
|
||||
.p2 = list_get(projected, triangle.idx2),
|
||||
.h0 = list_get(transformed, triangle.idx0).h,
|
||||
.h1 = list_get(transformed, triangle.idx1).h,
|
||||
.h2 = list_get(transformed, triangle.idx2).h,
|
||||
.h0 = v0.h,
|
||||
.h1 = v1.h,
|
||||
.h2 = v2.h,
|
||||
.z0 = v0.position.z,
|
||||
.z1 = v1.position.z,
|
||||
.z2 = v2.position.z,
|
||||
.colour = triangle.colour,
|
||||
};
|
||||
|
||||
@ -143,9 +150,12 @@ internal void render_instance(window_t *wnd, const rasteriser_scene_t *scene,
|
||||
case RASTERISER_RENDER_WIREFRAME:
|
||||
draw_wireframe_triangle(wnd, arena, tri);
|
||||
break;
|
||||
case RASTERISER_RENDER_SOLID:
|
||||
case RASTERISER_RENDER_FILLED:
|
||||
draw_filled_triangle(wnd, arena, tri);
|
||||
break;
|
||||
case RASTERISER_RENDER_SHADED:
|
||||
draw_shaded_triangle(wnd, arena, tri);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -176,22 +186,57 @@ void draw_filled_triangle(window_t *wnd, Arena *arena, triangle_t triangle) {
|
||||
list_pop(x01); // Last element of x01 is a duplicate of first element in x12
|
||||
list_merge(f32, arena, x012, x01, x12);
|
||||
|
||||
f32 z0 = triangle.z0;
|
||||
f32 z1 = triangle.z1;
|
||||
f32 z2 = triangle.z2;
|
||||
list_float *z01 = interpolate(arena, y0, z0, y1, z1);
|
||||
list_float *z12 = interpolate(arena, y1, z1, y2, z2);
|
||||
list_float *z02 = interpolate(arena, y0, z0, y2, z2);
|
||||
list_float *z012 = NULL;
|
||||
|
||||
list_pop(z01); // Last element of z01 is a duplicate of first element in z12
|
||||
list_merge(f32, arena, z012, z01, z12);
|
||||
|
||||
list_float *x_left;
|
||||
list_float *x_right;
|
||||
list_float *z_left;
|
||||
list_float *z_right;
|
||||
u64 middle = (u64)(floorf((f32)(x02->count) / 2.0f));
|
||||
if (list_get(x02, middle) < list_get(x012, middle)) {
|
||||
x_left = x02;
|
||||
z_left = z02;
|
||||
x_right = x012;
|
||||
z_right = z012;
|
||||
} else {
|
||||
x_left = x012;
|
||||
z_left = z012;
|
||||
x_right = x02;
|
||||
z_right = z02;
|
||||
}
|
||||
|
||||
list_float *z_segment = NULL;
|
||||
i32 index = -1;
|
||||
i64 xl = -1;
|
||||
i64 xr = -1;
|
||||
f32 current_z = INFINITY;
|
||||
f32 new_z = INFINITY;
|
||||
|
||||
for (i64 y = y0; y <= y2; ++y) {
|
||||
i32 index = y - y0;
|
||||
for (i64 x = (i64)list_get(x_left, index); x < list_get(x_right, index);
|
||||
++x) {
|
||||
set_pixel(wnd, x, y, triangle.colour);
|
||||
index = y - y0;
|
||||
xl = (i64)list_get(x_left, index);
|
||||
xr = (i64)list_get(x_right, index);
|
||||
|
||||
for (i64 x = xl; x < xr; ++x) {
|
||||
z_segment = interpolate(arena, xl, list_get(z_left, index), xr,
|
||||
list_get(z_right, index));
|
||||
|
||||
current_z = get_z_pixel(wnd, x, y);
|
||||
new_z = list_get(z_segment, x - xl);
|
||||
|
||||
if (new_z <= current_z) {
|
||||
set_z_pixel(wnd, x, y, new_z);
|
||||
set_pixel(wnd, x, y, triangle.colour);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -225,27 +270,47 @@ void draw_shaded_triangle(window_t *wnd, Arena *arena, triangle_t triangle) {
|
||||
list_pop(h01); // Last element of h01 is a duplicate of first element in h12
|
||||
list_merge(f32, arena, h012, h01, h12);
|
||||
|
||||
f32 z0 = triangle.z0;
|
||||
f32 z1 = triangle.z1;
|
||||
f32 z2 = triangle.z2;
|
||||
list_float *z01 = interpolate(arena, y0, z0, y1, z1);
|
||||
list_float *z12 = interpolate(arena, y1, z1, y2, z2);
|
||||
list_float *z02 = interpolate(arena, y0, z0, y2, z2);
|
||||
list_float *z012 = NULL;
|
||||
|
||||
list_pop(z01); // Last element of z01 is a duplicate of first element in z12
|
||||
list_merge(f32, arena, z012, z01, z12);
|
||||
|
||||
list_float *x_left;
|
||||
list_float *x_right;
|
||||
list_float *h_left;
|
||||
list_float *h_right;
|
||||
list_float *z_left;
|
||||
list_float *z_right;
|
||||
u64 middle = (u64)(floorf((f32)(x02->count) / 2.0f));
|
||||
if (list_get(x02, middle) < list_get(x012, middle)) {
|
||||
x_left = x02;
|
||||
h_left = h02;
|
||||
z_left = z02;
|
||||
x_right = x012;
|
||||
h_right = h012;
|
||||
z_right = z012;
|
||||
} else {
|
||||
x_left = x012;
|
||||
h_left = h012;
|
||||
z_left = z012;
|
||||
x_right = x02;
|
||||
h_right = h02;
|
||||
z_right = z02;
|
||||
}
|
||||
|
||||
list_float *h_segment = NULL;
|
||||
list_float *z_segment = NULL;
|
||||
i32 index = -1;
|
||||
i64 xl = -1;
|
||||
i64 xr = -1;
|
||||
f32 current_z = INFINITY;
|
||||
f32 new_z = INFINITY;
|
||||
colour_t shaded_colour = (colour_t){0};
|
||||
|
||||
for (i64 y = y0; y <= y2; ++y) {
|
||||
@ -255,8 +320,17 @@ void draw_shaded_triangle(window_t *wnd, Arena *arena, triangle_t triangle) {
|
||||
for (i64 x = xl; x < xr; ++x) {
|
||||
h_segment = interpolate(arena, xl, list_get(h_left, index), xr,
|
||||
list_get(h_right, index));
|
||||
z_segment = interpolate(arena, xl, list_get(z_left, index), xr,
|
||||
list_get(z_right, index));
|
||||
shaded_colour = colour_mul(triangle.colour, list_get(h_segment, x - xl));
|
||||
set_pixel(wnd, x, y, shaded_colour);
|
||||
|
||||
current_z = get_z_pixel(wnd, x, y);
|
||||
new_z = list_get(z_segment, x - xl);
|
||||
|
||||
if (new_z <= current_z) {
|
||||
set_z_pixel(wnd, x, y, new_z);
|
||||
set_pixel(wnd, x, y, shaded_colour);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ i32 main(i32 argc, char *argv[]) {
|
||||
|
||||
window_t window = {0};
|
||||
|
||||
if (!init_window(&window, 800, 800, "CG From Scratch Raytracer")) {
|
||||
if (!init_window(NULL, &window, 800, 800, "CG From Scratch Raytracer")) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
|
@ -1,21 +1,25 @@
|
||||
#include "window/window.h"
|
||||
#include "aliases.h"
|
||||
#include "math/math_utils.h"
|
||||
#include "mem_arena.h"
|
||||
#include "vector/vec.h"
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL2/SDL_error.h>
|
||||
#include <SDL2/SDL_pixels.h>
|
||||
#include <SDL2/SDL_surface.h>
|
||||
#include <math.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
u32 index_from_coordinates(window_t *wnd, u32 x, u32 y);
|
||||
u32 index_from_coordinates(const window_t *wnd, u32 x, u32 y);
|
||||
i32 denormalise(i32 value, u32 max, u32 abs_half);
|
||||
vec2i_t denormalised_coords(const window_t *wnd, i32 x, i32 y);
|
||||
void set_screen_pixel(window_t *wnd, u32 x, u32 y, colour_t colour);
|
||||
void set_z_buffer_pixel(window_t *wnd, u32 x, u32 y, f32 value);
|
||||
|
||||
bool init_window(window_t *wnd, u32 width, u32 height, const char *title) {
|
||||
bool init_window(Arena *arena, window_t *wnd, u32 width, u32 height,
|
||||
const char *title) {
|
||||
if (SDL_Init(SDL_INIT_EVERYTHING) != 0) {
|
||||
printf("Failed to initialise SDL: %s\n", SDL_GetError());
|
||||
|
||||
@ -64,6 +68,9 @@ bool init_window(window_t *wnd, u32 width, u32 height, const char *title) {
|
||||
wnd->half_width = width / 2;
|
||||
wnd->half_height = height / 2;
|
||||
wnd->title = title;
|
||||
if (arena) {
|
||||
wnd->z_buffer = wapp_mem_arena_alloc(arena, width * height * sizeof(f32));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -85,6 +92,8 @@ void close_window(window_t *wnd) {
|
||||
|
||||
wnd->back_buffer = NULL;
|
||||
}
|
||||
|
||||
wnd->z_buffer = NULL;
|
||||
}
|
||||
|
||||
SDL_Quit();
|
||||
@ -98,6 +107,7 @@ void clear_window(window_t *wnd, colour_t colour) {
|
||||
|
||||
for (u32 i = 0; i < count; ++i) {
|
||||
pixels[i] = colour.colour;
|
||||
wnd->z_buffer[i] = INFINITY;
|
||||
}
|
||||
|
||||
SDL_UnlockSurface(wnd->back_buffer);
|
||||
@ -117,13 +127,34 @@ void set_pixel(window_t *wnd, i32 x, i32 y, colour_t colour) {
|
||||
SDL_UnlockSurface(wnd->back_buffer);
|
||||
}
|
||||
|
||||
void set_z_pixel(window_t *wnd, i32 x, i32 y, f32 value) {
|
||||
vec2i_t coords = denormalised_coords(wnd, x, y);
|
||||
|
||||
if (coords.x < 0 || coords.y < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
set_z_buffer_pixel(wnd, (u32)(coords.x), (u32)(coords.y), value);
|
||||
}
|
||||
|
||||
f32 get_z_pixel(const window_t *wnd, i32 x, i32 y) {
|
||||
vec2i_t coords = denormalised_coords(wnd, x, y);
|
||||
|
||||
if (coords.x < 0 || coords.y < 0) {
|
||||
return INFINITY;
|
||||
}
|
||||
|
||||
u32 index = index_from_coordinates(wnd, (u32)(coords.x), (u32)(coords.y));
|
||||
return wnd->z_buffer[index];
|
||||
}
|
||||
|
||||
void swap_buffers(window_t *wnd) {
|
||||
SDL_BlitSurface(wnd->back_buffer, NULL, wnd->front_buffer, NULL);
|
||||
|
||||
SDL_UpdateWindowSurface(wnd->window);
|
||||
}
|
||||
|
||||
u32 index_from_coordinates(window_t *wnd, u32 x, u32 y) {
|
||||
u32 index_from_coordinates(const window_t *wnd, u32 x, u32 y) {
|
||||
return y * wnd->width + x;
|
||||
}
|
||||
|
||||
@ -159,6 +190,11 @@ void set_screen_pixel(window_t *wnd, u32 x, u32 y, colour_t colour) {
|
||||
pixels[index] = colour.colour;
|
||||
}
|
||||
|
||||
void set_z_buffer_pixel(window_t *wnd, u32 x, u32 y, f32 value) {
|
||||
u32 index = index_from_coordinates(wnd, x, y);
|
||||
wnd->z_buffer[index] = value;
|
||||
}
|
||||
|
||||
vec3f_t window_to_viewport(const window_t *wnd, i32 x, i32 y,
|
||||
vec3f_t viewport) {
|
||||
return (vec3f_t){
|
||||
|
Loading…
Reference in New Issue
Block a user