diff options
author | Vito Caputo <vcaputo@gnugeneration.com> | 2017-01-18 17:14:52 -0800 |
---|---|---|
committer | Vito Caputo <vcaputo@gnugeneration.com> | 2017-01-18 17:31:44 -0800 |
commit | 524db0cf19648e3c7c78d3e73103b7a0bdcd6bfc (patch) | |
tree | 6fd682629904a210927797c92d956c208666b03a /modules/ray | |
parent | ee2073d4e411555aba878277131b56f7eb562c84 (diff) |
*: move source into src/ subdir
Restoring some organizational sanity since adopting autotools.
Diffstat (limited to 'modules/ray')
-rw-r--r-- | modules/ray/Makefile.am | 4 | ||||
-rw-r--r-- | modules/ray/ray.c | 161 | ||||
-rw-r--r-- | modules/ray/ray.h | 8 | ||||
-rw-r--r-- | modules/ray/ray_3f.h | 161 | ||||
-rw-r--r-- | modules/ray/ray_camera.c | 85 | ||||
-rw-r--r-- | modules/ray/ray_camera.h | 77 | ||||
-rw-r--r-- | modules/ray/ray_color.h | 29 | ||||
-rw-r--r-- | modules/ray/ray_euler.h | 45 | ||||
-rw-r--r-- | modules/ray/ray_light_emitter.h | 18 | ||||
-rw-r--r-- | modules/ray/ray_object.c | 74 | ||||
-rw-r--r-- | modules/ray/ray_object.h | 24 | ||||
-rw-r--r-- | modules/ray/ray_object_light.h | 67 | ||||
-rw-r--r-- | modules/ray/ray_object_plane.h | 46 | ||||
-rw-r--r-- | modules/ray/ray_object_point.h | 37 | ||||
-rw-r--r-- | modules/ray/ray_object_sphere.h | 65 | ||||
-rw-r--r-- | modules/ray/ray_object_type.h | 11 | ||||
-rw-r--r-- | modules/ray/ray_ray.h | 11 | ||||
-rw-r--r-- | modules/ray/ray_scene.c | 188 | ||||
-rw-r--r-- | modules/ray/ray_scene.h | 27 | ||||
-rw-r--r-- | modules/ray/ray_surface.h | 14 | ||||
-rw-r--r-- | modules/ray/ray_threads.c | 111 | ||||
-rw-r--r-- | modules/ray/ray_threads.h | 30 |
22 files changed, 0 insertions, 1293 deletions
diff --git a/modules/ray/Makefile.am b/modules/ray/Makefile.am deleted file mode 100644 index a0b3fbb..0000000 --- a/modules/ray/Makefile.am +++ /dev/null @@ -1,4 +0,0 @@ -noinst_LIBRARIES = libray.a -libray_a_SOURCES = ray_3f.h ray.c ray_camera.c ray_camera.h ray_color.h ray_euler.h ray.h ray_light_emitter.h ray_object.c ray_object.h ray_object_light.h ray_object_plane.h ray_object_point.h ray_object_sphere.h ray_object_type.h ray_ray.h ray_scene.c ray_scene.h ray_surface.h ray_threads.c ray_threads.h -libray_a_CFLAGS = @ROTOTILLER_CFLAGS@ -ffast-math -libray_a_CPPFLAGS = @ROTOTILLER_CFLAGS@ -I../../ diff --git a/modules/ray/ray.c b/modules/ray/ray.c deleted file mode 100644 index 60d08cf..0000000 --- a/modules/ray/ray.c +++ /dev/null @@ -1,161 +0,0 @@ -#include <stdint.h> -#include <inttypes.h> -#include <math.h> - -#include "fb.h" -#include "rototiller.h" -#include "util.h" - -#include "ray_camera.h" -#include "ray_object.h" -#include "ray_scene.h" -#include "ray_threads.h" - -/* Copyright (C) 2016 Vito Caputo <vcaputo@pengaru.com> */ - -/* ray trace a simple scene into the fragment */ -static void ray(fb_fragment_t *fragment) -{ - static ray_object_t objects[] = { - { - .plane = { - .type = RAY_OBJECT_TYPE_PLANE, - .surface = { - .color = { .x = 0.4, .y = 0.2, .z = 0.5 }, - .diffuse = 1.0f, - .specular = 0.2f, - }, - .normal = { .x = 0.0, .y = 1.0, .z = 0.0 }, - .distance = -3.2f, - } - }, { - .sphere = { - .type = RAY_OBJECT_TYPE_SPHERE, - .surface = { - .color = { .x = 1.0, .y = 0.0, .z = 0.0 }, - .diffuse = 1.0f, - .specular = 0.05f, - }, - .center = { .x = 0.5, .y = 1.0, .z = 0.0 }, - .radius = 1.2f, - } - }, { - .sphere = { - .type = RAY_OBJECT_TYPE_SPHERE, - .surface = { - .color = { .x = 0.0, .y = 0.0, .z = 1.0 }, - .diffuse = 1.0f, - .specular = 1.0f, - }, - .center = { .x = -2.0, .y = 1.0, .z = 0.0 }, - .radius = 0.9f, - } - }, { - .sphere = { - .type = RAY_OBJECT_TYPE_SPHERE, - .surface = { - .color = { .x = 0.0, .y = 1.0, .z = 1.0 }, - .diffuse = 1.0f, - .specular = 1.0f, - }, - .center = { .x = 2.0, .y = -1.0, .z = 0.0 }, - .radius = 1.0f, - } - }, { - .sphere = { - .type = RAY_OBJECT_TYPE_SPHERE, - .surface = { - .color = { .x = 0.0, .y = 1.0, .z = 0.0 }, - .diffuse = 1.0f, - .specular = 1.0f, - }, - .center = { .x = 0.2, .y = -1.25, .z = 0.0 }, - .radius = 0.6f, - } - }, { - .light = { - .type = RAY_OBJECT_TYPE_LIGHT, - .brightness = 1.0, - .emitter = { - .point.type = RAY_LIGHT_EMITTER_TYPE_POINT, - .point.center = { .x = 3.0f, .y = 3.0f, .z = 3.0f }, - .point.surface = { - .color = { .x = 1.0f, .y = 1.0f, .z = 1.0f }, - }, - } - } - } - }; - - ray_camera_t camera = { - .position = { .x = 0.0, .y = 0.0, .z = 6.0 }, - .orientation = { - .yaw = RAY_EULER_DEGREES(0.0f), - .pitch = RAY_EULER_DEGREES(0.0f), - .roll = RAY_EULER_DEGREES(180.0f), - }, - .focal_length = 700.0f, - .width = fragment->width, - .height = fragment->height, - }; - - static ray_scene_t scene = { - .objects = objects, - .n_objects = nelems(objects), - .lights = &objects[5], - .n_lights = 1, - .ambient_color = { .x = 1.0f, .y = 1.0f, .z = 1.0f }, - .ambient_brightness = .04f, - }; - static int initialized; - static ray_threads_t *threads; - static fb_fragment_t *fragments; - static unsigned ncpus; -#if 1 - /* animated point light source */ - static double r; - - r += .02; - - scene.lights[0].light.emitter.point.center.x = cosf(r) * 3.5f; - scene.lights[0].light.emitter.point.center.z = sinf(r) * 3.5f; - camera.orientation.yaw = sinf(r) / 4; - camera.orientation.pitch = sinf(r * 10) / 100; - camera.orientation.roll = RAY_EULER_DEGREES(180.0f) + cosf(r) / 10; - camera.position.x = cosf(r) / 10; - camera.position.z = 4.0f + sinf(r) / 10; -#endif - - if (!initialized) { - initialized = 1; - ncpus = get_ncpus(); - - if (ncpus > 1) { - threads = ray_threads_create(ncpus - 1); - fragments = malloc(sizeof(fb_fragment_t) * ncpus); - } - } - - if (ncpus > 1) { - /* Always recompute the fragments[] geometry. - * This way the fragment geometry can change at any moment and things will - * continue functioning, which may prove important later on. - * (imagine things like a preview window, or perhaps composite modules - * which call on other modules supplying virtual fragments of varying dimensions..) - */ - fb_fragment_divide(fragment, ncpus, fragments); - } else { - fragments = fragment; - } - - ray_scene_render_fragments(&scene, &camera, threads, fragments); -} - - -rototiller_renderer_t ray_renderer = { - .render = ray, - .name = "ray", - .description = "Multi-threaded ray tracer", - .author = "Vito Caputo <vcaputo@pengaru.com>", - .license = "GPLv2", -}; diff --git a/modules/ray/ray.h b/modules/ray/ray.h deleted file mode 100644 index d33f96a..0000000 --- a/modules/ray/ray.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef _RAY_RAY_H -#define _RAY_RAY_H - -#include "fb.h" - -void ray(fb_fragment_t *fragment); - -#endif diff --git a/modules/ray/ray_3f.h b/modules/ray/ray_3f.h deleted file mode 100644 index 8408abb..0000000 --- a/modules/ray/ray_3f.h +++ /dev/null @@ -1,161 +0,0 @@ -#ifndef _RAY_3F_H -#define _RAY_3F_H - -#include <math.h> - -typedef struct ray_3f_t { - float x, y, z; -} ray_3f_t; - - -/* return the result of (a + b) */ -static inline ray_3f_t ray_3f_add(ray_3f_t *a, ray_3f_t *b) -{ - ray_3f_t res = { - .x = a->x + b->x, - .y = a->y + b->y, - .z = a->z + b->z, - }; - - return res; -} - - -/* return the result of (a - b) */ -static inline ray_3f_t ray_3f_sub(ray_3f_t *a, ray_3f_t *b) -{ - ray_3f_t res = { - .x = a->x - b->x, - .y = a->y - b->y, - .z = a->z - b->z, - }; - - return res; -} - - -/* return the result of (-v) */ -static inline ray_3f_t ray_3f_negate(ray_3f_t *v) -{ - ray_3f_t res = { - .x = -v->x, - .y = -v->y, - .z = -v->z, - }; - - return res; -} - - -/* return the result of (a * b) */ -static inline ray_3f_t ray_3f_mult(ray_3f_t *a, ray_3f_t *b) -{ - ray_3f_t res = { - .x = a->x * b->x, - .y = a->y * b->y, - .z = a->z * b->z, - }; - - return res; -} - - -/* return the result of (v * scalar) */ -static inline ray_3f_t ray_3f_mult_scalar(ray_3f_t *v, float scalar) -{ - ray_3f_t res = { - .x = v->x * scalar, - .y = v->y * scalar, - .z = v->z * scalar, - }; - - return res; -} - - -/* return the result of (uv / scalar) */ -static inline ray_3f_t ray_3f_div_scalar(ray_3f_t *v, float scalar) -{ - ray_3f_t res = { - .x = v->x / scalar, - .y = v->y / scalar, - .z = v->z / scalar, - }; - - return res; -} - - -/* return the result of (a . b) */ -static inline float ray_3f_dot(ray_3f_t *a, ray_3f_t *b) -{ - return a->x * b->x + a->y * b->y + a->z * b->z; -} - - -/* return the length of the supplied vector */ -static inline float ray_3f_length(ray_3f_t *v) -{ - return sqrtf(ray_3f_dot(v, v)); -} - - -/* return the normalized form of the supplied vector */ -static inline ray_3f_t ray_3f_normalize(ray_3f_t *v) -{ - ray_3f_t nv; - float f; - - f = 1.0f / ray_3f_length(v); - - nv.x = f * v->x; - nv.y = f * v->y; - nv.z = f * v->z; - - return nv; -} - - -/* return the distance between two arbitrary points */ -static inline float ray_3f_distance(ray_3f_t *a, ray_3f_t *b) -{ - return sqrtf(powf(a->x - b->x, 2) + powf(a->y - b->y, 2) + powf(a->z - b->z, 2)); -} - - -/* return the cross product of two unit vectors */ -static inline ray_3f_t ray_3f_cross(ray_3f_t *a, ray_3f_t *b) -{ - ray_3f_t product; - - product.x = a->y * b->z - a->z * b->y; - product.y = a->z * b->x - a->x * b->z; - product.z = a->x * b->y - a->y * b->x; - - return product; -} - - -/* return the linearly interpolated vector between the two vectors at point alpha (0-1.0) */ -static inline ray_3f_t ray_3f_lerp(ray_3f_t *a, ray_3f_t *b, float alpha) -{ - ray_3f_t lerp_a, lerp_b; - - lerp_a = ray_3f_mult_scalar(a, 1.0f - alpha); - lerp_b = ray_3f_mult_scalar(b, alpha); - - return ray_3f_add(&lerp_a, &lerp_b); -} - - -/* return the normalized linearly interpolated vector between the two vectors at point alpha (0-1.0) */ -static inline ray_3f_t ray_3f_nlerp(ray_3f_t *a, ray_3f_t *b, float alpha) -{ - ray_3f_t lerp; - - lerp = ray_3f_lerp(a, b, alpha); - - return ray_3f_normalize(&lerp); -} - -#endif diff --git a/modules/ray/ray_camera.c b/modules/ray/ray_camera.c deleted file mode 100644 index 0703c2e..0000000 --- a/modules/ray/ray_camera.c +++ /dev/null @@ -1,85 +0,0 @@ -#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(ray_camera_t *camera, ray_camera_frame_t *frame) -{ - ray_3f_t forward, left, up, right, down; - float half_horiz = (float)camera->width / 2.0f; - float half_vert = (float)camera->height / 2.0f; - - 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); -} - - -/* Begin a frame for the fragment of camera projection, initializing frame and ray. */ -void ray_camera_frame_begin(ray_camera_t *camera, fb_fragment_t *fragment, ray_ray_t *ray, ray_camera_frame_t *frame) -{ - /* References are kept to the camera, fragment, and ray to be traced. - * The ray is maintained as we step through the frame, that is the - * purpose of this api. - * - * Since the ray direction should be a normalized vector, the obvious - * implementation is a bit costly. The camera frame api hides this - * detail so we can explore interpolation techniques to potentially - * lessen the per-pixel cost. - */ - frame->camera = camera; - frame->fragment = fragment; - frame->ray = ray; - - frame->x = frame->y = 0; - - /* From camera->orientation and camera->focal_length compute the vectors - * through the viewport's corners, and place these normalized vectors - * in frame->(nw,ne,sw,se). - * - * These can than be interpolated between to produce the ray vectors - * throughout the frame's fragment. The efficient option of linear - * interpolation will not maintain the unit vector length, so to - * produce normalized interpolated directions will require the costly - * normalize function. - * - * I'm hoping a simple length correction table can be used to fixup the - * linearly interpolated vectors to make them unit vectors with just - * scalar multiplication instead of the sqrt of normalize. - */ - project_corners(camera, frame); - - frame->x_delta = 1.0f / (float)camera->width; - frame->y_delta = 1.0f / (float)camera->height; - frame->x_alpha = frame->x_delta * (float)fragment->x; - frame->y_alpha = frame->y_delta * (float)fragment->y; - - frame->cur_w = ray_3f_nlerp(&frame->nw, &frame->sw, frame->y_alpha); - frame->cur_e = ray_3f_nlerp(&frame->ne, &frame->se, frame->y_alpha); - - ray->origin = camera->position; - ray->direction = frame->cur_w; -} diff --git a/modules/ray/ray_camera.h b/modules/ray/ray_camera.h deleted file mode 100644 index 387f8c5..0000000 --- a/modules/ray/ray_camera.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef _RAY_CAMERA_H -#define _RAY_CAMERA_H - -#include <math.h> - -#include "fb.h" - -#include "ray_3f.h" -#include "ray_euler.h" -#include "ray_ray.h" - - -typedef struct ray_camera_t { - ray_3f_t position; /* position of camera, the origin of all its rays */ - ray_euler_t orientation; /* orientation of the camera */ - float focal_length; /* controls the field of view */ - unsigned width; /* width of camera viewport in pixels */ - unsigned height; /* height of camera viewport in pixels */ -} ray_camera_t; - - -typedef struct ray_camera_frame_t { - ray_camera_t *camera; /* the camera supplied to frame_begin() */ - fb_fragment_t *fragment; /* the fragment supplied to frame_begin() */ - ray_ray_t *ray; /* the ray supplied to frame_begin(), which gets updated as we step through the frame. */ - - ray_3f_t nw, ne, sw, se; /* directions pointing through the corners of the frame fragment */ - ray_3f_t cur_w, cur_e; /* current row's west and east ends */ - float x_alpha, y_alpha; /* interpolation position along the x and y axis */ - float x_delta, y_delta; /* interpolation step delta along the x and y axis */ - unsigned x, y; /* integral position within frame fragment */ -} ray_camera_frame_t; - - -void ray_camera_frame_begin(ray_camera_t *camera, fb_fragment_t *fragment, ray_ray_t *ray, ray_camera_frame_t *frame); - - -/* Step the ray through the frame on the x axis, returns 1 when rays remain on this axis, 0 at the end. */ -/* When 1 is returned, frame->ray is left pointing through the new coordinate. */ -static inline int ray_camera_frame_x_step(ray_camera_frame_t *frame) -{ - frame->x++; - - if (frame->x >= frame->fragment->width) { - frame->x = 0; - frame->x_alpha = frame->x_delta * (float)frame->fragment->x; - return 0; - } - - frame->x_alpha += frame->x_delta; - frame->ray->direction = ray_3f_nlerp(&frame->cur_w, &frame->cur_e, frame->x_alpha); - - return 1; -} - - -/* Step the ray through the frame on the y axis, returns 1 when rays remain on this axis, 0 at the end. */ -/* When 1 is returned, frame->ray is left pointing through the new coordinate. */ -static inline int ray_camera_frame_y_step(ray_camera_frame_t *frame) -{ - frame->y++; - - if (frame->y >= frame->fragment->height) { - frame->y = 0; - frame->y_alpha = frame->y_delta * (float)frame->fragment->y; - return 0; - } - - frame->y_alpha += frame->y_delta; - frame->cur_w = ray_3f_nlerp(&frame->nw, &frame->sw, frame->y_alpha); - frame->cur_e = ray_3f_nlerp(&frame->ne, &frame->se, frame->y_alpha); - frame->ray->direction = frame->cur_w; - - return 1; -} - -#endif diff --git a/modules/ray/ray_color.h b/modules/ray/ray_color.h deleted file mode 100644 index 9fe62c1..0000000 --- a/modules/ray/ray_color.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef _RAY_COLOR_H -#define _RAY_COLOR_H - -#include <stdint.h> - -#include "ray_3f.h" - -typedef ray_3f_t ray_color_t; - -/* convert a vector into a packed, 32-bit rgb pixel value */ -static inline uint32_t ray_color_to_uint32_rgb(ray_color_t color) { - uint32_t pixel; - - /* doing this all per-pixel, ugh. */ - - if (color.x > 1.0f) color.x = 1.0f; - if (color.y > 1.0f) color.y = 1.0f; - if (color.z > 1.0f) color.z = 1.0f; - - pixel = (uint32_t)(color.x * 255.0f); - pixel <<= 8; - pixel |= (uint32_t)(color.y * 255.0f); - pixel <<= 8; - pixel |= (uint32_t)(color.z * 255.0f); - - return pixel; -} - -#endif diff --git a/modules/ray/ray_euler.h b/modules/ray/ray_euler.h deleted file mode 100644 index 86f5221..0000000 --- a/modules/ray/ray_euler.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef _RAY_EULER_H -#define _RAY_EULER_H - -#include <math.h> - -#include "ray_3f.h" - - -/* euler angles are convenient for describing orientation */ -typedef struct ray_euler_t { - float pitch; /* pitch in radiasn */ - float yaw; /* yaw in radians */ - float roll; /* roll in radians */ -} ray_euler_t; - - -/* convenience macro for converting degrees to radians */ -#define RAY_EULER_DEGREES(_deg) \ - (_deg * (2 * M_PI / 360.0f)) - - -/* produce basis vectors from euler angles */ -static inline void ray_euler_basis(ray_euler_t *e, ray_3f_t *forward, ray_3f_t *up, ray_3f_t *left) -{ - float cos_yaw = cosf(e->yaw); - float sin_yaw = sinf(e->yaw); - float cos_roll = cosf(e->roll); - float sin_roll = sinf(e->roll); - float cos_pitch = cosf(e->pitch); - float sin_pitch = sinf(e->pitch); - - forward->x = sin_yaw; - forward->y = -sin_pitch * cos_yaw; - forward->z = cos_pitch * cos_yaw; - - up->x = -cos_yaw * sin_roll; - up->y = -sin_pitch * sin_yaw * sin_roll + cos_pitch * cos_roll; - up->z = cos_pitch * sin_yaw * sin_roll + sin_pitch * cos_roll; - - left->x = cos_yaw * cos_roll; - left->y = sin_pitch * sin_yaw * cos_roll + cos_pitch * sin_roll; - left->z = -cos_pitch * sin_yaw * cos_roll + sin_pitch * sin_roll; -} - -#endif diff --git a/modules/ray/ray_light_emitter.h b/modules/ray/ray_light_emitter.h deleted file mode 100644 index 3b5509e..0000000 --- a/modules/ray/ray_light_emitter.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef _RAY_LIGHT_EMITTER_H -#define _RAY_LIGHT_EMITTER_H - -#include "ray_object_point.h" -#include "ray_object_sphere.h" - -typedef enum ray_light_emitter_type_t { - RAY_LIGHT_EMITTER_TYPE_SPHERE, - RAY_LIGHT_EMITTER_TYPE_POINT, -} ray_light_emitter_type_t; - -typedef union ray_light_emitter_t { - ray_light_emitter_type_t type; - ray_object_sphere_t sphere; - ray_object_point_t point; -} ray_light_emitter_t; - -#endif diff --git a/modules/ray/ray_object.c b/modules/ray/ray_object.c deleted file mode 100644 index 4c5ccaf..0000000 --- a/modules/ray/ray_object.c +++ /dev/null @@ -1,74 +0,0 @@ -#include <assert.h> - -#include "ray_object.h" -#include "ray_object_light.h" -#include "ray_object_plane.h" -#include "ray_object_point.h" -#include "ray_object_sphere.h" -#include "ray_ray.h" -#include "ray_surface.h" - - -/* Determine if a ray intersects object. - * If the object is intersected, store where along the ray the intersection occurs in res_distance. - */ -int ray_object_intersects_ray(ray_object_t *object, ray_ray_t *ray, float *res_distance) -{ - switch (object->type) { - case RAY_OBJECT_TYPE_SPHERE: - return ray_object_sphere_intersects_ray(&object->sphere, ray, res_distance); - - case RAY_OBJECT_TYPE_POINT: - return ray_object_point_intersects_ray(&object->point, ray, res_distance); - - case RAY_OBJECT_TYPE_PLANE: - return ray_object_plane_intersects_ray(&object->plane, ray, res_distance); - - case RAY_OBJECT_TYPE_LIGHT: - return ray_object_light_intersects_ray(&object->light, ray, res_distance); - default: - assert(0); - } -} - - -/* Return the surface normal of object @ point */ -ray_3f_t ray_object_normal(ray_object_t *object, ray_3f_t *point) -{ - switch (object->type) { - case RAY_OBJECT_TYPE_SPHERE: - return ray_object_sphere_normal(&object->sphere, point); - - case RAY_OBJECT_TYPE_POINT: - return ray_object_point_normal(&object->point, point); - - case RAY_OBJECT_TYPE_PLANE: - return ray_object_plane_normal(&object->plane, point); - - case RAY_OBJECT_TYPE_LIGHT: - return ray_object_light_normal(&object->light, point); - default: - assert(0); - } -} - - -/* Return the surface of object @ point */ -ray_surface_t ray_object_surface(ray_object_t *object, ray_3f_t *point) -{ - switch (object->type) { - case RAY_OBJECT_TYPE_SPHERE: - return ray_object_sphere_surface(&object->sphere, point); - - case RAY_OBJECT_TYPE_POINT: - return ray_object_point_surface(&object->point, point); - - case RAY_OBJECT_TYPE_PLANE: - return ray_object_plane_surface(&object->plane, point); - - case RAY_OBJECT_TYPE_LIGHT: - return ray_object_light_surface(&object->light, point); - default: - assert(0); - } -} diff --git a/modules/ray/ray_object.h b/modules/ray/ray_object.h deleted file mode 100644 index abdb254..0000000 --- a/modules/ray/ray_object.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef _RAY_OBJECT_H -#define _RAY_OBJECT_H - -#include "ray_object_light.h" -#include "ray_object_plane.h" -#include "ray_object_point.h" -#include "ray_object_sphere.h" -#include "ray_object_type.h" -#include "ray_ray.h" -#include "ray_surface.h" - -typedef union ray_object_t { - ray_object_type_t type; - ray_object_sphere_t sphere; - ray_object_point_t point; - ray_object_plane_t plane; - ray_object_light_t light; -} ray_object_t; - -int ray_object_intersects_ray(ray_object_t *object, ray_ray_t *ray, float *res_distance); -ray_3f_t ray_object_normal(ray_object_t *object, ray_3f_t *point); -ray_surface_t ray_object_surface(ray_object_t *object, ray_3f_t *point); - -#endif diff --git a/modules/ray/ray_object_light.h b/modules/ray/ray_object_light.h deleted file mode 100644 index 342c050..0000000 --- a/modules/ray/ray_object_light.h +++ /dev/null @@ -1,67 +0,0 @@ -#ifndef _RAY_OBJECT_LIGHT_H -#define _RAY_OBJECT_LIGHT_H - -#include <assert.h> - -#include "ray_light_emitter.h" -#include "ray_object_light.h" -#include "ray_object_point.h" -#include "ray_object_sphere.h" -#include "ray_object_type.h" -#include "ray_ray.h" -#include "ray_surface.h" - - -typedef struct ray_object_light_t { - ray_object_type_t type; - float brightness; - ray_light_emitter_t emitter; -} ray_object_light_t; - - -/* TODO: point is really the only one I've implemented... */ -static inline int ray_object_light_intersects_ray(ray_object_light_t *light, ray_ray_t *ray, float *res_distance) -{ - switch (light->emitter.type) { - case RAY_LIGHT_EMITTER_TYPE_POINT: - return ray_object_point_intersects_ray(&light->emitter.point, ray, res_distance); - - case RAY_LIGHT_EMITTER_TYPE_SPHERE: - return ray_object_sphere_intersects_ray(&light->emitter.sphere, ray, res_distance); - default: - assert(0); - } -} - - -static inline ray_3f_t ray_object_light_normal(ray_object_light_t *light, ray_3f_t *point) -{ - ray_3f_t normal; - - /* TODO */ - switch (light->emitter.type) { - case RAY_LIGHT_EMITTER_TYPE_SPHERE: - return normal; - - case RAY_LIGHT_EMITTER_TYPE_POINT: - return normal; - default: - assert(0); - } -} - - -static inline ray_surface_t ray_object_light_surface(ray_object_light_t *light, ray_3f_t *point) -{ - switch (light->emitter.type) { - case RAY_LIGHT_EMITTER_TYPE_SPHERE: - return ray_object_sphere_surface(&light->emitter.sphere, point); - - case RAY_LIGHT_EMITTER_TYPE_POINT: - return ray_object_point_surface(&light->emitter.point, point); - default: - assert(0); - } -} - -#endif diff --git a/modules/ray/ray_object_plane.h b/modules/ray/ray_object_plane.h deleted file mode 100644 index b33f342..0000000 --- a/modules/ray/ray_object_plane.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef _RAY_OBJECT_PLANE_H -#define _RAY_OBJECT_PLANE_H - -#include "ray_object_type.h" -#include "ray_ray.h" -#include "ray_surface.h" - - -typedef struct ray_object_plane_t { - ray_object_type_t type; - ray_surface_t surface; - ray_3f_t normal; - float distance; -} ray_object_plane_t; - - -static inline int ray_object_plane_intersects_ray(ray_object_plane_t *plane, ray_ray_t *ray, float *res_distance) -{ - float d = ray_3f_dot(&plane->normal, &ray->direction); - - if (d != 0) { - float distance = -(ray_3f_dot(&plane->normal, &ray->origin) + plane->distance) / d; - - if (distance > 0) { - *res_distance = distance; - - return 1; - } - } - - return 0; -} - - -static inline ray_3f_t ray_object_plane_normal(ray_object_plane_t *plane, ray_3f_t *point) -{ - return plane->normal; -} - - -static inline ray_surface_t ray_object_plane_surface(ray_object_plane_t *plane, ray_3f_t *point) -{ - return plane->surface; -} - -#endif diff --git a/modules/ray/ray_object_point.h b/modules/ray/ray_object_point.h deleted file mode 100644 index c0c9610..0000000 --- a/modules/ray/ray_object_point.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef _RAY_OBJECT_POINT_H -#define _RAY_OBJECT_POINT_H - -#include "ray_3f.h" -#include "ray_object_type.h" -#include "ray_ray.h" -#include "ray_surface.h" - - -typedef struct ray_object_point_t { - ray_object_type_t type; - ray_surface_t surface; - ray_3f_t center; -} ray_object_point_t; - - -static inline int ray_object_point_intersects_ray(ray_object_point_t *point, ray_ray_t *ray, float *res_distance) -{ - /* TODO: determine a ray:point intersection */ - return 0; -} - - -static inline ray_3f_t ray_object_point_normal(ray_object_point_t *point, ray_3f_t *_point) -{ - ray_3f_t normal; - - return normal; -} - - -static inline ray_surface_t ray_object_point_surface(ray_object_point_t *point, ray_3f_t *_point) -{ - return point->surface; -} - -#endif diff --git a/modules/ray/ray_object_sphere.h b/modules/ray/ray_object_sphere.h deleted file mode 100644 index 85b3d93..0000000 --- a/modules/ray/ray_object_sphere.h +++ /dev/null @@ -1,65 +0,0 @@ -#ifndef _RAY_OBJECT_SPHERE_H -#define _RAY_OBJECT_SPHERE_H - -#include <math.h> -#include <stdio.h> - -#include "ray_3f.h" -#include "ray_color.h" -#include "ray_object_type.h" -#include "ray_ray.h" -#include "ray_surface.h" - - -typedef struct ray_object_sphere_t { - ray_object_type_t type; - ray_surface_t surface; - ray_3f_t center; - float radius; -} ray_object_sphere_t; - - -static inline int ray_object_sphere_intersects_ray(ray_object_sphere_t *sphere, ray_ray_t *ray, float *res_distance) -{ - ray_3f_t v = ray_3f_sub(&ray->origin, &sphere->center); - float b = ray_3f_dot(&v, &ray->direction); - float disc = (sphere->radius * sphere->radius) - ray_3f_dot(&v, &v) + (b * b); - - if (disc > 0) { - float i1, i2; - - disc = sqrtf(disc); - - i1 = b - disc; - i2 = b + disc; - - if (i2 > 0 && i1 > 0) { - *res_distance = i1; - return 1; - } - } - - return 0; -} - - -/* return the normal of the surface at the specified point */ -static inline ray_3f_t ray_object_sphere_normal(ray_object_sphere_t *sphere, ray_3f_t *point) -{ - ray_3f_t normal; - - normal = ray_3f_sub(point, &sphere->center); - normal = ray_3f_div_scalar(&normal, sphere->radius); /* normalize without the sqrt() */ - - return normal; -} - - -/* return the surface of the sphere @ point */ -static inline ray_surface_t ray_object_sphere_surface(ray_object_sphere_t *sphere, ray_3f_t *point) -{ - /* uniform solids for now... */ - return sphere->surface; -} - -#endif diff --git a/modules/ray/ray_object_type.h b/modules/ray/ray_object_type.h deleted file mode 100644 index 6ce20f5..0000000 --- a/modules/ray/ray_object_type.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef _RAY_OBJECT_TYPE_H -#define _RAY_OBJECT_TYPE_H - -typedef enum ray_object_type_t { - RAY_OBJECT_TYPE_SPHERE, - RAY_OBJECT_TYPE_POINT, - RAY_OBJECT_TYPE_PLANE, - RAY_OBJECT_TYPE_LIGHT, -} ray_object_type_t; - -#endif diff --git a/modules/ray/ray_ray.h b/modules/ray/ray_ray.h deleted file mode 100644 index 91469a2..0000000 --- a/modules/ray/ray_ray.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef _RAY_RAY_H -#define _RAY_RAY_H - -#include "ray_3f.h" - -typedef struct ray_ray_t { - ray_3f_t origin; - ray_3f_t direction; -} ray_ray_t; - -#endif diff --git a/modules/ray/ray_scene.c b/modules/ray/ray_scene.c deleted file mode 100644 index e44990b..0000000 --- a/modules/ray/ray_scene.c +++ /dev/null @@ -1,188 +0,0 @@ -#include <stdlib.h> -#include <math.h> - -#include "fb.h" - -#include "ray_camera.h" -#include "ray_color.h" -#include "ray_object.h" -#include "ray_ray.h" -#include "ray_scene.h" -#include "ray_threads.h" - -#define MAX_RECURSION_DEPTH 5 - - -static ray_color_t trace_ray(ray_scene_t *scene, ray_ray_t *ray, unsigned depth); - - -/* Determine if the ray is obstructed by an object within the supplied distance, for shadows */ -static inline int ray_is_obstructed(ray_scene_t *scene, ray_ray_t *ray, float distance) -{ - unsigned i; - - for (i = 0; i < scene->n_objects; i++) { - float ood; - - if (scene->objects[i].type == RAY_OBJECT_TYPE_LIGHT) - continue; - - if (ray_object_intersects_ray(&scene->objects[i], ray, &ood) && - ood < distance) { - return 1; - } - } - - return 0; -} - - -/* Determine the color @ distance on ray on object viewed from origin */ -static inline ray_color_t shade_ray(ray_scene_t *scene, ray_ray_t *ray, ray_object_t *object, float distance, unsigned depth) -{ - ray_surface_t surface; - ray_color_t color; - ray_3f_t rvec = ray_3f_mult_scalar(&ray->direction, distance); - ray_3f_t intersection = ray_3f_sub(&ray->origin, &rvec); - ray_3f_t normal = ray_object_normal(object, &intersection); - unsigned i; - - surface = ray_object_surface(object, &intersection); - color = ray_3f_mult_scalar(&scene->ambient_color, scene->ambient_brightness); - color = ray_3f_mult(&surface.color, &color); - - /* visit lights for shadows and illumination */ - for (i = 0; i < scene->n_lights; i++) { - ray_3f_t lvec = ray_3f_sub(&scene->lights[i].light.emitter.point.center, &intersection); - float ldist = ray_3f_length(&lvec); - float lvec_normal_dot; - ray_ray_t shadow_ray; - - lvec = ray_3f_mult_scalar(&lvec, (1.0f / ldist)); /* normalize lvec */ -#if 1 - /* skip this light if it's obstructed, - * we must shift the origin slightly towards the light to prevent - * spurious self-obstruction at the ray:object intersection */ - /* negate the light vector so it's pointed at the light rather than from it */ - shadow_ray.direction = ray_3f_negate(&lvec); - shadow_ray.origin = ray_3f_mult_scalar(&shadow_ray.direction, 0.00001f); - shadow_ray.origin = ray_3f_add(&shadow_ray.origin, &intersection); - - if (ray_is_obstructed(scene, &shadow_ray, ldist)) - continue; -#endif - lvec_normal_dot = ray_3f_dot(&normal, &lvec); - - if (lvec_normal_dot > 0) { -#if 1 - float rvec_lvec_dot = ray_3f_dot(&ray->direction, &lvec); - ray_color_t diffuse; - ray_color_t specular; - - diffuse = ray_3f_mult_scalar(&surface.color, lvec_normal_dot); - diffuse = ray_3f_mult_scalar(&diffuse, surface.diffuse); - color = ray_3f_add(&color, &diffuse); - - /* FIXME: assumes light is a point for its color, and 20 is a constant "Phong exponent", - * which should really be object/surface-specific - */ - specular = ray_3f_mult_scalar(&scene->lights[i].light.emitter.point.surface.color, powf(rvec_lvec_dot, 20)); - specular = ray_3f_mult_scalar(&specular, surface.specular); - color = ray_3f_add(&color, &specular); -#else - ray_color_t diffuse; - - diffuse = ray_3f_mult_scalar(&surface.color, lvec_normal_dot); - color = ray_3f_add(&color, &diffuse); -#endif - } - } - - /* generate a reflection ray */ -#if 1 - float dot = ray_3f_dot(&ray->direction, &normal); - ray_ray_t reflected_ray = { .direction = ray_3f_mult_scalar(&normal, dot * 2.0f) }; - ray_3f_t reflection; - - reflected_ray.origin = intersection; - reflected_ray.direction = ray_3f_sub(&ray->direction, &reflected_ray.direction); - - reflection = trace_ray(scene, &reflected_ray, depth + 1); - reflection = ray_3f_mult_scalar(&reflection, surface.specular); - color = ray_3f_add(&color, &reflection); -#endif - - /* TODO: generate a refraction ray */ - - return color; -} - - -static ray_color_t trace_ray(ray_scene_t *scene, ray_ray_t *ray, unsigned depth) -{ - ray_object_t *nearest_object = NULL; - float nearest_object_distance = INFINITY; - ray_color_t color = { .x = 0.0, .y = 0.0, .z = 0.0 }; - unsigned i; - - depth++; - if (depth > MAX_RECURSION_DEPTH) - return color; - - for (i = 0; i < scene->n_objects; i++) { - float distance; - - /* Does this ray intersect object? */ - if (ray_object_intersects_ray(&scene->objects[i], ray, &distance)) { - - /* Is it the nearest intersection? */ - if (!nearest_object || - distance < nearest_object_distance) { - nearest_object = &scene->objects[i]; - nearest_object_distance = distance; - } - } - } - - if (nearest_object) - color = shade_ray(scene, ray, nearest_object, nearest_object_distance, depth); - - depth--; - - return color; -} - - -void ray_scene_render_fragment(ray_scene_t *scene, ray_camera_t *camera, fb_fragment_t *fragment) -{ - ray_camera_frame_t frame; - ray_ray_t ray; - uint32_t *buf = fragment->buf; - unsigned stride = fragment->stride / 4; - - ray_camera_frame_begin(camera, fragment, &ray, &frame); - do { - do { - *buf = ray_color_to_uint32_rgb(trace_ray(scene, &ray, 0)); - buf++; - } while (ray_camera_frame_x_step(&frame)); - - buf += stride; - } while (ray_camera_frame_y_step(&frame)); -} - -/* we expect fragments[threads->n_threads + 1], or fragments[1] when threads == NULL */ -void ray_scene_render_fragments(ray_scene_t *scene, ray_camera_t *camera, ray_threads_t *threads, fb_fragment_t *fragments) -{ - unsigned n_threads = threads ? threads->n_threads + 1 : 1; - unsigned i; - - for (i = 1; i < n_threads; i++) - ray_thread_fragment_submit(&threads->threads[i - 1], scene, camera, &fragments[i]); - - /* always render the zero fragment in-line */ - ray_scene_render_fragment(scene, camera, &fragments[0]); - - for (i = 1; i < n_threads; i++) - ray_thread_wait_idle(&threads->threads[i - 1]); -} diff --git a/modules/ray/ray_scene.h b/modules/ray/ray_scene.h deleted file mode 100644 index e9781c6..0000000 --- a/modules/ray/ray_scene.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef _RAY_SCENE_H -#define _RAY_SCENE_H - -#include "fb.h" - -#include "ray_camera.h" -#include "ray_color.h" -#include "ray_ray.h" -#include "ray_threads.h" - -typedef union ray_object_t ray_object_t; - -typedef struct ray_scene_t { - ray_object_t *objects; - unsigned n_objects; - - ray_object_t *lights; - unsigned n_lights; - - ray_color_t ambient_color; - float ambient_brightness; -} ray_scene_t; - -void ray_scene_render_fragments(ray_scene_t *scene, ray_camera_t *camera, ray_threads_t *threads, fb_fragment_t *fragments); -void ray_scene_render_fragment(ray_scene_t *scene, ray_camera_t *camera, fb_fragment_t *fragment); - -#endif diff --git a/modules/ray/ray_surface.h b/modules/ray/ray_surface.h deleted file mode 100644 index b3e3c68..0000000 --- a/modules/ray/ray_surface.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef _RAY_MATERIAL_H -#define _RAY_MATERIAL_H - -#include "ray_3f.h" -#include "ray_color.h" - -/* Surface properties we expect every object to be able to introspect */ -typedef struct ray_surface_t { - ray_color_t color; - float specular; - float diffuse; -} ray_surface_t; - -#endif diff --git a/modules/ray/ray_threads.c b/modules/ray/ray_threads.c deleted file mode 100644 index 2369687..0000000 --- a/modules/ray/ray_threads.c +++ /dev/null @@ -1,111 +0,0 @@ -#include <pthread.h> -#include <stdlib.h> - -#include "fb.h" - -#include "ray_scene.h" -#include "ray_threads.h" - -#define BUSY_WAIT_NUM 1000000000 /* How much to spin before sleeping in pthread_cond_wait() */ - -/* for now assuming x86 */ -#define cpu_relax() \ - __asm__ __volatile__ ( "pause\n" : : : "memory") - -/* This is a very simple/naive implementation, there's certainly room for improvement. - * - * Without the BUSY_WAIT_NUM spinning this approach seems to leave a fairly - * substantial proportion of CPU idle while waiting for the render thread to - * complete on my core 2 duo. - * - * It's probably just latency in getting the render thread woken when the work - * is submitted, and since the fragments are split equally the main thread gets - * a head start and has to wait when it finishes first. The spinning is just - * an attempt to avoid going to sleep while the render threads finish, there - * still needs to be improvement in how the work is submitted. - * - * I haven't spent much time on optimizing the raytracer yet. - */ - -static void * ray_thread_func(void *_thread) -{ - ray_thread_t *thread = _thread; - - for (;;) { - pthread_mutex_lock(&thread->mutex); - while (thread->fragment == NULL) - pthread_cond_wait(&thread->cond, &thread->mutex); - - ray_scene_render_fragment(thread->scene, thread->camera, thread->fragment); - thread->fragment = NULL; - pthread_mutex_unlock(&thread->mutex); - pthread_cond_signal(&thread->cond); - } - - return NULL; -} - - -void ray_thread_fragment_submit(ray_thread_t *thread, ray_scene_t *scene, ray_camera_t *camera, fb_fragment_t *fragment) -{ - pthread_mutex_lock(&thread->mutex); - while (thread->fragment != NULL) /* XXX: never true due to ray_thread_wait_idle() */ - pthread_cond_wait(&thread->cond, &thread->mutex); - - thread->fragment = fragment; - thread->scene = scene; - thread->camera = camera; - - pthread_mutex_unlock(&thread->mutex); - pthread_cond_signal(&thread->cond); -} - - -void ray_thread_wait_idle(ray_thread_t *thread) -{ - unsigned n; - - /* Spin before going to sleep, the other thread should not take substantially longer. */ - for (n = 0; thread->fragment != NULL && n < BUSY_WAIT_NUM; n++) - cpu_relax(); - - pthread_mutex_lock(&thread->mutex); - while (thread->fragment != NULL) - pthread_cond_wait(&thread->cond, &thread->mutex); - pthread_mutex_unlock(&thread->mutex); -} - - -ray_threads_t * ray_threads_create(unsigned num) -{ - ray_threads_t *threads; - unsigned i; - - threads = malloc(sizeof(ray_threads_t) + sizeof(ray_thread_t) * num); - if (!threads) - return NULL; - - for (i = 0; i < num; i++) { - pthread_mutex_init(&threads->threads[i].mutex, NULL); - pthread_cond_init(&threads->threads[i].cond, NULL); - threads->threads[i].fragment = NULL; - pthread_create(&threads->threads[i].thread, NULL, ray_thread_func, &threads->threads[i]); - } - threads->n_threads = num; - - return threads; -} - - -void ray_threads_destroy(ray_threads_t *threads) -{ - unsigned i; - - for (i = 0; i < threads->n_threads; i++) - pthread_cancel(threads->threads[i].thread); - - for (i = 0; i < threads->n_threads; i++) - pthread_join(threads->threads[i].thread, NULL); - - free(threads); -} diff --git a/modules/ray/ray_threads.h b/modules/ray/ray_threads.h deleted file mode 100644 index b4c601d..0000000 --- a/modules/ray/ray_threads.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef _RAY_THREADS_H -#define _RAY_THREADS_H - -#include <pthread.h> - -typedef struct ray_scene_t ray_scene_t; -typedef struct ray_camera_t ray_camera_t; -typedef struct fb_fragment_t fb_fragment_t; - -typedef struct ray_thread_t { - pthread_t thread; - pthread_mutex_t mutex; - pthread_cond_t cond; - ray_scene_t *scene; - ray_camera_t *camera; - fb_fragment_t *fragment; -} ray_thread_t; - -typedef struct ray_threads_t { - unsigned n_threads; - ray_thread_t threads[]; -} ray_threads_t; - - -ray_threads_t * ray_threads_create(unsigned num); -void ray_threads_destroy(ray_threads_t *threads); - -void ray_thread_fragment_submit(ray_thread_t *thread, ray_scene_t *scene, ray_camera_t *camera, fb_fragment_t *fragment); -void ray_thread_wait_idle(ray_thread_t *thread); -#endif |