diff options
author | Tavian Barnes <tavianator@gmail.com> | 2009-11-17 19:08:00 -0500 |
---|---|---|
committer | Tavian Barnes <tavianator@gmail.com> | 2009-11-17 19:08:00 -0500 |
commit | 324de43f622ace14a51384cdf8bb7bb190b58699 (patch) | |
tree | b72aa30713627c15f352894ea0a366373f1d43e4 | |
parent | 9f36c26a7f75a58564f60878c42381b451d7d7ba (diff) | |
download | dimension-324de43f622ace14a51384cdf8bb7bb190b58699.tar.xz |
Implement phong shading.
-rw-r--r-- | libdimension/dimension/finishes.h | 5 | ||||
-rw-r--r-- | libdimension/finishes.c | 51 | ||||
-rw-r--r-- | libdimension/scene.c | 4 | ||||
-rw-r--r-- | tests/libdimension/tests.c | 10 |
4 files changed, 56 insertions, 14 deletions
diff --git a/libdimension/dimension/finishes.h b/libdimension/dimension/finishes.h index 5f00d43..e3d0597 100644 --- a/libdimension/dimension/finishes.h +++ b/libdimension/dimension/finishes.h @@ -25,7 +25,8 @@ #ifndef DIMENSION_FINISHES_H #define DIMENSION_FINISHES_H -/* A diffuse finish */ -dmnsn_finish *dmnsn_new_diffuse_finish(); +/* A phong finish */ +dmnsn_finish *dmnsn_new_phong_finish(double diffuse, double specular, + double exp); #endif /* DIMENSION_FINISHES_H */ diff --git a/libdimension/finishes.c b/libdimension/finishes.c index d70cfb7..a7cfaea 100644 --- a/libdimension/finishes.c +++ b/libdimension/finishes.c @@ -20,25 +20,56 @@ #include "dimension.h" #include <stdlib.h> /* For malloc */ +#include <math.h> dmnsn_color -dmnsn_diffuse_finish_fn(const dmnsn_finish *finish, - dmnsn_color light, dmnsn_color color, - dmnsn_vector ray, dmnsn_vector normal, - dmnsn_vector viewer) +dmnsn_phong_finish_fn(const dmnsn_finish *finish, + dmnsn_color light, dmnsn_color color, + dmnsn_vector ray, dmnsn_vector normal, + dmnsn_vector viewer) { - double diffuse = dmnsn_vector_dot(ray, normal); - dmnsn_color illum = dmnsn_color_illuminate(light, color); - return dmnsn_color_mul(diffuse, illum); + double *params = finish->ptr; + + double diffuse = params[0]; + double specular = params[1]; + double exp = params[2]; + + /* Diffuse component */ + double diffuse_factor = diffuse*dmnsn_vector_dot(ray, normal); + dmnsn_color diffuse_color + = dmnsn_color_mul(diffuse_factor, dmnsn_color_illuminate(light, color)); + + /* Specular component */ + + dmnsn_vector proj = dmnsn_vector_mul(2*dmnsn_vector_dot(ray, normal), normal); + dmnsn_vector reflected = dmnsn_vector_sub(proj, ray); + + double specular_factor + = specular*pow(dmnsn_vector_dot(reflected, viewer), exp); + dmnsn_color specular_color = dmnsn_color_mul(specular_factor, light); + + return dmnsn_color_add(diffuse_color, specular_color); } -/* A diffuse finish */ +/* A phong finish */ dmnsn_finish * -dmnsn_new_diffuse_finish() +dmnsn_new_phong_finish(double diffuse, double specular, double exp) { dmnsn_finish *finish = dmnsn_new_finish(); if (finish) { - finish->finish_fn = &dmnsn_diffuse_finish_fn; + double *params = malloc(3*sizeof(double)); + if (!params) { + dmnsn_delete_finish(finish); + return NULL; + } + + params[0] = diffuse; + params[1] = specular; + params[2] = exp; + + finish->ptr = params; + finish->finish_fn = &dmnsn_phong_finish_fn; + finish->free_fn = &free; } return finish; } diff --git a/libdimension/scene.c b/libdimension/scene.c index 38b1d19..7a39679 100644 --- a/libdimension/scene.c +++ b/libdimension/scene.c @@ -28,6 +28,10 @@ dmnsn_new_scene() dmnsn_scene *scene = malloc(sizeof(dmnsn_scene)); if (scene) { scene->default_texture = dmnsn_new_texture(); + if (!scene->default_texture) { + dmnsn_delete_scene(scene); + return NULL; + } scene->camera = NULL; scene->canvas = NULL; diff --git a/tests/libdimension/tests.c b/tests/libdimension/tests.c index fe914f4..e5d4a06 100644 --- a/tests/libdimension/tests.c +++ b/tests/libdimension/tests.c @@ -31,7 +31,13 @@ dmnsn_new_default_scene() } /* Default finish */ - scene->default_texture->finish = dmnsn_new_diffuse_finish(); + + scene->default_texture->finish = dmnsn_new_phong_finish(1.0, 0.5, 50.0); + if (!scene->default_texture->finish) { + dmnsn_delete_scene(scene); + return NULL; + } + scene->default_texture->finish->ambient = 0.1; /* Background color */ @@ -116,7 +122,7 @@ dmnsn_new_default_scene() /* Now make a light */ dmnsn_light *light = dmnsn_new_point_light( - dmnsn_vector_construct(-5.0, 20.0, -5.0), + dmnsn_vector_construct(-15.0, 20.0, -5.0), dmnsn_white ); if (!light) { |