diff --git a/main/Light.h b/main/Light.h index 99b5db9..9ee4299 100644 --- a/main/Light.h +++ b/main/Light.h @@ -28,7 +28,7 @@ class Light } const Color & getSpecularColor() const { return m_specular_color; } - void setJitter(int j) { m_jitter = j; } + void setJitter(int j) { m_jitter = j >= 1 ? j : 1; } int getJitter() const { return m_jitter; } void setRadius(double r) { m_radius = r; } diff --git a/main/Scene.cc b/main/Scene.cc index 3f237e3..0fffb98 100644 --- a/main/Scene.cc +++ b/main/Scene.cc @@ -1,5 +1,5 @@ -#include /* exp(), pow() */ +#include /* exp(), pow(), M_PI */ #include #include @@ -224,48 +224,64 @@ Color Scene::computePhong(const refptr material, it != m_lights.end(); it++) { - for (int jitter_index = 0, jitter_max = (*it)->getJitter(); - jitter_index < jitter_max; - jitter_index++) + Vector lightC = (*it)->getPosition(); + double lightRadius = (*it)->getRadius(); + Vector directionToLightC = lightC - surfacePoint; + Vector lightPlaneX = directionToLightC.getPerpendicular().normalize(); + Vector lightPlaneY = (directionToLightC * lightPlaneX).normalize(); + int jitter_samples = 0, jitter_level = (*it)->getJitter();; + for (int jitter_index = 0; jitter_index < jitter_level; jitter_index++) { - Vector lightPosition = (*it)->getJitterPosition(jitter_index); - Vector directionToLight = lightPosition - surfacePoint; - directionToLight.normalize(); - Vector reflectedLightDirection = - directionToLight.reflect(surfaceNormal); - - Ray surfaceToLight(surfacePoint, directionToLight); - Color light_contribution = - calculateLightContribution(surfaceToLight.shift(0.0001), - lightPosition); - - if ( light_contribution.r > 0.0 - || light_contribution.g > 0.0 - || light_contribution.b > 0.0 ) +#if 0 + double offset = ((double)rand()) / RAND_MAX * M_2_PI; +#endif + double offset = 0.0; + double jitterRadius = jitter_index * lightRadius + / (jitter_level - 0.5); + for (int i = 0, num = (int) (M_PI * jitter_index) + 1; i < num; i++) { - /* calculate the diffuse term */ - double diffuse_coef = directionToLight % surfaceNormal; - if (diffuse_coef > 0.0) - { - result += diffuseColor - * (*it)->getDiffuseColor() - * diffuse_coef - * light_contribution - / jitter_max; - } + jitter_samples++; + double jitter_angle = offset + i * M_2_PI / num; + Vector jitterPosition = lightC + + lightPlaneX * jitterRadius * cos(jitter_angle) + + lightPlaneY * jitterRadius * sin(jitter_angle); + Vector directionToLight = jitterPosition - surfacePoint; + directionToLight.normalize(); + Vector reflectedLightDirection = + directionToLight.reflect(surfaceNormal); - /* calculate the specular term */ - double specular_coef = reflectedLightDirection % viewDirection; - if (specular_coef > 0.0) + Ray surfaceToLight(surfacePoint, directionToLight); + Color light_contribution = + calculateLightContribution(surfaceToLight.shift(0.0001), + jitterPosition); + + if ( light_contribution.r > 0.0 + || light_contribution.g > 0.0 + || light_contribution.b > 0.0 ) { - result += specularColor - * (*it)->getSpecularColor() - * pow(specular_coef, shininess) - * light_contribution - / jitter_max; + /* calculate the diffuse term */ + double diffuse_coef = directionToLight % surfaceNormal; + if (diffuse_coef > 0.0) + { + result += diffuseColor + * (*it)->getDiffuseColor() + * diffuse_coef + * light_contribution; + } + + /* calculate the specular term */ + double specular_coef = reflectedLightDirection % viewDirection; + if (specular_coef > 0.0) + { + result += specularColor + * (*it)->getSpecularColor() + * pow(specular_coef, shininess) + * light_contribution; + } } } } + result /= jitter_samples; } return result; diff --git a/scenes/subtract-subtract.fart b/scenes/subtract-subtract.fart index 0909b98..b8ba565 100644 --- a/scenes/subtract-subtract.fart +++ b/scenes/subtract-subtract.fart @@ -15,7 +15,7 @@ scene light { position <-1, -3, 4> - jitter 50 + jitter 3 } plane diff --git a/util/Color.cc b/util/Color.cc index 86b8a45..ca358f1 100644 --- a/util/Color.cc +++ b/util/Color.cc @@ -87,6 +87,22 @@ Color & Color::operator*=(const Color & other) return *this; } +Color & Color::operator/=(double scale) +{ + r /= scale; + g /= scale; + b /= scale; + return *this; +} + +Color & Color::operator/=(const Color & other) +{ + r /= other.r; + g /= other.g; + b /= other.b; + 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 e46b871..448aa4c 100644 --- a/util/Color.h +++ b/util/Color.h @@ -23,6 +23,8 @@ class Color Color & operator-=(const Color & other); Color & operator*=(double scale); Color & operator*=(const Color & other); + Color & operator/=(double scale); + Color & operator/=(const Color & other); static const Color black; static const Color white; diff --git a/util/Vector.cc b/util/Vector.cc index 9e2df3a..6f66c72 100644 --- a/util/Vector.cc +++ b/util/Vector.cc @@ -83,7 +83,7 @@ Vector Vector::reflect(const Vector & target) const return (*this) + me_to_proj * 2.0; } -Vector Vector::getPerpendicularVector() const +Vector Vector::getPerpendicular() const { Vector t = *this; t.normalize(); diff --git a/util/Vector.h b/util/Vector.h index 8b37eae..687c389 100644 --- a/util/Vector.h +++ b/util/Vector.h @@ -20,7 +20,7 @@ class Vector Vector proj(const Vector & target) const; Vector reflect(const Vector & target) const; operator double() const { return mag(); } - Vector getPerpendicularVector() const; + Vector getPerpendicular() const; protected: double m_array[3];