Create initial raytraced scene
This commit is contained in:
parent
36913bf365
commit
6b0732980a
@ -1,22 +1,77 @@
|
||||
#include "SDL_events.h"
|
||||
#include "c_cpp_aliases/aliases.h"
|
||||
#include "vector/vec.h"
|
||||
#include "window/window.h"
|
||||
#include <math.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define ARR_LEN(ARR) sizeof(ARR) / sizeof(ARR[0])
|
||||
|
||||
typedef struct {
|
||||
f32 radius;
|
||||
vec3f_t centre;
|
||||
colour_t colour;
|
||||
} sphere_t;
|
||||
|
||||
typedef struct {
|
||||
sphere_t *spheres;
|
||||
u32 count;
|
||||
} scene_t;
|
||||
|
||||
typedef struct {
|
||||
f32 t1;
|
||||
f32 t2;
|
||||
} solutions_t;
|
||||
|
||||
solutions_t ray_intersects_sphere(vec3f_t origin, vec3f_t direction,
|
||||
sphere_t sphere);
|
||||
colour_t trace_ray(vec3f_t origin, vec3f_t direction, f32 t_min, f32 t_max,
|
||||
const scene_t *scene, colour_t default_colour);
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
colour_t bg = (colour_t){.r = 128, .g = 128, .b = 128, .a = 255};
|
||||
vec3f_t camera = {.x = 0.0f, .y = 0.0f, .z = 0.0f};
|
||||
vec3f_t viewport = {.x = 1.0f, .y = 1.0f, .z = 1.0f};
|
||||
|
||||
window_t window = {0};
|
||||
|
||||
if (!init_window(&window, 1000, 800, "CG From Scratch")) {
|
||||
if (!init_window(&window, 800, 800, "CG From Scratch")) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
bool running = true;
|
||||
SDL_Event event = {0};
|
||||
|
||||
sphere_t spheres[] = {
|
||||
(sphere_t){
|
||||
.radius = 1.0f,
|
||||
.centre = (vec3f_t){.x = 0.0f, .y = -1.0f, .z = 3.0f},
|
||||
.colour = (colour_t){.r = 255, .g = 0, .b = 0, .a = 255},
|
||||
},
|
||||
(sphere_t){
|
||||
.radius = 1.0f,
|
||||
.centre = (vec3f_t){.x = -2.0f, .y = 0.0f, .z = 4.0f},
|
||||
.colour = (colour_t){.r = 0, .g = 255, .b = 0, .a = 255},
|
||||
},
|
||||
(sphere_t){
|
||||
.radius = 1.0f,
|
||||
.centre = (vec3f_t){.x = 2.0f, .y = 0.0f, .z = 4.0f},
|
||||
.colour = (colour_t){.r = 0, .g = 0, .b = 255, .a = 255},
|
||||
},
|
||||
};
|
||||
|
||||
scene_t scene = {
|
||||
.spheres = spheres,
|
||||
.count = ARR_LEN(spheres),
|
||||
};
|
||||
|
||||
i32 w_min = ((i32)window.half_width) * -1;
|
||||
i32 w_max = (i32)window.half_width;
|
||||
i32 h_min = ((i32)window.half_height) * -1;
|
||||
i32 h_max = (i32)window.half_height;
|
||||
|
||||
while (running) {
|
||||
while (SDL_PollEvent(&event)) {
|
||||
switch (event.type) {
|
||||
@ -28,6 +83,14 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
clear_window(&window, bg);
|
||||
|
||||
for (i32 y = h_min; y < h_max; ++y) {
|
||||
for (i32 x = w_min; x < w_max; ++x) {
|
||||
vec3f_t direction = window_to_viewport(&window, x, y, viewport);
|
||||
colour_t colour = trace_ray(camera, direction, 1, INFINITY, &scene, bg);
|
||||
set_pixel(&window, x, y, colour);
|
||||
}
|
||||
}
|
||||
|
||||
swap_buffers(&window);
|
||||
}
|
||||
|
||||
@ -35,3 +98,52 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
solutions_t ray_intersects_sphere(vec3f_t origin, vec3f_t direction,
|
||||
sphere_t sphere) {
|
||||
f32 r = sphere.radius;
|
||||
vec3f_t CO = vec_sub(vec3f_t, origin, sphere.centre);
|
||||
|
||||
f32 a = vec_dot(vec3f_t, direction, direction);
|
||||
f32 b = 2.0f * vec_dot(vec3f_t, CO, direction);
|
||||
f32 c = vec_dot(vec3f_t, CO, CO) - r * r;
|
||||
|
||||
f32 discriminant = b * b - 4 * a * c;
|
||||
if (discriminant < 0) {
|
||||
return (solutions_t){INFINITY, INFINITY};
|
||||
}
|
||||
|
||||
f32 t1 = (-b + sqrtf(discriminant)) / (2 * a);
|
||||
f32 t2 = (-b - sqrtf(discriminant)) / (2 * a);
|
||||
|
||||
return (solutions_t){t1, t2};
|
||||
}
|
||||
|
||||
colour_t trace_ray(vec3f_t origin, vec3f_t direction, f32 t_min, f32 t_max,
|
||||
const scene_t *scene, colour_t default_colour) {
|
||||
f32 closest_t = INFINITY;
|
||||
sphere_t *closest_sphere = NULL;
|
||||
|
||||
for (u32 i = 0; i < scene->count; ++i) {
|
||||
solutions_t solutions =
|
||||
ray_intersects_sphere(origin, direction, scene->spheres[i]);
|
||||
|
||||
if (solutions.t1 >= t_min && solutions.t1 <= t_max &&
|
||||
solutions.t1 < closest_t) {
|
||||
closest_t = solutions.t1;
|
||||
closest_sphere = &(scene->spheres[i]);
|
||||
}
|
||||
|
||||
if (solutions.t2 >= t_min && solutions.t2 <= t_max &&
|
||||
solutions.t2 < closest_t) {
|
||||
closest_t = solutions.t2;
|
||||
closest_sphere = &(scene->spheres[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (!closest_sphere) {
|
||||
return default_colour;
|
||||
}
|
||||
|
||||
return closest_sphere->colour;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user