From 9f36c26a7f75a58564f60878c42381b451d7d7ba Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Tue, 17 Nov 2009 18:32:39 -0500 Subject: Make finish callback a propper BRDF. --- libdimension/dimension/geometry.h | 8 ++++++ libdimension/dimension/texture.h | 9 ++++--- libdimension/finishes.c | 11 +++++--- libdimension/raytrace.c | 55 ++++++++++++++++++++++----------------- 4 files changed, 52 insertions(+), 31 deletions(-) (limited to 'libdimension') 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 @@ -76,6 +76,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) { 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 /* 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 /* For sysconf */ +#include /* 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); -- cgit v1.2.3