const Vec3f& pos,
const Vec3f& dir,
const Vec3f& intensity,
- float alpha_min,
- float alpha_max)
+ float alpha_min, // in degree
+ float alpha_max) // in degree
: Light(scene),
m_pos(pos),
m_dir(dir),
m_intensity(intensity),
- m_alpha_min(alpha_min),
+ m_alpha_min(alpha_min),
m_alpha_max(alpha_max)
{
+ m_dir.normalize();
}
SpotLight::~SpotLight()
}
bool
-SpotLight::Illuminate(Ray& ray, Vec3f& intensity)
+SpotLight::Illuminate(Ray& shadow_ray, Vec3f& intensity)
{
- return false;
+ // direction vector from light source to surface point
+ Vec3f D = shadow_ray.origin()-m_pos;
+ D.normalize();
+ // angle between light source dir and shadow ray dir
+ float phi = fabs(acos(D.dot(m_dir))*180/M_PI);
+
+ // outside cone
+ if(phi > m_alpha_max)
+ {
+ return false;
+ }
+ else
+ {
+ Vec3f dir = m_pos-shadow_ray.origin();
+ float r = dir.norm()-Epsilon;
+ float falloff = 1.0f/(r*r); // falloff for distance
+
+ // modify ray for shadow computation
+ shadow_ray.setHit(0);
+ // for shadow calculation
+ shadow_ray.setT(r);
+ // set direction to light source
+ dir.normalize();
+ shadow_ray.setDir(dir);
+
+ if(phi < m_alpha_min)
+ {
+ intensity = m_intensity * falloff;
+ }
+ else
+ {
+ // linear falloff from 1 at alpha_min to 0 at alpha_max
+ float partial = 1.0f-(phi-m_alpha_min)/(m_alpha_max-m_alpha_min);
+ intensity = m_intensity * falloff * partial;
+
+ }
+ return true;
+ }
+ return true;
}
const Vec3f&
{
return m_dir;
}
+
+bool
+SpotLight::IsArea()
+{
+ return false;
+}