From ba99860760eda6ec221b15190547736407723f84 Mon Sep 17 00:00:00 2001 From: Julian T Date: Thu, 7 May 2020 09:46:56 +0200 Subject: Global illumination --- Makefile | 2 +- ctranslate.c | 20 ++++++++++++--- main.c | 23 ++++++++++++++---- ray.c | 79 ++++++++++++++++++++++++++++++++++++++---------------------- scene.h | 1 + vector.c | 11 +++++++++ vector.h | 1 + 7 files changed, 99 insertions(+), 38 deletions(-) diff --git a/Makefile b/Makefile index 66cf39b..bf2a5dc 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ CC=gcc # Enable debugging -CFLAGS=-ggdb -O3 +CFLAGS=-ggdb -O3 -Wall # We need math LDFLAGS=-lm -lpthread diff --git a/ctranslate.c b/ctranslate.c index f7dfe64..8d03d39 100644 --- a/ctranslate.c +++ b/ctranslate.c @@ -1,9 +1,11 @@ #include "ctranslate.h" +#include "vector.h" #include // TODO remove dublicate pi definitions #define PI 3.14159265359 +#define DEBUG 0 void csystem_init(csystem_t *cs, vector_t *up) { @@ -11,23 +13,35 @@ void csystem_init(csystem_t *cs, vector_t *up) // Create new coordinate system where N is up. To do this we need two more vectors for the other axises. // Create the 2. by setting x or y to 0 - if (up->x > up->y) { + if (fabs(up->x) > fabs(up->y)) { vector_set(&cs->ax, up->z, 0, -up->x); } else { vector_set(&cs->ax, 0, -up->z, up->y); } // Normalice - vector_scale_inv(&cs->ax, &cs->ax, vector_len(&cs->ax)); + vector_norm(&cs->ax); + // Create the 3. axis by taking the cross of the other vector_cross(&cs->az, up, &cs->ax); +#if DEBUG == 1 + printf("up "); vector_print(up); + printf("ax "); vector_print(&cs->ax); + printf("az "); vector_print(&cs->az); +#endif } void csystem_calc_real(csystem_t *cs, vector_t *inside, vector_t *real) { - vector_set(real, inside->x * cs->ax.x + inside->y * cs->up->x + inside->z * cs->az.x, + vector_t tmp; + vector_set(&tmp, inside->x * cs->ax.x + inside->y * cs->up->x + inside->z * cs->az.x, inside->x * cs->ax.y + inside->y * cs->up->y + inside->z * cs->az.y, inside->x * cs->ax.z + inside->y * cs->up->z + inside->z * cs->az.z); + + vector_copy(real, &tmp); +#if DEBUG == 1 + printf("Haha "); vector_print(real); +#endif } void csystem_hemisphere_random(csystem_t *cs, COORD_T r1, COORD_T r2, vector_t *out) diff --git a/main.c b/main.c index e4c8c1a..356976a 100644 --- a/main.c +++ b/main.c @@ -37,15 +37,27 @@ container_t *cont = (container_t *) container; settings_t gfx_high = { .arealight_samples = 64, .envlight_samples = 64, - .antialias_samples = 8, - .depth = 16, + .antialias_samples = 2, + .globallight_samples = 32, + .gl_opt_depth = 1, + .depth = 2, }; settings_t gfx_low = { .arealight_samples = 16, .envlight_samples = 16, .antialias_samples = 2, - .globallight_samples = 5, + .globallight_samples = 16, + .gl_opt_depth = 1, + .depth = 1, +}; + +settings_t gfx_very = { + .arealight_samples = 8, + .envlight_samples = 8, + .antialias_samples = 2, + .globallight_samples = 2, + .gl_opt_depth = 0, .depth = 1, }; @@ -64,7 +76,8 @@ int main() // Set space options color_set(&s->ambient, 0.09, 0.09, 0.09); - color_set(&s->back, 0.8, 0.8, 0.8); + //color_set(&s->back, 0.8, 0.8, 0.8); + color_set(&s->back, 0.0, 0.0, 0.0); color_set(&s->env_color, 0.13, 0.13, 0.13); s->env_enabled = false; s->gfx = &gfx_low; @@ -166,7 +179,7 @@ int main() o->m = ml; light_t *l = add_light(cont, TYPE_L_AREA); - //vector_set(&l->point.pos, 2, 8, -1); + //vector_set(&l->point.pos, 0, 5, 0); l->area = o; color_set(&l->color, 1, 1, 1); l->radiance = 0.1; diff --git a/ray.c b/ray.c index e2789ca..83708f6 100644 --- a/ray.c +++ b/ray.c @@ -135,30 +135,28 @@ object_t *ray_cast(space_t *s, ray_t *r, COORD_T *dist_ret, bool chk, COORD_T ch return smallest; } -// Light (l) the object o reflects. Given is the point of intersect, vector to the light l, vector to viewer V, and normal at point N. -static void reflected_at(object_t *o, color_t *dest, light_t *light, COORD_T dist, vector_t *point, vector_t *l, vector_t *V, vector_t *N) { - // Calculate light intensity - COORD_T i = light->radiance / ( dist * dist); +// Color the object o reflects. Given is the point of intersect, vector to the light dir, vector to viewer V, and normal at point N. +static void reflected_at(object_t *o, color_t *dest, color_t *incolor, COORD_T intensity, vector_t *point, vector_t *dir, vector_t *V, vector_t *N) { // Calculate Deffuse part color_t tmp; - COORD_T cl = vector_dot(l, N) * i; + COORD_T cl = vector_dot(dir, N) * intensity; if (cl > 0) { - color_scale(&tmp, &light->color, cl * o->m->defuse); + color_scale(&tmp, incolor, cl * o->m->defuse); color_add(dest, &tmp, dest); } // 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); + vector_scale(&R, N, 2 * vector_dot(dir, N)); + vector_sub(&R, &R, dir); // Add it to the light - cl = vector_dot(&R, V) * i; + cl = vector_dot(&R, V) * intensity; if (cl > 0) { cl = pow(cl, o->m->shine); - color_scale(&tmp, &light->color, cl * o->m->specular); + color_scale(&tmp, incolor, cl * o->m->specular); color_add(dest, &tmp, dest); } } @@ -177,7 +175,7 @@ static void contribution_from_pointlight(space_t *s, color_t *dest, object_t *o, COORD_T d = vector_len(&l); // Normalice - vector_scale_inv(&l, &l, vector_len(&l)); + vector_norm(&l); // Find obstacles r.direction = &l; @@ -187,7 +185,8 @@ static void contribution_from_pointlight(space_t *s, color_t *dest, object_t *o, } // Calculate the reflected light - reflected_at(o, dest, light, d, point, &l, V, N); + COORD_T i = light->radiance / ( d * d); + reflected_at(o, dest, &light->color, i, point, &l, V, N); } // Many of these can maybe be put in a context struct @@ -206,7 +205,7 @@ static void contribution_from_arealight(space_t *s, color_t *dest, object_t *o, // Calculate vector from light to point vector_t l; vector_sub(&l, point, &light->area->sph.center); - vector_scale_inv(&l, &l, vector_len(&l)); + vector_norm(&l); // Initialize the transformation stuff csystem_t cs; @@ -241,8 +240,9 @@ static void contribution_from_arealight(space_t *s, color_t *dest, object_t *o, continue; } - // Add the light contribution, Not sure why it is scaled - reflected_at(o, &c, light, dist, point, &randpoint, V, N); + // Add the light contribution + COORD_T i = light->radiance / ( dist * dist); + reflected_at(o, &c, &light->color, i, point, &randpoint, V, N); } @@ -260,7 +260,7 @@ static void direct_light(space_t *s, color_t *dest, object_t *o, vector_t *N, ve vector_sub(&V, eye, point); // Normalice it - vector_scale_inv(&V, &V, vector_len(&V)); + vector_norm(&V); // Loop lights light_t *light = s->lights; @@ -348,8 +348,16 @@ static void global_light(space_t *s, color_t *dest, object_t *o, vector_t *N, ve // Value for accumilating colors color_t acc; color_set(&acc, 0, 0, 0); - - for (unsigned i = 0; i < s->gfx->globallight_samples; i++) { + + // Samples is lowered for every hop + unsigned samples; + if (hop < s->gfx->gl_opt_depth) { + samples = s->gfx->globallight_samples / (hop + 1); + } else { + samples = s->gfx->globallight_samples / (s->gfx->gl_opt_depth + 1); + } + + for (unsigned i = 0; i < samples; i++) { COORD_T r1 = ray_rand(seed); // Calculate the random direction vector @@ -361,15 +369,25 @@ static void global_light(space_t *s, color_t *dest, object_t *o, vector_t *N, ve // Check the direction for obstacles r.direction = &randdir; - - // Cast ray in direction if we have more hops - if (hop < s->gfx->depth) { - ray_trace_recur(s, &acc, &r, hop+1, r1, seed); + COORD_T cl = vector_dot(&randdir, N); + + // Only recurse if neccesary + if (cl > 0.01) { + // Cast ray in direction if we have more hops + color_t tmp; + color_set(&tmp, 0, 0, 0); + if (hop < s->gfx->depth) { + ray_trace_recur(s, &tmp, &r, hop+1, r1, seed); + } + + // Calculate Deffuse light + color_scale(&tmp, &tmp, cl * o->m->defuse); + color_add(&acc, &tmp, &acc); } } // Devide by number of samples and pdf - color_scale(&acc, &acc, ((COORD_T) 1/ s->gfx->globallight_samples) * (2 * PI)); + color_scale(&acc, &acc, ((COORD_T) 1/ samples) * (2 * PI)); // Add to dest color_add(dest, dest, &acc); @@ -378,15 +396,15 @@ static void global_light(space_t *s, color_t *dest, object_t *o, vector_t *N, ve int ray_trace_recur(space_t *s, color_t *dest, ray_t *ray, unsigned hop, COORD_T scale, void *seed) { COORD_T dist; - color_t c; - color_set(&c, 0, 0, 0); object_t *o = ray_cast(s, ray, &dist, false, 0); if (!o) { - color_add(&c, &c, &s->back); - goto exit; + return 1; } + color_t c; + color_set(&c, 0, 0, 0); + vector_t rdir, rstart; ray_t r = {.start = &rstart, .direction = &rdir}; @@ -406,6 +424,7 @@ int ray_trace_recur(space_t *s, color_t *dest, ray_t *ray, unsigned hop, COORD_T if (o->m->defuse + o->m->specular > ZERO_APROX) { // Add all light hitting o at r.start to c direct_light(s, &c, o, &N, ray->start, r.start, seed); + global_light(s, &c, o, &N, r.start, hop, seed); } // Calculate environmental light @@ -413,7 +432,6 @@ int ray_trace_recur(space_t *s, color_t *dest, ray_t *ray, unsigned hop, COORD_T env_light(s, &c, o, &N, r.start, seed); } - global_light(s, &c, o, &N, r.start, hop, seed); // Calculate reflection vector if (hop < 10 && o->m->reflective > ZERO_APROX) { @@ -459,7 +477,10 @@ void ray_trace(space_t *s, unsigned int x, unsigned int y, color_t *c, void *see viewpoint_ray(&s->view, r.direction, x + tmp, y + tmp); // Run the recursive ray trace - ray_trace_recur(s, &ctmp, &r, 0, 1, seed); + if (ray_trace_recur(s, &ctmp, &r, 0, 1, seed)) { + // Hit nothing add back + color_add(&ctmp, &ctmp, &s->back); + } // Color_add will not go above 1. In this case we don't want that. c->r += ctmp.r; c->g += ctmp.g; c->b += ctmp.b; diff --git a/scene.h b/scene.h index 738f143..e7ee95f 100644 --- a/scene.h +++ b/scene.h @@ -80,6 +80,7 @@ typedef struct { unsigned globallight_samples; unsigned depth; + unsigned gl_opt_depth; } settings_t; typedef struct { diff --git a/vector.c b/vector.c index 0bcd1dc..661516e 100644 --- a/vector.c +++ b/vector.c @@ -43,6 +43,17 @@ COORD_T vector_len(vector_t *v) return sqrt( v->x * v->x + v->y * v->y + v->z * v->z ); } +void vector_norm(vector_t *v) +{ + COORD_T len = vector_len(v); + if (len == 0) { + vector_set(v, 0, 0, 0); + return; + } + + vector_scale_inv(v, v, len); +} + vector_t *vector_add(vector_t *dest, vector_t *a, vector_t *b) { dest = vector_exists(dest); diff --git a/vector.h b/vector.h index 81b5df1..7e4dccb 100644 --- a/vector.h +++ b/vector.h @@ -18,6 +18,7 @@ vector_t *vector_copy(vector_t *dest, vector_t *src); // Calculate the length of v COORD_T vector_len(vector_t *v); +void vector_norm(vector_t *v); COORD_T vector_dot(vector_t *a, vector_t *b); -- cgit v1.2.3