00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifndef LUX_LIGHT_H
00024 #define LUX_LIGHT_H
00025
00026 #include "lux.h"
00027 #include "spectrum.h"
00028 #include "texture.h"
00029 #include "primitive.h"
00030 #include "error.h"
00031 #include "sphericalfunction.h"
00032
00033
00034 namespace lux
00035 {
00036
00037 class Light {
00038 public:
00039
00040 virtual ~Light();
00041 Light(const Transform &l2w, int ns = 1)
00042 : nSamples(max(1, ns)), LightToWorld(l2w),
00043 WorldToLight(l2w.GetInverse()) {
00044 if (WorldToLight.HasScale())
00045 luxError(LUX_UNIMPLEMENT,LUX_WARNING,"Scaling detected in world-to-light transformation!\nThe system has numerous assumptions, implicit and explicit,\nthat this transform will have no scale factors in it.\nProceed at your own risk; your image may have errors or\nthe system may crash as a result of this.");
00046 havePortalShape = false;
00047 nrPortalShapes = 0;
00048 PortalArea = 0;
00049 warnOnce = false;
00050 }
00051 virtual SWCSpectrum Power(const TsPack *tspack, const Scene *) const = 0;
00052 virtual bool IsDeltaLight() const = 0;
00053 virtual bool IsEnvironmental() const = 0;
00054 virtual SWCSpectrum Le(const TsPack *tspack, const RayDifferential &r) const;
00055 virtual SWCSpectrum Le(const TsPack *tspack, const Scene *scene, const Ray &r,
00056 const Normal &n, BSDF **bsdf, float *pdf, float *pdfDirect) const;
00057 virtual SWCSpectrum Sample_L(const TsPack *tspack, const Point &p, float u1,
00058 float u2, float u3, Vector *wi, float *pdf,
00059 VisibilityTester *vis) const = 0;
00060 virtual float Pdf(const Point &p,
00061 const Vector &wi) const = 0;
00062 virtual SWCSpectrum Sample_L(const TsPack *tspack, const Point &p, const Normal &n,
00063 float u1, float u2, float u3, Vector *wi, float *pdf,
00064 VisibilityTester *visibility) const {
00065 return Sample_L(tspack, p, u1, u2, u3, wi, pdf, visibility);
00066 }
00067 virtual float Pdf(const Point &p, const Normal &n,
00068 const Vector &wi) const {
00069 return Pdf(p, wi);
00070 }
00071 virtual float Pdf(const Point &p, const Normal &n,
00072 const Point &po, const Normal &ns) const = 0;
00073 virtual SWCSpectrum Sample_L(const TsPack *tspack, const Scene *scene, float u1,
00074 float u2, float u3, float u4,
00075 Ray *ray, float *pdf) const = 0;
00076 virtual bool Sample_L(const TsPack *tspack, const Scene *scene, float u1, float u2, float u3, BSDF **bsdf, float *pdf, SWCSpectrum *L) const {
00077 if (!warnOnce)
00078 luxError(LUX_BUG, LUX_SEVERE, "Unimplemented Light::Sample_L");
00079 warnOnce = true;
00080 return false;
00081 }
00082 virtual bool Sample_L(const TsPack *tspack, const Scene *scene, const Point &p, const Normal &n, float u1, float u2, float u3, BSDF **bsdf, float *pdf, float *pdfDirect, VisibilityTester *visibility, SWCSpectrum *L) const {
00083 if (!warnOnce)
00084 luxError(LUX_BUG, LUX_SEVERE, "Unimplemented Light::Sample_L");
00085 warnOnce = true;
00086 return false;
00087 }
00088
00089 void AddPortalShape(boost::shared_ptr<Primitive> shape);
00090
00091
00092 const int nSamples;
00093 bool havePortalShape;
00094 int nrPortalShapes;
00095 vector<boost::shared_ptr<Primitive> > PortalShapes;
00096 float PortalArea;
00097 int group;
00098 protected:
00099
00100 const Transform LightToWorld, WorldToLight;
00101 mutable bool warnOnce;
00102 };
00103
00104 struct VisibilityTester {
00105
00106
00107 void SetSegment(const Point &p1, const Point & p2, float time) {
00108
00109
00110 const Vector w = p2 - p1;
00111 const float length = w.Length();
00112 const float shadowRayEpsilon = min(length,
00113 max(MachineEpsilon::E(p1), MachineEpsilon::E(length)));
00114 r = Ray(p1, w / length, shadowRayEpsilon, length - shadowRayEpsilon);
00115 r.time = time;
00116 }
00117
00118 void SetRay(const Point &p, const Vector & w, float time) {
00119 r = Ray(p, Normalize(w));
00120 r.time = time;
00121 }
00122
00123 bool Unoccluded(const Scene * scene) const;
00124 bool TestOcclusion(const TsPack *tspack, const Scene *scene, SWCSpectrum * f, float *pdf = NULL, float *pdfR = NULL) const;
00125
00126 void Transmittance(const TsPack *tspack, const Scene * scene, const Sample *sample, SWCSpectrum *const L) const;
00127 Ray r;
00128 };
00129
00130 class AreaLight : public Light {
00131 public:
00132
00133 AreaLight(const Transform &light2world,
00134 boost::shared_ptr<Texture<SWCSpectrum> > Le, float g, float pow, float e,
00135 SampleableSphericalFunction *ssf,
00136 int ns, const boost::shared_ptr<Primitive> &prim);
00137 virtual ~AreaLight();
00138 virtual SWCSpectrum L(const TsPack *tspack, const DifferentialGeometry &dg, const Vector& w) const {
00139 if( Dot(dg.nn, w) > 0 ) {
00140 SWCSpectrum Ll(Le->Evaluate(tspack, dg) * gain);
00141 if(func) {
00142
00143 const Vector wLocal(
00144 Dot(dg.dpdu, w), Dot(dg.dpdv, w), Dot(dg.nn, w)
00145 );
00146 Ll *= SWCSpectrum(tspack, func->f(wLocal));
00147 }
00148 return Ll;
00149 }
00150 else {
00151 return 0.f;
00152 }
00153 }
00154 virtual SWCSpectrum L(const TsPack *tspack, const Ray &ray, const DifferentialGeometry &dg, const Normal &n, BSDF **bsdf, float *pdf, float *pdfDirect) const;
00155 SWCSpectrum Power(const TsPack *tspack, const Scene *) const {
00156 return Le->Evaluate(tspack, dummydg) * gain * area * M_PI * (func ? 2.f * func->Average_f() : 1.f);
00157 }
00158 virtual bool IsDeltaLight() const { return false; }
00159 virtual bool IsEnvironmental() const { return false; }
00160 virtual float Pdf(const Point &, const Vector &) const;
00161 virtual float Pdf(const Point &, const Normal &, const Vector &) const;
00162 virtual float Pdf(const Point &p, const Normal &n,
00163 const Point &po, const Normal &ns) const;
00164 virtual SWCSpectrum Sample_L(const TsPack *tspack, const Point &P, const Normal &N,
00165 float u1, float u2, float u3, Vector *wo, float *pdf,
00166 VisibilityTester *visibility) const;
00167 virtual SWCSpectrum Sample_L(const TsPack *tspack, const Point &P, float u1, float u2, float u3,
00168 Vector *wo, float *pdf, VisibilityTester *visibility) const;
00169 virtual SWCSpectrum Sample_L(const TsPack *tspack, const Scene *scene, float u1, float u2,
00170 float u3, float u4, Ray *ray, float *pdf) const;
00171 virtual bool Sample_L(const TsPack *tspack, const Scene *scene, float u1, float u2, float u3, BSDF **bsdf, float *pdf, SWCSpectrum *Le) const;
00172 virtual bool Sample_L(const TsPack *tspack, const Scene *scene, const Point &p, const Normal &n, float u1, float u2, float u3, BSDF **bsdf, float *pdf, float *pdfDirect, VisibilityTester *visibility, SWCSpectrum *Le) const;
00173 static AreaLight *CreateAreaLight(const Transform &light2world, const ParamSet ¶mSet, const TextureParams &tp,
00174 const boost::shared_ptr<Primitive> &prim);
00175 protected:
00176
00177 boost::shared_ptr<Texture<SWCSpectrum> > Le;
00178 DifferentialGeometry dummydg;
00179 boost::shared_ptr<Primitive> prim;
00180 float gain, power, efficacy, area;
00181 SampleableSphericalFunction *func;
00182 };
00183
00184 }
00185
00186 #endif // LUX_LIGHT_H