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 "light.h"
00025 #include "mc.h"
00026 #include "primitive.h"
00027 #include "paramset.h"
00028 #include "rgbillum.h"
00029 #include "blackbody.h"
00030 #include "reflection/bxdf.h"
00031 #include "reflection/bxdf/lambertian.h"
00032
00033 using namespace lux;
00034
00035
00036 AreaLight::AreaLight(const Transform &light2world,
00037 const Spectrum &le, float g, int ns,
00038 const boost::shared_ptr<Shape> &s)
00039 : Light(light2world, ns) {
00040
00041 LSPD = new RGBIllumSPD(le);
00042 LSPD->Scale(g);
00043
00044 if (s->CanIntersect())
00045 shape = s;
00046 else {
00047
00048 boost::shared_ptr<Shape> shapeSet = s;
00049 vector<boost::shared_ptr<Shape> > todo, done;
00050 todo.push_back(shapeSet);
00051 while (todo.size()) {
00052 boost::shared_ptr<Shape> sh = todo.back();
00053 todo.pop_back();
00054 if (sh->CanIntersect())
00055 done.push_back(sh);
00056 else
00057 sh->Refine(todo);
00058 }
00059 if (done.size() == 1) shape = done[0];
00060 else {
00061 boost::shared_ptr<Shape> o (new ShapeSet(done, s->ObjectToWorld, s->reverseOrientation));
00062 shape = o;
00063 }
00064 }
00065 area = shape->Area();
00066 }
00067 SWCSpectrum AreaLight::Sample_L(const Point &p,
00068 const Normal &n, float u1, float u2, float u3,
00069 Vector *wi, float *pdf,
00070 VisibilityTester *visibility) const {
00071 Normal ns;
00072 Point ps = shape->Sample(p, u1, u2, &ns);
00073 *wi = Normalize(ps - p);
00074 *pdf = shape->Pdf(p, *wi);
00075 visibility->SetSegment(p, ps);
00076 return L(ps, ns, -*wi);
00077 }
00078 float AreaLight::Pdf(const Point &p, const Normal &N,
00079 const Vector &wi) const {
00080 return shape->Pdf(p, wi);
00081 }
00082 SWCSpectrum AreaLight::Sample_L(const Point &P,
00083 float u1, float u2, float u3, Vector *wo, float *pdf,
00084 VisibilityTester *visibility) const {
00085 Normal Ns;
00086 Point Ps = shape->Sample(P, u1, u2, &Ns);
00087 *wo = Normalize(Ps - P);
00088 *pdf = shape->Pdf(P, *wo);
00089 visibility->SetSegment(P, Ps);
00090 return L(Ps, Ns, -*wo);
00091 }
00092 SWCSpectrum AreaLight::Sample_L(const Scene *scene, float u1,
00093 float u2, float u3, float u4,
00094 Ray *ray, float *pdf) const {
00095 Normal ns;
00096 ray->o = shape->Sample(u1, u2, &ns);
00097 ray->d = UniformSampleSphere(u3, u4);
00098 if (Dot(ray->d, ns) < 0.) ray->d *= -1;
00099 *pdf = shape->Pdf(ray->o) * INV_TWOPI;
00100 return L(ray->o, ns, ray->d);
00101 }
00102 float AreaLight::Pdf(const Point &P, const Vector &w) const {
00103 return shape->Pdf(P, w);
00104 }
00105 SWCSpectrum AreaLight::Sample_L(const Point &P, Vector *wo,
00106 VisibilityTester *visibility) const {
00107 Normal Ns;
00108 Point Ps = shape->Sample(P, lux::random::floatValue(), lux::random::floatValue(), &Ns);
00109 *wo = Normalize(Ps - P);
00110 visibility->SetSegment(P, Ps);
00111 float pdf = shape->Pdf(P, *wo);
00112 if (pdf == 0.f) return SWCSpectrum(0.f);
00113 return L(P, Ns, -*wo) / pdf;
00114 }
00115 SWCSpectrum AreaLight::Sample_L(const Scene *scene, float u1, float u2, BSDF **bsdf, float *pdf) const
00116 {
00117 Normal ns;
00118 Point ps = shape->Sample(u1, u2, &ns);
00119 Vector dpdu, dpdv;
00120 CoordinateSystem(Vector(ns), &dpdu, &dpdv);
00121 DifferentialGeometry dg(ps, ns, dpdu, dpdv, Vector(0, 0, 0), Vector(0, 0, 0), 0, 0, NULL);
00122 *bsdf = BSDF_ALLOC(BSDF)(dg, ns);
00123 (*bsdf)->Add(BSDF_ALLOC(Lambertian)(SWCSpectrum(1.f)));
00124 *pdf = shape->Pdf(ps);
00125 return L(ps, ns, Vector(ns)) ;
00126 }
00127 SWCSpectrum AreaLight::Sample_L(const Scene *scene, const Point &p, const Normal &n,
00128 float u1, float u2, float u3, BSDF **bsdf, float *pdf, float *pdfDirect,
00129 VisibilityTester *visibility) const
00130 {
00131 Normal ns;
00132 Point ps = shape->Sample(p, u1, u2, &ns);
00133 Vector wo(Normalize(ps - p));
00134 *pdf = shape->Pdf(ps);
00135 *pdfDirect = shape->Pdf(p, wo) * AbsDot(wo, ns) / DistanceSquared(ps, p);
00136 Vector dpdu, dpdv;
00137 CoordinateSystem(Vector(ns), &dpdu, &dpdv);
00138 DifferentialGeometry dg(ps, ns, dpdu, dpdv, Vector(0, 0, 0), Vector(0, 0, 0), 0, 0, NULL);
00139 *bsdf = BSDF_ALLOC(BSDF)(dg, ns);
00140 (*bsdf)->Add(BSDF_ALLOC(Lambertian)(SWCSpectrum(1.f)));
00141 visibility->SetSegment(p, ps);
00142 return L(ps, ns, -wo) ;
00143 }
00144 float AreaLight::Pdf(const Scene *scene, const Point &p) const
00145 {
00146 return shape->Pdf(p);
00147 }
00148 SWCSpectrum AreaLight::L(const Ray &ray, const DifferentialGeometry &dg, const Normal &n, BSDF **bsdf, float *pdf, float *pdfDirect) const
00149 {
00150 *bsdf = BSDF_ALLOC(BSDF)(dg, dg.nn);
00151 (*bsdf)->Add(BSDF_ALLOC(Lambertian)(SWCSpectrum(1.f)));
00152 *pdf = shape->Pdf(dg.p);
00153 *pdfDirect = shape->Pdf(ray.o, ray.d) * AbsDot(ray.d, n) / DistanceSquared(dg.p, ray.o);
00154 return L(dg.p, dg.nn, -ray.d) ;
00155 }
00156
00157 void AreaLight::SamplePosition(float u1, float u2, Point *p, Normal *n, float *pdf) const
00158 {
00159 *p = shape->Sample(u1, u2, n);
00160 *pdf = shape->Pdf(*p);
00161 }
00162 void AreaLight::SampleDirection(float u1, float u2,const Normal &nn, Vector *wo, float *pdf) const
00163 {
00164
00165
00166
00167
00168 Vector v;
00169 v = CosineSampleHemisphere(u1, u2);
00170 TransformAccordingNormal(nn, v, wo);
00171 *pdf = INV_PI * AbsDot(*wo,nn);
00172 }
00173 float AreaLight::EvalPositionPdf(const Point p, const Normal &n, const Vector &w) const
00174 {
00175 return Dot(n, w) > 0 ? shape->Pdf(p) : 0.;
00176 }
00177 float AreaLight::EvalDirectionPdf(const Point p, const Normal &n, const Vector &w) const
00178 {
00179 return Dot(n, w) > 0 ? INV_PI * AbsDot(w,n) : 0.;
00180 }
00181 SWCSpectrum AreaLight::Eval(const Normal &n, const Vector &w) const
00182 {
00183 return Dot(n, w) > 0 ? SWCSpectrum(LSPD) : 0.;
00184 }
00185
00186 AreaLight* AreaLight::CreateAreaLight(const Transform &light2world, const ParamSet ¶mSet,
00187 const boost::shared_ptr<Shape> &shape) {
00188 Spectrum L = paramSet.FindOneSpectrum("L", Spectrum(1.0));
00189 float g = paramSet.FindOneFloat("gain", 1.f);
00190 int nSamples = paramSet.FindOneInt("nsamples", 1);
00191 return new AreaLight(light2world, L, g, nSamples, shape);
00192 }
00193
00194