diff --git a/demo.c b/demo.c index cf04dd8..15bd1a5 100644 --- a/demo.c +++ b/demo.c @@ -1,27 +1,16 @@ #include "camera.h" #include "ff.h" #include "obj.h" -#include "ray.h" -#include "vec3.h" -#include -#include -#include -#include #include #define W 800 #define H 600 - #define FOCAL_LEN 1.0 #define VIEWPORT_H 2.0 #define NELEMS(arr) (sizeof(arr) / sizeof(arr[0])) -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 red = { 1.0, 0.1, 0.2 }; - static const vec3_t camera_pos = { 0.0, 0.0, 0.0 }; static const obj_t scene[] = { @@ -32,54 +21,11 @@ static const obj_t scene[] = { static pix_t pixbuf[W * H]; -static vec3_t raycol(ray_t ray) -{ - bool got_hit = false; - hit_t hit = { .t = DBL_MAX }; - for (unsigned i = 0; i < NELEMS(scene); ++i) { - if (scene[i].intersect(scene[i].params, ray, &hit, 0.0, hit.t)) - got_hit = true; - } - if (got_hit) - return vec3_scale(vec3_add(hit.normal, white), 0.5); - - const double a = (ray.dir.y + 1.0) / 2.0; - return vec3_add(vec3_scale(lightblue, a), vec3_scale(white, 1 - a)); -} - -static void setpix(vec3_t col, pix_t *out) -{ - out->r = UINT16_MAX * col.x; - out->g = UINT16_MAX * col.y; - out->b = UINT16_MAX * col.z; - out->a = UINT16_MAX; -} - int main() { - img_t img = { .w = W, .h = H, .pix = pixbuf }; + img_t img = { .pix = pixbuf }; camera_t camera = camera_init(camera_pos, FOCAL_LEN, VIEWPORT_H, W, H); - - for (unsigned y = 0; y < H; ++y) { - fprintf(stderr, "\r[%3d/%3d]", y, H); - fflush(stderr); - - const vec3_t row - = vec3_add(camera.pix_origin, vec3_scale(camera.y_step, y)); - for (unsigned x = 0; x < W; ++x) { - const vec3_t pix = vec3_add(row, vec3_scale(camera.x_step, x)); - const ray_t ray = { - .orig = camera.pos, - .dir = vec3_unit(pix), - }; - const vec3_t col = raycol(ray); - setpix(col, img.pix + (W * y + x)); - } - } - - fprintf(stderr, "\r[%3d/%3d]\n", H, H); - + camera_render(&camera, scene, NELEMS(scene), &img); ff_write(STDOUT_FILENO, img); - return 0; } diff --git a/include/camera.h b/include/camera.h index c4d6e0c..cf434f5 100644 --- a/include/camera.h +++ b/include/camera.h @@ -1,6 +1,8 @@ #ifndef CAMERA_H #define CAMERA_H +#include "img.h" +#include "obj.h" #include "vec3.h" #include @@ -8,10 +10,15 @@ typedef struct { vec3_t pos; vec3_t pix_origin, x_step, y_step; + uint32_t img_width, img_height; } camera_t; camera_t camera_init( vec3_t pos, double focal_len, double viewport_height, uint32_t img_width, uint32_t img_height); +void camera_render( + const camera_t *camera, const obj_t *scene, unsigned scene_count, + img_t *img_out); + #endif diff --git a/src/camera.c b/src/camera.c index dbd200b..c9c9047 100644 --- a/src/camera.c +++ b/src/camera.c @@ -1,5 +1,36 @@ #include "camera.h" +#include "ray.h" + +#include +#include + +static const vec3_t lightblue = { 0.4, 0.6, 1.0 }; +static const vec3_t white = { 1.0, 1.0, 1.0 }; + +static vec3_t trace(ray_t ray, const obj_t *scene, unsigned scene_count) +{ + bool got_hit = false; + hit_t hit = { .t = DBL_MAX }; + for (unsigned i = 0; i < scene_count; ++i) { + if (scene[i].intersect(scene[i].params, ray, &hit, 0.0, hit.t)) + got_hit = true; + } + if (got_hit) + return vec3_scale(vec3_add(hit.normal, white), 0.5); + + const double a = (ray.dir.y + 1.0) / 2.0; + return vec3_add(vec3_scale(lightblue, a), vec3_scale(white, 1 - a)); +} + +static void setpix(vec3_t col, pix_t *out) +{ + out->r = UINT16_MAX * col.x; + out->g = UINT16_MAX * col.y; + out->b = UINT16_MAX * col.z; + out->a = UINT16_MAX; +} + camera_t camera_init( vec3_t pos, double focal_len, double viewport_height, uint32_t img_width, uint32_t img_height) @@ -22,5 +53,34 @@ camera_t camera_init( .pix_origin = pix_origin, .x_step = x_step, .y_step = y_step, + .img_width = img_width, + .img_height = img_height, }; } + +void camera_render( + const camera_t *camera, const obj_t *scene, unsigned scene_count, + img_t *img_out) +{ + const uint32_t w = img_out->w = camera->img_width; + const uint32_t h = img_out->h = camera->img_height; + + for (unsigned y = 0; y < h; ++y) { + fprintf(stderr, "\r[%3d/%3d]", y, h); + fflush(stderr); + + const vec3_t row + = vec3_add(camera->pix_origin, vec3_scale(camera->y_step, y)); + for (unsigned x = 0; x < w; ++x) { + const vec3_t pix = vec3_add(row, vec3_scale(camera->x_step, x)); + const ray_t ray = { + .orig = camera->pos, + .dir = vec3_unit(pix), + }; + const vec3_t col = trace(ray, scene, scene_count); + setpix(col, img_out->pix + (w * y + x)); + } + } + + fprintf(stderr, "\r[%3d/%3d]\n", h, h); +}