diff --git a/main/Scene.cc b/main/Scene.cc index 750d563..efdefa8 100644 --- a/main/Scene.cc +++ b/main/Scene.cc @@ -139,10 +139,13 @@ void Scene::renderPixel(int x, int y, unsigned char * pixel) Color Scene::traceRay(const Ray & ray) { - return traceRayDepth(ray, m_max_depth); + return traceRayRecurse(ray, m_max_depth, 1.0); } -Color Scene::traceRayDepth(const Ray & ray, int depth) +/** + * factor: the proportion of the final color that this computation is worth + */ +Color Scene::traceRayRecurse(const Ray & ray, int depth, double factor) { Color color; @@ -154,13 +157,44 @@ Color Scene::traceRayDepth(const Ray & ray, int depth) refptr material = hit.shape->getMaterial(); Vector surfacePoint = ray[hit.dist]; + Vector surfaceNormal = hit.shape->getNormalAt(surfacePoint); - color += Lighting::computePhong(material, - m_lights, - ray, - surfacePoint, - hit.shape->getNormalAt(surfacePoint), - m_ambient_light); + color = Lighting::computePhong(material, + m_lights, + ray, + surfacePoint, + surfaceNormal, + m_ambient_light); + + 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(surfaceNormal); + Ray newRay(surfacePoint, reflected_direction); + Vector jitter_surface_point = newRay[0.001]; + Ray jitterNewRay(jitter_surface_point, reflected_direction); + Color c = traceRayRecurse(jitterNewRay, + depth - 1, + factor * reflectance); + color += c * reflectance; + } + + double transparency = material->getTransparency(); + if (factor * transparency > SCENE_FACTOR_THRESHOLD) + { + color *= (1.0 - transparency); + Vector jitter_surface_point = ray[hit.dist + 0.001]; + Ray newRay(jitter_surface_point, ray.getDirection()); + Color c = traceRayRecurse(newRay, + depth - 1, + factor * transparency); + color += c * transparency; + } + } } return color; diff --git a/main/Scene.h b/main/Scene.h index 8630109..fa15fb5 100644 --- a/main/Scene.h +++ b/main/Scene.h @@ -17,8 +17,7 @@ #include "parser/parser.h" #include "parser/nodes.h" -#define SCENE_MAX_TRANSPARENT_HITS 8 -#define SCENE_TRANSPARENCY_THRESHOLD 0.01 +#define SCENE_FACTOR_THRESHOLD 0.02 class Scene { @@ -51,7 +50,7 @@ class Scene /* private methods */ void renderPixel(int x, int y, unsigned char * pixel); Color traceRay(const Ray & ray); - Color traceRayDepth(const Ray & ray, int depth); + Color traceRayRecurse(const Ray & ray, int depth, double factor); ShapeDistance getRayClosestHit(const Ray & ray); /* In Scene-load.cc */ diff --git a/scenes/infinity.fart b/scenes/infinity.fart index c5dfcd9..04f9647 100644 --- a/scenes/infinity.fart +++ b/scenes/infinity.fart @@ -15,12 +15,19 @@ scene up <0, 0, 1> } - plane { position <1, 0, 0>, 2 } - plane { position <-1, 0, 0>, 2 } - plane { position <0, 1, 0>, 2 } - plane { position <0, -1, 0>, 2 } - plane { position <0, 0, 1>, 2 } - plane { position <0, 0, -1>, 2 } + define material mirror + { + color <1, 0, 0> + specular <0, 0, 0> + reflectance 1.0 + } + + plane { position <1, 0, 0>, 2 material mirror } + plane { position <-1, 0, 0>, 2 material mirror } + plane { position <0, 1, 0>, 2 material mirror } + plane { position <0, -1, 0>, 2 material mirror } + plane { position <0, 0, 1>, 2 material mirror } + plane { position <0, 0, -1>, 2 material mirror } sphere { diff --git a/shapes/Shape.cc b/shapes/Shape.cc index 7f496de..940e8fa 100755 --- a/shapes/Shape.cc +++ b/shapes/Shape.cc @@ -10,7 +10,6 @@ static bool default_material_initialized = false; Shape::Shape() { - m_transparency = 0.0; if (default_material_initialized == false) { default_material = new Material(); diff --git a/shapes/Shape.h b/shapes/Shape.h index babb0a3..1e57b6f 100644 --- a/shapes/Shape.h +++ b/shapes/Shape.h @@ -106,16 +106,12 @@ class Shape } Transform & getTransform() { return m_transform; } - void setTransparency(double t) { m_transparency = t; } - double getTransparency() const { return m_transparency; } - void setMaterial(refptr material) { m_material = material; } refptr getMaterial() const { return m_material; } protected: Transform m_transform; Transform m_inverse; - double m_transparency; refptr m_material; }; diff --git a/util/Color.cc b/util/Color.cc index a4f155b..1649356 100644 --- a/util/Color.cc +++ b/util/Color.cc @@ -71,6 +71,14 @@ Color & Color::operator-=(const Color & other) return *this; } +Color & Color::operator*=(double scale) +{ + r *= scale; + g *= scale; + b *= scale; + return *this; +} + Color operator+(const Color & c1, const Color & c2) { return Color(c1.r + c2.r, c1.g + c2.g, c1.b + c2.b); diff --git a/util/Color.h b/util/Color.h index a3abaf8..01d19cb 100644 --- a/util/Color.h +++ b/util/Color.h @@ -21,6 +21,7 @@ class Color Color operator/(double scale) const; Color & operator+=(const Color & other); Color & operator-=(const Color & other); + Color & operator*=(double scale); static const Color black; static const Color white; diff --git a/util/Material.cc b/util/Material.cc index f541fbe..8311887 100644 --- a/util/Material.cc +++ b/util/Material.cc @@ -8,4 +8,5 @@ Material::Material() m_specular_color = Color::white; m_shininess = 50.0; m_reflectance = 0.0; + m_transparency = 0.0; } diff --git a/util/Material.h b/util/Material.h index 63f2d73..6f12714 100644 --- a/util/Material.h +++ b/util/Material.h @@ -33,12 +33,16 @@ class Material void setReflectance(double reflectance) { m_reflectance = reflectance; } double getReflectance() const { return m_reflectance; } + void setTransparency(double t) { m_transparency = t; } + double getTransparency() const { return m_transparency; } + protected: Color m_ambient_color; Color m_diffuse_color; Color m_specular_color; double m_shininess; double m_reflectance; + double m_transparency; }; #endif