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 "projection.h"
00025 #include "imagereader.h"
00026 #include "mc.h"
00027 #include "paramset.h"
00028 #include "dynload.h"
00029
00030 using namespace lux;
00031
00032
00033 ProjectionLight::
00034 ProjectionLight(const Transform &light2world,
00035 const boost::shared_ptr< Texture<SWCSpectrum> > L,
00036 float g, const string &texname,
00037 float fov)
00038 : Light(light2world) {
00039 lightPos = LightToWorld(Point(0,0,0));
00040 Lbase = L;
00041 Lbase->SetIlluminant();
00042 gain = g;
00043
00044 int width = 0, height = 0;
00045 auto_ptr<ImageData> imgdata(ReadImage(texname));
00046 if (imgdata.get()!=NULL) {
00047 width=imgdata->getWidth();
00048 height=imgdata->getHeight();
00049 projectionMap =imgdata->createMIPMap<RGBColor>();
00050 }
00051 else
00052 projectionMap = NULL;
00053
00054
00055 float aspect = float(width) / float(height);
00056 if (aspect > 1.f) {
00057 screenX0 = -aspect; screenX1 = aspect;
00058 screenY0 = -1.f; screenY1 = 1.f;
00059 }
00060 else {
00061 screenX0 = -1.f; screenX1 = 1.f;
00062 screenY0 = -1.f / aspect; screenY1 = 1.f / aspect;
00063 }
00064 hither = DEFAULT_EPSILON_STATIC;
00065 yon = 1e30f;
00066 lightProjection = Perspective(fov, hither, yon);
00067
00068 float opposite = tanf(Radians(fov) / 2.f);
00069 float tanDiag = opposite * sqrtf(1.f + 1.f/(aspect*aspect));
00070 cosTotalWidth = cosf(atanf(tanDiag));
00071 }
00072 ProjectionLight::~ProjectionLight() { delete projectionMap; }
00073 RGBColor ProjectionLight::Projection(const Vector &w) const {
00074 Vector wl = WorldToLight(w);
00075
00076 if (wl.z < hither) return 0.;
00077
00078 Point Pl = lightProjection(Point(wl.x, wl.y, wl.z));
00079 if (Pl.x < screenX0 || Pl.x > screenX1 ||
00080 Pl.y < screenY0 || Pl.y > screenY1) return 0.;
00081 if (!projectionMap) return 1;
00082 float s = (Pl.x - screenX0) / (screenX1 - screenX0);
00083 float t = (Pl.y - screenY0) / (screenY1 - screenY0);
00084 return projectionMap->Lookup(s, t);
00085 }
00086 SWCSpectrum ProjectionLight::Sample_L(const TsPack *tspack, const Point &p, float u1, float u2,
00087 float u3, Vector *wi, float *pdf,
00088 VisibilityTester *visibility) const {
00089 *wi = Normalize(lightPos - p);
00090 *pdf = 1.f;
00091 visibility->SetSegment(p, lightPos, tspack->time);
00092 return Lbase->Evaluate(tspack, dummydg) * gain * SWCSpectrum(tspack, Projection(-*wi)) / DistanceSquared(lightPos, p);
00093 }
00094 SWCSpectrum ProjectionLight::Sample_L(const TsPack *tspack, const Scene *scene, float u1, float u2,
00095 float u3, float u4, Ray *ray, float *pdf) const {
00096 ray->o = lightPos;
00097 Vector v = UniformSampleCone(u1, u2, cosTotalWidth);
00098 ray->d = LightToWorld(v);
00099 *pdf = UniformConePdf(cosTotalWidth);
00100 return Lbase->Evaluate(tspack, dummydg) * gain * SWCSpectrum(tspack, Projection(ray->d));
00101 }
00102 float ProjectionLight::Pdf(const Point &, const Vector &) const {
00103 return 0.;
00104 }
00105 float ProjectionLight::Pdf(const Point &p, const Normal &n,
00106 const Point &po, const Normal &ns) const
00107 {
00108 return 0.f;
00109 }
00110 Light* ProjectionLight::CreateLight(const Transform &light2world,
00111 const ParamSet ¶mSet, const TextureParams &tp) {
00112 boost::shared_ptr<Texture<SWCSpectrum> > L = tp.GetSWCSpectrumTexture("L", RGBColor(1.f));
00113 float g = paramSet.FindOneFloat("gain", 1.f);
00114 float fov = paramSet.FindOneFloat("fov", 45.);
00115 string texname = paramSet.FindOneString("mapname", "");
00116 return new ProjectionLight(light2world, L, g, texname, fov);
00117 }
00118
00119 static DynamicLoader::RegisterLight<ProjectionLight> r("projection");
00120