00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "pointlight.h"
00024 #include "hit.h"
00025 #include "scene.h"
00026 #include "statistics.h"
00027
00028 #include <cassert>
00029 #include <cmath>
00030
00031 using namespace sheep;
00032 using namespace toxic;
00033
00034 PointLight::PointLight(const Matrix4 &m,
00035 const Color3 &power,
00036 bool cast_shadows ) :
00037 Basis(m),
00038 ILight(cast_shadows),
00039 m_power(power),
00040 m_scaled_power(power / (4.0 * PI)),
00041 m_origin(TransformToWorld(Point3(0.0)))
00042 {
00043 }
00044
00045 void PointLight::ComputeIrradiance(const Context &context,
00046 const Scene *scene,
00047 const Point3 &point,
00048 const Vector3 &geometric_normal,
00049 const Vector3 &shading_normal,
00050 const ISurfaceSampler::SampleVector &,
00051 IrradianceSampleVector *output) const
00052 {
00053 assert(scene);
00054 assert(geometric_normal.IsUnitLength());
00055 assert(shading_normal.IsUnitLength());
00056 assert(output);
00057
00058 Vector3 incoming = m_origin - point;
00059 const Real inv_distance2 = 1.0 / incoming.SquareNorm();
00060
00061
00062 incoming *= sqrt(inv_distance2);
00063 assert(incoming.IsUnitLength());
00064
00065 const Real cos_theta = shading_normal * incoming;
00066
00067 if(cos_theta <= 0.0) {
00068
00069 output->push_back(IrradianceSample(Color3(0.0), incoming));
00070 return;
00071 }
00072
00073 if(m_cast_shadows) {
00074 ++context.m_statistics->m_shadow_rays;
00075
00076 if(!scene->ArePointsMutuallyVisible(
00077 context,
00078 point,
00079 geometric_normal,
00080 m_origin,
00081 Ray::SHADOW_RAY))
00082 {
00083
00084 output->push_back(IrradianceSample(Color3(0.0), incoming));
00085 return;
00086 }
00087 }
00088
00089 const Color3 irradiance = (cos_theta * inv_distance2) * m_scaled_power;
00090
00091 output->push_back(IrradianceSample(irradiance, incoming));
00092 }