summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libdimension/dimension/finishes.h5
-rw-r--r--libdimension/finishes.c51
-rw-r--r--libdimension/scene.c4
-rw-r--r--tests/libdimension/tests.c10
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) {