aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian T <julian@jtle.dk>2020-03-27 16:21:44 +0100
committerJulian T <julian@jtle.dk>2020-03-27 16:21:44 +0100
commit86848ec1abaec38435d93d99a80cd5476967bd23 (patch)
tree4d421ed64e3e022fbc95553983286f20476b7829
parenta9651189ac52139c374f97a311d090a8d95b957e (diff)
Sphere light workingarea_light
-rw-r--r--main.c14
-rw-r--r--ray.c56
2 files changed, 55 insertions, 15 deletions
diff --git a/main.c b/main.c
index 50d8829..9dd30d9 100644
--- a/main.c
+++ b/main.c
@@ -124,7 +124,7 @@ int main()
o->m = mpl;
o = add_object(cont, TYPE_PLANE);
- vector_set(&o->pl.start, 0, 0, -3);
+ vector_set(&o->pl.start, 0, 0, -5);
vector_set(&o->pl.norm, 0, 0, 1);
o->m = mpl;
@@ -144,18 +144,16 @@ int main()
o->m = mplred;
// Used for the light ball
- /*
o = add_object(cont, TYPE_SPHERE);
- vector_set(&o->sph.center, 2, 8, -2);
+ vector_set(&o->sph.center, 2, 7, 0);
o->sph.radius = 1;
o->m = ml;
- */
- light_t *l = add_light(cont, TYPE_L_POINT);
- vector_set(&l->point.pos, 2, 8, -1);
- //l->area = o;
+ light_t *l = add_light(cont, TYPE_L_AREA);
+ //vector_set(&l->point.pos, 2, 8, -1);
+ l->area = o;
color_set(&l->color, 1, 1, 1);
- l->radiance = 5;
+ l->radiance = 0.8;
pgm_write_header(stdout, TESTW, TESTH);
diff --git a/ray.c b/ray.c
index 3932f23..c445530 100644
--- a/ray.c
+++ b/ray.c
@@ -192,28 +192,63 @@ static void contribution_from_pointlight(space_t *s, color_t *dest, object_t *o,
static void contribution_from_arealight(space_t *s, color_t *dest, object_t *o, light_t *light, vector_t *point, vector_t *V, vector_t *N, void *seed)
{
// This only works with spheres
- assert(o->type == TYPE_SPHERE);
+ assert(light->area->type == TYPE_SPHERE);
// Color to collect temporary results in
color_t c;
+ color_set(&c, 0, 0, 0);
ray_t ray;
ray.start = point;
+ // Calculate vector from light to point
+ vector_t l;
+ vector_sub(&l, point, &light->area->sph.center);
+ vector_scale_inv(&l, &l, vector_len(&l));
+
+ // Initialize the transformation stuff
+ csystem_t cs;
+ csystem_init(&cs, &l);
+
// Do the same monte carlo as with environment but the starting point is the center of the circle.
// And the result is a point on the circle
for (int i = 0; i < 16; i++) {
// Do the monte carlo random distribution thing from the article
COORD_T r1 = ray_rand(seed);
- COORD_T r2 = ray_rand(seed);
- COORD_T sinTheta = sqrt(1 - r1 * r1);
- COORD_T phi = 2 * PI * r2;
+ // Random direction on halv sphere pointing towards point
+ vector_t randpoint;
+ csystem_hemisphere_random(&cs, r1, ray_rand(seed), &randpoint);
+ csystem_calc_real(&cs, &randpoint, &randpoint);
+
+ // Shift it up to center of circle
+ vector_add(&randpoint, &randpoint, &light->area->sph.center);
+
+ // Cast a ray towards it, reuse randpoint as direction
+ vector_sub(&randpoint, &randpoint, point);
+ COORD_T dist = vector_len(&randpoint);
- // Cast a ray
+ vector_t dir;
+ vector_scale_inv(&dir, &randpoint, dist);
+
+ ray.direction = &dir;
+
+ object_t *obs = ray_cast(s, &ray, NULL, true, dist - ZERO_APROX);
+ if (obs) {
+ // We hit something skip it.
+ continue;
+ }
+
+ // Add the light contribution, Not sure why it is scaled
+ reflected_at(o, &c, light, dist, point, &randpoint, V, N);
}
+ // Device by pdf
+ color_scale(&c, &c, ((COORD_T) 1 / 16) * (2 * PI));
+
+ color_add(dest, dest, &c);
+
}
static void direct_light(space_t *s, color_t *dest, object_t *o, vector_t *N, vector_t *eye, vector_t *point, void *seed)
@@ -229,7 +264,14 @@ static void direct_light(space_t *s, color_t *dest, object_t *o, vector_t *N, ve
light_t *light = s->lights;
while (light) {
// Calculate contribution depending on the light type
- contribution_from_pointlight(s, dest, o, light, point, &V, N);
+ switch (light->type) {
+ case TYPE_L_POINT:
+ contribution_from_pointlight(s, dest, o, light, point, &V, N);
+ break;
+ case TYPE_L_AREA:
+ contribution_from_arealight(s, dest, o, light, point, &V, N, seed);
+ break;
+ }
light = light->next;
}
@@ -252,7 +294,7 @@ static void env_light(space_t *s, color_t *dest, object_t *o, vector_t *N, vecto
for (unsigned i = 0; i < s->env_samples; i++) {
COORD_T r1 = ray_rand(seed);
- //
+
// Calculate the random direction vector
vector_t randdir;
csystem_hemisphere_random(&cs, r1, ray_rand(seed), &randdir);