diff -r 33f95441790e -r b4e09433934a src/raytracer.cc --- 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::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; } }