From cbc6c0eaf45a7ede48465d1f6d6f7e24c14bd9ce Mon Sep 17 00:00:00 2001 From: Vito Caputo Date: Fri, 2 Jun 2017 11:00:36 -0700 Subject: ray: plumb depth and camera to objects To enable prepare to precompute aspects of primary rays which all have a common origin at the camera, bring the camera to ray_object*_prepare() and bring the depth to ray_object*_intersects_ray() for primary ray detection. This is only scaffolding, functionally unchanged. --- src/modules/ray/ray.c | 2 +- src/modules/ray/ray_object.h | 21 +++++++++++---------- src/modules/ray/ray_object_light.h | 9 +++++---- src/modules/ray/ray_object_plane.h | 5 +++-- src/modules/ray/ray_object_point.h | 5 +++-- src/modules/ray/ray_object_sphere.h | 5 +++-- src/modules/ray/ray_scene.c | 20 +++++++++++--------- src/modules/ray/ray_scene.h | 2 +- 8 files changed, 38 insertions(+), 31 deletions(-) diff --git a/src/modules/ray/ray.c b/src/modules/ray/ray.c index 1143db1..b80f384 100644 --- a/src/modules/ray/ray.c +++ b/src/modules/ray/ray.c @@ -146,7 +146,7 @@ static void ray_prepare_frame(void *context, unsigned n_cpus, fb_fragment_t *fra /* tilt camera pitch in time with up and down movements, phase shifted appreciably */ camera.orientation.pitch = sinf((M_PI * 1.5f) + r * 1.3f) * .6f + -.35f; #endif - ray_scene_prepare(&scene); + ray_scene_prepare(&scene, &camera); } diff --git a/src/modules/ray/ray_object.h b/src/modules/ray/ray_object.h index f4c3225..f882e86 100644 --- a/src/modules/ray/ray_object.h +++ b/src/modules/ray/ray_object.h @@ -3,6 +3,7 @@ #include +#include "ray_camera.h" #include "ray_object_light.h" #include "ray_object_plane.h" #include "ray_object_point.h" @@ -25,20 +26,20 @@ typedef union ray_object_t { * If the object has any pre-calculating to do, this is where it happens. * The pre-calculated stuff is object-resident under a _prepared struct member. */ -static inline void ray_object_prepare(ray_object_t *object) +static inline void ray_object_prepare(ray_object_t *object, ray_camera_t *camera) { switch (object->type) { case RAY_OBJECT_TYPE_SPHERE: - return ray_object_sphere_prepare(&object->sphere); + return ray_object_sphere_prepare(&object->sphere, camera); case RAY_OBJECT_TYPE_POINT: - return ray_object_point_prepare(&object->point); + return ray_object_point_prepare(&object->point, camera); case RAY_OBJECT_TYPE_PLANE: - return ray_object_plane_prepare(&object->plane); + return ray_object_plane_prepare(&object->plane, camera); case RAY_OBJECT_TYPE_LIGHT: - return ray_object_light_prepare(&object->light); + return ray_object_light_prepare(&object->light, camera); default: assert(0); } @@ -48,20 +49,20 @@ static inline void ray_object_prepare(ray_object_t *object) /* Determine if a ray intersects object. * If the object is intersected, store where along the ray the intersection occurs in res_distance. */ -static inline int ray_object_intersects_ray(ray_object_t *object, ray_ray_t *ray, float *res_distance) +static inline int ray_object_intersects_ray(ray_object_t *object, unsigned depth, 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); + return ray_object_sphere_intersects_ray(&object->sphere, depth, ray, res_distance); case RAY_OBJECT_TYPE_POINT: - return ray_object_point_intersects_ray(&object->point, ray, res_distance); + return ray_object_point_intersects_ray(&object->point, depth, ray, res_distance); case RAY_OBJECT_TYPE_PLANE: - return ray_object_plane_intersects_ray(&object->plane, ray, res_distance); + return ray_object_plane_intersects_ray(&object->plane, depth, ray, res_distance); case RAY_OBJECT_TYPE_LIGHT: - return ray_object_light_intersects_ray(&object->light, ray, res_distance); + return ray_object_light_intersects_ray(&object->light, depth, ray, res_distance); default: assert(0); } diff --git a/src/modules/ray/ray_object_light.h b/src/modules/ray/ray_object_light.h index 44b59d4..a6213e8 100644 --- a/src/modules/ray/ray_object_light.h +++ b/src/modules/ray/ray_object_light.h @@ -3,6 +3,7 @@ #include +#include "ray_camera.h" #include "ray_light_emitter.h" #include "ray_object_light.h" #include "ray_object_point.h" @@ -19,20 +20,20 @@ typedef struct ray_object_light_t { } ray_object_light_t; -static void ray_object_light_prepare(ray_object_light_t *light) +static void ray_object_light_prepare(ray_object_light_t *light, ray_camera_t *camera) { } /* 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) +static inline int ray_object_light_intersects_ray(ray_object_light_t *light, unsigned depth, 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); + return ray_object_point_intersects_ray(&light->emitter.point, depth, ray, res_distance); case RAY_LIGHT_EMITTER_TYPE_SPHERE: - return ray_object_sphere_intersects_ray(&light->emitter.sphere, ray, res_distance); + return ray_object_sphere_intersects_ray(&light->emitter.sphere, depth, ray, res_distance); default: assert(0); } diff --git a/src/modules/ray/ray_object_plane.h b/src/modules/ray/ray_object_plane.h index cc7ea8d..0be28f4 100644 --- a/src/modules/ray/ray_object_plane.h +++ b/src/modules/ray/ray_object_plane.h @@ -2,6 +2,7 @@ #define _RAY_OBJECT_PLANE_H #include "ray_3f.h" +#include "ray_camera.h" #include "ray_object_type.h" #include "ray_ray.h" #include "ray_surface.h" @@ -15,12 +16,12 @@ typedef struct ray_object_plane_t { } ray_object_plane_t; -static void ray_object_plane_prepare(ray_object_plane_t *plane) +static void ray_object_plane_prepare(ray_object_plane_t *plane, ray_camera_t *camera) { } -static inline int ray_object_plane_intersects_ray(ray_object_plane_t *plane, ray_ray_t *ray, float *res_distance) +static inline int ray_object_plane_intersects_ray(ray_object_plane_t *plane, unsigned depth, ray_ray_t *ray, float *res_distance) { float d = ray_3f_dot(&plane->normal, &ray->direction); diff --git a/src/modules/ray/ray_object_point.h b/src/modules/ray/ray_object_point.h index 0eddf25..2b58f5f 100644 --- a/src/modules/ray/ray_object_point.h +++ b/src/modules/ray/ray_object_point.h @@ -2,6 +2,7 @@ #define _RAY_OBJECT_POINT_H #include "ray_3f.h" +#include "ray_camera.h" #include "ray_object_type.h" #include "ray_ray.h" #include "ray_surface.h" @@ -14,12 +15,12 @@ typedef struct ray_object_point_t { } ray_object_point_t; -static void ray_object_point_prepare(ray_object_point_t *point) +static void ray_object_point_prepare(ray_object_point_t *point, ray_camera_t *camera) { } -static inline int ray_object_point_intersects_ray(ray_object_point_t *point, ray_ray_t *ray, float *res_distance) +static inline int ray_object_point_intersects_ray(ray_object_point_t *point, unsigned depth, ray_ray_t *ray, float *res_distance) { /* TODO: determine a ray:point intersection */ return 0; diff --git a/src/modules/ray/ray_object_sphere.h b/src/modules/ray/ray_object_sphere.h index aadda18..9c74752 100644 --- a/src/modules/ray/ray_object_sphere.h +++ b/src/modules/ray/ray_object_sphere.h @@ -4,6 +4,7 @@ #include #include "ray_3f.h" +#include "ray_camera.h" #include "ray_color.h" #include "ray_object_type.h" #include "ray_ray.h" @@ -22,7 +23,7 @@ typedef struct ray_object_sphere_t { } ray_object_sphere_t; -static void ray_object_sphere_prepare(ray_object_sphere_t *sphere) +static void ray_object_sphere_prepare(ray_object_sphere_t *sphere, ray_camera_t *camera) { sphere->_prepared.r2 = sphere->radius * sphere->radius; @@ -31,7 +32,7 @@ static void ray_object_sphere_prepare(ray_object_sphere_t *sphere) } -static inline int ray_object_sphere_intersects_ray(ray_object_sphere_t *sphere, ray_ray_t *ray, float *res_distance) +static inline int ray_object_sphere_intersects_ray(ray_object_sphere_t *sphere, unsigned depth, 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); diff --git a/src/modules/ray/ray_scene.c b/src/modules/ray/ray_scene.c index a95058f..b5d1e81 100644 --- a/src/modules/ray/ray_scene.c +++ b/src/modules/ray/ray_scene.c @@ -16,14 +16,14 @@ 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) +static inline int ray_is_obstructed(ray_scene_t *scene, unsigned depth, ray_ray_t *ray, float distance) { unsigned i; for (i = 0; i < scene->n_objects; i++) { float ood; - if (ray_object_intersects_ray(&scene->objects[i], ray, &ood) && + if (ray_object_intersects_ray(&scene->objects[i], depth, ray, &ood) && ood < distance) { return 1; } @@ -34,7 +34,7 @@ static inline int ray_is_obstructed(ray_scene_t *scene, ray_ray_t *ray, float di /* shadow test */ -static inline int point_is_shadowed(ray_scene_t *scene, ray_3f_t *light_direction, float distance, ray_3f_t *point) +static inline int point_is_shadowed(ray_scene_t *scene, unsigned depth, ray_3f_t *light_direction, float distance, ray_3f_t *point) { ray_ray_t shadow_ray; @@ -46,7 +46,7 @@ static inline int point_is_shadowed(ray_scene_t *scene, ray_3f_t *light_directio shadow_ray.origin = ray_3f_mult_scalar(&shadow_ray.direction, 0.00001f); shadow_ray.origin = ray_3f_add(&shadow_ray.origin, point); - if (ray_is_obstructed(scene, &shadow_ray, distance)) + if (ray_is_obstructed(scene, depth + 1, &shadow_ray, distance)) return 1; return 0; @@ -84,7 +84,7 @@ static inline ray_color_t shade_ray(ray_scene_t *scene, ray_ray_t *ray, ray_obje lvec = ray_3f_mult_scalar(&lvec, (1.0f / ldist)); /* normalize lvec */ #if 1 - if (point_is_shadowed(scene, &lvec, ldist, &intersection)) + if (point_is_shadowed(scene, depth, &lvec, ldist, &intersection)) continue; #endif lvec_normal_dot = ray_3f_dot(&normal, &lvec); @@ -149,7 +149,7 @@ static ray_color_t trace_ray(ray_scene_t *scene, ray_ray_t *ray, unsigned depth) float distance; /* Does this ray intersect object? */ - if (ray_object_intersects_ray(&scene->objects[i], ray, &distance)) { + if (ray_object_intersects_ray(&scene->objects[i], depth, ray, &distance)) { /* Is it the nearest intersection? */ if (distance < nearest_object_distance) { @@ -187,13 +187,15 @@ void ray_scene_render_fragment(ray_scene_t *scene, ray_camera_t *camera, fb_frag } -/* prepare the scene for rendering, must be called whenever the scene has been changed. */ -void ray_scene_prepare(ray_scene_t *scene) +/* prepare the scene for rendering with camera, must be called whenever anything in the scene+camera pair has been changed. */ +/* this is basically a time for the raytracer to precompute whatever it can which otherwise ends up occurring per-ray */ +/* the camera is included so primary rays which all have a common origin may be optimized for */ +void ray_scene_prepare(ray_scene_t *scene, ray_camera_t *camera) { unsigned i; scene->_prepared.ambient_light = ray_3f_mult_scalar(&scene->ambient_color, scene->ambient_brightness); for (i = 0; i < scene->n_objects; i++) - ray_object_prepare(&scene->objects[i]); + ray_object_prepare(&scene->objects[i], camera); } diff --git a/src/modules/ray/ray_scene.h b/src/modules/ray/ray_scene.h index 820b16b..98928ee 100644 --- a/src/modules/ray/ray_scene.h +++ b/src/modules/ray/ray_scene.h @@ -24,7 +24,7 @@ typedef struct ray_scene_t { } _prepared; } ray_scene_t; -void ray_scene_prepare(ray_scene_t *scene); +void ray_scene_prepare(ray_scene_t *scene, ray_camera_t *camera); void ray_scene_render_fragment(ray_scene_t *scene, ray_camera_t *camera, fb_fragment_t *fragment); #endif -- cgit v1.2.3