diff options
author | Vito Caputo <vcaputo@pengaru.com> | 2017-05-27 09:46:49 -0700 |
---|---|---|
committer | Vito Caputo <vcaputo@pengaru.com> | 2017-05-27 09:46:49 -0700 |
commit | 9ec2d061958458ff430073905397c2cb0df85a87 (patch) | |
tree | 038f8f4e2452dd5736db7b871dbb0544f47daa37 /src/modules | |
parent | 28d8022265a12e5032ddb54077f90af9f1bcb4f5 (diff) |
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.
Diffstat (limited to 'src/modules')
-rw-r--r-- | src/modules/ray/ray_scene.c | 20 |
1 files 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; |