--- a/src/raytracer.cc Sat Dec 08 16:02:37 2007 +0100
+++ b/src/raytracer.cc Sun Dec 09 10:45:26 2007 +0100
@@ -99,13 +99,19 @@
if (nearest_shape == NULL) {
return bg_colour;
} else {
- Colour acc = Colour();
+ Colour col = Colour();
Vector3 P = ray.o + ray.dir * nearest_distance; // point of intersection
Vector3 normal = nearest_shape->normal(P);
+ bool from_inside = false;
+
// make shapes double sided
if (dot(normal, ray.dir) > 0.0)
+ {
normal = - normal;
- acc = PhongShader_ambient(*nearest_shape->material, P);
+ from_inside = true;
+ }
+
+ col = PhongShader_ambient(*nearest_shape->material, P);
vector<Light*>::iterator light;
for (light = lights.begin(); light != lights.end(); light++) {
@@ -123,22 +129,66 @@
// shading function
Vector3 R = L - 2.0 * L_dot_N * normal;
- acc += PhongShader_calculate(*nearest_shape->material,
+ col += PhongShader_calculate(*nearest_shape->material,
P, normal, R, ray.dir, **light);
}
}
- // reflection
- Vector3 newdir = ray.dir - 2.0 * dot(ray.dir, normal) * normal;
- if (depth < max_depth && nearest_shape->material->reflection > 0.01) {
- Ray newray = Ray(P, newdir);
- Colour refl_col = raytrace(newray, depth + 1, nearest_shape);
- acc += nearest_shape->material->reflection * refl_col;
+ if (depth < max_depth)
+ {
+ Colour trans_col, refl_col;
+ Float trans = nearest_shape->material->transmissivity;
+ Float refl = nearest_shape->material->reflectivity;
+ const Float cos_i = - dot(normal, ray.dir);
+
+ // reflection
+ if (refl > 0.01)
+ {
+ Vector3 newdir = ray.dir + 2.0 * cos_i * normal;
+ Ray newray = Ray(P, newdir);
+ refl_col = raytrace(newray, depth + 1, nearest_shape);
+ }
+
+ // refraction
+ if (trans > 0.01)
+ {
+ Float n, n1, n2;
+ if (from_inside)
+ {
+ n1 = nearest_shape->material->refract_index;
+ n2 = 1.0;
+ n = n1;
+ }
+ else
+ {
+ n1 = 1.0;
+ n2 = nearest_shape->material->refract_index;
+ n = 1.0 / n2;
+ }
+ const Float sin2_t = n*n * (1 - cos_i*cos_i);
+ if (sin2_t >= 1.0)
+ {
+ // totally reflected
+ refl += trans;
+ trans = 0;
+ }
+ else
+ {
+ const Float cos_t = sqrtf(1 - sin2_t);
+ const Float Rdiv = 1.0/(n1*cos_i + n2*cos_t);
+ const Float Rper = (n1*cos_i - n2*cos_t)*Rdiv;
+ const Float Rpar = (n2*cos_i - n1*cos_t)*Rdiv;
+ const Float R = (Rper*Rper + Rpar*Rpar)/2;
+ refl += R*trans;
+ trans = (1-R)*trans;
+ Vector3 newdir = n * ray.dir + (n*cos_i - cos_t) * normal;
+ Ray newray = Ray(P, newdir);
+ trans_col = raytrace(newray, depth + 1, nearest_shape);
+ }
+ }
+ col = (1-refl-trans)*col + refl*refl_col + trans*trans_col;
}
- // refraction
- /* ... */
-
// ambient occlusion
if (ao_samples)
{
@@ -154,10 +204,10 @@
miss += dist / ao_distance;
}
Float ao_intensity = miss / ao_samples;
- acc = acc * ao_intensity;
+ col = col * ao_intensity;
}
- return acc;
+ return col;
}
}