diff options
-rw-r--r-- | ctranslate.c | 41 | ||||
-rw-r--r-- | ctranslate.h | 30 | ||||
-rw-r--r-- | ray.c | 69 |
3 files changed, 111 insertions, 29 deletions
diff --git a/ctranslate.c b/ctranslate.c new file mode 100644 index 0000000..f7dfe64 --- /dev/null +++ b/ctranslate.c @@ -0,0 +1,41 @@ +#include "ctranslate.h" + +#include <math.h> + +// TODO remove dublicate pi definitions +#define PI 3.14159265359 + +void csystem_init(csystem_t *cs, vector_t *up) +{ + cs->up = 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) { + 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)); + + // Create the 3. axis by taking the cross of the other + vector_cross(&cs->az, up, &cs->ax); +} + +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, + 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); +} + +void csystem_hemisphere_random(csystem_t *cs, COORD_T r1, COORD_T r2, vector_t *out) +{ + COORD_T sinTheta = sqrt(1 - r1 * r1); + COORD_T phi = 2 * PI * r2; + + // Calculate the random direction vector + vector_set(out, sinTheta * cos(phi), r1, sinTheta * sin(phi)); +} + diff --git a/ctranslate.h b/ctranslate.h new file mode 100644 index 0000000..a2cc9b2 --- /dev/null +++ b/ctranslate.h @@ -0,0 +1,30 @@ +#ifndef CTRANS_H +#define CTRANS_H + +#include "vector.h" + +// Used to create a sort of "virtual" coordinate system where up is defined by a given vector +// Implemented from https://www.scratchapixel.com/lessons/3d-basic-rendering/global-illumination-path-tracing/global-illumination-path-tracing-practical-implementation +// These methods assume y is up + +typedef struct { + vector_t *up; + + // These are calculated from the given up vector + vector_t ax; + vector_t az; +} csystem_t; + +// Inits the given csystem_t with a given up vector. +// Will overwrite everything in cs +void csystem_init(csystem_t *cs, vector_t *up); + +// Translates the inside coordinates to real and saves them in real. +// Will overwrite real +void csystem_calc_real(csystem_t *cs, vector_t *inside, vector_t *real); + +// Writes the inside coordinates of a random direction in the upper hemisphere, and saves in out +// One must provide random numbers r1 and r2 between 0 and 1 +void csystem_hemisphere_random(csystem_t *cs, COORD_T r1, COORD_T r2, vector_t *out); + +#endif @@ -1,7 +1,9 @@ #include <stdio.h> #include <math.h> #include <stdlib.h> +#include <assert.h> #include "vector.h" +#include "ctranslate.h" #include "ray.h" @@ -186,7 +188,35 @@ static void contribution_from_pointlight(space_t *s, color_t *dest, object_t *o, reflected_at(o, dest, light, d, point, &l, V, N); } -static void direct_light(space_t *s, color_t *dest, object_t *o, vector_t *N, vector_t *eye, vector_t *point) +// Many of these can maybe be put in a context struct +static void contribution_from_arealight(space_t *s, color_t *dest, object_t *o, light_t *light, vector_t *point, vector_t *V, vector_t *N, void *seed) +{ + // This only works with spheres + assert(o->type == TYPE_SPHERE); + + // Color to collect temporary results in + color_t c; + + ray_t ray; + ray.start = point; + + // Do the same monte carlo as with environment but the starting point is the center of the circle. + // And the result is a point on the circle + for (int i = 0; i < 16; i++) { + // Do the monte carlo random distribution thing from the article + COORD_T r1 = ray_rand(seed); + COORD_T r2 = ray_rand(seed); + + COORD_T sinTheta = sqrt(1 - r1 * r1); + COORD_T phi = 2 * PI * r2; + + // Cast a ray + + } + +} + +static void direct_light(space_t *s, color_t *dest, object_t *o, vector_t *N, vector_t *eye, vector_t *point, void *seed) { // And vector towards viewer vector_t V; @@ -209,21 +239,9 @@ static void direct_light(space_t *s, color_t *dest, object_t *o, vector_t *N, ve // https://www.scratchapixel.com/lessons/3d-basic-rendering/global-illumination-path-tracing/global-illumination-path-tracing-practical-implementation static void env_light(space_t *s, color_t *dest, object_t *o, vector_t *N, vector_t *point, void *seed) { - // 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 - vector_t Nt; - if (N->x > N->y) { - vector_set(&Nt, N->z, 0, -N->x); - } else { - vector_set(&Nt, 0, -N->z, N->y); - } - // Normalice - vector_scale_inv(&Nt, &Nt, vector_len(&Nt)); - - // Create the 3. axis by taking the cross of the other - vector_t Nb; - vector_cross(&Nb, N, &Nt); - + csystem_t cs; + csystem_init(&cs, N); + // Prepare ray ray_t r; r.start = point; @@ -233,21 +251,14 @@ static void env_light(space_t *s, color_t *dest, object_t *o, vector_t *N, vecto color_set(&acc, 0, 0, 0); for (unsigned i = 0; i < s->env_samples; i++) { - // Do the monte carlo random distribution thing from the article COORD_T r1 = ray_rand(seed); - COORD_T r2 = ray_rand(seed); - - COORD_T sinTheta = sqrt(1 - r1 * r1); - COORD_T phi = 2 * PI * r2; - + // // Calculate the random direction vector vector_t randdir; - vector_set(&randdir, sinTheta * cos(phi), r1, sinTheta * sin(phi)); + csystem_hemisphere_random(&cs, r1, ray_rand(seed), &randdir); // Convert to world cordinates using the calculated N vectors. - vector_set(&randdir, randdir.x * Nb.x + randdir.y * N->x + randdir.z * Nt.x, - randdir.x * Nb.y + randdir.y * N->y + randdir.z * Nt.y, - randdir.x * Nb.z + randdir.y * N->z + randdir.z * Nt.z); + csystem_calc_real(&cs, &randdir, &randdir); // Check the direction for obstacles r.direction = &randdir; @@ -261,7 +272,7 @@ static void env_light(space_t *s, color_t *dest, object_t *o, vector_t *N, vecto color_t tmp; color_scale(&tmp, &s->env_color, r1); - acc.r += tmp.r; acc.g += tmp.g; acc.b += tmp.b; + color_add(&acc, &acc, &tmp); } // Devide by number of samples and pdf @@ -285,7 +296,7 @@ int ray_trace_recur(space_t *s, color_t *dest, ray_t *ray, unsigned hop, COORD_T } vector_t rdir, rstart; - ray_t r = {start: &rstart, direction: &rdir}; + ray_t r = {.start = &rstart, .direction = &rdir}; vector_scale(r.start, ray->direction, dist); vector_add(r.start, r.start, ray->start); @@ -302,7 +313,7 @@ int ray_trace_recur(space_t *s, color_t *dest, ray_t *ray, unsigned hop, COORD_T // 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 - direct_light(s, &c, o, &N, ray->start, r.start); + direct_light(s, &c, o, &N, ray->start, r.start, seed); } // Calculate environmental light |