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_PHOTONMAP_H
00024 #define LUX_PHOTONMAP_H
00025
00026 #include "lux.h"
00027 #include "scene.h"
00028 #include "spectrum.h"
00029 #include "spectrumwavelengths.h"
00030 #include "kdtree.h"
00031 #include "bxdf.h"
00032 #include "primitive.h"
00033 #include "mc.h"
00034
00035 namespace lux
00036 {
00037
00038
00039
00040
00041
00042
00043 class BasicPhoton {
00044 public:
00045 BasicPhoton(const Point &pp)
00046 : p(pp) {
00047 }
00048
00049 BasicPhoton() {
00050 }
00051
00052 virtual ~BasicPhoton() {}
00053
00054 virtual void save(bool isLittleEndian, std::basic_ostream<char> &stream) const = 0;
00055 virtual void load(bool isLittleEndian, std::basic_istream<char> &stream) = 0;
00056
00057 Point p;
00058 };
00059
00060 class BasicColorPhoton : public BasicPhoton {
00061 public:
00062 BasicColorPhoton(const TsPack *tspack, const Point &pp,
00063 const SWCSpectrum &wt)
00064 : BasicPhoton(pp), alpha(wt) {
00065 for (u_int i = 0; i < WAVELENGTH_SAMPLES; ++i)
00066 w[i] = tspack->swl->w[i];
00067 if (tspack->swl->single) {
00068 const float a = alpha.c[tspack->swl->single_w] * WAVELENGTH_SAMPLES;
00069 alpha = SWCSpectrum(0.f);
00070 alpha.c[tspack->swl->single_w] = a;
00071 }
00072 }
00073
00074 BasicColorPhoton() : BasicPhoton() { }
00075 virtual ~BasicColorPhoton() { }
00076
00077 SWCSpectrum GetSWCSpectrum(const TsPack* tspack, u_int nb) const;
00078
00079 virtual void save(bool isLittleEndian, std::basic_ostream<char> &stream) const;
00080 virtual void load(bool isLittleEndian, std::basic_istream<char> &stream);
00081
00082 SWCSpectrum alpha;
00083 float w[WAVELENGTH_SAMPLES];
00084 };
00085
00086 class LightPhoton : public BasicColorPhoton {
00087 public:
00088 LightPhoton(const TsPack *tspack, const Point &pp,
00089 const SWCSpectrum &wt, const Vector &wi_)
00090 : BasicColorPhoton(tspack, pp, wt), wi(wi_) { }
00091
00092 LightPhoton() : BasicColorPhoton() { }
00093 virtual ~LightPhoton() { }
00094
00095 virtual void save(bool isLittleEndian, std::basic_ostream<char> &stream) const;
00096 virtual void load(bool isLittleEndian, std::basic_istream<char> &stream);
00097
00098 Vector wi;
00099 };
00100
00101 class RadiancePhoton : public BasicColorPhoton {
00102 public:
00103 RadiancePhoton(const TsPack *tspack, const Point &pp,
00104 const SWCSpectrum &wt, const Normal &nn)
00105 : BasicColorPhoton(tspack, pp, wt), n(nn) { }
00106 RadiancePhoton(const TsPack *tspack, const Point &pp, const Normal & nn)
00107 : BasicColorPhoton(tspack, pp, SWCSpectrum(0.0f)), n(nn) { }
00108
00109 RadiancePhoton() : BasicColorPhoton() { }
00110 virtual ~RadiancePhoton() { }
00111
00112 virtual void save(bool isLittleEndian, std::basic_ostream<char> &stream) const;
00113 virtual void load(bool isLittleEndian, std::basic_istream<char> &stream);
00114
00115 Normal n;
00116 };
00117
00118 class PdfPhoton : public BasicPhoton {
00119 public:
00120
00121 class Direction {
00122 public:
00123 Direction() { }
00124 Direction(float aWeight) : weight(aWeight) { }
00125 Direction(const Vector& aDir, float aRadius, float aWeight)
00126 : dir(aDir), cosRadius(cosf(aRadius)), weight(aWeight) { }
00127
00128 bool operator < (const Direction& other) const {
00129 return weight < other.weight;
00130 }
00131
00132 Vector dir;
00133 float cosRadius;
00134 float weight;
00135 };
00136
00137 PdfPhoton(const Point &pp, const vector<Direction>& aDirs)
00138 : BasicPhoton(pp), dirs(aDirs)
00139 {
00140 float totWeight = 0.f;
00141 for(u_int i = 0; i<dirs.size(); i++)
00142 totWeight += dirs[i].weight;
00143 for(u_int i = 0; i<dirs.size(); i++)
00144 dirs[i].weight /= totWeight;
00145 }
00146
00147 PdfPhoton() : BasicPhoton(), dirs(0) { }
00148 virtual ~PdfPhoton() { }
00149
00150 virtual void save(bool isLittleEndian, std::basic_ostream<char> &stream) {
00151 }
00152
00153 float Sample(const TsPack *tspack, Vector *wi, float u1, float u2, float u3) const {
00154 u_int dn = Clamp(
00155 (u_int)(std::upper_bound(dirs.begin(), dirs.end(), Direction(u3)) - dirs.begin()),
00156 (u_int)(0), (u_int)(dirs.size() - 1));
00157
00158 Vector vx, vy;
00159 CoordinateSystem(dirs[dn].dir, &vx, &vy);
00160 *wi = UniformSampleCone(u1, u2, dirs[dn].cosRadius, vx, vy, dirs[dn].dir);
00161
00162 return Pdf(tspack, *wi);
00163 }
00164 float Pdf(const TsPack *tspack, const Vector &wi) const {
00165 float pdf = 0.f;
00166 for (u_int i = 0; i < dirs.size(); ++i) {
00167 if (Dot(dirs[i].dir, wi) > dirs[i].cosRadius)
00168 pdf += UniformConePdf(dirs[i].cosRadius);
00169 }
00170 return pdf;
00171 }
00172
00173 private:
00174 vector<Direction> dirs;
00175 };
00176
00177
00178
00179
00180
00181
00182
00183 template <class PhotonType> class BasicPhotonProcess {
00184 public:
00185 BasicPhotonProcess() {
00186 }
00187 };
00188
00189
00190
00191
00192
00193 template <class PhotonType> class ClosePhoton {
00194 public:
00195 ClosePhoton(const PhotonType *p = NULL,
00196 float md2 = INFINITY) {
00197 photon = p;
00198 distanceSquared = md2;
00199 }
00200
00201 bool operator<(const ClosePhoton & p2) const {
00202 return distanceSquared == p2.distanceSquared ? (photon < p2.photon) :
00203 distanceSquared < p2.distanceSquared;
00204 }
00205
00206 const PhotonType *photon;
00207 float distanceSquared;
00208 };
00209
00210 template <class PhotonType> class NearSetPhotonProcess : BasicPhotonProcess<PhotonType> {
00211 public:
00212 NearSetPhotonProcess(u_int mp, const Point &P): p(P) {
00213 photons = NULL;
00214 nLookup = mp;
00215 foundPhotons = 0;
00216 }
00217
00218 void operator()(const PhotonType &photon, float distSquared, float &maxDistSquared) const {
00219
00220 if (foundPhotons < nLookup) {
00221
00222 photons[foundPhotons++] = ClosePhoton<PhotonType>(&photon, distSquared);
00223 if (foundPhotons == nLookup) {
00224 std::make_heap(&photons[0], &photons[nLookup]);
00225 maxDistSquared = photons[0].distanceSquared;
00226 }
00227 } else {
00228
00229 std::pop_heap(&photons[0], &photons[nLookup]);
00230 photons[nLookup - 1] = ClosePhoton<PhotonType>(&photon, distSquared);
00231 std::push_heap(&photons[0], &photons[nLookup]);
00232 maxDistSquared = photons[0].distanceSquared;
00233 }
00234 }
00235
00236 const Point &p;
00237 ClosePhoton<PhotonType> *photons;
00238 u_int nLookup;
00239 mutable u_int foundPhotons;
00240 };
00241
00242
00243
00244
00245
00246 template <class PhotonType> class NearPhotonProcess : public BasicPhotonProcess<PhotonType> {
00247 public:
00248 NearPhotonProcess(const Point &pp, const Normal & nn)
00249 : p(pp), n(nn) {
00250 photon = NULL;
00251 }
00252
00253 void operator()(const PhotonType &rp,
00254 float distSquared, float &maxDistSquared) const {
00255 if (Dot(rp.n, n) > 0) {
00256 photon = &rp;
00257 maxDistSquared = distSquared;
00258 }
00259 }
00260
00261 const Point &p;
00262 const Normal &n;
00263 mutable const PhotonType *photon;
00264 };
00265
00266
00267
00268
00269
00270 template <class PhotonType, class PhotonProcess> class PhotonMap {
00271 public:
00272 PhotonMap() : photonCount(0), photonmap(NULL) { }
00273
00274 virtual ~PhotonMap() {
00275 if (photonmap)
00276 delete photonmap;
00277 }
00278
00290 void lookup(const Point &p, const PhotonProcess &proc,
00291 float &maxDistSquared) const {
00292 if (photonmap)
00293 photonmap->Lookup(p, proc, maxDistSquared);
00294 }
00295
00296 int getPhotonCount() { return photonCount; }
00297
00298 protected:
00299 int photonCount;
00300 KdTree<PhotonType, PhotonProcess> *photonmap;
00301 };
00302
00303 class RadiancePhotonMap : public PhotonMap<RadiancePhoton, NearPhotonProcess<RadiancePhoton> > {
00304 public:
00305 RadiancePhotonMap(u_int nl, float md) :
00306 PhotonMap<RadiancePhoton, NearPhotonProcess<RadiancePhoton> >(),
00307 nLookup(nl), maxDistSquared(md) { }
00308 virtual ~RadiancePhotonMap() { }
00309
00310 void init(const vector<RadiancePhoton> &photons) {
00311 photonCount = photons.size();
00312 photonmap = new KdTree<RadiancePhoton, NearPhotonProcess<RadiancePhoton> >(photons);
00313 }
00314
00325 SWCSpectrum LPhoton(const TsPack *tspack,
00326 const Intersection& isect,
00327 const Vector& wo,
00328 const BxDFType bxdfType) const;
00329
00330 void save(std::basic_ostream<char> &stream) const;
00331
00332 static void load(std::basic_istream<char> &stream, RadiancePhotonMap *map);
00333
00334
00335 const u_int nLookup;
00336 const float maxDistSquared;
00337 };
00338
00339 class LightPhotonMap : public PhotonMap<LightPhoton, NearSetPhotonProcess<LightPhoton> > {
00340 public:
00341 LightPhotonMap(u_int nl, float md) :
00342 PhotonMap<LightPhoton, NearSetPhotonProcess<LightPhoton> >(),
00343 nLookup(nl), maxDistSquared(md), nPaths(0) { }
00344 virtual ~LightPhotonMap() { }
00345
00346 void init(int npaths, const vector<LightPhoton> &photons) {
00347 photonCount = photons.size();
00348 nPaths = npaths;
00349 photonmap = new KdTree<LightPhoton, NearSetPhotonProcess<LightPhoton> >(photons);
00350 }
00351
00352 bool isEmpty() {
00353 return (nPaths == 0);
00354 }
00355
00365 SWCSpectrum EPhoton(
00366 const TsPack *tspack,
00367 const Point &p,
00368 const Normal &n) const;
00369
00381 SWCSpectrum LPhoton(
00382 const TsPack* tspack,
00383 const BSDF *bsdf,
00384 const Intersection &isect,
00385 const Vector &wo,
00386 const BxDFType bxdfType) const;
00387
00400 SWCSpectrum LPhotonDiffuseApprox(
00401 const TsPack* tspack,
00402 const BSDF *bsdf,
00403 const Intersection &isect,
00404 const Vector &wo,
00405 const BxDFType bxdfType) const;
00406
00418 SWCSpectrum LDiffusePhoton(
00419 const TsPack* tspack,
00420 const BSDF *bsdf,
00421 const Intersection &isect,
00422 const Vector &wo) const;
00423
00424 void save(std::basic_ostream<char> &stream) const;
00425
00426 static void load(std::basic_istream<char> &stream, LightPhotonMap *map);
00427
00428 const u_int nLookup;
00429 const float maxDistSquared;
00430 private:
00431 u_int nPaths;
00432 };
00433
00434 inline float Ekernel(const BasicPhoton *photon, const Point &p, float md2) {
00435 float s = (1.f - DistanceSquared(photon->p, p) / md2);
00436
00437 return 3.f / (md2 * M_PI) * s * s;
00438 }
00439
00440 enum PhotonMapRRStrategy { RR_EFFICIENCY, RR_PROBABILITY, RR_NONE };
00441
00461 extern void PhotonMapPreprocess(
00462 const TsPack* tspack,
00463 const Scene *scene,
00464 const string *mapFileName,
00465 const BxDFType photonBxdfType,
00466 const BxDFType radianceBxdfType,
00467 u_int nDirectPhotons,
00468 u_int nRadiancePhotons, RadiancePhotonMap *radianceMap,
00469 u_int nIndirectPhotons, LightPhotonMap *indirectMap,
00470 u_int nCausticPhotons, LightPhotonMap *causticMap,
00471 u_int maxDepth);
00472
00498 extern SWCSpectrum PhotonMapFinalGatherWithImportaceSampling(
00499 const TsPack* tspack,
00500 const Scene *scene,
00501 const Sample *sample,
00502 int sampleFinalGather1Offset,
00503 int sampleFinalGather2Offset,
00504 int gatherSamples,
00505 float cosGatherAngle,
00506 PhotonMapRRStrategy rrStrategy,
00507 float rrContinueProbability,
00508 const LightPhotonMap *indirectMap,
00509 const RadiancePhotonMap *radianceMap,
00510 const Vector &wo,
00511 const BSDF *bsdf,
00512 const BxDFType bxdfType);
00513
00534 extern SWCSpectrum PhotonMapFinalGather(
00535 const TsPack* tspack,
00536 const Scene *scene,
00537 const Sample *sample,
00538 int sampleFinalGatherOffset,
00539 int gatherSamples,
00540 PhotonMapRRStrategy rrStrategy,
00541 float rrContinueProbability,
00542 const LightPhotonMap *indirectMap,
00543 const RadiancePhotonMap *radianceMap,
00544 const Vector &wo,
00545 const BSDF *bsdf,
00546 const BxDFType bxdfType);
00547
00548 }
00549
00550 #endif // LUX_KDTREE_H
00551