diff options
author | Vito Caputo <vcaputo@pengaru.com> | 2018-03-19 21:39:09 -0700 |
---|---|---|
committer | Vito Caputo <vcaputo@pengaru.com> | 2018-03-19 22:02:08 -0700 |
commit | b5bc962e834992eeba2abdd10f6e37ee2ba20295 (patch) | |
tree | 11bf58a64208806817c0fcab481588086297ce6c /src/libs/ray/ray_camera.c | |
parent | 3b9a4861d6937a66b03791b5b497e47c52189a7d (diff) |
ray: libize raytracer core, introduces src/libs
This is the first step of breaking out all the core rendering stuffs
into reusable libraries and making modules purely compositional,
consumers of various included rendering/effects libraries.
Expect multiple modules leveraging libray for a variety of scenes and
such. Also expect compositions mixing the various libraries for more
interesting visuals.
Diffstat (limited to 'src/libs/ray/ray_camera.c')
-rw-r--r-- | src/libs/ray/ray_camera.c | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/src/libs/ray/ray_camera.c b/src/libs/ray/ray_camera.c new file mode 100644 index 0000000..b942cf3 --- /dev/null +++ b/src/libs/ray/ray_camera.c @@ -0,0 +1,70 @@ +#include "fb.h" + +#include "ray_camera.h" +#include "ray_euler.h" + + +/* Produce a vector from the provided orientation vectors and proportions. */ +static ray_3f_t project_corner(ray_3f_t *forward, ray_3f_t *left, ray_3f_t *up, float focal_length, float horiz, float vert) +{ + ray_3f_t tmp; + ray_3f_t corner; + + corner = ray_3f_mult_scalar(forward, focal_length); + tmp = ray_3f_mult_scalar(left, horiz); + corner = ray_3f_add(&corner, &tmp); + tmp = ray_3f_mult_scalar(up, vert); + corner = ray_3f_add(&corner, &tmp); + + return ray_3f_normalize(&corner); +} + + +/* Produce vectors for the corners of the entire camera frame, used for interpolation. */ +static void project_corners(const ray_camera_t *camera, ray_camera_frame_t *frame) +{ + ray_3f_t forward, left, up, right, down; + float half_horiz = (float)camera->width * 0.5f; + float half_vert = (float)camera->height * 0.5f; + + ray_euler_basis(&camera->orientation, &forward, &up, &left); + right = ray_3f_negate(&left); + down = ray_3f_negate(&up); + + frame->nw = project_corner(&forward, &left, &up, camera->focal_length, half_horiz, half_vert); + frame->ne = project_corner(&forward, &right, &up, camera->focal_length, half_horiz, half_vert); + frame->se = project_corner(&forward, &right, &down, camera->focal_length, half_horiz, half_vert); + frame->sw = project_corner(&forward, &left, &down, camera->focal_length, half_horiz, half_vert); +} + + +/* Prepare a frame of camera projection, initializing res_frame. */ +void ray_camera_frame_prepare(const ray_camera_t *camera, ray_camera_frame_t *res_frame) +{ + res_frame->camera = camera; + + project_corners(camera, res_frame); + + res_frame->x_delta = 1.0f / (float)camera->width; + res_frame->y_delta = 1.0f / (float)camera->height; +} + + +/* Begin a frame's fragment, initializing frame and ray. */ +void ray_camera_fragment_begin(ray_camera_frame_t *frame, fb_fragment_t *fb_fragment, ray_ray_t *res_ray, ray_camera_fragment_t *res_fragment) +{ + res_fragment->frame = frame; + res_fragment->fb_fragment = fb_fragment; + res_fragment->ray = res_ray; + + res_fragment->x = res_fragment->y = 0; + + res_fragment->x_alpha = frame->x_delta * (float)fb_fragment->x; + res_fragment->y_alpha = frame->y_delta * (float)fb_fragment->y; + + res_fragment->cur_w = ray_3f_lerp(&frame->nw, &frame->sw, res_fragment->y_alpha); + res_fragment->cur_e = ray_3f_lerp(&frame->ne, &frame->se, res_fragment->y_alpha); + + res_ray->origin = frame->camera->position; + res_ray->direction = ray_3f_nlerp(&res_fragment->cur_w, &res_fragment->cur_e, res_fragment->x_alpha); +} |