00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "pbrt.h"
00026 #include "light.h"
00027 #include "shape.h"
00028 #include "scene.h"
00029
00030 class DistantLight : public Light {
00031 public:
00032
00033 DistantLight(const Transform &light2world, const Spectrum &radiance, const Vector &dir);
00034 bool IsDeltaLight() const { return true; }
00035 Spectrum Sample_L(const Point &p, Vector *wi, VisibilityTester *) const;
00036 Spectrum Power(const Scene *scene) const {
00037 Point worldCenter;
00038 float worldRadius;
00039 scene->WorldBound().BoundingSphere(&worldCenter,
00040 &worldRadius);
00041 return L * M_PI * worldRadius * worldRadius;
00042 }
00043 Spectrum Sample_L(const Point &P, float u1, float u2, Vector *wo, float *pdf,
00044 VisibilityTester *visibility) const;
00045 Spectrum Sample_L(const Scene *scene, float u1, float u2,
00046 float u3, float u4, Ray *ray, float *pdf) const;
00047 float Pdf(const Point &, const Vector &) const;
00048 private:
00049
00050 Vector lightDir;
00051 Spectrum L;
00052 };
00053
00054 DistantLight::DistantLight(const Transform &light2world,
00055 const Spectrum &radiance, const Vector &dir)
00056 : Light(light2world) {
00057 lightDir = Normalize(LightToWorld(dir));
00058 L = radiance;
00059 }
00060 Spectrum DistantLight::Sample_L(const Point &p,
00061 Vector *wi, VisibilityTester *visibility) const {
00062 *wi = lightDir;
00063 visibility->SetRay(p, *wi);
00064 return L;
00065 }
00066 Spectrum DistantLight::Sample_L(const Point &p, float u1, float u2,
00067 Vector *wi, float *pdf, VisibilityTester *visibility) const {
00068 *pdf = 1.f;
00069 return Sample_L(p, wi, visibility);
00070 }
00071 float DistantLight::Pdf(const Point &, const Vector &) const {
00072 return 0.;
00073 }
00074 Spectrum DistantLight::Sample_L(const Scene *scene,
00075 float u1, float u2, float u3, float u4,
00076 Ray *ray, float *pdf) const {
00077
00078 Point worldCenter;
00079 float worldRadius;
00080 scene->WorldBound().BoundingSphere(&worldCenter,
00081 &worldRadius);
00082 Vector v1, v2;
00083 CoordinateSystem(lightDir, &v1, &v2);
00084 float d1, d2;
00085 ConcentricSampleDisk(u1, u2, &d1, &d2);
00086 Point Pdisk =
00087 worldCenter + worldRadius * (d1 * v1 + d2 * v2);
00088
00089 ray->o = Pdisk + worldRadius * lightDir;
00090 ray->d = -lightDir;
00091 *pdf = 1.f / (M_PI * worldRadius * worldRadius);
00092 return L;
00093 }
00094 extern "C" DLLEXPORT Light *CreateLight(const Transform &light2world,
00095 const ParamSet ¶mSet) {
00096 Spectrum L = paramSet.FindOneSpectrum("L", Spectrum(1.0));
00097 Point from = paramSet.FindOnePoint("from", Point(0,0,0));
00098 Point to = paramSet.FindOnePoint("to", Point(0,0,1));
00099 Vector dir = from-to;
00100 return new DistantLight(light2world, L, dir);
00101 }