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 "infinite.h"
00025 #include "imagereader.h"
00026 #include "mc.h"
00027 #include "paramset.h"
00028 #include "blackbody.h"
00029 using namespace lux;
00030
00031
00032 InfiniteAreaLight::~InfiniteAreaLight() {
00033 delete radianceMap;
00034 delete SPDbase;
00035 }
00036 InfiniteAreaLight
00037 ::InfiniteAreaLight(const Transform &light2world, const Spectrum &l, int ns, const string &texmap, float gain, float gamma)
00038 : Light(light2world, ns) {
00039 radianceMap = NULL;
00040 if (texmap != "") {
00041 auto_ptr<ImageData> imgdata(ReadImage(texmap));
00042 if(imgdata.get()!=NULL)
00043 {
00044 radianceMap = imgdata->createMIPMap<Spectrum>(BILINEAR, 8.f,
00045 TEXTURE_REPEAT, 1.f, gamma);
00046 }
00047 else
00048 radianceMap=NULL;
00049 }
00050
00051
00052 SPDbase = new BlackbodySPD();
00053 SPDbase->Normalize();
00054 SPDbase->Scale(gain);
00055
00056
00057 Lbase = l;
00058 }
00059
00060 SWCSpectrum
00061 InfiniteAreaLight::Le(const RayDifferential &r) const {
00062 Vector w = r.d;
00063
00064
00065 Spectrum L = Lbase;
00066 if (radianceMap != NULL) {
00067 Vector wh = Normalize(WorldToLight(w));
00068 float s = SphericalPhi(wh) * INV_TWOPI;
00069 float t = SphericalTheta(wh) * INV_PI;
00070 L *= radianceMap->Lookup(s, t);
00071 }
00072
00073 return SWCSpectrum(SPDbase) * SWCSpectrum(L);
00074 }
00075 SWCSpectrum InfiniteAreaLight::Sample_L(const Point &p,
00076 const Normal &n, float u1, float u2, float u3,
00077 Vector *wi, float *pdf,
00078 VisibilityTester *visibility) const {
00079 if(!havePortalShape) {
00080
00081 float x, y, z;
00082 ConcentricSampleDisk(u1, u2, &x, &y);
00083 z = sqrtf(max(0.f, 1.f - x*x - y*y));
00084 if (u3 < .5) z *= -1;
00085 *wi = Vector(x, y, z);
00086
00087 *pdf = fabsf(wi->z) * INV_TWOPI;
00088
00089 Vector v1, v2;
00090 CoordinateSystem(Normalize(Vector(n)), &v1, &v2);
00091 *wi = Vector(v1.x * wi->x + v2.x * wi->y + n.x * wi->z,
00092 v1.y * wi->x + v2.y * wi->y + n.y * wi->z,
00093 v1.z * wi->x + v2.z * wi->y + n.z * wi->z);
00094 } else {
00095
00096 int shapeidx = 0;
00097 if(nrPortalShapes > 1)
00098 shapeidx = min<float>(nrPortalShapes - 1,
00099 Floor2Int(u3 * nrPortalShapes));
00100 Normal ns;
00101 Point ps;
00102 bool found = false;
00103 for (int i = 0; i < nrPortalShapes; ++i) {
00104 ps = PortalShapes[shapeidx]->Sample(p, u1, u2, &ns);
00105 *wi = Normalize(ps - p);
00106 if (Dot(*wi, ns) < 0.f) {
00107 found = true;
00108 break;
00109 }
00110
00111 if (++shapeidx >= nrPortalShapes)
00112 shapeidx = 0;
00113 }
00114
00115 if (found)
00116 *pdf = PortalShapes[shapeidx]->Pdf(p, *wi);
00117 else {
00118 *pdf = 0.f;
00119 return SWCSpectrum(0.f);
00120 }
00121 }
00122 visibility->SetRay(p, *wi);
00123 return Le(RayDifferential(p, *wi));
00124 }
00125 float InfiniteAreaLight::Pdf(const Point &, const Normal &n,
00126 const Vector &wi) const {
00127 return AbsDot(n, wi) * INV_TWOPI;
00128 }
00129 SWCSpectrum InfiniteAreaLight::Sample_L(const Point &p,
00130 float u1, float u2, float u3, Vector *wi, float *pdf,
00131 VisibilityTester *visibility) const {
00132 if(!havePortalShape) {
00133 *wi = UniformSampleSphere(u1, u2);
00134 *pdf = UniformSpherePdf();
00135 } else {
00136
00137 int shapeidx = 0;
00138 if(nrPortalShapes > 1)
00139 shapeidx = min<float>(nrPortalShapes - 1,
00140 Floor2Int(lux::random::floatValue() * nrPortalShapes));
00141 Normal ns;
00142 Point ps;
00143 bool found = false;
00144 for (int i = 0; i < nrPortalShapes; ++i) {
00145 ps = PortalShapes[shapeidx]->Sample(p, u1, u2, &ns);
00146 *wi = Normalize(ps - p);
00147 if (Dot(*wi, ns) < 0.f) {
00148 found = true;
00149 break;
00150 }
00151
00152 if (++shapeidx >= nrPortalShapes)
00153 shapeidx = 0;
00154 }
00155
00156 if (found)
00157 *pdf = PortalShapes[shapeidx]->Pdf(p, *wi);
00158 else {
00159 *pdf = 0.f;
00160 return SWCSpectrum(0.f);
00161 }
00162 }
00163 visibility->SetRay(p, *wi);
00164 return Le(RayDifferential(p, *wi));
00165 }
00166 float InfiniteAreaLight::Pdf(const Point &, const Vector &) const {
00167 return 1.f / (4.f * M_PI);
00168 }
00169 SWCSpectrum InfiniteAreaLight::Sample_L(const Scene *scene,
00170 float u1, float u2, float u3, float u4,
00171 Ray *ray, float *pdf) const {
00172 if(!havePortalShape) {
00173
00174 Point worldCenter;
00175 float worldRadius;
00176 scene->WorldBound().BoundingSphere(&worldCenter,
00177 &worldRadius);
00178 worldRadius *= 1.01f;
00179 Point p1 = worldCenter + worldRadius *
00180 UniformSampleSphere(u1, u2);
00181 Point p2 = worldCenter + worldRadius *
00182 UniformSampleSphere(u3, u4);
00183
00184 ray->o = p1;
00185 ray->d = Normalize(p2-p1);
00186
00187 Vector to_center = Normalize(worldCenter - p1);
00188 float costheta = AbsDot(to_center,ray->d);
00189 *pdf =
00190 costheta / ((4.f * M_PI * worldRadius * worldRadius));
00191 } else {
00192
00193
00194 int shapeidx = 0;
00195 if(nrPortalShapes > 1)
00196 shapeidx = min<float>(nrPortalShapes - 1,
00197 Floor2Int(lux::random::floatValue() * nrPortalShapes));
00198
00199 Normal ns;
00200 ray->o = PortalShapes[shapeidx]->Sample(u1, u2, &ns);
00201 ray->d = UniformSampleSphere(u3, u4);
00202 if (Dot(ray->d, ns) < 0.) ray->d *= -1;
00203
00204 *pdf = PortalShapes[shapeidx]->Pdf(ray->o) * INV_TWOPI / nrPortalShapes;
00205 }
00206
00207 return Le(RayDifferential(ray->o, -ray->d));
00208 }
00209 SWCSpectrum InfiniteAreaLight::Sample_L(const Point &p,
00210 Vector *wi, VisibilityTester *visibility) const {
00211 float pdf;
00212 SWCSpectrum L = Sample_L(p, lux::random::floatValue(), lux::random::floatValue(),
00213 lux::random::floatValue(), wi, &pdf, visibility);
00214 if (pdf == 0.f) return SWCSpectrum(0.f);
00215 return L / pdf;
00216 }
00217 Light* InfiniteAreaLight::CreateLight(const Transform &light2world,
00218 const ParamSet ¶mSet) {
00219 Spectrum L = paramSet.FindOneSpectrum("L", Spectrum(1.0));
00220 string texmap = paramSet.FindOneString("mapname", "");
00221 int nSamples = paramSet.FindOneInt("nsamples", 1);
00222
00223
00224 float gain = paramSet.FindOneFloat("gain", 1.0f);
00225 float gamma = paramSet.FindOneFloat("gamma", 1.0f);
00226
00227 return new InfiniteAreaLight(light2world, L, nSamples, texmap, gain, gamma);
00228 }