From 324de43f622ace14a51384cdf8bb7bb190b58699 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Tue, 17 Nov 2009 19:08:00 -0500 Subject: Implement phong shading. --- libdimension/dimension/finishes.h | 5 ++-- libdimension/finishes.c | 51 +++++++++++++++++++++++++++++++-------- libdimension/scene.c | 4 +++ 3 files changed, 48 insertions(+), 12 deletions(-) (limited to 'libdimension') 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 /* For malloc */ +#include 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; -- cgit v1.2.3