00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "spot.h"
00025 #include "mc.h"
00026 #include "paramset.h"
00027
00028 using namespace lux;
00029
00030
00031 SpotLight::SpotLight(const Transform &light2world,
00032 const Spectrum &intensity, float gain, float width, float fall)
00033 : Light(light2world) {
00034 lightPos = LightToWorld(Point(0,0,0));
00035
00036
00037 LSPD = new RGBIllumSPD(intensity);
00038 LSPD->Scale(gain);
00039
00040 cosTotalWidth = cosf(Radians(width));
00041 cosFalloffStart = cosf(Radians(fall));
00042 }
00043 SWCSpectrum SpotLight::Sample_L(const Point &p, Vector *wi,
00044 VisibilityTester *visibility) const {
00045 *wi = Normalize(lightPos - p);
00046 visibility->SetSegment(p, lightPos);
00047 return SWCSpectrum(LSPD) * Falloff(-*wi) /
00048 DistanceSquared(lightPos, p);
00049 }
00050 float SpotLight::Falloff(const Vector &w) const {
00051 Vector wl = Normalize(WorldToLight(w));
00052 float costheta = wl.z;
00053 if (costheta < cosTotalWidth)
00054 return 0.;
00055 if (costheta > cosFalloffStart)
00056 return 1.;
00057
00058 float delta = (costheta - cosTotalWidth) /
00059 (cosFalloffStart - cosTotalWidth);
00060 return delta*delta*delta*delta;
00061 }
00062 SWCSpectrum SpotLight::Sample_L(const Point &p, float u1, float u2, float u3,
00063 Vector *wi, float *pdf, VisibilityTester *visibility) const {
00064 *pdf = 1.f;
00065 return Sample_L(p, wi, visibility);
00066 }
00067 float SpotLight::Pdf(const Point &, const Vector &) const {
00068 return 0.;
00069 }
00070 SWCSpectrum SpotLight::Sample_L(const Scene *scene, float u1,
00071 float u2, float u3, float u4,
00072 Ray *ray, float *pdf) const {
00073 ray->o = lightPos;
00074 Vector v = UniformSampleCone(u1, u2, cosTotalWidth);
00075 ray->d = LightToWorld(v);
00076 *pdf = UniformConePdf(cosTotalWidth);
00077 return SWCSpectrum(LSPD) * Falloff(ray->d);
00078 }
00079 Light* SpotLight::CreateLight(const Transform &l2w, const ParamSet ¶mSet) {
00080 Spectrum I = paramSet.FindOneSpectrum("I", Spectrum(1.0));
00081 float g = paramSet.FindOneFloat("gain", 1.f);
00082 float coneangle = paramSet.FindOneFloat("coneangle", 30.);
00083 float conedelta = paramSet.FindOneFloat("conedeltaangle", 5.);
00084
00085 Point from = paramSet.FindOnePoint("from", Point(0,0,0));
00086 Point to = paramSet.FindOnePoint("to", Point(0,0,1));
00087 Vector dir = Normalize(to - from);
00088 Vector du, dv;
00089 CoordinateSystem(dir, &du, &dv);
00090 boost::shared_ptr<Matrix4x4> o (new Matrix4x4( du.x, du.y, du.z, 0.,
00091 dv.x, dv.y, dv.z, 0.,
00092 dir.x, dir.y, dir.z, 0.,
00093 0, 0, 0, 1.));
00094 Transform dirToZ = Transform(o);
00095 Transform light2world =
00096 l2w *
00097 Translate(Vector(from.x, from.y, from.z)) *
00098 dirToZ.GetInverse();
00099 return new SpotLight(light2world, I, g, coneangle,
00100 coneangle-conedelta);
00101 }