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/finishes.c | 51 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 10 deletions(-) (limited to 'libdimension/finishes.c') 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; } -- cgit v1.2.3