aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ctranslate.c41
-rw-r--r--ctranslate.h30
-rw-r--r--ray.c69
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
diff --git a/ray.c b/ray.c
index 465b154..3932f23 100644
--- a/ray.c
+++ b/ray.c
@@ -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