aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian T <julian@jtle.dk>2020-02-21 14:42:42 +0100
committerJulian T <julian@jtle.dk>2020-02-21 14:42:42 +0100
commit9b40029e42f994aeff59ecc44a6d3b8fba93071d (patch)
treec133f8f6190b445560c4d8438ba89d7caaa0a7cd
parent623fee395425ab33f14fb9cd8ffa790e362f59d7 (diff)
Pretty realistic colors
-rw-r--r--main.c7
-rw-r--r--pgm.c39
-rw-r--r--pgm.h4
-rw-r--r--ray.c43
-rw-r--r--scene.c23
-rw-r--r--scene.h15
6 files changed, 108 insertions, 23 deletions
diff --git a/main.c b/main.c
index 011f2c1..0f0103a 100644
--- a/main.c
+++ b/main.c
@@ -19,6 +19,9 @@ int main()
s.objects = NULL;
s.lights = NULL;
+ material_t m;
+ vector_set(&m.color, 0, 1, 0);
+
vector_set(&s.view.position, 0, 15, 10);
vector_set(&s.view.target, 0, 0, 0);
s.view.width = TESTW;
@@ -27,8 +30,8 @@ int main()
viewpoint_init(&s.view);
// Setup plane
- add_sphere(&s, vector_set(NULL, 0, 0, 5), 5);
- add_sphere(&s, vector_set(NULL, 10, 0, 5), 5);
+ add_sphere(&s, vector_set(NULL, 0, 0, 5), 5, &m);
+ //add_sphere(&s, vector_set(NULL, 10, 0, 5), 5);
add_plane(&s, vector_set(NULL, 0, 0, 2), vector_set(NULL, 0, 0, 1));
add_light(&s, vector_set(NULL, 10, 0, 20), color_set(NULL, 255, 255, 255));
diff --git a/pgm.c b/pgm.c
index 058b445..90791de 100644
--- a/pgm.c
+++ b/pgm.c
@@ -25,3 +25,42 @@ color_t *color_set(color_t *c, uint8_t r, uint8_t g, uint8_t b)
return c;
}
+
+color_t *color_add(color_t *dest, color_t *a, color_t *b)
+{
+ if (!dest) {
+ dest = (color_t *) malloc(sizeof(dest));
+ }
+
+ dest->r = a->r + b->r;
+ dest->g = a->g + b->g;
+ dest->b = a->b + b->b;
+
+ return dest;
+}
+
+color_t *color_scale(color_t *dest, color_t *a, float b)
+{
+ if (!dest) {
+ dest = (color_t *) malloc(sizeof(dest));
+ }
+
+ dest->r = a->r * b;
+ dest->g = a->g * b;
+ dest->b = a->b * b;
+
+ return dest;
+}
+
+color_t *color_scale_vector(color_t *dest, color_t *a, vector_t *v)
+{
+ if (!dest) {
+ dest = (color_t *) malloc(sizeof(dest));
+ }
+
+ dest->r = a->r * v->x;
+ dest->g = a->g * v->y;
+ dest->b = a->b * v->z;
+
+ return dest;
+}
diff --git a/pgm.h b/pgm.h
index b8900b8..3e40034 100644
--- a/pgm.h
+++ b/pgm.h
@@ -3,12 +3,16 @@
#include <stdio.h>
#include <stdint.h>
+#include "vector.h"
typedef struct {
uint8_t r, g, b;
} color_t;
color_t *color_set(color_t *c, uint8_t r, uint8_t g, uint8_t b);
+color_t *color_scale(color_t *dest, color_t *a, float b);
+color_t *color_add(color_t *dest, color_t *a, color_t *b);
+color_t *color_scale_vector(color_t *dest, color_t *a, vector_t *v);
int pgm_write_header(FILE *fp, unsigned int w, unsigned int h);
int pgm_write_pixel(FILE *fp, color_t *c);
diff --git a/ray.c b/ray.c
index 3736773..0e82546 100644
--- a/ray.c
+++ b/ray.c
@@ -142,33 +142,46 @@ color_t *ray_trace(space_t *s, unsigned int x, unsigned int y)
if (!o) {
return NULL;
}
- //printf("dist: %f\n", dist);
// Calculate new ray point
r.start = vector_scale(NULL, r.direction, dist);
vector_add(r.start, r.start, &s->view.position);
+ // Calculate normal vector
+ vector_t n;
+ obj_norm_at(o, &n, r.start);
+
+ // Hit color
+ color_t *c = color_set(NULL, 0, 0, 0);
+
// Cast light rays
- light_t *l = s->lights;
- while (l) {
- vector_t tmp;
+ light_t *light = s->lights;
+ while (light) {
+ vector_t l;
// Calculate distance to light
- vector_sub(&tmp, l->pos, r.start);
- COORD_T d = vector_len(&tmp);
-
- // Calculate unit
- vector_scale_inv(&tmp, &tmp, vector_len(&tmp));
+ vector_sub(&l, light->pos, r.start);
+ COORD_T d = vector_len(&l);
// Find obstacles
- r.direction = &tmp;
+ r.direction = &l;
object_t *obs = ray_cast(s, &r, NULL, true, d);
-
- if (!obs) {
- return color_set(NULL, 100, 100, o->type == TYPE_SPHERE ? 200 :0);
+ if (obs) {
+ light = light->next;
+ continue;
}
+
+ // Calculate unit
+ vector_scale_inv(&l, &l, vector_len(&l));
+ color_t tmp;
+ color_scale(&tmp, light->defuse, vector_dot(&l, &n));
+ color_add(c, &tmp, c);
- l = l->next;
+ light = light->next;
+ }
+
+ if (o->m) {
+ color_scale_vector(c, c, &o->m->color);
}
- return NULL;
+ return c;
}
diff --git a/scene.c b/scene.c
index a75b329..99ae0e8 100644
--- a/scene.c
+++ b/scene.c
@@ -12,11 +12,13 @@ static inline void link_object(space_t *s, object_t *o)
}
}
-object_t *add_sphere(space_t *s, vector_t *c, COORD_T r)
+object_t *add_sphere(space_t *s, vector_t *c, COORD_T r, material_t *m)
{
object_t *o = (object_t *) malloc(sizeof(object_t));
o->type = TYPE_SPHERE;
+ o->m = m;
+
o->sph.center = c;
o->sph.radius = r;
@@ -38,12 +40,12 @@ object_t *add_plane(space_t *s, vector_t *start, vector_t *dir)
return o;
}
-light_t *add_light(space_t *s, vector_t *pos, color_t *c)
+light_t *add_light(space_t *s, vector_t *pos, color_t *defuse)
{
light_t *o = (light_t *) malloc(sizeof(light_t));
o->pos = pos;
- o->col = c;
+ o->defuse = defuse;
if (s) {
o->next = s->lights;
@@ -54,3 +56,18 @@ light_t *add_light(space_t *s, vector_t *pos, color_t *c)
return o;
}
+
+void obj_norm_at(object_t *o, vector_t *dest, vector_t *point)
+{
+ switch(o->type) {
+ case TYPE_SPHERE:
+ vector_sub(dest, point, o->sph.center);
+ vector_scale_inv(dest, dest, vector_len(dest));
+ break;
+ case TYPE_PLANE:
+ vector_copy(dest, o->pl.norm);
+ break;
+ }
+
+ return;
+}
diff --git a/scene.h b/scene.h
index 1c6363b..7efb5cd 100644
--- a/scene.h
+++ b/scene.h
@@ -23,16 +23,23 @@ typedef struct {
typedef struct light_s{
vector_t *pos;
- color_t *col;
+ color_t *defuse;
struct light_s *next;
} light_t;
+typedef struct {
+ vector_t color;
+} material_t;
+
// General object structure
typedef struct object_s{
uint8_t type;
struct object_s *next;
+ // Color and light information
+ material_t *m;
+
union {
sphere_t sph;
plane_t pl;
@@ -45,8 +52,10 @@ typedef struct {
light_t *lights;
} space_t;
-object_t *add_sphere(space_t *s, vector_t *c, COORD_T r);
+object_t *add_sphere(space_t *s, vector_t *c, COORD_T r, material_t *m);
object_t *add_plane(space_t *s, vector_t *start, vector_t *dir);
-light_t *add_light(space_t *s, vector_t *pos, color_t *c);
+light_t *add_light(space_t *s, vector_t *pos, color_t *defuse);
+
+void obj_norm_at(object_t *o, vector_t *dest, vector_t *point);
#endif