diff --git a/src/camera.c b/src/camera.c index d225961..05f96d9 100644 --- a/src/camera.c +++ b/src/camera.c @@ -1,23 +1,46 @@ #include "camera.h" #include "ray.h" +#include "rng.h" #include #include +#define MAX_ITER 10 +#define MIN_T 1e-6 + static const vec3_t lightblue = { 0.4, 0.6, 1.0 }; static const vec3_t white = { 1.0, 1.0, 1.0 }; +static const vec3_t black = { 0.0, 0.0, 0.0 }; + +static ray_t scatter(hit_t hit) +{ + const vec3_t rand = rng_vec3(); + const vec3_t dir + = vec3_dot(rand, hit.normal) > 0.0 ? rand : vec3_scale(rand, -1.0); + return (ray_t) { .orig = hit.point, .dir = dir }; +} static vec3_t trace(ray_t ray, const obj_t *scene, unsigned scene_count) { - hit_t hit = { .t = DBL_MAX }; - for (unsigned i = 0; i < scene_count; ++i) - scene[i].intersect(scene[i].params, ray, &hit, 0.0, hit.t); - if (hit.t != DBL_MAX) - return vec3_scale(vec3_add(hit.normal, white), 0.5); + double coeff = 1.0; + for (unsigned i = 0; i < MAX_ITER; ++i) { + hit_t hit = { .t = DBL_MAX }; + for (unsigned j = 0; j < scene_count; ++j) + scene[j].intersect(scene[j].params, ray, &hit, MIN_T, hit.t); - const double a = (ray.dir.y + 1.0) / 2.0; - return vec3_add(vec3_scale(lightblue, a), vec3_scale(white, 1 - a)); + if (hit.t == DBL_MAX) { + const double a = (ray.dir.y + 1.0) / 2.0; + return vec3_scale( + vec3_add(vec3_scale(lightblue, a), vec3_scale(white, 1 - a)), + coeff); + } + + ray = scatter(hit); + coeff *= 0.5; + } + + return black; } static void setpix(vec3_t col, pix_t *out)