From 445e9481bbe598d1eabcae7a70534c51a52c6de5 Mon Sep 17 00:00:00 2001 From: Vito Caputo Date: Wed, 13 Sep 2017 18:04:31 -0700 Subject: ray: simplify object iterators using sentinel type Trivial optimization eliminates some instructions from the hot path, no need to maintain a separate index from the current object pointer. --- src/modules/ray/ray.c | 6 ++++-- src/modules/ray/ray_object_type.h | 1 + src/modules/ray/ray_scene.c | 25 ++++++++++++------------- 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/src/modules/ray/ray.c b/src/modules/ray/ray.c index 60784db..4af9715 100644 --- a/src/modules/ray/ray.c +++ b/src/modules/ray/ray.c @@ -73,6 +73,8 @@ static ray_object_t objects[] = { .center = { .x = 0.2, .y = -1.25, .z = 0.0 }, .radius = 0.6f, } + }, { + .type = RAY_OBJECT_TYPE_SENTINEL, } }; @@ -89,6 +91,8 @@ static ray_object_t lights[] = { }, } } + }, { + .type = RAY_OBJECT_TYPE_SENTINEL, } }; @@ -105,9 +109,7 @@ static ray_camera_t camera = { static ray_scene_t scene = { .objects = objects, - .n_objects = nelems(objects), .lights = lights, - .n_lights = nelems(lights), .ambient_color = { .x = 1.0f, .y = 1.0f, .z = 1.0f }, .ambient_brightness = .04f, }; diff --git a/src/modules/ray/ray_object_type.h b/src/modules/ray/ray_object_type.h index 6ce20f5..ab797d2 100644 --- a/src/modules/ray/ray_object_type.h +++ b/src/modules/ray/ray_object_type.h @@ -2,6 +2,7 @@ #define _RAY_OBJECT_TYPE_H typedef enum ray_object_type_t { + RAY_OBJECT_TYPE_SENTINEL, RAY_OBJECT_TYPE_SPHERE, RAY_OBJECT_TYPE_POINT, RAY_OBJECT_TYPE_PLANE, diff --git a/src/modules/ray/ray_scene.c b/src/modules/ray/ray_scene.c index cf8fb44..91249f3 100644 --- a/src/modules/ray/ray_scene.c +++ b/src/modules/ray/ray_scene.c @@ -16,12 +16,12 @@ /* 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, unsigned depth, ray_ray_t *ray, float distance) { - unsigned i; + ray_object_t *object; - for (i = 0; i < scene->n_objects; i++) { + for (object = scene->objects; object->type; object++) { float ood; - if (ray_object_intersects_ray(&scene->objects[i], depth, ray, &ood) && + if (ray_object_intersects_ray(object, depth, ray, &ood) && ood < distance) { return 1; } @@ -61,11 +61,11 @@ static inline ray_color_t shade_intersection(ray_scene_t *scene, ray_object_t *o { ray_surface_t surface = ray_object_surface(object, intersection); ray_color_t color = ray_3f_mult(&surface.color, &scene->_prepared.ambient_light); - unsigned i; + ray_object_t *light; /* 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); + for (light = scene->lights; light->type; light++) { + ray_3f_t lvec = ray_3f_sub(&light->light.emitter.point.center, intersection); float ldist = ray_3f_length(&lvec); float lvec_normal_dot; @@ -89,7 +89,7 @@ static inline ray_color_t shade_intersection(ray_scene_t *scene, ray_object_t *o ray_color_t specular; /* FIXME: assumes light is a point for its color */ - specular = ray_3f_mult_scalar(&scene->lights[i].light.emitter.point.surface.color, approx_powf(rvec_lvec_dot, surface.highlight_exponent)); + specular = ray_3f_mult_scalar(&light->light.emitter.point.surface.color, approx_powf(rvec_lvec_dot, surface.highlight_exponent)); specular = ray_3f_mult_scalar(&specular, surface.specular); color = ray_3f_add(&color, &specular); } @@ -113,10 +113,9 @@ static inline ray_object_t * find_nearest_intersection(ray_scene_t *scene, ray_o { ray_object_t *nearest_object = NULL; float nearest_object_distance = INFINITY; - unsigned i; + ray_object_t *object; - for (i = 0; i < scene->n_objects; i++) { - ray_object_t *object = &scene->objects[i]; + for (object = scene->objects; object->type; object++) { float distance; /* Don't bother checking if a reflected ray intersects the object reflecting it, @@ -213,11 +212,11 @@ void ray_scene_render_fragment(ray_scene_t *scene, fb_fragment_t *fb_fragment) /* 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; + ray_object_t *object; scene->_prepared.ambient_light = ray_3f_mult_scalar(&scene->ambient_color, scene->ambient_brightness); ray_camera_frame_prepare(camera, &scene->_prepared.frame); - for (i = 0; i < scene->n_objects; i++) - ray_object_prepare(&scene->objects[i], camera); + for (object = scene->objects; object->type; object++) + ray_object_prepare(object, camera); } -- cgit v1.2.1