Compare commits
21 Commits
26fc513d4a
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| b35a7d9cbe | |||
| ade35f3940 | |||
| e96400f74e | |||
| 70dfb5d5ee | |||
| 51099ae97e | |||
| 5a3b143762 | |||
| 83fa308a4b | |||
| 94287ff081 | |||
| 48735adf7b | |||
| f6848b5f4f | |||
| 77edf714bb | |||
| 5d61e8a616 | |||
| e236cd8bbe | |||
| b0bf4f593b | |||
| f6f2483b61 | |||
| 00e7293b28 | |||
| 3c293198bb | |||
| ae072ec70e | |||
| c3e1aac779 | |||
| 4430ea872c | |||
| df1620319c |
3
compile
3
compile
@@ -9,15 +9,14 @@ LIBS="$(pkg-config --libs sdl2) -lm"
|
|||||||
|
|
||||||
RAYTRACER_SRC="src/window/*.c \
|
RAYTRACER_SRC="src/window/*.c \
|
||||||
src/vector/*.c \
|
src/vector/*.c \
|
||||||
src/scene/*.c \
|
|
||||||
src/raytracer/*.c \
|
src/raytracer/*.c \
|
||||||
src/math/*.c \
|
src/math/*.c \
|
||||||
src/camera/*.c \
|
src/camera/*.c \
|
||||||
|
$WAPP_SRC \
|
||||||
"
|
"
|
||||||
|
|
||||||
RASTERISER_SRC="src/window/*.c \
|
RASTERISER_SRC="src/window/*.c \
|
||||||
src/vector/*.c \
|
src/vector/*.c \
|
||||||
src/scene/*.c \
|
|
||||||
src/list/*.c \
|
src/list/*.c \
|
||||||
src/rasteriser/*.c \
|
src/rasteriser/*.c \
|
||||||
src/math/*.c \
|
src/math/*.c \
|
||||||
|
|||||||
@@ -44,8 +44,13 @@
|
|||||||
LP->items[(LP->count)++] = ITEM; \
|
LP->items[(LP->count)++] = ITEM; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
#define list_remove(LP, IDX) \
|
||||||
|
do { \
|
||||||
|
LP->items[IDX] = LP->items[(LP->count)--]; \
|
||||||
|
} while (0)
|
||||||
#define list_pop(LP) (LP->count -= 1)
|
#define list_pop(LP) (LP->count -= 1)
|
||||||
|
|
||||||
|
#define list_set(LP, IDX, ITEM) LP->items[IDX] = ITEM
|
||||||
#define list_get(LP, IDX) LP->items[IDX]
|
#define list_get(LP, IDX) LP->items[IDX]
|
||||||
|
|
||||||
#define list_merge(T, ARENA, DST, LP1, LP2) \
|
#define list_merge(T, ARENA, DST, LP1, LP2) \
|
||||||
|
|||||||
@@ -8,19 +8,36 @@
|
|||||||
#include "vector/vec.h"
|
#include "vector/vec.h"
|
||||||
#include "window/window.h"
|
#include "window/window.h"
|
||||||
|
|
||||||
|
#define INVALID_VERTEX -1
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u64 idx0;
|
vec3f_t position;
|
||||||
u64 idx1;
|
f32 h;
|
||||||
u64 idx2;
|
} vertex_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
i64 idx0;
|
||||||
|
i64 idx1;
|
||||||
|
i64 idx2;
|
||||||
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);
|
||||||
MAKE_LIST_TYPE(vec4f_t);
|
MAKE_LIST_TYPE(vec4f_t);
|
||||||
|
MAKE_LIST_TYPE(vertex_t);
|
||||||
MAKE_LIST_TYPE(scene_triangle_t);
|
MAKE_LIST_TYPE(scene_triangle_t);
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
RASTERISER_RENDER_WIREFRAME,
|
||||||
|
RASTERISER_RENDER_FILLED,
|
||||||
|
RASTERISER_RENDER_SHADED,
|
||||||
|
|
||||||
|
COUNT_RASTERISER_RENDER,
|
||||||
|
} render_type_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
vec2i_t p0;
|
vec2i_t p0;
|
||||||
vec2i_t p1;
|
vec2i_t p1;
|
||||||
@@ -33,13 +50,17 @@ typedef struct {
|
|||||||
f32 h0;
|
f32 h0;
|
||||||
f32 h1;
|
f32 h1;
|
||||||
f32 h2;
|
f32 h2;
|
||||||
|
f32 z0;
|
||||||
|
f32 z1;
|
||||||
|
f32 z2;
|
||||||
colour_t colour;
|
colour_t colour;
|
||||||
} triangle_t;
|
} triangle_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
list_vec3f_t *vertices;
|
list_vertex_t *vertices;
|
||||||
list_scene_triangle_t *triangles;
|
list_scene_triangle_t *triangles;
|
||||||
} model_t;
|
} model_t;
|
||||||
|
#define NULL_MODEL ((model_t){0})
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
f32 scale;
|
f32 scale;
|
||||||
@@ -47,6 +68,11 @@ typedef struct {
|
|||||||
vec3f_t position;
|
vec3f_t position;
|
||||||
} transform_t;
|
} transform_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
vec3f_t centre;
|
||||||
|
f32 radius;
|
||||||
|
} bounding_sphere_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
model_t *model;
|
model_t *model;
|
||||||
transform_t transform;
|
transform_t transform;
|
||||||
@@ -57,24 +83,21 @@ typedef struct {
|
|||||||
f32 distance;
|
f32 distance;
|
||||||
} clipping_plane_t;
|
} clipping_plane_t;
|
||||||
|
|
||||||
|
#define CLIPPING_PLANE_COUNT 5
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u64 instance_count;
|
u64 instance_count;
|
||||||
instance_t *instances;
|
instance_t *instances;
|
||||||
camera_t *camera;
|
camera_t *camera;
|
||||||
const mat3x4f_t *proj_matrix;
|
const mat3x4f_t *proj_matrix;
|
||||||
clipping_plane_t near;
|
clipping_plane_t planes[CLIPPING_PLANE_COUNT];
|
||||||
clipping_plane_t left;
|
|
||||||
clipping_plane_t right;
|
|
||||||
clipping_plane_t bottom;
|
|
||||||
clipping_plane_t top;
|
|
||||||
} rasteriser_scene_t;
|
} rasteriser_scene_t;
|
||||||
|
|
||||||
void render_scene(window_t *wnd, Arena *arena, const rasteriser_scene_t *scene);
|
void render_scene(window_t *wnd, Arena *arena, const rasteriser_scene_t *scene,
|
||||||
void render_instance(window_t *wnd, Arena *arena, mat4x4f_t camera_matrix,
|
render_type_t type);
|
||||||
mat3x4f_t projection_matrix, const instance_t *instance);
|
|
||||||
void draw_wireframe_triangle(window_t *wnd, Arena *arena, triangle_t triangle);
|
void draw_wireframe_triangle(window_t *wnd, Arena *arena, triangle_t triangle);
|
||||||
void draw_filled_triangle(window_t *wnd, Arena *arena, triangle_t triangle);
|
void draw_filled_triangle(window_t *wnd, Arena *arena, triangle_t triangle);
|
||||||
void draw_shaded_triangle(window_t *wnd, Arena *arena, triangle_t triangle);
|
void draw_shaded_triangle(window_t *wnd, Arena *arena, triangle_t triangle);
|
||||||
void draw_line(window_t *wnd, Arena *arena, line_t line, colour_t colour);
|
void draw_line(window_t *wnd, Arena *arena, line_t line, colour_t colour);
|
||||||
|
bool is_null_model(const model_t *model);
|
||||||
|
|
||||||
#endif // !RASTERISER_H
|
#endif // !RASTERISER_H
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
#define RAYTRACER_H
|
#define RAYTRACER_H
|
||||||
|
|
||||||
#include "aliases.h"
|
#include "aliases.h"
|
||||||
#include "scene/scene.h"
|
|
||||||
#include "vector/vec.h"
|
#include "vector/vec.h"
|
||||||
#include "window/window.h"
|
#include "window/window.h"
|
||||||
|
|
||||||
@@ -11,13 +10,46 @@ typedef struct {
|
|||||||
f32 t2;
|
f32 t2;
|
||||||
} solutions_t;
|
} solutions_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
f32 radius;
|
||||||
|
vec3f_t centre;
|
||||||
|
colour_t colour;
|
||||||
|
f32 specular;
|
||||||
|
f32 reflective;
|
||||||
|
} sphere_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
f32 closest_t;
|
f32 closest_t;
|
||||||
const sphere_t *closest_sphere;
|
const sphere_t *closest_sphere;
|
||||||
} intersection_t;
|
} intersection_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
LIGHT_TYPE_POINT,
|
||||||
|
LIGHT_TYPE_DIRECTIONAL,
|
||||||
|
LIGHT_TYPE_AMBIENT,
|
||||||
|
|
||||||
|
COUNT_LIGHT_TYPE,
|
||||||
|
} light_type_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
light_type_t type;
|
||||||
|
f32 intensity;
|
||||||
|
union {
|
||||||
|
vec3f_t position;
|
||||||
|
vec3f_t direction;
|
||||||
|
};
|
||||||
|
} light_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const sphere_t *spheres;
|
||||||
|
const light_t *lights;
|
||||||
|
u32 spheres_count;
|
||||||
|
u32 lights_count;
|
||||||
|
} raytracer_scene_t;
|
||||||
|
|
||||||
|
const raytracer_scene_t *build_test_scene(void);
|
||||||
colour_t trace_ray(vec3f_t origin, vec3f_t direction, f32 t_min, f32 t_max,
|
colour_t trace_ray(vec3f_t origin, vec3f_t direction, f32 t_min, f32 t_max,
|
||||||
const scene_t *scene, colour_t default_colour,
|
const raytracer_scene_t *scene, colour_t default_colour,
|
||||||
u32 recursion_depth);
|
u32 recursion_depth);
|
||||||
|
|
||||||
#endif // !RAYTRACER_H
|
#endif // !RAYTRACER_H
|
||||||
|
|||||||
@@ -1,42 +0,0 @@
|
|||||||
#ifndef SCENE_H
|
|
||||||
#define SCENE_H
|
|
||||||
|
|
||||||
#include "aliases.h"
|
|
||||||
#include "vector/vec.h"
|
|
||||||
#include "window/window.h"
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
f32 radius;
|
|
||||||
vec3f_t centre;
|
|
||||||
colour_t colour;
|
|
||||||
f32 specular;
|
|
||||||
f32 reflective;
|
|
||||||
} sphere_t;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
LIGHT_TYPE_POINT,
|
|
||||||
LIGHT_TYPE_DIRECTIONAL,
|
|
||||||
LIGHT_TYPE_AMBIENT,
|
|
||||||
|
|
||||||
COUNT_LIGHT_TYPE,
|
|
||||||
} light_type_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
light_type_t type;
|
|
||||||
f32 intensity;
|
|
||||||
union {
|
|
||||||
vec3f_t position;
|
|
||||||
vec3f_t direction;
|
|
||||||
};
|
|
||||||
} light_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
const sphere_t *spheres;
|
|
||||||
const light_t *lights;
|
|
||||||
u32 spheres_count;
|
|
||||||
u32 lights_count;
|
|
||||||
} scene_t;
|
|
||||||
|
|
||||||
const scene_t *build_test_scene(void);
|
|
||||||
|
|
||||||
#endif // !SCENE_H
|
|
||||||
@@ -64,6 +64,7 @@ typedef struct {
|
|||||||
#define vec_mul_num(T, v1, num) vec_mul_num_##T(v1, num)
|
#define vec_mul_num(T, v1, num) vec_mul_num_##T(v1, num)
|
||||||
#define vec_div_num(T, v1, num) vec_div_num_##T(v1, num)
|
#define vec_div_num(T, v1, num) vec_div_num_##T(v1, num)
|
||||||
#define vec_dot(T, v1, v2) vec_dot_##T(v1, v2)
|
#define vec_dot(T, v1, v2) vec_dot_##T(v1, v2)
|
||||||
|
#define vec_cross(T, v1, v2) vec_cross_##T(v1, v2)
|
||||||
#define vec_magnitude(T, v) vec_magnitude_##T(v)
|
#define vec_magnitude(T, v) vec_magnitude_##T(v)
|
||||||
#define vec_unit(T, v) vec_unit_##T(v)
|
#define vec_unit(T, v) vec_unit_##T(v)
|
||||||
|
|
||||||
@@ -91,6 +92,7 @@ vec3i_t vec_mul_vec3i_t(vec3i_t v1, vec3i_t v2);
|
|||||||
vec3i_t vec_mul_num_vec3i_t(vec3i_t v1, i32 num);
|
vec3i_t vec_mul_num_vec3i_t(vec3i_t v1, i32 num);
|
||||||
vec3i_t vec_div_num_vec3i_t(vec3i_t v1, i32 num);
|
vec3i_t vec_div_num_vec3i_t(vec3i_t v1, i32 num);
|
||||||
i32 vec_dot_vec3i_t(vec3i_t v1, vec3i_t v2);
|
i32 vec_dot_vec3i_t(vec3i_t v1, vec3i_t v2);
|
||||||
|
vec3i_t vec_cross_vec3i_t(vec3i_t v1, vec3i_t v2);
|
||||||
i32 vec_magnitude_vec3i_t(vec3i_t v);
|
i32 vec_magnitude_vec3i_t(vec3i_t v);
|
||||||
vec3i_t vec_unit_vec3i_t(vec3i_t v);
|
vec3i_t vec_unit_vec3i_t(vec3i_t v);
|
||||||
|
|
||||||
@@ -100,6 +102,7 @@ vec3f_t vec_mul_vec3f_t(vec3f_t v1, vec3f_t v2);
|
|||||||
vec3f_t vec_mul_num_vec3f_t(vec3f_t v1, f32 num);
|
vec3f_t vec_mul_num_vec3f_t(vec3f_t v1, f32 num);
|
||||||
vec3f_t vec_div_num_vec3f_t(vec3f_t v1, f32 num);
|
vec3f_t vec_div_num_vec3f_t(vec3f_t v1, f32 num);
|
||||||
f32 vec_dot_vec3f_t(vec3f_t v1, vec3f_t v2);
|
f32 vec_dot_vec3f_t(vec3f_t v1, vec3f_t v2);
|
||||||
|
vec3f_t vec_cross_vec3f_t(vec3f_t v1, vec3f_t v2);
|
||||||
f32 vec_magnitude_vec3f_t(vec3f_t v);
|
f32 vec_magnitude_vec3f_t(vec3f_t v);
|
||||||
vec3f_t vec_unit_vec3f_t(vec3f_t v);
|
vec3f_t vec_unit_vec3f_t(vec3f_t v);
|
||||||
vec3f_t vec_rotate_vec3f_t(vec3f_t original, vec3f_t rotation);
|
vec3f_t vec_rotate_vec3f_t(vec3f_t original, vec3f_t rotation);
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#define WINDOW_H
|
#define WINDOW_H
|
||||||
|
|
||||||
#include "aliases.h"
|
#include "aliases.h"
|
||||||
|
#include "mem_arena.h"
|
||||||
#include "vector/vec.h"
|
#include "vector/vec.h"
|
||||||
#include <SDL2/SDL_video.h>
|
#include <SDL2/SDL_video.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
@@ -29,13 +30,17 @@ typedef struct {
|
|||||||
SDL_Window *window;
|
SDL_Window *window;
|
||||||
SDL_Surface *front_buffer;
|
SDL_Surface *front_buffer;
|
||||||
SDL_Surface *back_buffer;
|
SDL_Surface *back_buffer;
|
||||||
|
f32 *z_buffer;
|
||||||
} window_t;
|
} 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 close_window(window_t *wnd);
|
||||||
|
|
||||||
void clear_window(window_t *wnd, colour_t colour);
|
void clear_window(window_t *wnd, colour_t colour);
|
||||||
void set_pixel(window_t *wnd, i32 x, i32 y, 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);
|
void swap_buffers(window_t *wnd);
|
||||||
|
|
||||||
vec3f_t window_to_viewport(const window_t *wnd, i32 x, i32 y, vec3f_t viewport);
|
vec3f_t window_to_viewport(const window_t *wnd, i32 x, i32 y, vec3f_t viewport);
|
||||||
|
|||||||
@@ -9,6 +9,8 @@
|
|||||||
#include <SDL2/SDL_events.h>
|
#include <SDL2/SDL_events.h>
|
||||||
#include <SDL2/SDL_keycode.h>
|
#include <SDL2/SDL_keycode.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
@@ -20,31 +22,36 @@ int main(void) {
|
|||||||
};
|
};
|
||||||
vec3f_t viewport = {.x = 1.0f, .y = 1.0f, .z = 1.0f};
|
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;
|
Arena *arena = NULL;
|
||||||
u64 main_arena_capacity = 20ull * 1024ull * 1024ull * 1024ull;
|
u64 main_arena_capacity = 64ull * 1024ull * 1024ull * 1024ull;
|
||||||
if (!wapp_mem_arena_init(&arena, main_arena_capacity, WAPP_MEM_ALLOC_RESERVE,
|
if (!wapp_mem_arena_init(&arena, main_arena_capacity, WAPP_MEM_ALLOC_RESERVE,
|
||||||
false)) {
|
false)) {
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
list_vec3f_t *vertices = list_create(vec3f_t, arena);
|
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) {
|
if (!vertices) {
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
// Vertices
|
// Vertices
|
||||||
vec3f_t verts[] = {
|
vertex_t verts[] = {
|
||||||
(vec3f_t){1, 1, 1}, (vec3f_t){-1, 1, 1}, (vec3f_t){-1, -1, 1},
|
(vertex_t){.position = {1, 1, 1}, .h = 1.0f},
|
||||||
(vec3f_t){1, -1, 1}, (vec3f_t){1, 1, -1}, (vec3f_t){-1, 1, -1},
|
(vertex_t){.position = {-1, 1, 1}, .h = 1.0f},
|
||||||
(vec3f_t){-1, -1, -1}, (vec3f_t){1, -1, -1},
|
(vertex_t){.position = {-1, -1, 1}, .h = 1.0f},
|
||||||
|
(vertex_t){.position = {1, -1, 1}, .h = 1.0f},
|
||||||
|
(vertex_t){.position = {1, 1, -1}, .h = 1.0f},
|
||||||
|
(vertex_t){.position = {-1, 1, -1}, .h = 1.0f},
|
||||||
|
(vertex_t){.position = {-1, -1, -1}, .h = 1.0f},
|
||||||
|
(vertex_t){.position = {1, -1, -1}, .h = 1.0f},
|
||||||
};
|
};
|
||||||
for (u64 i = 0; i < ARR_LEN(verts); ++i) {
|
for (u64 i = 0; i < ARR_LEN(verts); ++i) {
|
||||||
list_append(vec3f_t, arena, vertices, verts[i]);
|
list_append(vertex_t, arena, vertices, verts[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
list_scene_triangle_t *triangles = list_create(scene_triangle_t, arena);
|
list_scene_triangle_t *triangles = list_create(scene_triangle_t, arena);
|
||||||
@@ -107,31 +114,36 @@ int main(void) {
|
|||||||
.instances = instances,
|
.instances = instances,
|
||||||
.camera = &camera,
|
.camera = &camera,
|
||||||
.proj_matrix = &proj_matrix,
|
.proj_matrix = &proj_matrix,
|
||||||
.near =
|
.planes =
|
||||||
|
{
|
||||||
|
[0] =
|
||||||
(clipping_plane_t){
|
(clipping_plane_t){
|
||||||
.normal = (vec3f_t){0.0f, 0.0f, 1.0f},
|
.normal = (vec3f_t){0.0f, 0.0f, 1.0f},
|
||||||
.distance = viewport.z,
|
.distance = viewport.z,
|
||||||
},
|
},
|
||||||
.left =
|
[1] =
|
||||||
(clipping_plane_t){
|
(clipping_plane_t){
|
||||||
.normal = (vec3f_t){one_div_sqrt_2, 0.0f, one_div_sqrt_2},
|
.normal = (vec3f_t){one_div_sqrt_2, 0.0f, one_div_sqrt_2},
|
||||||
.distance = 0.0f,
|
.distance = 0.0f,
|
||||||
},
|
},
|
||||||
.right =
|
[2] =
|
||||||
(clipping_plane_t){
|
(clipping_plane_t){
|
||||||
.normal = (vec3f_t){neg_one_div_sqrt_2, 0.0f, one_div_sqrt_2},
|
.normal =
|
||||||
|
(vec3f_t){neg_one_div_sqrt_2, 0.0f, one_div_sqrt_2},
|
||||||
.distance = 0.0f,
|
.distance = 0.0f,
|
||||||
},
|
},
|
||||||
.bottom =
|
[3] =
|
||||||
(clipping_plane_t){
|
(clipping_plane_t){
|
||||||
.normal = (vec3f_t){0.0f, one_div_sqrt_2, one_div_sqrt_2},
|
.normal = (vec3f_t){0.0f, one_div_sqrt_2, one_div_sqrt_2},
|
||||||
.distance = 0.0f,
|
.distance = 0.0f,
|
||||||
},
|
},
|
||||||
.top =
|
[4] =
|
||||||
(clipping_plane_t){
|
(clipping_plane_t){
|
||||||
.normal = (vec3f_t){0.0f, neg_one_div_sqrt_2, one_div_sqrt_2},
|
.normal =
|
||||||
|
(vec3f_t){0.0f, neg_one_div_sqrt_2, one_div_sqrt_2},
|
||||||
.distance = 0.0f,
|
.distance = 0.0f,
|
||||||
},
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
bool running = true;
|
bool running = true;
|
||||||
@@ -143,12 +155,14 @@ int main(void) {
|
|||||||
// i32 h_max = (i32)window.half_height;
|
// i32 h_max = (i32)window.half_height;
|
||||||
|
|
||||||
Arena *frame_arena = NULL;
|
Arena *frame_arena = NULL;
|
||||||
u64 frame_arena_capacity = 10ull * 1024ull * 1024ull * 1024ull;
|
u64 frame_arena_capacity = 32ull * 1024ull * 1024ull * 1024ull;
|
||||||
if (!wapp_mem_arena_init(&frame_arena, frame_arena_capacity,
|
if (!wapp_mem_arena_init(&frame_arena, frame_arena_capacity,
|
||||||
WAPP_MEM_ALLOC_RESERVE, false)) {
|
WAPP_MEM_ALLOC_RESERVE, false)) {
|
||||||
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) {
|
||||||
@@ -157,13 +171,15 @@ int main(void) {
|
|||||||
break;
|
break;
|
||||||
case SDL_KEYDOWN:
|
case SDL_KEYDOWN:
|
||||||
if (event.key.keysym.sym == SDLK_w) {
|
if (event.key.keysym.sym == SDLK_w) {
|
||||||
camera.rotation.x += 1.0f;
|
|
||||||
} else if (event.key.keysym.sym == SDLK_s) {
|
|
||||||
camera.rotation.x -= 1.0f;
|
camera.rotation.x -= 1.0f;
|
||||||
|
} else if (event.key.keysym.sym == SDLK_s) {
|
||||||
|
camera.rotation.x += 1.0f;
|
||||||
} else if (event.key.keysym.sym == SDLK_d) {
|
} else if (event.key.keysym.sym == SDLK_d) {
|
||||||
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;
|
||||||
}
|
}
|
||||||
@@ -171,7 +187,7 @@ int main(void) {
|
|||||||
|
|
||||||
clear_window(&window, bg);
|
clear_window(&window, bg);
|
||||||
|
|
||||||
render_scene(&window, frame_arena, &scene);
|
render_scene(&window, frame_arena, &scene, type);
|
||||||
|
|
||||||
swap_buffers(&window);
|
swap_buffers(&window);
|
||||||
|
|
||||||
|
|||||||
@@ -7,15 +7,54 @@
|
|||||||
#include "window/window.h"
|
#include "window/window.h"
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
|
||||||
internal list_float *interpolate(Arena *arena, i32 i0, f32 d0, i32 i1, f32 d1);
|
#define CULL_ENABLED 0
|
||||||
internal inline void order_triangle_points(triangle_t *triangle);
|
|
||||||
|
|
||||||
void render_scene(window_t *wnd, Arena *arena,
|
internal void render_instance(window_t *wnd, const rasteriser_scene_t *scene,
|
||||||
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);
|
||||||
|
internal void clip_triangles_against_plane(Arena *arena, model_t *model,
|
||||||
|
const clipping_plane_t *plane);
|
||||||
|
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);
|
||||||
|
internal inline vertex_t segment_intersection(const vertex_t *a,
|
||||||
|
const vertex_t *b,
|
||||||
|
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,
|
||||||
|
const clipping_plane_t *plane);
|
||||||
|
|
||||||
|
void render_scene(window_t *wnd, Arena *arena, const rasteriser_scene_t *scene,
|
||||||
|
render_type_t type) {
|
||||||
mat4x4f_t cam_inverse_rotation =
|
mat4x4f_t cam_inverse_rotation =
|
||||||
inverse_camera_rotation_matrix(scene->camera);
|
inverse_camera_rotation_matrix(scene->camera);
|
||||||
mat4x4f_t cam_inverse_translation =
|
mat4x4f_t cam_inverse_translation =
|
||||||
@@ -24,19 +63,25 @@ void render_scene(window_t *wnd, Arena *arena,
|
|||||||
mul_mat4x4f(cam_inverse_rotation, cam_inverse_translation);
|
mul_mat4x4f(cam_inverse_rotation, cam_inverse_translation);
|
||||||
|
|
||||||
for (u64 i = 0; i < scene->instance_count; ++i) {
|
for (u64 i = 0; i < scene->instance_count; ++i) {
|
||||||
render_instance(wnd, arena, cam_matrix, *(scene->proj_matrix),
|
render_instance(wnd, scene, arena, cam_matrix, *(scene->proj_matrix),
|
||||||
&(scene->instances[i]));
|
&(scene->instances[i]), type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void render_instance(window_t *wnd, Arena *arena, mat4x4f_t camera_matrix,
|
internal void render_instance(window_t *wnd, const rasteriser_scene_t *scene,
|
||||||
mat3x4f_t projection_matrix, const instance_t *instance) {
|
Arena *arena, mat4x4f_t camera_matrix,
|
||||||
list_vec4f_t *transformed = list_create_with_capacity(
|
mat3x4f_t projection_matrix,
|
||||||
vec4f_t, arena, instance->model->vertices->count * sizeof(vec4f_t));
|
const instance_t *instance, render_type_t type) {
|
||||||
if (!transformed) {
|
list_vertex_t *transformed = list_create_with_capacity(
|
||||||
|
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);
|
||||||
|
if (!transformed || !triangles) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
copy_triangles(arena, triangles, instance->model->triangles);
|
||||||
|
|
||||||
mat4x4f_t t_mat = get_translation_matrix(instance->transform.position);
|
mat4x4f_t t_mat = get_translation_matrix(instance->transform.position);
|
||||||
mat4x4f_t r_mat = get_rotation_matrix(instance->transform.rotation);
|
mat4x4f_t r_mat = get_rotation_matrix(instance->transform.rotation);
|
||||||
mat4x4f_t s_mat = get_scaling_matrix((vec3f_t){instance->transform.scale,
|
mat4x4f_t s_mat = get_scaling_matrix((vec3f_t){instance->transform.scale,
|
||||||
@@ -47,41 +92,87 @@ void render_instance(window_t *wnd, Arena *arena, mat4x4f_t camera_matrix,
|
|||||||
|
|
||||||
mat4x4f_t xf_cam_mat = mul_mat4x4f(camera_matrix, trs_mat);
|
mat4x4f_t xf_cam_mat = mul_mat4x4f(camera_matrix, trs_mat);
|
||||||
|
|
||||||
vec3f_t vertex = {0};
|
vertex_t vertex = {0};
|
||||||
vec4f_t xf_vertex = {0};
|
vec4f_t xf_vertex = {0};
|
||||||
for (u64 i = 0; i < instance->model->vertices->count; ++i) {
|
for (u64 i = 0; i < instance->model->vertices->count; ++i) {
|
||||||
vertex = list_get(instance->model->vertices, i);
|
vertex = list_get(instance->model->vertices, i);
|
||||||
|
|
||||||
xf_vertex = mul_mat4x4f_by_vec4f(
|
xf_vertex = mul_mat4x4f_by_vec4f(
|
||||||
xf_cam_mat, (vec4f_t){vertex.x, vertex.y, vertex.z, 1.0f});
|
xf_cam_mat, (vec4f_t){vertex.position.x, vertex.position.y,
|
||||||
list_append(vec4f_t, arena, transformed, xf_vertex);
|
vertex.position.z, 1.0f});
|
||||||
|
xf_vertex = vec_div_num(vec4f_t, xf_vertex, xf_vertex.w);
|
||||||
|
|
||||||
|
vertex.position = (vec3f_t){xf_vertex.x, xf_vertex.y, xf_vertex.z};
|
||||||
|
|
||||||
|
list_append(vertex_t, arena, transformed, vertex);
|
||||||
|
}
|
||||||
|
|
||||||
|
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(
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
vec2i_t point = {0};
|
vec2i_t point = {0};
|
||||||
|
vertex_t *vp = NULL;
|
||||||
for (u64 i = 0; i < transformed->count; ++i) {
|
for (u64 i = 0; i < transformed->count; ++i) {
|
||||||
xf_vertex = list_get(transformed, i);
|
vp = &(list_get(transformed, i));
|
||||||
vertex = mul_mat3x4f_by_vec4f(projection_matrix, xf_vertex);
|
vp->position = mul_mat3x4f_by_vec4f(
|
||||||
point = (vec2i_t){(i32)(vertex.x / vertex.z), (i32)(vertex.y / vertex.z)};
|
projection_matrix,
|
||||||
|
(vec4f_t){vp->position.x, vp->position.y, vp->position.z, 1.0f});
|
||||||
|
point = (vec2i_t){(i32)(vp->position.x / vp->position.z),
|
||||||
|
(i32)(vp->position.y / vp->position.z)};
|
||||||
list_append(vec2i_t, arena, projected, point);
|
list_append(vec2i_t, arena, projected, point);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (u64 i = 0; i < instance->model->triangles->count; ++i) {
|
vertex_t v0, v1, v2;
|
||||||
scene_triangle_t triangle = list_get(instance->model->triangles, i);
|
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 = {
|
triangle_t tri = {
|
||||||
.p0 = list_get(projected, triangle.idx0),
|
.p0 = list_get(projected, triangle.idx0),
|
||||||
.p1 = list_get(projected, triangle.idx1),
|
.p1 = list_get(projected, triangle.idx1),
|
||||||
.p2 = list_get(projected, triangle.idx2),
|
.p2 = list_get(projected, triangle.idx2),
|
||||||
.h0 = 1.0f,
|
.h0 = v0.h,
|
||||||
.h1 = 1.0f,
|
.h1 = v1.h,
|
||||||
.h2 = 1.0f,
|
.h2 = v2.h,
|
||||||
|
.z0 = 1.0f / v0.position.z,
|
||||||
|
.z1 = 1.0f / v1.position.z,
|
||||||
|
.z2 = 1.0f / v2.position.z,
|
||||||
.colour = triangle.colour,
|
.colour = triangle.colour,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if ((tri.p0.x == tri.p1.x && tri.p0.x == tri.p2.x) &&
|
||||||
|
(tri.p0.y == tri.p1.y && tri.p0.y == tri.p2.y)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case RASTERISER_RENDER_WIREFRAME:
|
||||||
draw_wireframe_triangle(wnd, arena, tri);
|
draw_wireframe_triangle(wnd, arena, tri);
|
||||||
|
break;
|
||||||
|
case RASTERISER_RENDER_FILLED:
|
||||||
|
draw_filled_triangle(wnd, arena, tri);
|
||||||
|
break;
|
||||||
|
case RASTERISER_RENDER_SHADED:
|
||||||
|
draw_shaded_triangle(wnd, arena, tri);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,25 +202,60 @@ 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_pop(x01); // Last element of x01 is a duplicate of first element in x12
|
||||||
list_merge(f32, arena, x012, x01, 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_left;
|
||||||
list_float *x_right;
|
list_float *x_right;
|
||||||
|
list_float *z_left;
|
||||||
|
list_float *z_right;
|
||||||
u64 middle = (u64)(floorf((f32)(x02->count) / 2.0f));
|
u64 middle = (u64)(floorf((f32)(x02->count) / 2.0f));
|
||||||
if (list_get(x02, middle) < list_get(x012, middle)) {
|
if (list_get(x02, middle) < list_get(x012, middle)) {
|
||||||
x_left = x02;
|
x_left = x02;
|
||||||
|
z_left = z02;
|
||||||
x_right = x012;
|
x_right = x012;
|
||||||
|
z_right = z012;
|
||||||
} else {
|
} else {
|
||||||
x_left = x012;
|
x_left = x012;
|
||||||
|
z_left = z012;
|
||||||
x_right = x02;
|
x_right = x02;
|
||||||
|
z_right = z02;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
list_float *z_segment = NULL;
|
||||||
|
i32 index = -1;
|
||||||
|
i64 xl = -1;
|
||||||
|
i64 xr = -1;
|
||||||
|
f32 current_z = 0.0f;
|
||||||
|
f32 new_z = 0.0f;
|
||||||
|
|
||||||
for (i64 y = y0; y <= y2; ++y) {
|
for (i64 y = y0; y <= y2; ++y) {
|
||||||
i32 index = y - y0;
|
index = y - y0;
|
||||||
for (i64 x = (i64)list_get(x_left, index); x < list_get(x_right, index);
|
xl = (i64)list_get(x_left, index);
|
||||||
++x) {
|
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);
|
set_pixel(wnd, x, y, triangle.colour);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void draw_shaded_triangle(window_t *wnd, Arena *arena, triangle_t triangle) {
|
void draw_shaded_triangle(window_t *wnd, Arena *arena, triangle_t triangle) {
|
||||||
order_triangle_points(&triangle);
|
order_triangle_points(&triangle);
|
||||||
@@ -160,27 +286,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_pop(h01); // Last element of h01 is a duplicate of first element in h12
|
||||||
list_merge(f32, arena, h012, h01, 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_left;
|
||||||
list_float *x_right;
|
list_float *x_right;
|
||||||
list_float *h_left;
|
list_float *h_left;
|
||||||
list_float *h_right;
|
list_float *h_right;
|
||||||
|
list_float *z_left;
|
||||||
|
list_float *z_right;
|
||||||
u64 middle = (u64)(floorf((f32)(x02->count) / 2.0f));
|
u64 middle = (u64)(floorf((f32)(x02->count) / 2.0f));
|
||||||
if (list_get(x02, middle) < list_get(x012, middle)) {
|
if (list_get(x02, middle) < list_get(x012, middle)) {
|
||||||
x_left = x02;
|
x_left = x02;
|
||||||
h_left = h02;
|
h_left = h02;
|
||||||
|
z_left = z02;
|
||||||
x_right = x012;
|
x_right = x012;
|
||||||
h_right = h012;
|
h_right = h012;
|
||||||
|
z_right = z012;
|
||||||
} else {
|
} else {
|
||||||
x_left = x012;
|
x_left = x012;
|
||||||
h_left = h012;
|
h_left = h012;
|
||||||
|
z_left = z012;
|
||||||
x_right = x02;
|
x_right = x02;
|
||||||
h_right = h02;
|
h_right = h02;
|
||||||
|
z_right = z02;
|
||||||
}
|
}
|
||||||
|
|
||||||
list_float *h_segment = NULL;
|
list_float *h_segment = NULL;
|
||||||
|
list_float *z_segment = NULL;
|
||||||
i32 index = -1;
|
i32 index = -1;
|
||||||
i64 xl = -1;
|
i64 xl = -1;
|
||||||
i64 xr = -1;
|
i64 xr = -1;
|
||||||
|
f32 current_z = INFINITY;
|
||||||
|
f32 new_z = INFINITY;
|
||||||
colour_t shaded_colour = (colour_t){0};
|
colour_t shaded_colour = (colour_t){0};
|
||||||
|
|
||||||
for (i64 y = y0; y <= y2; ++y) {
|
for (i64 y = y0; y <= y2; ++y) {
|
||||||
@@ -190,11 +336,20 @@ void draw_shaded_triangle(window_t *wnd, Arena *arena, triangle_t triangle) {
|
|||||||
for (i64 x = xl; x < xr; ++x) {
|
for (i64 x = xl; x < xr; ++x) {
|
||||||
h_segment = interpolate(arena, xl, list_get(h_left, index), xr,
|
h_segment = interpolate(arena, xl, list_get(h_left, index), xr,
|
||||||
list_get(h_right, index));
|
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));
|
shaded_colour = colour_mul(triangle.colour, list_get(h_segment, x - xl));
|
||||||
|
|
||||||
|
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);
|
set_pixel(wnd, x, y, shaded_colour);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void draw_line(window_t *wnd, Arena *arena, line_t line, colour_t colour) {
|
void draw_line(window_t *wnd, Arena *arena, line_t line, colour_t colour) {
|
||||||
list_float *values = NULL;
|
list_float *values = NULL;
|
||||||
@@ -238,6 +393,185 @@ void draw_line(window_t *wnd, Arena *arena, line_t line, colour_t colour) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_null_model(const model_t *model) {
|
||||||
|
return model->vertices == NULL && model->triangles == NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void clip_instance(Arena *arena, model_t *model,
|
||||||
|
const rasteriser_scene_t *scene) {
|
||||||
|
bounding_sphere_t sphere = get_bounding_sphere(model->vertices);
|
||||||
|
const clipping_plane_t *plane = NULL;
|
||||||
|
|
||||||
|
for (u64 i = 0; i < CLIPPING_PLANE_COUNT; ++i) {
|
||||||
|
plane = &(scene->planes[i]);
|
||||||
|
clip_instance_against_plane(arena, model, &sphere, plane);
|
||||||
|
if (is_null_model(model)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#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;
|
||||||
|
vertex_t v1;
|
||||||
|
vertex_t v2;
|
||||||
|
vec3f_t sum;
|
||||||
|
vec3f_t midpoint;
|
||||||
|
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);
|
||||||
|
v1 = list_get(model->vertices, triangle->idx1);
|
||||||
|
v2 = list_get(model->vertices, triangle->idx2);
|
||||||
|
|
||||||
|
sum = vec_add(vec3f_t, v0.position,
|
||||||
|
vec_add(vec3f_t, v1.position, v2.position));
|
||||||
|
midpoint = vec_div_num(vec3f_t, sum, 3);
|
||||||
|
|
||||||
|
normal = calculate_triangle_normal(model, triangle);
|
||||||
|
viewing_vector = vec_sub(vec3f_t, midpoint, 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) {
|
||||||
|
f32 distance = signed_distance(&(sphere->centre), plane);
|
||||||
|
f32 neg_radius = -1.0f * sphere->radius;
|
||||||
|
|
||||||
|
if (distance > sphere->radius) {
|
||||||
|
return;
|
||||||
|
} else if (distance < neg_radius) {
|
||||||
|
*model = NULL_MODEL;
|
||||||
|
} else {
|
||||||
|
clip_triangles_against_plane(arena, model, plane);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void clip_triangles_against_plane(Arena *arena, model_t *model,
|
||||||
|
const clipping_plane_t *plane) {
|
||||||
|
u64 count = model->triangles->count;
|
||||||
|
for (u64 i = 0; i < count; ++i) {
|
||||||
|
clip_triangle_against_plane(arena, model, i, plane);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void clip_triangle_against_plane(Arena *arena, model_t *model,
|
||||||
|
i64 triangle_index,
|
||||||
|
const clipping_plane_t *plane) {
|
||||||
|
scene_triangle_t *triangle = &(list_get(model->triangles, triangle_index));
|
||||||
|
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));
|
||||||
|
|
||||||
|
f32 d0 = signed_distance(&(v0->position), plane);
|
||||||
|
f32 d1 = signed_distance(&(v1->position), plane);
|
||||||
|
f32 d2 = signed_distance(&(v2->position), plane);
|
||||||
|
|
||||||
|
if (d0 >= 0.0f && d1 >= 0.0f && d2 >= 0.0f) {
|
||||||
|
return;
|
||||||
|
} else if (d0 < 0.0f && d1 < 0.0f && d2 < 0.0f) {
|
||||||
|
triangle->idx0 = INVALID_VERTEX;
|
||||||
|
triangle->idx1 = INVALID_VERTEX;
|
||||||
|
triangle->idx2 = INVALID_VERTEX;
|
||||||
|
} else if ((d0 < 0.0f && d1 < 0.0f) || (d0 < 0.0f && d2 < 0.0f) ||
|
||||||
|
(d1 < 0.0f && d2 < 0.0f)) {
|
||||||
|
vertex_t *vp;
|
||||||
|
vertex_t *vn0;
|
||||||
|
vertex_t *vn1;
|
||||||
|
i64 *in0;
|
||||||
|
i64 *in1;
|
||||||
|
if (d0 > 0.0f) {
|
||||||
|
vp = v0;
|
||||||
|
vn0 = v1;
|
||||||
|
vn1 = v2;
|
||||||
|
in0 = &(triangle->idx1);
|
||||||
|
in1 = &(triangle->idx2);
|
||||||
|
} else if (d1 > 0.0f) {
|
||||||
|
vp = v1;
|
||||||
|
vn0 = v0;
|
||||||
|
vn1 = v2;
|
||||||
|
in0 = &(triangle->idx0);
|
||||||
|
in1 = &(triangle->idx2);
|
||||||
|
} else {
|
||||||
|
vp = v2;
|
||||||
|
vn0 = v0;
|
||||||
|
vn1 = v1;
|
||||||
|
in0 = &(triangle->idx0);
|
||||||
|
in1 = &(triangle->idx1);
|
||||||
|
}
|
||||||
|
|
||||||
|
vertex_t r0 = segment_intersection(vp, vn0, plane);
|
||||||
|
vertex_t r1 = segment_intersection(vp, vn1, plane);
|
||||||
|
list_append(vertex_t, arena, model->vertices, r0);
|
||||||
|
list_append(vertex_t, arena, model->vertices, r1);
|
||||||
|
|
||||||
|
*in0 = model->vertices->count - 2;
|
||||||
|
*in1 = model->vertices->count - 1;
|
||||||
|
} else {
|
||||||
|
vertex_t *vn;
|
||||||
|
vertex_t *vp0;
|
||||||
|
vertex_t *vp1;
|
||||||
|
i64 *in;
|
||||||
|
i64 *ip;
|
||||||
|
if (d0 < 0.0f) {
|
||||||
|
vn = v0;
|
||||||
|
vp0 = v1;
|
||||||
|
vp1 = v2;
|
||||||
|
in = &(triangle->idx0);
|
||||||
|
ip = &(triangle->idx2);
|
||||||
|
} else if (d1 < 0.0f) {
|
||||||
|
vn = v1;
|
||||||
|
vp0 = v0;
|
||||||
|
vp1 = v2;
|
||||||
|
in = &(triangle->idx1);
|
||||||
|
ip = &(triangle->idx2);
|
||||||
|
} else {
|
||||||
|
vn = v2;
|
||||||
|
vp0 = v0;
|
||||||
|
vp1 = v1;
|
||||||
|
in = &(triangle->idx2);
|
||||||
|
ip = &(triangle->idx1);
|
||||||
|
}
|
||||||
|
|
||||||
|
vertex_t r0 = segment_intersection(vp0, vn, plane);
|
||||||
|
vertex_t r1 = segment_intersection(vp1, vn, plane);
|
||||||
|
list_append(vertex_t, arena, model->vertices, r0);
|
||||||
|
list_append(vertex_t, arena, model->vertices, r1);
|
||||||
|
|
||||||
|
*in = model->vertices->count - 2;
|
||||||
|
|
||||||
|
scene_triangle_t tri = {
|
||||||
|
.idx0 = *in,
|
||||||
|
.idx1 = *ip,
|
||||||
|
.idx2 = model->vertices->count - 1,
|
||||||
|
.colour = triangle->colour,
|
||||||
|
};
|
||||||
|
|
||||||
|
list_append(scene_triangle_t, arena, model->triangles, tri);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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) {
|
||||||
list_float *values;
|
list_float *values;
|
||||||
if (i0 == i1) {
|
if (i0 == i1) {
|
||||||
@@ -265,6 +599,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);
|
||||||
@@ -279,3 +628,56 @@ internal inline void order_triangle_points(triangle_t *triangle) {
|
|||||||
swap(f32, triangle->h1, triangle->h2);
|
swap(f32, triangle->h1, triangle->h2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal inline bounding_sphere_t
|
||||||
|
get_bounding_sphere(const list_vertex_t *vertices) {
|
||||||
|
vec3f_t sum = {0};
|
||||||
|
for (u64 i = 0; i < vertices->count; ++i) {
|
||||||
|
sum = vec_add(vec3f_t, list_get(vertices, i).position, sum);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3f_t centre = vec_div_num(vec3f_t, sum, vertices->count);
|
||||||
|
f32 radius = 0.0f;
|
||||||
|
f32 tmp = 0.0f;
|
||||||
|
vec3f_t dst = {0};
|
||||||
|
for (u64 i = 0; i < vertices->count; ++i) {
|
||||||
|
dst = vec_sub(vec3f_t, list_get(vertices, i).position, centre);
|
||||||
|
tmp = vec_magnitude(vec3f_t, dst);
|
||||||
|
radius = tmp > radius ? tmp : radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (bounding_sphere_t){
|
||||||
|
.centre = centre,
|
||||||
|
.radius = radius,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
internal inline vertex_t segment_intersection(const vertex_t *a,
|
||||||
|
const vertex_t *b,
|
||||||
|
const clipping_plane_t *plane) {
|
||||||
|
f32 neg_d = plane->distance * -1.0f;
|
||||||
|
f32 na_dot = vec_dot(vec3f_t, plane->normal, a->position);
|
||||||
|
vec3f_t ba = vec_sub(vec3f_t, b->position, a->position);
|
||||||
|
f32 nba_dot = vec_dot(vec3f_t, plane->normal, ba);
|
||||||
|
|
||||||
|
f32 t = (neg_d - na_dot) / nba_dot;
|
||||||
|
|
||||||
|
return (vertex_t){
|
||||||
|
.position = vec_add(vec3f_t, a->position, vec_mul_num(vec3f_t, ba, t)),
|
||||||
|
.h = a->h + t * (b->h - a->h),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
internal inline void copy_triangles(Arena *arena, list_scene_triangle_t *dst,
|
||||||
|
const list_scene_triangle_t *src) {
|
||||||
|
for (u64 i = 0; i < src->count; ++i) {
|
||||||
|
scene_triangle_t tri = list_get(src, i);
|
||||||
|
list_append(scene_triangle_t, arena, dst, tri);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal inline f32 signed_distance(const vec3f_t *vertex,
|
||||||
|
const clipping_plane_t *plane) {
|
||||||
|
return (vertex->x * plane->normal.x) + (vertex->y * plane->normal.y) +
|
||||||
|
(vertex->z * plane->normal.z) + plane->distance;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#include "aliases.h"
|
#include "aliases.h"
|
||||||
#include "camera/camera.h"
|
#include "camera/camera.h"
|
||||||
#include "raytracer/raytracer.h"
|
#include "raytracer/raytracer.h"
|
||||||
#include "scene/scene.h"
|
|
||||||
#include "vector/vec.h"
|
#include "vector/vec.h"
|
||||||
#include "window/window.h"
|
#include "window/window.h"
|
||||||
#include <SDL2/SDL_events.h>
|
#include <SDL2/SDL_events.h>
|
||||||
@@ -23,11 +22,11 @@ i32 main(i32 argc, char *argv[]) {
|
|||||||
|
|
||||||
window_t window = {0};
|
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;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
const scene_t *scene = build_test_scene();
|
const raytracer_scene_t *scene = build_test_scene();
|
||||||
|
|
||||||
bool running = true;
|
bool running = true;
|
||||||
SDL_Event event = {0};
|
SDL_Event event = {0};
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#include "raytracer/raytracer.h"
|
#include "raytracer/raytracer.h"
|
||||||
#include "aliases.h"
|
#include "aliases.h"
|
||||||
|
#include "misc/misc_utils.h"
|
||||||
#include "vector/vec.h"
|
#include "vector/vec.h"
|
||||||
#include "window/window.h"
|
#include "window/window.h"
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
@@ -7,15 +8,14 @@
|
|||||||
#define SPECULAR_EPSILON 0.001f
|
#define SPECULAR_EPSILON 0.001f
|
||||||
#define REFLECTIVE_EPSILON 0.1f
|
#define REFLECTIVE_EPSILON 0.1f
|
||||||
|
|
||||||
internal intersection_t find_closest_intersection(vec3f_t origin,
|
internal intersection_t
|
||||||
vec3f_t direction, f32 t_min,
|
find_closest_intersection(vec3f_t origin, vec3f_t direction, f32 t_min,
|
||||||
f32 t_max,
|
f32 t_max, const raytracer_scene_t *scene);
|
||||||
const scene_t *scene);
|
|
||||||
internal solutions_t ray_intersects_sphere(vec3f_t origin, vec3f_t direction,
|
internal solutions_t ray_intersects_sphere(vec3f_t origin, vec3f_t direction,
|
||||||
sphere_t sphere);
|
sphere_t sphere);
|
||||||
internal f32 compute_lighting(vec3f_t position, vec3f_t surface_normal,
|
internal f32 compute_lighting(vec3f_t position, vec3f_t surface_normal,
|
||||||
vec3f_t view_vector, f32 specular_exponent,
|
vec3f_t view_vector, f32 specular_exponent,
|
||||||
const scene_t *scene);
|
const raytracer_scene_t *scene);
|
||||||
internal f32 light_diffuse(f32 light_intensity, vec3f_t light_direction,
|
internal f32 light_diffuse(f32 light_intensity, vec3f_t light_direction,
|
||||||
vec3f_t surface_normal);
|
vec3f_t surface_normal);
|
||||||
internal f32 light_specular(f32 light_intensity, vec3f_t light_direction,
|
internal f32 light_specular(f32 light_intensity, vec3f_t light_direction,
|
||||||
@@ -24,8 +24,73 @@ internal f32 light_specular(f32 light_intensity, vec3f_t light_direction,
|
|||||||
internal vec3f_t reflect_ray(vec3f_t light_direction, vec3f_t surface_normal);
|
internal vec3f_t reflect_ray(vec3f_t light_direction, vec3f_t surface_normal);
|
||||||
internal f32 cos_angle_between_vectors(vec3f_t v1, vec3f_t v2);
|
internal f32 cos_angle_between_vectors(vec3f_t v1, vec3f_t v2);
|
||||||
|
|
||||||
|
internal const sphere_t spheres[] = {
|
||||||
|
(sphere_t){
|
||||||
|
.radius = 1.0f,
|
||||||
|
.centre = (vec3f_t){.x = 0.0f, .y = -1.0f, .z = 3.0f},
|
||||||
|
.colour =
|
||||||
|
(colour_t){
|
||||||
|
.rgba.r = 245, .rgba.g = 238, .rgba.b = 158, .rgba.a = 255},
|
||||||
|
.specular = 500.0f,
|
||||||
|
.reflective = 0.3f,
|
||||||
|
},
|
||||||
|
(sphere_t){
|
||||||
|
.radius = 1.0f,
|
||||||
|
.centre = (vec3f_t){.x = -2.0f, .y = 0.0f, .z = 4.0f},
|
||||||
|
.colour =
|
||||||
|
(colour_t){
|
||||||
|
.rgba.r = 59, .rgba.g = 142, .rgba.b = 165, .rgba.a = 255},
|
||||||
|
.specular = 10.0f,
|
||||||
|
.reflective = 0.1f,
|
||||||
|
},
|
||||||
|
(sphere_t){
|
||||||
|
.radius = 1.0f,
|
||||||
|
.centre = (vec3f_t){.x = 2.0f, .y = 0.0f, .z = 4.0f},
|
||||||
|
.colour =
|
||||||
|
(colour_t){
|
||||||
|
.rgba.r = 171, .rgba.g = 52, .rgba.b = 40, .rgba.a = 255},
|
||||||
|
.specular = 500.0f,
|
||||||
|
.reflective = 0.4f,
|
||||||
|
},
|
||||||
|
(sphere_t){
|
||||||
|
.radius = 5000.0f,
|
||||||
|
.centre = (vec3f_t){.x = 0.0f, .y = -5001.0f, .z = 0.0f},
|
||||||
|
.colour =
|
||||||
|
(colour_t){
|
||||||
|
.rgba.r = 255, .rgba.g = 255, .rgba.b = 0, .rgba.a = 255},
|
||||||
|
.specular = 1000.0f,
|
||||||
|
.reflective = 0.5f,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
internal const light_t lights[] = {
|
||||||
|
(light_t){
|
||||||
|
.type = LIGHT_TYPE_AMBIENT,
|
||||||
|
.intensity = 0.2f,
|
||||||
|
},
|
||||||
|
(light_t){
|
||||||
|
.type = LIGHT_TYPE_POINT,
|
||||||
|
.intensity = 0.6f,
|
||||||
|
.position = (vec3f_t){.x = 2.0f, .y = 1.0f, .z = 0.0f},
|
||||||
|
},
|
||||||
|
(light_t){
|
||||||
|
.type = LIGHT_TYPE_DIRECTIONAL,
|
||||||
|
.intensity = 0.2f,
|
||||||
|
.direction = (vec3f_t){.x = 1.0f, .y = 4.0f, .z = 4.0f},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
internal raytracer_scene_t scene = (raytracer_scene_t){
|
||||||
|
.spheres = spheres,
|
||||||
|
.lights = lights,
|
||||||
|
.spheres_count = ARR_LEN(spheres),
|
||||||
|
.lights_count = ARR_LEN(lights),
|
||||||
|
};
|
||||||
|
|
||||||
|
const raytracer_scene_t *build_test_scene(void) { return &scene; }
|
||||||
|
|
||||||
colour_t trace_ray(vec3f_t origin, vec3f_t direction, f32 t_min, f32 t_max,
|
colour_t trace_ray(vec3f_t origin, vec3f_t direction, f32 t_min, f32 t_max,
|
||||||
const scene_t *scene, colour_t default_colour,
|
const raytracer_scene_t *scene, colour_t default_colour,
|
||||||
u32 recursion_depth) {
|
u32 recursion_depth) {
|
||||||
intersection_t intersection =
|
intersection_t intersection =
|
||||||
find_closest_intersection(origin, direction, t_min, t_max, scene);
|
find_closest_intersection(origin, direction, t_min, t_max, scene);
|
||||||
@@ -67,10 +132,9 @@ colour_t trace_ray(vec3f_t origin, vec3f_t direction, f32 t_min, f32 t_max,
|
|||||||
return colour_add_colour(local_colour, reflected_colour);
|
return colour_add_colour(local_colour, reflected_colour);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal intersection_t find_closest_intersection(vec3f_t origin,
|
internal intersection_t
|
||||||
vec3f_t direction, f32 t_min,
|
find_closest_intersection(vec3f_t origin, vec3f_t direction, f32 t_min,
|
||||||
f32 t_max,
|
f32 t_max, const raytracer_scene_t *scene) {
|
||||||
const scene_t *scene) {
|
|
||||||
f32 closest_t = INFINITY;
|
f32 closest_t = INFINITY;
|
||||||
const sphere_t *closest_sphere = NULL;
|
const sphere_t *closest_sphere = NULL;
|
||||||
|
|
||||||
@@ -116,7 +180,7 @@ internal solutions_t ray_intersects_sphere(vec3f_t origin, vec3f_t direction,
|
|||||||
|
|
||||||
internal f32 compute_lighting(vec3f_t position, vec3f_t surface_normal,
|
internal f32 compute_lighting(vec3f_t position, vec3f_t surface_normal,
|
||||||
vec3f_t view_vector, f32 specular_exponent,
|
vec3f_t view_vector, f32 specular_exponent,
|
||||||
const scene_t *scene) {
|
const raytracer_scene_t *scene) {
|
||||||
f32 I = 0.0f;
|
f32 I = 0.0f;
|
||||||
light_t light = {0};
|
light_t light = {0};
|
||||||
|
|
||||||
|
|||||||
@@ -1,70 +0,0 @@
|
|||||||
#include "scene/scene.h"
|
|
||||||
#include "aliases.h"
|
|
||||||
#include "misc/misc_utils.h"
|
|
||||||
#include "vector/vec.h"
|
|
||||||
#include "window/window.h"
|
|
||||||
|
|
||||||
internal const sphere_t spheres[] = {
|
|
||||||
(sphere_t){
|
|
||||||
.radius = 1.0f,
|
|
||||||
.centre = (vec3f_t){.x = 0.0f, .y = -1.0f, .z = 3.0f},
|
|
||||||
.colour =
|
|
||||||
(colour_t){
|
|
||||||
.rgba.r = 245, .rgba.g = 238, .rgba.b = 158, .rgba.a = 255},
|
|
||||||
.specular = 500.0f,
|
|
||||||
.reflective = 0.3f,
|
|
||||||
},
|
|
||||||
(sphere_t){
|
|
||||||
.radius = 1.0f,
|
|
||||||
.centre = (vec3f_t){.x = -2.0f, .y = 0.0f, .z = 4.0f},
|
|
||||||
.colour =
|
|
||||||
(colour_t){
|
|
||||||
.rgba.r = 59, .rgba.g = 142, .rgba.b = 165, .rgba.a = 255},
|
|
||||||
.specular = 10.0f,
|
|
||||||
.reflective = 0.1f,
|
|
||||||
},
|
|
||||||
(sphere_t){
|
|
||||||
.radius = 1.0f,
|
|
||||||
.centre = (vec3f_t){.x = 2.0f, .y = 0.0f, .z = 4.0f},
|
|
||||||
.colour =
|
|
||||||
(colour_t){
|
|
||||||
.rgba.r = 171, .rgba.g = 52, .rgba.b = 40, .rgba.a = 255},
|
|
||||||
.specular = 500.0f,
|
|
||||||
.reflective = 0.4f,
|
|
||||||
},
|
|
||||||
(sphere_t){
|
|
||||||
.radius = 5000.0f,
|
|
||||||
.centre = (vec3f_t){.x = 0.0f, .y = -5001.0f, .z = 0.0f},
|
|
||||||
.colour =
|
|
||||||
(colour_t){
|
|
||||||
.rgba.r = 255, .rgba.g = 255, .rgba.b = 0, .rgba.a = 255},
|
|
||||||
.specular = 1000.0f,
|
|
||||||
.reflective = 0.5f,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
internal const light_t lights[] = {
|
|
||||||
(light_t){
|
|
||||||
.type = LIGHT_TYPE_AMBIENT,
|
|
||||||
.intensity = 0.2f,
|
|
||||||
},
|
|
||||||
(light_t){
|
|
||||||
.type = LIGHT_TYPE_POINT,
|
|
||||||
.intensity = 0.6f,
|
|
||||||
.position = (vec3f_t){.x = 2.0f, .y = 1.0f, .z = 0.0f},
|
|
||||||
},
|
|
||||||
(light_t){
|
|
||||||
.type = LIGHT_TYPE_DIRECTIONAL,
|
|
||||||
.intensity = 0.2f,
|
|
||||||
.direction = (vec3f_t){.x = 1.0f, .y = 4.0f, .z = 4.0f},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
internal scene_t scene = (scene_t){
|
|
||||||
.spheres = spheres,
|
|
||||||
.lights = lights,
|
|
||||||
.spheres_count = ARR_LEN(spheres),
|
|
||||||
.lights_count = ARR_LEN(lights),
|
|
||||||
};
|
|
||||||
|
|
||||||
const scene_t *build_test_scene(void) { return &scene; }
|
|
||||||
@@ -94,6 +94,14 @@ i32 vec_dot_vec3i_t(vec3i_t v1, vec3i_t v2) {
|
|||||||
return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
|
return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vec3i_t vec_cross_vec3i_t(vec3i_t v1, vec3i_t v2) {
|
||||||
|
return (vec3i_t){
|
||||||
|
.x = v1.y * v2.z - v1.z * v2.y,
|
||||||
|
.y = v1.z * v2.x - v1.x * v2.z,
|
||||||
|
.z = v1.x * v2.y - v1.y * v2.x,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
i32 vec_magnitude_vec3i_t(vec3i_t v) {
|
i32 vec_magnitude_vec3i_t(vec3i_t v) {
|
||||||
i32 dot_product = vec_dot_vec3i_t(v, v);
|
i32 dot_product = vec_dot_vec3i_t(v, v);
|
||||||
return (i32)sqrtf((f32)dot_product);
|
return (i32)sqrtf((f32)dot_product);
|
||||||
@@ -128,6 +136,14 @@ f32 vec_dot_vec3f_t(vec3f_t v1, vec3f_t v2) {
|
|||||||
return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
|
return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vec3f_t vec_cross_vec3f_t(vec3f_t v1, vec3f_t v2) {
|
||||||
|
return (vec3f_t){
|
||||||
|
.x = v1.y * v2.z - v1.z * v2.y,
|
||||||
|
.y = v1.z * v2.x - v1.x * v2.z,
|
||||||
|
.z = v1.x * v2.y - v1.y * v2.x,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
f32 vec_magnitude_vec3f_t(vec3f_t v) {
|
f32 vec_magnitude_vec3f_t(vec3f_t v) {
|
||||||
f32 dot_product = vec_dot_vec3f_t(v, v);
|
f32 dot_product = vec_dot_vec3f_t(v, v);
|
||||||
return sqrtf(dot_product);
|
return sqrtf(dot_product);
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "window/window.h"
|
#include "window/window.h"
|
||||||
#include "aliases.h"
|
#include "aliases.h"
|
||||||
#include "math/math_utils.h"
|
#include "math/math_utils.h"
|
||||||
|
#include "mem_arena.h"
|
||||||
#include "vector/vec.h"
|
#include "vector/vec.h"
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
#include <SDL2/SDL_error.h>
|
#include <SDL2/SDL_error.h>
|
||||||
@@ -10,12 +11,14 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.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);
|
i32 denormalise(i32 value, u32 max, u32 abs_half);
|
||||||
vec2i_t denormalised_coords(const window_t *wnd, i32 x, i32 y);
|
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_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) {
|
if (SDL_Init(SDL_INIT_EVERYTHING) != 0) {
|
||||||
printf("Failed to initialise SDL: %s\n", SDL_GetError());
|
printf("Failed to initialise SDL: %s\n", SDL_GetError());
|
||||||
|
|
||||||
@@ -64,6 +67,9 @@ bool init_window(window_t *wnd, u32 width, u32 height, const char *title) {
|
|||||||
wnd->half_width = width / 2;
|
wnd->half_width = width / 2;
|
||||||
wnd->half_height = height / 2;
|
wnd->half_height = height / 2;
|
||||||
wnd->title = title;
|
wnd->title = title;
|
||||||
|
if (arena) {
|
||||||
|
wnd->z_buffer = wapp_mem_arena_alloc(arena, width * height * sizeof(f32));
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -85,6 +91,8 @@ void close_window(window_t *wnd) {
|
|||||||
|
|
||||||
wnd->back_buffer = NULL;
|
wnd->back_buffer = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wnd->z_buffer = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
@@ -98,6 +106,7 @@ void clear_window(window_t *wnd, colour_t colour) {
|
|||||||
|
|
||||||
for (u32 i = 0; i < count; ++i) {
|
for (u32 i = 0; i < count; ++i) {
|
||||||
pixels[i] = colour.colour;
|
pixels[i] = colour.colour;
|
||||||
|
wnd->z_buffer[i] = 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_UnlockSurface(wnd->back_buffer);
|
SDL_UnlockSurface(wnd->back_buffer);
|
||||||
@@ -117,13 +126,34 @@ void set_pixel(window_t *wnd, i32 x, i32 y, colour_t colour) {
|
|||||||
SDL_UnlockSurface(wnd->back_buffer);
|
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 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 index = index_from_coordinates(wnd, (u32)(coords.x), (u32)(coords.y));
|
||||||
|
return wnd->z_buffer[index];
|
||||||
|
}
|
||||||
|
|
||||||
void swap_buffers(window_t *wnd) {
|
void swap_buffers(window_t *wnd) {
|
||||||
SDL_BlitSurface(wnd->back_buffer, NULL, wnd->front_buffer, NULL);
|
SDL_BlitSurface(wnd->back_buffer, NULL, wnd->front_buffer, NULL);
|
||||||
|
|
||||||
SDL_UpdateWindowSurface(wnd->window);
|
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;
|
return y * wnd->width + x;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,6 +189,11 @@ void set_screen_pixel(window_t *wnd, u32 x, u32 y, colour_t colour) {
|
|||||||
pixels[index] = colour.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 window_to_viewport(const window_t *wnd, i32 x, i32 y,
|
||||||
vec3f_t viewport) {
|
vec3f_t viewport) {
|
||||||
return (vec3f_t){
|
return (vec3f_t){
|
||||||
|
|||||||
Reference in New Issue
Block a user