From 1d5d0439283916f190218a827a7cd7f1fe6de600 Mon Sep 17 00:00:00 2001 From: Josh Holtrop Date: Tue, 12 Oct 2010 16:39:29 +0000 Subject: [PATCH] reworked Scene::traceRayRecurse() to handle backfaces properly for refraction git-svn-id: svn://anubis/fart/trunk@378 7f9b0f55-74a9-4bce-be96-3c2cd072584d --- main/Scene.cc | 106 ++++++++++++++++++++++++------------------- scenes/for-test.fart | 18 +++++++- 2 files changed, 76 insertions(+), 48 deletions(-) diff --git a/main/Scene.cc b/main/Scene.cc index 542ccfa..306ae55 100644 --- a/main/Scene.cc +++ b/main/Scene.cc @@ -119,8 +119,7 @@ void Scene::renderPixel(int x, int y, unsigned char * pixel) Color Scene::traceRay(const Ray & ray) { - static refptr air = new Material(); - return traceRayRecurse(ray, m_max_depth, 1.0, air); + return traceRayRecurse(ray, m_max_depth, 1.0, NULL); } /** @@ -129,7 +128,11 @@ Color Scene::traceRay(const Ray & ray) Color Scene::traceRayRecurse(const Ray & ray, int depth, double factor, refptr last_material) { - Color color; + static refptr air = new Material(); + Color color(0, 0, 0); + + if (last_material.isNull()) + last_material = air; Shape::Intersection hit = getRayClosestHit(ray); @@ -139,52 +142,63 @@ Color Scene::traceRayRecurse(const Ray & ray, int depth, double factor, refptr material = hit.shape->getMaterial(); /* check for backfaces */ - if (ray.getDirection() % hit.normal > 0.0) + bool frontface = ray.getDirection() % hit.normal < 0.0; + + if (frontface) { - /* if dot product is positive, this is a back-face */ - hit.normal = -hit.normal; + color = computePhong(material, + ray, + hit.position, + hit.normal); + + if (depth > 0 && factor > SCENE_FACTOR_THRESHOLD) + { + double reflectance = material->getReflectance(); + if (factor * reflectance > SCENE_FACTOR_THRESHOLD) + { + color *= (1.0 - reflectance); + Vector reflected_direction = + ray.getDirection().reflect(hit.normal); + Ray newRay(hit.position, reflected_direction); + Vector jitter_surface_point = newRay[0.0001]; + Ray jitterNewRay(jitter_surface_point, reflected_direction); + Color c = traceRayRecurse(jitterNewRay, + depth - 1, + factor * reflectance, + material); + color += c * reflectance; + } + + double transparency = material->getTransparency(); + if (factor * transparency > SCENE_FACTOR_THRESHOLD) + { + color *= (1.0 - transparency); + Vector jitter_surface_point = hit.position + + ray.getDirection() * 0.0001; + Vector refracted_direction = + ray.getDirection().refract(hit.normal, + last_material->getRefraction(), + material->getRefraction()); + Ray newRay(jitter_surface_point, refracted_direction); + Color c = traceRayRecurse(newRay, + depth - 1, + factor * transparency, + material); + color += c * transparency; + } + } } - - color = computePhong(material, - ray, - hit.position, - hit.normal); - - if (depth > 0 && factor > SCENE_FACTOR_THRESHOLD) + else { - double reflectance = material->getReflectance(); - if (factor * reflectance > SCENE_FACTOR_THRESHOLD) - { - color *= (1.0 - reflectance); - Vector reflected_direction = - ray.getDirection().reflect(hit.normal); - Ray newRay(hit.position, reflected_direction); - Vector jitter_surface_point = newRay[0.0001]; - Ray jitterNewRay(jitter_surface_point, reflected_direction); - Color c = traceRayRecurse(jitterNewRay, - depth - 1, - factor * reflectance, - material); - color += c * reflectance; - } - - double transparency = material->getTransparency(); - if (factor * transparency > SCENE_FACTOR_THRESHOLD) - { - color *= (1.0 - transparency); - Vector jitter_surface_point = hit.position - + ray.getDirection() * 0.0001; - Vector refracted_direction = - ray.getDirection().refract(hit.normal, - last_material->getRefraction(), - material->getRefraction()); - Ray newRay(jitter_surface_point, refracted_direction); - Color c = traceRayRecurse(newRay, - depth - 1, - factor * transparency, - material); - color += c * transparency; - } + material = air; + Vector jitter_surface_point = hit.position + + ray.getDirection() * 0.0001; + Vector refracted_direction = + ray.getDirection().refract(-hit.normal, + last_material->getRefraction(), + material->getRefraction()); + Ray newRay(jitter_surface_point, refracted_direction); + color = traceRayRecurse(newRay, depth, factor, material); } } diff --git a/scenes/for-test.fart b/scenes/for-test.fart index fdef550..1288cd5 100644 --- a/scenes/for-test.fart +++ b/scenes/for-test.fart @@ -3,7 +3,7 @@ scene { camera { - position <0, 0, 40> + position <0, -40, 40> look_at <0, 100, 5> } @@ -17,6 +17,12 @@ scene color <0, 0.8, 1> } + define material glass + { + transparency 1 + refraction 1.5 + } + plane { position <0, 0, 1>, 0 @@ -34,7 +40,15 @@ scene { radius 10 translate <$x, $y, 10> - material mat + if ($x == 0 && $y == 0) + { + material glass + translate <0, 0, 20> + } + else + { + material mat + } } } }