From 9ec2d061958458ff430073905397c2cb0df85a87 Mon Sep 17 00:00:00 2001 From: Vito Caputo Date: Sat, 27 May 2017 09:46:49 -0700 Subject: ray: use approximate power in specular reflection powf() is slow but precise, this isn't the fastest method but it's at least portable and a bit faster. --- src/modules/ray/ray_scene.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/modules/ray/ray_scene.c b/src/modules/ray/ray_scene.c index 87a77af..d9b8277 100644 --- a/src/modules/ray/ray_scene.c +++ b/src/modules/ray/ray_scene.c @@ -36,6 +36,16 @@ static inline int ray_is_obstructed(ray_scene_t *scene, ray_ray_t *ray, float di } +/* a faster powf() that's good enough for our purposes. + * XXX: note there's a faster technique which exploits the IEEE floating point format: + * https://github.com/ekmett/approximate/blob/master/cbits/fast.c#L185 + */ +static inline float approx_powf(float x, float y) +{ + return expf(y * logf(x)); +} + + /* 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) { @@ -82,10 +92,12 @@ static inline ray_color_t shade_ray(ray_scene_t *scene, ray_ray_t *ray, ray_obje diffuse = ray_3f_mult_scalar(&diffuse, surface.diffuse); color = ray_3f_add(&color, &diffuse); - /* FIXME: assumes light is a point for its color */ - specular = ray_3f_mult_scalar(&scene->lights[i].light.emitter.point.surface.color, powf(rvec_lvec_dot, surface.highlight_exponent)); - specular = ray_3f_mult_scalar(&specular, surface.specular); - color = ray_3f_add(&color, &specular); + if (rvec_lvec_dot > 0) { + /* 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(&specular, surface.specular); + color = ray_3f_add(&color, &specular); + } #else ray_color_t diffuse; -- cgit v1.2.3