Spectrum ExPhotonIntegrator::LPhoton( KdTree<Photon, PhotonProcess> *map, int nPaths, int nLookup, BSDF *bsdf, const Intersection &isect, const Vector &wo, float maxDistSquared) { Spectrum L(0.); if (!map) return L; BxDFType nonSpecular = BxDFType(BSDF_REFLECTION | BSDF_TRANSMISSION | BSDF_DIFFUSE | BSDF_GLOSSY); if (bsdf->NumComponents(nonSpecular) == 0) return L; static StatsCounter lookups("Photon Map", "Total lookups"); // NOBOOK // Initialize _PhotonProcess_ object, _proc_, for photon map lookups PhotonProcess proc(nLookup, isect.dg.p); proc.photons = (ClosePhoton *)alloca(nLookup * sizeof(ClosePhoton)); // Do photon map lookup ++lookups; // NOBOOK map->Lookup(isect.dg.p, proc, maxDistSquared); // Accumulate light from nearby photons static StatsRatio foundRate("Photon Map", "Photons found per lookup"); // NOBOOK foundRate.Add(proc.foundPhotons, 1); // NOBOOK // Estimate reflected light from photons ClosePhoton *photons = proc.photons; int nFound = proc.foundPhotons; Normal Nf = Dot(wo, bsdf->dgShading.nn) < 0 ? -bsdf->dgShading.nn : bsdf->dgShading.nn; if (bsdf->NumComponents(BxDFType(BSDF_REFLECTION | BSDF_TRANSMISSION | BSDF_GLOSSY)) > 0) { // Compute exitant radiance from photons for glossy surface for (int i = 0; i < nFound; ++i) { const Photon *p = photons[i].photon; BxDFType flag = Dot(Nf, p->wi) > 0.f ? BSDF_ALL_REFLECTION : BSDF_ALL_TRANSMISSION; float k = kernel(p, isect.dg.p, maxDistSquared); L += (k / nPaths) * bsdf->f(wo, p->wi, flag) * p->alpha; } } else { // Compute exitant radiance from photons for diffuse surface Spectrum Lr(0.), Lt(0.); for (int i = 0; i < nFound; ++i) { if (Dot(Nf, photons[i].photon->wi) > 0.f) { float k = kernel(photons[i].photon, isect.dg.p, maxDistSquared); Lr += (k / nPaths) * photons[i].photon->alpha; } else { float k = kernel(photons[i].photon, isect.dg.p, maxDistSquared); Lt += (k / nPaths) * photons[i].photon->alpha; } } L += Lr * bsdf->rho(wo, BSDF_ALL_REFLECTION) * INV_PI + Lt * bsdf->rho(wo, BSDF_ALL_TRANSMISSION) * INV_PI; } return L; }
Spectrum LPhoton(KdTree<Photon> *map, int nPaths, int nLookup, MemoryArena &arena, BSDF *bsdf, RNG &rng, const Intersection &isect, const Vector &wo, float maxDistSquared) { Spectrum L(0.); BxDFType nonSpecular = BxDFType(BSDF_REFLECTION | BSDF_TRANSMISSION | BSDF_DIFFUSE | BSDF_GLOSSY); if (map && bsdf->NumComponents(nonSpecular) > 0) { PBRT_PHOTON_MAP_STARTED_LOOKUP(const_cast<DifferentialGeometry *>(&isect.dg)); // Do photon map lookup at intersection point PhotonProcess proc(nLookup, arena.Alloc<ClosePhoton>(nLookup)); map->Lookup(isect.dg.p, proc, maxDistSquared); // Estimate reflected radiance due to incident photons ClosePhoton *photons = proc.photons; int nFound = proc.nFound; Normal Nf = Faceforward(bsdf->dgShading.nn, wo); if (bsdf->NumComponents(BxDFType(BSDF_REFLECTION | BSDF_TRANSMISSION | BSDF_GLOSSY)) > 0) { // Compute exitant radiance from photons for glossy surface for (int i = 0; i < nFound; ++i) { const Photon *p = photons[i].photon; float k = kernel(p, isect.dg.p, maxDistSquared); L += (k / (nPaths * maxDistSquared)) * bsdf->f(wo, p->wi) * p->alpha; } } else { // Compute exitant radiance from photons for diffuse surface Spectrum Lr(0.), Lt(0.); for (int i = 0; i < nFound; ++i) { if (Dot(Nf, photons[i].photon->wi) > 0.f) { float k = kernel(photons[i].photon, isect.dg.p, maxDistSquared); Lr += (k / (nPaths * maxDistSquared)) * photons[i].photon->alpha; } else { float k = kernel(photons[i].photon, isect.dg.p, maxDistSquared); Lt += (k / (nPaths * maxDistSquared)) * photons[i].photon->alpha; } } const int sqrtRhoSamples = 4; float rhoRSamples[2*sqrtRhoSamples*sqrtRhoSamples]; StratifiedSample2D(rhoRSamples, sqrtRhoSamples, sqrtRhoSamples, rng); float rhoTSamples[2*sqrtRhoSamples*sqrtRhoSamples]; StratifiedSample2D(rhoTSamples, sqrtRhoSamples, sqrtRhoSamples, rng); L += Lr * bsdf->rho(wo, sqrtRhoSamples*sqrtRhoSamples, rhoRSamples, BSDF_ALL_REFLECTION) * INV_PI + Lt * bsdf->rho(wo, sqrtRhoSamples*sqrtRhoSamples, rhoTSamples, BSDF_ALL_TRANSMISSION) * INV_PI; } PBRT_PHOTON_MAP_FINISHED_LOOKUP(const_cast<DifferentialGeometry *>(&isect.dg), proc.nFound, proc.nLookup, &L); } return L; }
void RowChecksumMatrixTest::testMatrix() { RowChecksumMatrix<double>& Lr = *this->Lr; RowChecksumMatrix<double>& L2r = *this->L2r; RowChecksumMatrix<double>& Ur = *this->Ur; // getM(), getN() CPPUNIT_ASSERT(Lr.getM() == 2); CPPUNIT_ASSERT(Lr.getN() == 3); // getData() CPPUNIT_ASSERT(Ur.getData() == UData); // getDataAllocation() CPPUNIT_ASSERT(!Lr.getDataAllocation()); CPPUNIT_ASSERT(!L2r.getDataAllocation()); CPPUNIT_ASSERT(!Ur.getDataAllocation()); // operator== CPPUNIT_ASSERT(Lr == Lr); CPPUNIT_ASSERT(Lr == L2r); CPPUNIT_ASSERT(!(Lr == Ur)); // operator= (IMatrix<double>&) L2r = Ur; CPPUNIT_ASSERT(L2r == Ur); CPPUNIT_ASSERT(*L2 == *U); CPPUNIT_ASSERT(!(Lr == L2r)); // operator() CPPUNIT_ASSERT(Lr(1,1) == 1.); CPPUNIT_ASSERT(Lr(1,2) == 0.); CPPUNIT_ASSERT(Lr(1,3) == 1.); CPPUNIT_ASSERT(Lr(2,1) == 1.5); CPPUNIT_ASSERT(Lr(2,2) == 1.); CPPUNIT_ASSERT(Lr(2,3) == 2.5); L2r(1,1) = 1.; L2r(1,2) = 0.; L2r(1,3) = 1.; L2r(2,1) = 1.5; L2r(2,2) = 1.; L2r(2,3) = 2.5; CPPUNIT_ASSERT(L2r(1,1) == 1.); CPPUNIT_ASSERT(L2r(1,2) == 0.); CPPUNIT_ASSERT(L2r(1,3) == 1.); CPPUNIT_ASSERT(L2r(2,1) == 1.5); CPPUNIT_ASSERT(L2r(2,2) == 1.); CPPUNIT_ASSERT(L2r(2,3) == 2.5); CPPUNIT_ASSERT(Lr == L2r); // distance() CPPUNIT_ASSERT(Lr.distance(Lr) == 0); CPPUNIT_ASSERT(Lr.distance(L2r) == 0); CPPUNIT_ASSERT(L2r.distance(Lr) == 0); CPPUNIT_ASSERT(Lr.distance(Ur) == 6); CPPUNIT_ASSERT(Ur.distance(Lr) == 6); L2r(2,2) = 0.; CPPUNIT_ASSERT(Lr.distance(L2r) == 1); CPPUNIT_ASSERT(L2r.distance(Lr) == 1); // weight() CPPUNIT_ASSERT(Lr.weight() == 5); CPPUNIT_ASSERT(L2r.weight() == 4); CPPUNIT_ASSERT(Ur.weight() == 5); // toString() CPPUNIT_ASSERT(Lr.toString().compare("[\n1 0 1 \n1.5 1 2.5 \n]\n") == 0); // locationId() for(int i = 1; i <= Lr.getM(); i++){ for(int j = 1; j <= Lr.getN(); j++){ for(int k = 1; k <= Lr.getM(); k++){ for(int l = 1; l <= Lr.getN(); l++){ if(!(i == k && j == l)) CPPUNIT_ASSERT(Lr.locationId(i, j) != Lr.locationId(k, l)); } } } } }