diff options
author | Tavian Barnes <tavianator@gmail.com> | 2009-11-17 18:32:39 -0500 |
---|---|---|
committer | Tavian Barnes <tavianator@gmail.com> | 2009-11-17 18:32:39 -0500 |
commit | 9f36c26a7f75a58564f60878c42381b451d7d7ba (patch) | |
tree | ec070dd2d2f7078bf3aebba4dade28d69043b375 | |
parent | 54e1ad43c7629d85f88cefbecdfe3e60e8c42294 (diff) | |
download | dimension-9f36c26a7f75a58564f60878c42381b451d7d7ba.tar.xz |
Make finish callback a propper BRDF.
-rw-r--r-- | libdimension/dimension/geometry.h | 8 | ||||
-rw-r--r-- | libdimension/dimension/texture.h | 9 | ||||
-rw-r--r-- | libdimension/finishes.c | 11 | ||||
-rw-r--r-- | libdimension/raytrace.c | 55 | ||||
-rw-r--r-- | tests/libdimension/tests.c | 1 |
5 files changed, 53 insertions, 31 deletions
diff --git a/libdimension/dimension/geometry.h b/libdimension/dimension/geometry.h index 86a0111..08ac1b3 100644 --- a/libdimension/dimension/geometry.h +++ b/libdimension/dimension/geometry.h @@ -77,6 +77,14 @@ dmnsn_line_construct(dmnsn_vector x0, dmnsn_vector n) /* Vector and matrix arithmetic */ DMNSN_INLINE dmnsn_vector +dmnsn_vector_negate(dmnsn_vector rhs) +{ + /* 3 negations */ + dmnsn_vector v = { -rhs.x, -rhs.y, -rhs.z }; + return v; +} + +DMNSN_INLINE dmnsn_vector dmnsn_vector_add(dmnsn_vector lhs, dmnsn_vector rhs) { /* 3 additions */ diff --git a/libdimension/dimension/texture.h b/libdimension/dimension/texture.h index 4d0e2d7..e5a1bfd 100644 --- a/libdimension/dimension/texture.h +++ b/libdimension/dimension/texture.h @@ -58,12 +58,15 @@ typedef struct dmnsn_finish dmnsn_finish; /* Finish callback */ typedef dmnsn_color dmnsn_finish_fn(const dmnsn_finish *finish, - dmnsn_color color, dmnsn_vector x0, - dmnsn_vector normal, - dmnsn_vector reflected); + dmnsn_color light, dmnsn_color color, + dmnsn_vector ray, dmnsn_vector normal, + dmnsn_vector viewer); /* dmnsn_finish definition */ struct dmnsn_finish { + /* Ambient contribution factor */ + double ambient; + /* Callbacks */ dmnsn_finish_fn *finish_fn; dmnsn_free_fn *free_fn; diff --git a/libdimension/finishes.c b/libdimension/finishes.c index befe6c6..d70cfb7 100644 --- a/libdimension/finishes.c +++ b/libdimension/finishes.c @@ -21,12 +21,15 @@ #include "dimension.h" #include <stdlib.h> /* For malloc */ -static dmnsn_color +dmnsn_color dmnsn_diffuse_finish_fn(const dmnsn_finish *finish, - dmnsn_color color, dmnsn_vector x0, - dmnsn_vector normal, dmnsn_vector reflected) + dmnsn_color light, dmnsn_color color, + dmnsn_vector ray, dmnsn_vector normal, + dmnsn_vector viewer) { - return dmnsn_color_mul(dmnsn_vector_dot(normal, reflected), color); + double diffuse = dmnsn_vector_dot(ray, normal); + dmnsn_color illum = dmnsn_color_illuminate(light, color); + return dmnsn_color_mul(diffuse, illum); } /* A diffuse finish */ diff --git a/libdimension/raytrace.c b/libdimension/raytrace.c index 3a266a2..7608d85 100644 --- a/libdimension/raytrace.c +++ b/libdimension/raytrace.c @@ -20,6 +20,7 @@ #include "dimension_impl.h" #include <unistd.h> /* For sysconf */ +#include <stdbool.h> /* Payload type for passing arguments to worker thread */ @@ -279,8 +280,8 @@ dmnsn_raytrace_pigment(dmnsn_intersection *intersection, dmnsn_scene *scene) } static dmnsn_color -dmnsn_raytrace_shadow(dmnsn_intersection *intersection, dmnsn_scene *scene, - dmnsn_kD_splay_tree *kD_splay_tree, dmnsn_color color) +dmnsn_raytrace_lighting(dmnsn_intersection *intersection, dmnsn_scene *scene, + dmnsn_kD_splay_tree *kD_splay_tree, dmnsn_color color) { /* Use the default texture if given a NULL texture */ const dmnsn_texture *texture = intersection->texture ? intersection->texture @@ -292,13 +293,17 @@ dmnsn_raytrace_shadow(dmnsn_intersection *intersection, dmnsn_scene *scene, finish = texture->finish ? texture->finish : scene->default_texture->finish; } - dmnsn_color illum = dmnsn_color_mul(0.1, color); + /* The illuminated color */ + dmnsn_color illum = dmnsn_black; + if (finish) + illum = dmnsn_color_mul(finish->ambient, color); const dmnsn_light *light; unsigned int i; for (i = 0; i < dmnsn_array_size(scene->lights); ++i) { dmnsn_array_get(scene->lights, i, &light); + dmnsn_vector x0 = dmnsn_line_point(intersection->ray, intersection->t); dmnsn_line shadow_ray = dmnsn_line_construct( /* Add epsilon*(light->x0 - x0) to avoid hitting ourself with the shadow @@ -310,31 +315,30 @@ dmnsn_raytrace_shadow(dmnsn_intersection *intersection, dmnsn_scene *scene, dmnsn_vector_sub(light->x0, x0) ); + /* Search for an object in the way of the light source */ dmnsn_intersection *shadow_caster = dmnsn_kD_splay_search(kD_splay_tree, shadow_ray); + bool lit = !shadow_caster || shadow_caster->t > 1.0; + dmnsn_delete_intersection(shadow_caster); - if (!shadow_caster || shadow_caster->t > 1.0) { - dmnsn_vector normal = intersection->normal; - dmnsn_vector reflected = dmnsn_vector_normalize( - dmnsn_vector_add( - dmnsn_vector_normalize(dmnsn_vector_sub(intersection->ray.x0, x0)), - dmnsn_vector_normalize(dmnsn_vector_sub(light->x0, x0)) - ) - ); - - dmnsn_color effective - = dmnsn_color_illuminate((*light->light_fn)(light, x0), color); + if (scene->quality >= DMNSN_RENDER_FINISH && finish) { + dmnsn_color light_color = dmnsn_black; + if (lit) + light_color = (*light->light_fn)(light, x0); - if (scene->quality >= DMNSN_RENDER_FINISH && finish) { - illum = dmnsn_color_add((*finish->finish_fn)(finish, effective, x0, - normal, reflected), - illum); - } else { - illum = effective; - } + dmnsn_vector ray = dmnsn_vector_normalize(shadow_ray.n); + dmnsn_vector normal = intersection->normal; + dmnsn_vector viewer + = dmnsn_vector_normalize(dmnsn_vector_negate(intersection->ray.n)); + + /* Get this light's color contribution to the object */ + dmnsn_color contrib = (*finish->finish_fn)(finish, + light_color, color, + ray, normal, viewer); + illum = dmnsn_color_add(contrib, illum); + } else if (lit) { + illum = color; } - - dmnsn_delete_intersection(shadow_caster); } return illum; @@ -356,7 +360,10 @@ dmnsn_raytrace_shoot(dmnsn_line ray, dmnsn_scene *scene, } if (scene->quality >= DMNSN_RENDER_LIGHTS) { - color = dmnsn_raytrace_shadow(intersection, scene, kD_splay_tree, color); + color = dmnsn_raytrace_lighting(intersection, + scene, + kD_splay_tree, + color); } dmnsn_delete_intersection(intersection); diff --git a/tests/libdimension/tests.c b/tests/libdimension/tests.c index 85c43a6..fe914f4 100644 --- a/tests/libdimension/tests.c +++ b/tests/libdimension/tests.c @@ -32,6 +32,7 @@ dmnsn_new_default_scene() /* Default finish */ scene->default_texture->finish = dmnsn_new_diffuse_finish(); + scene->default_texture->finish->ambient = 0.1; /* Background color */ dmnsn_sRGB sRGB = { .R = 0.0, .G = 0.0, .B = 0.1 }; |