From 9b40029e42f994aeff59ecc44a6d3b8fba93071d Mon Sep 17 00:00:00 2001 From: Julian T Date: Fri, 21 Feb 2020 14:42:42 +0100 Subject: Pretty realistic colors --- main.c | 7 +++++-- pgm.c | 39 +++++++++++++++++++++++++++++++++++++++ pgm.h | 4 ++++ ray.c | 43 ++++++++++++++++++++++++++++--------------- scene.c | 23 ++++++++++++++++++++--- scene.h | 15 ++++++++++++--- 6 files changed, 108 insertions(+), 23 deletions(-) diff --git a/main.c b/main.c index 011f2c1..0f0103a 100644 --- a/main.c +++ b/main.c @@ -19,6 +19,9 @@ int main() s.objects = NULL; s.lights = NULL; + material_t m; + vector_set(&m.color, 0, 1, 0); + vector_set(&s.view.position, 0, 15, 10); vector_set(&s.view.target, 0, 0, 0); s.view.width = TESTW; @@ -27,8 +30,8 @@ int main() viewpoint_init(&s.view); // Setup plane - add_sphere(&s, vector_set(NULL, 0, 0, 5), 5); - add_sphere(&s, vector_set(NULL, 10, 0, 5), 5); + add_sphere(&s, vector_set(NULL, 0, 0, 5), 5, &m); + //add_sphere(&s, vector_set(NULL, 10, 0, 5), 5); add_plane(&s, vector_set(NULL, 0, 0, 2), vector_set(NULL, 0, 0, 1)); add_light(&s, vector_set(NULL, 10, 0, 20), color_set(NULL, 255, 255, 255)); diff --git a/pgm.c b/pgm.c index 058b445..90791de 100644 --- a/pgm.c +++ b/pgm.c @@ -25,3 +25,42 @@ color_t *color_set(color_t *c, uint8_t r, uint8_t g, uint8_t b) return c; } + +color_t *color_add(color_t *dest, color_t *a, color_t *b) +{ + if (!dest) { + dest = (color_t *) malloc(sizeof(dest)); + } + + dest->r = a->r + b->r; + dest->g = a->g + b->g; + dest->b = a->b + b->b; + + return dest; +} + +color_t *color_scale(color_t *dest, color_t *a, float b) +{ + if (!dest) { + dest = (color_t *) malloc(sizeof(dest)); + } + + dest->r = a->r * b; + dest->g = a->g * b; + dest->b = a->b * b; + + return dest; +} + +color_t *color_scale_vector(color_t *dest, color_t *a, vector_t *v) +{ + if (!dest) { + dest = (color_t *) malloc(sizeof(dest)); + } + + dest->r = a->r * v->x; + dest->g = a->g * v->y; + dest->b = a->b * v->z; + + return dest; +} diff --git a/pgm.h b/pgm.h index b8900b8..3e40034 100644 --- a/pgm.h +++ b/pgm.h @@ -3,12 +3,16 @@ #include #include +#include "vector.h" typedef struct { uint8_t r, g, b; } color_t; color_t *color_set(color_t *c, uint8_t r, uint8_t g, uint8_t b); +color_t *color_scale(color_t *dest, color_t *a, float b); +color_t *color_add(color_t *dest, color_t *a, color_t *b); +color_t *color_scale_vector(color_t *dest, color_t *a, vector_t *v); int pgm_write_header(FILE *fp, unsigned int w, unsigned int h); int pgm_write_pixel(FILE *fp, color_t *c); diff --git a/ray.c b/ray.c index 3736773..0e82546 100644 --- a/ray.c +++ b/ray.c @@ -142,33 +142,46 @@ color_t *ray_trace(space_t *s, unsigned int x, unsigned int y) if (!o) { return NULL; } - //printf("dist: %f\n", dist); // Calculate new ray point r.start = vector_scale(NULL, r.direction, dist); vector_add(r.start, r.start, &s->view.position); + // Calculate normal vector + vector_t n; + obj_norm_at(o, &n, r.start); + + // Hit color + color_t *c = color_set(NULL, 0, 0, 0); + // Cast light rays - light_t *l = s->lights; - while (l) { - vector_t tmp; + light_t *light = s->lights; + while (light) { + vector_t l; // Calculate distance to light - vector_sub(&tmp, l->pos, r.start); - COORD_T d = vector_len(&tmp); - - // Calculate unit - vector_scale_inv(&tmp, &tmp, vector_len(&tmp)); + vector_sub(&l, light->pos, r.start); + COORD_T d = vector_len(&l); // Find obstacles - r.direction = &tmp; + r.direction = &l; object_t *obs = ray_cast(s, &r, NULL, true, d); - - if (!obs) { - return color_set(NULL, 100, 100, o->type == TYPE_SPHERE ? 200 :0); + if (obs) { + light = light->next; + continue; } + + // Calculate unit + vector_scale_inv(&l, &l, vector_len(&l)); + color_t tmp; + color_scale(&tmp, light->defuse, vector_dot(&l, &n)); + color_add(c, &tmp, c); - l = l->next; + light = light->next; + } + + if (o->m) { + color_scale_vector(c, c, &o->m->color); } - return NULL; + return c; } diff --git a/scene.c b/scene.c index a75b329..99ae0e8 100644 --- a/scene.c +++ b/scene.c @@ -12,11 +12,13 @@ static inline void link_object(space_t *s, object_t *o) } } -object_t *add_sphere(space_t *s, vector_t *c, COORD_T r) +object_t *add_sphere(space_t *s, vector_t *c, COORD_T r, material_t *m) { object_t *o = (object_t *) malloc(sizeof(object_t)); o->type = TYPE_SPHERE; + o->m = m; + o->sph.center = c; o->sph.radius = r; @@ -38,12 +40,12 @@ object_t *add_plane(space_t *s, vector_t *start, vector_t *dir) return o; } -light_t *add_light(space_t *s, vector_t *pos, color_t *c) +light_t *add_light(space_t *s, vector_t *pos, color_t *defuse) { light_t *o = (light_t *) malloc(sizeof(light_t)); o->pos = pos; - o->col = c; + o->defuse = defuse; if (s) { o->next = s->lights; @@ -54,3 +56,18 @@ light_t *add_light(space_t *s, vector_t *pos, color_t *c) return o; } + +void obj_norm_at(object_t *o, vector_t *dest, vector_t *point) +{ + switch(o->type) { + case TYPE_SPHERE: + vector_sub(dest, point, o->sph.center); + vector_scale_inv(dest, dest, vector_len(dest)); + break; + case TYPE_PLANE: + vector_copy(dest, o->pl.norm); + break; + } + + return; +} diff --git a/scene.h b/scene.h index 1c6363b..7efb5cd 100644 --- a/scene.h +++ b/scene.h @@ -23,16 +23,23 @@ typedef struct { typedef struct light_s{ vector_t *pos; - color_t *col; + color_t *defuse; struct light_s *next; } light_t; +typedef struct { + vector_t color; +} material_t; + // General object structure typedef struct object_s{ uint8_t type; struct object_s *next; + // Color and light information + material_t *m; + union { sphere_t sph; plane_t pl; @@ -45,8 +52,10 @@ typedef struct { light_t *lights; } space_t; -object_t *add_sphere(space_t *s, vector_t *c, COORD_T r); +object_t *add_sphere(space_t *s, vector_t *c, COORD_T r, material_t *m); object_t *add_plane(space_t *s, vector_t *start, vector_t *dir); -light_t *add_light(space_t *s, vector_t *pos, color_t *c); +light_t *add_light(space_t *s, vector_t *pos, color_t *defuse); + +void obj_norm_at(object_t *o, vector_t *dest, vector_t *point); #endif -- cgit v1.2.3