summaryrefslogtreecommitdiffstats
path: root/libdimension
diff options
context:
space:
mode:
Diffstat (limited to 'libdimension')
-rw-r--r--libdimension/dimension/finishes.h5
-rw-r--r--libdimension/finishes.c51
-rw-r--r--libdimension/scene.c4
3 files changed, 48 insertions, 12 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;