summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@gmail.com>2009-11-17 18:32:39 -0500
committerTavian Barnes <tavianator@gmail.com>2009-11-17 18:32:39 -0500
commit9f36c26a7f75a58564f60878c42381b451d7d7ba (patch)
treeec070dd2d2f7078bf3aebba4dade28d69043b375
parent54e1ad43c7629d85f88cefbecdfe3e60e8c42294 (diff)
downloaddimension-9f36c26a7f75a58564f60878c42381b451d7d7ba.tar.xz
Make finish callback a propper BRDF.
-rw-r--r--libdimension/dimension/geometry.h8
-rw-r--r--libdimension/dimension/texture.h9
-rw-r--r--libdimension/finishes.c11
-rw-r--r--libdimension/raytrace.c55
-rw-r--r--tests/libdimension/tests.c1
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 };