summaryrefslogtreecommitdiffstats
path: root/libdimension
diff options
context:
space:
mode:
Diffstat (limited to 'libdimension')
-rw-r--r--libdimension/dimension.h1
-rw-r--r--libdimension/dimension/scene.h1
-rw-r--r--libdimension/kD_splay_tree.c11
-rw-r--r--libdimension/raytrace.c153
4 files changed, 101 insertions, 65 deletions
diff --git a/libdimension/dimension.h b/libdimension/dimension.h
index 7fc25c5..d6affc2 100644
--- a/libdimension/dimension.h
+++ b/libdimension/dimension.h
@@ -70,6 +70,7 @@ typedef void dmnsn_free_fn(void *ptr);
#include <dimension/png.h>
#include <dimension/texture.h>
#include <dimension/pigments.h>
+#include <dimension/finishes.h>
#include <dimension/object.h>
#include <dimension/objects.h>
#include <dimension/light.h>
diff --git a/libdimension/dimension/scene.h b/libdimension/dimension/scene.h
index e3f9662..8108b2b 100644
--- a/libdimension/dimension/scene.h
+++ b/libdimension/dimension/scene.h
@@ -30,6 +30,7 @@ typedef enum {
DMNSN_RENDER_OBJECTS,
DMNSN_RENDER_PIGMENT,
DMNSN_RENDER_LIGHTS,
+ DMNSN_RENDER_FINISH,
DMNSN_RENDER_FULL
} dmnsn_quality;
diff --git a/libdimension/kD_splay_tree.c b/libdimension/kD_splay_tree.c
index 77e57dd..924d3a9 100644
--- a/libdimension/kD_splay_tree.c
+++ b/libdimension/kD_splay_tree.c
@@ -356,10 +356,13 @@ dmnsn_kD_splay_search_recursive(dmnsn_kD_splay_node *node, dmnsn_line ray,
result.intersection = result_temp.intersection;
t = result.intersection->t;
- /* Transform the normal vector back to the observer's view */
- result.intersection->normal = dmnsn_matrix_vector_mul(
- node->object->trans,
- result.intersection->normal
+ /* Transform the intersection back to the observer's view */
+ result.intersection->ray = ray;
+ result.intersection->normal = dmnsn_vector_normalize(
+ dmnsn_matrix_vector_mul(
+ node->object->trans,
+ result.intersection->normal
+ )
);
} else {
dmnsn_delete_intersection(result_temp.intersection);
diff --git a/libdimension/raytrace.c b/libdimension/raytrace.c
index 262929f..63385a7 100644
--- a/libdimension/raytrace.c
+++ b/libdimension/raytrace.c
@@ -254,6 +254,95 @@ dmnsn_raytrace_scene_impl(dmnsn_progress *progress, dmnsn_scene *scene,
return 0;
}
+static dmnsn_color
+dmnsn_raytrace_pigment(dmnsn_intersection *intersection, dmnsn_scene *scene)
+{
+ /* Default to black if there's no texture/pigment */
+ dmnsn_color color = dmnsn_black;
+
+ /* Use the default texture if given a NULL texture */
+ const dmnsn_texture *texture = intersection->texture ? intersection->texture
+ : scene->default_texture;
+
+ if (texture) {
+ /* Use the default pigment if given a NULL pigment */
+ const dmnsn_pigment *pigment
+ = texture->pigment ? texture->pigment
+ : scene->default_texture->pigment;
+
+ if (pigment) {
+ color = (*pigment->pigment_fn)(
+ pigment,
+ dmnsn_line_point(intersection->ray, intersection->t)
+ );
+ }
+ }
+
+ return color;
+}
+
+static dmnsn_color
+dmnsn_raytrace_shadow(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
+ : scene->default_texture;
+
+ const dmnsn_finish *finish = NULL;
+ if (texture) {
+ /* Use the default finish if given a NULL finish */
+ finish = texture->finish ? texture->finish : scene->default_texture->finish;
+ }
+
+ dmnsn_color illum = dmnsn_color_mul(0.3, 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
+ ray */
+ dmnsn_vector_add(
+ x0,
+ dmnsn_vector_mul(1.0e-9, dmnsn_vector_sub(light->x0, x0))
+ ),
+ dmnsn_vector_sub(light->x0, x0)
+ );
+
+ dmnsn_intersection *shadow_caster
+ = dmnsn_kD_splay_search(kD_splay_tree, shadow_ray);
+
+ 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) {
+ illum = dmnsn_color_add((*finish->finish_fn)(finish, effective, x0,
+ normal, reflected),
+ illum);
+ } else {
+ illum = effective;
+ }
+ }
+
+ dmnsn_delete_intersection(shadow_caster);
+ }
+
+ return illum;
+}
+
/* Shoot a ray, and calculate the color, using `color' as the background */
static dmnsn_color
dmnsn_raytrace_shoot(dmnsn_line ray, dmnsn_scene *scene,
@@ -262,75 +351,17 @@ dmnsn_raytrace_shoot(dmnsn_line ray, dmnsn_scene *scene,
dmnsn_intersection *intersection = dmnsn_kD_splay_search(kD_splay_tree, ray);
if (intersection) {
- /* Default to black if we have no texture/pigment */
+ /* Default to black if we aren't rendering pigments */
color = dmnsn_black;
if (scene->quality >= DMNSN_RENDER_PIGMENT) {
- /* Use the default texture if given a NULL texture */
- const dmnsn_texture *texture
- = intersection->texture ? intersection->texture
- : scene->default_texture;
-
- if (texture) {
- /* Use the default pigment if given a NULL pigment */
- const dmnsn_pigment *pigment
- = texture->pigment ? texture->pigment
- : scene->default_texture->pigment;
-
- if (pigment) {
- color = (*pigment->pigment_fn)(
- pigment,
- dmnsn_line_point(intersection->ray, intersection->t)
- );
- }
- }
+ color = dmnsn_raytrace_pigment(intersection, scene);
}
if (scene->quality >= DMNSN_RENDER_LIGHTS) {
- dmnsn_color illum = dmnsn_color_mul(0.3, 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(ray, intersection->t);
- dmnsn_line shadow_ray = dmnsn_line_construct(
- dmnsn_vector_add(
- x0,
- dmnsn_vector_mul(1.0e-6, dmnsn_vector_sub(light->x0, x0))
- ),
- dmnsn_vector_sub(light->x0, x0)
- );
-
- dmnsn_intersection *shadow_caster
- = dmnsn_kD_splay_search(kD_splay_tree, shadow_ray);
-
- if (!shadow_caster || shadow_caster->t > 1.0) {
- dmnsn_vector object_normal = intersection->normal;
- dmnsn_vector normal = dmnsn_vector_normalize(
- dmnsn_vector_add(
- dmnsn_vector_normalize(dmnsn_vector_sub(ray.x0, x0)),
- dmnsn_vector_normalize(dmnsn_vector_sub(light->x0, x0))
- )
- );
-
- illum = dmnsn_color_add(
- dmnsn_color_mul(
- dmnsn_vector_dot(normal, object_normal),
- dmnsn_color_illuminate((*light->light_fn)(light, x0), color)
- ),
- illum
- );
- }
-
- dmnsn_delete_intersection(shadow_caster);
- }
-
- color = illum;
+ color = dmnsn_raytrace_shadow(intersection, scene, kD_splay_tree, color);
}
- /* Delete the intersection */
dmnsn_delete_intersection(intersection);
}