From b0079eaa628a1f2fd99014cd12e6baac17f4d17a Mon Sep 17 00:00:00 2001 From: Julian T Date: Sun, 23 Feb 2020 18:30:21 +0100 Subject: Added phong light model and fixed sphere intersect --- ray.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 66 insertions(+), 16 deletions(-) (limited to 'ray.c') diff --git a/ray.c b/ray.c index 0e82546..d5b6a89 100644 --- a/ray.c +++ b/ray.c @@ -4,6 +4,8 @@ #include "ray.h" +extern int print; + // https://en.wikipedia.org/wiki/Line%E2%80%93sphere_intersection // http://viclw17.github.io/2018/07/16/raytracing-ray-sphere-intersection/ // https://www.scratchapixel.com/lessons/3d-basic-rendering/minimal-ray-tracer-rendering-simple-shapes/ray-sphere-intersection @@ -26,6 +28,9 @@ COORD_T ray_intersect_sphere(sphere_t *s, ray_t *ray, bool skip_dist) return -1; } if (skip_dist) { + if (print) { + printf("sph dist: skip\n"); + } return 1; } @@ -34,11 +39,11 @@ COORD_T ray_intersect_sphere(sphere_t *s, ray_t *ray, bool skip_dist) -0.5 * (b + sqrt(d)) : -0.5 * (b - sqrt(d)); - COORD_T x0 = q / a; - COORD_T x1 = c / q; + COORD_T x1 = q / a; + COORD_T x0 = c / q; // Take the correct result. If one is zero take the other. - if (x0 <= 0) { + if (x0 <= ZERO_APROX) { if (x1 <= 0) { return -1; } @@ -47,9 +52,12 @@ COORD_T ray_intersect_sphere(sphere_t *s, ray_t *ray, bool skip_dist) } // If point is on sphere it will be zero close to zero - if (x0 < 1e-3) { + if (x0 < ZERO_APROX) { return -1; } + if (print) { + printf("sph dist: %f\n", x0); + } return x0; } @@ -60,12 +68,18 @@ COORD_T ray_intersect_plane(plane_t *p, ray_t *ray, bool skip_dist) { // If zero ray is parralel to plane COORD_T nr = vector_dot(p->norm, ray->direction); - // + // Take care of rounding errors if (nr < ZERO_APROX && nr > -ZERO_APROX) { + if (print) { + printf("Ohh no"); + } return -1; } if (skip_dist) { + if (print) { + printf("pdist: skip\n"); + } return 1; } @@ -75,6 +89,9 @@ COORD_T ray_intersect_plane(plane_t *p, ray_t *ray, bool skip_dist) vector_sub(&tmp, &tmp, ray->start); COORD_T t = vector_dot(&tmp, p->norm) / nr; + if (print) { + printf("pdist: %f\n", t); + } return t; } @@ -102,7 +119,10 @@ object_t *ray_cast(space_t *s, ray_t *r, COORD_T *dist_ret, bool chk, COORD_T ch while (o) { COORD_T d = ray_intersect(o, r, false); - if (d > 0) { + if (print) + printf("Distance: %f\n", d); + + if (d > ZERO_APROX) { if (chk && chk_dist > d) { if (dist_ret) { *dist_ret = d; @@ -143,16 +163,23 @@ color_t *ray_trace(space_t *s, unsigned int x, unsigned int y) return NULL; } - // 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); + + // And vector towards viewer + //printf("point: "); vector_print(r.start); + vector_t V; + vector_sub(&V, &s->view.position, r.start); + // Normalice it + vector_scale_inv(&V, &V, vector_len(&V)); + //printf("V: "); vector_print(&V); // Hit color - color_t *c = color_set(NULL, 0, 0, 0); + color_t *c = color_set(NULL, s->ambient.r, s->ambient.g, s->ambient.b); // Cast light rays light_t *light = s->lights; @@ -162,26 +189,49 @@ color_t *ray_trace(space_t *s, unsigned int x, unsigned int y) vector_sub(&l, light->pos, r.start); COORD_T d = vector_len(&l); + vector_scale_inv(&l, &l, vector_len(&l)); + // Find obstacles + if (print) printf("Starting\n"); r.direction = &l; object_t *obs = ray_cast(s, &r, NULL, true, d); if (obs) { + if (print) + printf("Light ray hit\n"); + light = light->next; continue; } + if (print) + printf("Light ray went through\n"); - // Calculate unit - vector_scale_inv(&l, &l, vector_len(&l)); + // Calculate Deffuse part color_t tmp; - color_scale(&tmp, light->defuse, vector_dot(&l, &n)); - color_add(c, &tmp, c); - + COORD_T cl = vector_dot(&l, &n); + if (cl > 0) { + color_scale(&tmp, light->defuse, cl * o->m->defuse); + color_add(c, &tmp, c); + } + + // calculate specular part. TODO implement blinn-phong + // Calculate R_m + vector_t R; + vector_scale(&R, &n, 2 * vector_dot(&l, &n)); + vector_sub(&R, &R, &l); + //printf("R: ");vector_print(&R); + + // Add it to the light + cl = 1 * vector_dot(&R, &V); + if (cl > 0) { + cl = pow(cl, o->m->shine); + color_scale(&tmp, light->specular, cl * o->m->specular); + color_add(c, &tmp, c); + } + light = light->next; } - if (o->m) { - color_scale_vector(c, c, &o->m->color); - } + color_scale_vector(c, c, &o->m->color); return c; } -- cgit v1.2.3