diff options
-rw-r--r-- | main.c | 35 | ||||
-rw-r--r-- | ray.c | 75 | ||||
-rw-r--r-- | scene.h | 4 | ||||
-rw-r--r-- | viewpoint.h | 4 |
4 files changed, 82 insertions, 36 deletions
@@ -10,7 +10,7 @@ #define TESTW 1000 #define TESTH 1000 -color_t back = {0, 0, 0}; +color_t back = {255, 255, 255}; int print = 0; int main() @@ -19,22 +19,31 @@ int main() space_t s; s.objects = NULL; s.lights = NULL; - color_set(&s.ambient, 30, 30, 30); + color_set(&s.ambient, 25, 25, 25); material_t m; - vector_set(&m.color, 0, 1, 0); - m.defuse = 1; - m.specular = 0.3; - m.shine = 20; + vector_set(&m.color, 1, 1, 1); + m.defuse = 0.0; + m.specular = 0.0; + m.shine = 40; + m.reflective = 0.5; + + material_t m2; + vector_set(&m2.color, 0.1, 1, 0.7); + m2.defuse = 1; + m2.specular = 0.0; + m2.shine = 40; + m2.reflective = 0.0; material_t mpl; //vector_set(&mpl.color, 0, 0.396, 0.7019); vector_set(&mpl.color, 1, 1, 1); mpl.defuse = 1; - mpl.specular = 0.3; - mpl.shine = 20; + mpl.specular = 0.0; + mpl.shine = 50; + mpl.reflective = 0; - vector_set(&s.view.position, 0, 15, 8); + vector_set(&s.view.position, 0, 14, 8); vector_set(&s.view.target, 0, 0, 0); s.view.width = TESTW; s.view.height = TESTH; @@ -42,11 +51,11 @@ int main() viewpoint_init(&s.view); // Setup plane - add_sphere(&s, vector_set(NULL, 3, 0, 5), 5, &m); - add_sphere(&s, vector_set(NULL, -6, -3, 7), 3, &m); - //add_sphere(&s, vector_set(NULL, 10, 0, 5), 5); + add_sphere(&s, vector_set(NULL, 3, -1, 5), 5, &m); + add_sphere(&s, vector_set(NULL, 3, 7, 3), 2, &m2); add_plane(&s, vector_set(NULL, 0, 0, 2), vector_set(NULL, 0, 0, 1), &mpl); - add_light(&s, vector_set(NULL, 10, 0, 20), color_set(NULL, 255, 255, 255), color_set(NULL, 150, 150, 150)); + add_plane(&s, vector_set(NULL, 0, -20, 0), vector_set(NULL, 0, 1, 0), &mpl); + add_light(&s, vector_set(NULL, 20, 0, 20), color_set(NULL, 255, 255, 255), color_set(NULL, 150, 150, 150)); //add_light(&s, vector_set(NULL, 0, 10, 20), color_set(NULL, 255, 255, 255), color_set(NULL, 150, 150, 150)); pgm_write_header(stdout, TESTW, TESTH); @@ -1,5 +1,6 @@ #include <stdio.h> #include <math.h> +#include <stdlib.h> #include "vector.h" #include "ray.h" @@ -148,14 +149,10 @@ object_t *ray_cast(space_t *s, ray_t *r, COORD_T *dist_ret, bool chk, COORD_T ch return smallest; } -static void ray_calc_light(space_t *s, color_t *dest, object_t *o, vector_t *eye, vector_t *point) +static void ray_calc_light(space_t *s, color_t *dest, object_t *o, vector_t *N, vector_t *eye, vector_t *point) { ray_t r; r.start = point; - - // Calculate normal vector - vector_t N; - obj_norm_at(o, &N, point); // And vector towards viewer vector_t V; @@ -186,7 +183,7 @@ static void ray_calc_light(space_t *s, color_t *dest, object_t *o, vector_t *eye // Calculate Deffuse part color_t tmp; - COORD_T cl = vector_dot(&l, &N); + COORD_T cl = vector_dot(&l, N); if (cl > 0) { color_scale(&tmp, light->defuse, cl * o->m->defuse); color_add(dest, &tmp, dest); @@ -195,7 +192,7 @@ static void ray_calc_light(space_t *s, color_t *dest, object_t *o, vector_t *eye // calculate specular part. TODO implement blinn-phong // Calculate R_m vector_t R; - vector_scale(&R, &N, 2 * vector_dot(&l, &N)); + vector_scale(&R, N, 2 * vector_dot(&l, N)); vector_sub(&R, &R, &l); // Add it to the light @@ -210,6 +207,49 @@ static void ray_calc_light(space_t *s, color_t *dest, object_t *o, vector_t *eye } } +int ray_trace_recur(space_t *s, color_t *dest, ray_t *ray, unsigned hop, COORD_T scale) +{ + COORD_T dist; + color_t c; + color_set(&c, 0, 0, 0); + + object_t *o = ray_cast(s, ray, &dist, false, 0); + if (!o) { + return 1; + } + + vector_t rdir, rstart; + ray_t r = {start: &rstart, direction: &rdir}; + + vector_scale(r.start, ray->direction, dist); + vector_add(r.start, r.start, ray->start); + + // Calculate normal vector + vector_t N; + obj_norm_at(o, &N, r.start); + + // Check if we should calculate light + if (o->m->defuse + o->m->specular > ZERO_APROX) { + // Add all light hitting o at r.start to c + ray_calc_light(s, &c, o, &N, ray->start, r.start); + } + + // Calculate reflection vector + if (hop < 2 && o->m->reflective > ZERO_APROX) { + vector_scale(r.direction, &N, 2 * vector_dot(ray->direction, &N)); + vector_sub(r.direction, ray->direction, r.direction); + + ray_trace_recur(s, &c, &r, hop+1, o->m->reflective); + } + + // Scale by the objects own color. + color_scale_vector(&c, &c, &o->m->color); + color_scale(&c, &c, scale); + color_add(dest, dest, &c); + + return 0; +} + color_t *ray_trace(space_t *s, unsigned int x, unsigned int y) { // Setup primary ray @@ -218,22 +258,15 @@ color_t *ray_trace(space_t *s, unsigned int x, unsigned int y) r.direction = vector_copy(NULL, NULL); viewpoint_ray(&s->view, r.direction, x, y); - // Cast it - COORD_T dist; - object_t *o = ray_cast(s, &r, &dist, false, 0); - if (!o) { - return NULL; - } - - r.start = vector_scale(NULL, r.direction, dist); - vector_add(r.start, r.start, &s->view.position); - - // Hit color + // Init return color. Will be accumilated with all the detected light. color_t *c = color_set(NULL, s->ambient.r, s->ambient.g, s->ambient.b); - ray_calc_light(s, c, o, &s->view.position, r.start); - - color_scale_vector(c, c, &o->m->color); + // Run the recursive ray trace + int status = ray_trace_recur(s, c, &r, 0, 1); + if (status) { + free(c); + return NULL; + } return c; } @@ -32,9 +32,13 @@ typedef struct light_s{ typedef struct { vector_t color; + // Light properties COORD_T defuse; COORD_T specular; unsigned int shine; + + // Reflective properties + COORD_T reflective; } material_t; // General object structure diff --git a/viewpoint.h b/viewpoint.h index 0aae5db..6e5178c 100644 --- a/viewpoint.h +++ b/viewpoint.h @@ -3,8 +3,8 @@ #include "vector.h" -// 90 degrees -#define FOV 3.1415/2 +// 100 degrees +#define FOV 1.74533 typedef struct { // Viewpoint dimensions |