void InstantRadiosity( int N, double rho ) { double Start = N; for ( int Reflections = 0, End = N; End > 0; End = (int)Start, Reflections++ ) { Start *= rho; for ( int i = (int)Start; i < End; i++ ) { // Select starting point on light source Point y( phi( 2, i ), phi( 3, i ) ); Color L( Le( y ) ); // Le( y ) * supp Le; supp Le? double w = N; // trace reflections for ( int j = 0; j <= Reflections; j++ ) { glRenderShadowedScene( N / floor( w ) * L, y ); glAccum( GL_ACCUM, 1 / N ); // diffuse scattering Vector ω = ωd( phi( 2 * j + 2, i ), phi( 2 * j + 3, ( i ) ); //trace ray from y into direction ω y = h( y, ω ); // Attenuate and compensate L *= fd( y ); w *= ρ; } } } glAccum( GL_RETURN, 1.0 ); }
TEST_F(EventTest, EventDifference) { const double e = 1e-2; StreamFactory streamFactory; Device device(0); device.setActiveDevice(); ASSERT_TRUE(device.isActive()); Stream* stream = streamFactory.constructStream(device); Event before(*stream); //TODO a kernel here that waits a while Event after(*stream); stream->syncStream(); float diff = after - before; const float realDiff = 1; float l = realDiff - e; float h = realDiff + e; EXPECT_THAT(diff, Ge(l)); EXPECT_THAT(diff, Le(h)); delete stream; }
TEST_F(LogisticTransformTest, KernelSmallVector) { const int numberOfRows = 5; double e = 10e-5; Container::PinnedHostVector* hostVectorFrom = new Container::PinnedHostVector(numberOfRows); for(int i = 0; i < numberOfRows; ++i){ (*hostVectorFrom)(i) = i / 10; } Container::DeviceVector* logitDeviceVector = hostToDeviceStream1.transferVector(*hostVectorFrom); Container::DeviceVector* probDeviceVector = new Container::DeviceVector(numberOfRows); kernelWrapper.logisticTransform(*logitDeviceVector, *probDeviceVector); Container::HostVector* resultHostVector = deviceToHostStream1.transferVector(*probDeviceVector); stream->syncStream(); handleCudaStatus(cudaGetLastError(), "Error in LogisticTransform test: "); ASSERT_EQ(numberOfRows, resultHostVector->getNumberOfRows()); for(int i = 0; i < numberOfRows; ++i){ PRECISION x = i / 10; x = exp(x) / (1 + exp(x)); double l = x - e; double h = x + e; EXPECT_THAT((*resultHostVector)(i), Ge(l)); EXPECT_THAT((*resultHostVector)(i), Le(h)); } delete hostVectorFrom; delete logitDeviceVector; delete probDeviceVector; delete resultHostVector; }
void testList(int testSize) { printf("\n ==== Test %2d. Generate two lists each of size %d by random insertions\n", testID++, testSize); List<T> La; randomList(La, testSize); PRINT(La); List<T> Lb; randomList(Lb, testSize); PRINT(Lb); printf("\n ==== Test %2d. Call list members by rank (with high complexity)\n", testID++); for (int i = 0; i < La.size(); i++) print(La[i]->data); printf("\n"); for (int i = 0; i < Lb.size(); i++) print(Lb[i]->data); printf("\n"); printf("\n ==== Test %2d. Concatenation\n", testID++); PRINT(La); PRINT(Lb); while (0 < Lb.size()) La.insertAsLast(Lb.remove(Lb.first())); PRINT(La); PRINT(Lb); printf("\n ==== Test %2d. Increase\n", testID++); PRINT(La); increase(La); PRINT(La); printf("\n ==== Test %2d. Copy\n", testID++); PRINT(La); List<T> Ld(La); PRINT(Ld); printf("\n ==== Test %2d. Trim by random deletions\n", testID++); PRINT(Ld); while (testSize/4 < Ld.size()) { int N = rand() % Ld.size(); printf("removing L[%d]=", N); ListNodePosi(T) p = Ld.first(); while (0 < N--) p = p->succ; print(p->data); printf(" ...\n"); Ld.remove(p); PRINT(Ld); } printf("\n ==== Test %2d. Copy\n", testID++); PRINT(La); List<T> Le(La); PRINT(Le); printf("\n ==== Test %2d. FIND in\n", testID++); PRINT(Le); for (int i = 0; i <= testSize*2; i++) { //逐一测试[0, 2n]中的所有可能 ListNodePosi(T) p = Le.find((T) i); printf("Looking for "); print((T)i); printf(": "); if (p) { printf(" found with"); print(p->data); } else printf(" not found"); printf("\n"); } //正确的结构应该是大致(n+1次)失败、(n次)成功相间 printf("\n ==== Test %2d. Sort\n", testID++); PRINT(La); La.sort(); PRINT(La); printf("\n ==== Test %2d. SEARCH in\n", testID++); PRINT(La); for (int i = 0; i <= testSize*2; i++) { //逐一测试[0, 2n]中的所有可能 ListNodePosi(T) p = La.search((T) i); printf("Looking for "); print((T)i); printf(": "); printf(" stopped at"); print(p->data); if ((T) i == p->data) printf(" and found"); printf("\n"); } //正确的结构应该是大致(n+1次)失败、(n次)成功相间 printf("\n ==== Test %2d. Remove redundancy in\n", testID++); PRINT(La); printf("%d node(s) removed\n", La.uniquify()); PRINT(La); printf("\n ==== Test %2d. Remove redundancy in\n", testID++); PRINT(Le); printf("%d node(s) removed\n", Le.deduplicate()); PRINT(Le); printf("\n ==== Test %2d. Sort\n", testID++); PRINT(Le); Le.sort(); PRINT(Le); return; }
Vector sampleDirection(Point2 sample, Float &pdf, Spectrum &value) const { #if defined(SAMPLE_UNIFORMLY) pdf = 1.0f / (4*M_PI); Vector d = squareToSphere(sample); value = Le(-d); return d; #endif }
Color3f Li(const Scene *scene, Sampler *sampler, const Ray3f &ray) const { /* Find the surface that is visible in the requested direction */ Intersection its; //check if the ray intersects the scene if (!scene->rayIntersect(ray, its)) { //check if a distant disk light is set const Emitter* distantsDisk = scene->getDistantEmitter(); if(distantsDisk == nullptr ) return Color3f(0.0f); //sample the distant disk light return distantsDisk->sampleL(ray.d); } //get the radiance of hitten object Color3f Le(0.0f, 0.0f, 0.0f); if (its.mesh->isEmitter() ) { const Emitter* areaLightEM = its.mesh->getEmitter(); const areaLight* aEM = static_cast<const areaLight *> (areaLightEM); Le = aEM->sampleL(-ray.d, its.shFrame.n, its); } //get the asigned BSDF const BSDF* curBSDF = its.mesh->getBSDF(); Color3f Ld(0.0f, 0.0f, 0.0f); Color3f f(0.0f, 0.0f, 0.0f); Color3f totalLight(0.0f, 0.0f, 0.0f); //transform to the local frame //create a BRDF Query BSDFQueryRecord query = BSDFQueryRecord(its.toLocal(-ray.d), Vector3f(0.0f), EMeasure::ESolidAngle); //sample the BRDF Color3f mats = curBSDF->sample(query, sampler->next2D()); if(mats.maxCoeff() > 0.0f) { //Check for the light source Vector3f wo = its.toWorld(query.wo); Ray3f shadowRay(its.p, wo); Intersection itsShadow; if (scene->rayIntersect(shadowRay, itsShadow)) { //intersection check if mesh is emitter if(itsShadow.mesh->isEmitter()){ Ld = itsShadow.mesh->getEmitter()->radiance(); } } else { //check for distant disk light const Emitter* distantsDisk = scene->getDistantEmitter(); if(distantsDisk != nullptr ) Ld = distantsDisk->sampleL(wo); } totalLight += Ld * mats; } return Le + totalLight; }
TEST_F(RandomTests, NextNumber_TwoArgument) { int a = rnd.nextInt(10, 20); EXPECT_THAT(a, Ge(10)); EXPECT_THAT(a, Lt(20)); long long b = rnd.nextLongLong(1000000000000ll, 2000000000000ll); EXPECT_THAT(b, Ge(1000000000000ll)); EXPECT_THAT(b, Lt(2000000000000ll)); double c = rnd.nextDouble(100.0, 200.0); EXPECT_THAT(c, Ge(100.0)); EXPECT_THAT(c, Le(200.0)); }
glm::vec3 BidirectionalIntegrator::TraceRay(Ray r, unsigned int depth) { Intersection isx = intersection_engine->GetIntersection(r); if(isx.t < 0) return glm::vec3(0); else if(isx.object_hit->material->is_light_source) { return isx.object_hit->material->base_color * isx.texture_color; } glm::vec3 resultColor(0); for(Geometry* light : scene->lights) { std::vector<PathNode> eyePath = generateEyePath(r); std::vector<PathNode> lightPath = generateLightPath(light); if(!eyePath.empty() && !lightPath.empty()) { PathNode* node = &lightPath[0]; float lightPdf = light->RayPDF(node->isx,Ray(node->isx.point,node->dirIn_world)); glm::vec3 Le(0); if(lightPdf != 0) Le = light->material->base_color * light->material->intensity / lightPdf; glm::vec3 directWt(1.0f); for(int i=1;i<=eyePath.size();i++) { node = &eyePath[i-1]; Ray ray(light->transform.position(), - node->dirIn_world); resultColor += directWt * EstimateDirectLight(node->isx, ray, light) / WeightPath(i,0); directWt *= node->F * glm::abs(glm::dot(node->dirOut_world,node->isx.normal)) / node->pdf; for(int j=1;j<=lightPath.size();j++) { resultColor += Le * EvaluatePath(eyePath,i,lightPath,j) / WeightPath(i,j); } } } else { continue; } } return resultColor; }
void TestTermination( Integrator const& integrator) { Length const q_initial = 1 * Metre; Speed const v_initial = 0 * Metre / Second; Instant const t_initial; Instant const t_final = t_initial + 163 * Second; Time const step = 42 * Second; int const steps = static_cast<int>(std::floor((t_final - t_initial) / step)); int evaluations = 0; std::vector<ODE::SystemState> solution; ODE harmonic_oscillator; harmonic_oscillator.compute_acceleration = std::bind(ComputeHarmonicOscillatorAcceleration, _1, _2, _3, &evaluations); IntegrationProblem<ODE> problem; problem.equation = harmonic_oscillator; ODE::SystemState const initial_state = {{q_initial}, {v_initial}, t_initial}; problem.initial_state = &initial_state; problem.t_final = t_final; problem.append_state = [&solution](ODE::SystemState const& state) { solution.push_back(state); }; integrator.Solve(problem, step); EXPECT_EQ(steps, solution.size()); EXPECT_THAT(solution.back().time.value, AllOf(Gt(t_final - step), Le(t_final))); switch (integrator.composition) { case BA: case ABA: EXPECT_EQ(steps * integrator.evaluations, evaluations); break; case BAB: EXPECT_EQ(steps * integrator.evaluations + 1, evaluations); break; default: LOG(FATAL) << "Invalid composition"; } Length q_error; Speed v_error; for (int i = 0; i < steps; ++i) { Time const t = solution[i].time.value - t_initial; EXPECT_THAT(t, AlmostEquals((i + 1) * step, 0)); } }
void sampleEmissionArea(EmissionRecord &eRec, const Point2 &sample) const { if (eRec.type == EmissionRecord::ENormal) { Vector d = squareToSphere(sample); eRec.sRec.p = m_bsphere.center + d * m_bsphere.radius; eRec.sRec.n = Normal(-d); eRec.pdfArea = 1.0f / (4 * M_PI * m_bsphere.radius * m_bsphere.radius); eRec.value = Spectrum(M_PI); } else { /* Preview mode, which is more suitable for VPL-based rendering: approximate the infinitely far-away source with set of diffuse point sources */ const Float radius = m_bsphere.radius * 1.5f; Vector d = squareToSphere(sample); eRec.sRec.p = m_bsphere.center + d * radius; eRec.sRec.n = Normal(-d); eRec.pdfArea = 1.0f / (4 * M_PI * radius * radius); eRec.value = Le(d) * M_PI; } }
// Solving Δt * Δt == n. TEST_F(RootFindersTest, SquareRoots) { Instant const t_0; Instant const t_max = t_0 + 10 * Second; Length const n_max = Pow<2>(t_max - t_0) * SIUnit<Acceleration>(); for (Length n = 1 * Metre; n < n_max; n += 1 * Metre) { int evaluations = 0; auto const equation = [t_0, n, &evaluations](Instant const& t) { ++evaluations; return Pow<2>(t - t_0) * SIUnit<Acceleration>() - n; }; EXPECT_THAT(Bisect(equation, t_0, t_max) - t_0, AlmostEquals(Sqrt(n / SIUnit<Acceleration>()), 0, 1)); if (n == 25 * Metre) { EXPECT_EQ(3, evaluations); } else { EXPECT_THAT(evaluations, AllOf(Ge(49), Le(58))); } } }
Spectrum sampleEmissionDirection(EmissionRecord &eRec, const Point2 &sample) const { Float radius = m_bsphere.radius; if (eRec.type == EmissionRecord::EPreview) radius *= 1.5f; Point p2 = m_bsphere.center + squareToSphere(sample) * radius; eRec.d = p2 - eRec.sRec.p; Float length = eRec.d.length(); if (length == 0.0f) { eRec.pdfDir = 1.0f; return Spectrum(0.0f); } eRec.d /= length; eRec.pdfDir = INV_PI * dot(eRec.sRec.n, eRec.d); if (eRec.type == EmissionRecord::ENormal) return Le(-eRec.d) * INV_PI; else return Spectrum(INV_PI); }
Spectrum AreaLight::Sample_L( const Point3f& p , Vector3f* wi , LightSample& _lightSample , float* pdf , VisibilityTester* pVisibility ) const { // 采样光源对应的图元 int index = ( int )( _lightSample.value[0] * ( m_pPrimitive->GetShapeCount() - 1 ) ); Vector3f LightSourceSampleNormal; Point3f LightSourceSamplePoint = m_pPrimitive->GetShape( index )->Sample( p , _lightSample , LightSourceSampleNormal ); *wi = Normalize( LightSourceSamplePoint - p ); // Compute Primitive PDF value *pdf = m_pPrimitive->PDF( p , *wi ); pVisibility->SetSegment( p , 1e-3f , LightSourceSamplePoint , 1e-3f ); // Compute Li Spectrum Li = Le( LightSourceSamplePoint , LightSourceSampleNormal , -*wi ); return Li; }
Spectrum InfiniteAreaLightIS::Sample_L(const Scene *scene, float u1, float u2, float u3, float u4, Ray *ray, float *pdf) const { // Choose two points _p1_ and _p2_ on scene bounding sphere Point worldCenter; float worldRadius; scene->WorldBound().BoundingSphere(&worldCenter, &worldRadius); worldRadius *= 1.01f; Point p1 = worldCenter + worldRadius * UniformSampleSphere(u1, u2); Point p2 = worldCenter + worldRadius * UniformSampleSphere(u3, u4); // Construct ray between _p1_ and _p2_ ray->o = p1; ray->d = Normalize(p2-p1); // Compute _InfiniteAreaLightIS_ ray weight Vector to_center = Normalize(worldCenter - p1); float costheta = AbsDot(to_center,ray->d); *pdf = costheta / ((4.f * M_PI * worldRadius * worldRadius)); return Le(RayDifferential(ray->o, -ray->d)); }
/** * This is the tricky bit - we want to sample a ray that * has uniform density over the set of all rays passing * through the scene. * For more detail, see "Using low-discrepancy sequences and * the Crofton formula to compute surface areas of geometric models" * by Li, X. and Wang, W. and Martin, R.R. and Bowyer, A. * (Computer-Aided Design vol 35, #9, pp. 771--782) */ void sampleEmission(EmissionRecord &eRec, const Point2 &sample1, const Point2 &sample2) const { Assert(eRec.type == EmissionRecord::ENormal); /* Chord model - generate the ray passing through two uniformly distributed points on a sphere containing the scene */ Vector d = squareToSphere(sample1); eRec.sRec.p = m_bsphere.center + d * m_bsphere.radius; eRec.sRec.n = Normal(-d); Point p2 = m_bsphere.center + squareToSphere(sample2) * m_bsphere.radius; eRec.d = p2 - eRec.sRec.p; Float length = eRec.d.length(); if (length == 0) { eRec.value = Spectrum(0.0f); eRec.pdfArea = eRec.pdfDir = 1.0f; return; } eRec.d /= length; eRec.pdfArea = 1.0f / (4 * M_PI * m_bsphere.radius * m_bsphere.radius); eRec.pdfDir = INV_PI * dot(eRec.sRec.n, eRec.d); eRec.value = Le(-eRec.d); }
void TestTermination(Integrator const& integrator) { Length const q_initial = 1 * Metre; Speed const v_initial = 0 * Metre / Second; Instant const t_initial; Instant const t_final = t_initial + 1630 * Second; Time const step = 42 * Second; int const steps = static_cast<int>(std::floor((t_final - t_initial) / step)); int evaluations = 0; std::vector<ODE::SystemState> solution; ODE harmonic_oscillator; harmonic_oscillator.compute_acceleration = std::bind(ComputeHarmonicOscillatorAcceleration, _1, _2, _3, &evaluations); IntegrationProblem<ODE> problem; problem.equation = harmonic_oscillator; ODE::SystemState const initial_state = {{q_initial}, {v_initial}, t_initial}; problem.initial_state = &initial_state; auto append_state = [&solution](ODE::SystemState const& state) { solution.push_back(state); }; auto const instance = integrator.NewInstance(problem, std::move(append_state), step); integrator.Solve(t_final, *instance); EXPECT_EQ(steps, solution.size()); EXPECT_THAT(solution.back().time.value, AllOf(Gt(t_final - step), Le(t_final))); Length q_error; Speed v_error; for (int i = 0; i < steps; ++i) { Time const t = solution[i].time.value - t_initial; EXPECT_THAT(t, AlmostEquals((i + 1) * step, 0)); } }
TEST_F(EmbeddedExplicitRungeKuttaNyströmIntegratorTest, MaxSteps) { AdaptiveStepSizeIntegrator<ODE> const& integrator = DormandElMikkawyPrince1986RKN434FM<Length>(); Length const x_initial = 1 * Metre; Speed const v_initial = 0 * Metre / Second; Speed const v_amplitude = 1 * Metre / Second; Time const period = 2 * π * Second; AngularFrequency const ω = 1 * Radian / Second; Instant const t_initial; Instant const t_final = t_initial + 10 * period; Length const length_tolerance = 1 * Milli(Metre); Speed const speed_tolerance = 1 * Milli(Metre) / Second; // The number of steps if no step limit is set. std::int64_t const steps_forward = 132; int evaluations = 0; auto const step_size_callback = [](bool tolerable) {}; std::vector<ODE::SystemState> solution; ODE harmonic_oscillator; harmonic_oscillator.compute_acceleration = std::bind(ComputeHarmonicOscillatorAcceleration, _1, _2, _3, &evaluations); IntegrationProblem<ODE> problem; problem.equation = harmonic_oscillator; ODE::SystemState const initial_state = {{x_initial}, {v_initial}, t_initial}; problem.initial_state = &initial_state; problem.t_final = t_final; problem.append_state = [&solution](ODE::SystemState const& state) { solution.push_back(state); }; AdaptiveStepSize<ODE> adaptive_step_size; adaptive_step_size.first_time_step = t_final - t_initial; adaptive_step_size.safety_factor = 0.9; adaptive_step_size.tolerance_to_error_ratio = std::bind(HarmonicOscillatorToleranceRatio, _1, _2, length_tolerance, speed_tolerance, step_size_callback); adaptive_step_size.max_steps = 100; auto const outcome = integrator.Solve(problem, adaptive_step_size); EXPECT_EQ(termination_condition::ReachedMaximalStepCount, outcome.error()); EXPECT_THAT(AbsoluteError( x_initial * Cos(ω * (solution.back().time.value - t_initial)), solution.back().positions[0].value), AllOf(Ge(8e-4 * Metre), Le(9e-4 * Metre))); EXPECT_THAT(AbsoluteError( -v_amplitude * Sin(ω * (solution.back().time.value - t_initial)), solution.back().velocities[0].value), AllOf(Ge(1e-3 * Metre / Second), Le(2e-3 * Metre / Second))); EXPECT_THAT(solution.back().time.value, Lt(t_final)); EXPECT_EQ(100, solution.size()); // Check that a |max_steps| greater than or equal to the unconstrained number // of steps has no effect. for (std::int64_t const max_steps : {steps_forward, steps_forward + 1234}) { solution.clear(); adaptive_step_size.max_steps = steps_forward; auto const outcome = integrator.Solve(problem, adaptive_step_size); EXPECT_EQ(termination_condition::Done, outcome.error()); EXPECT_THAT(AbsoluteError(x_initial, solution.back().positions[0].value), AllOf(Ge(3e-4 * Metre), Le(4e-4 * Metre))); EXPECT_THAT(AbsoluteError(v_initial, solution.back().velocities[0].value), AllOf(Ge(2e-3 * Metre / Second), Le(3e-3 * Metre / Second))); EXPECT_EQ(t_final, solution.back().time.value); EXPECT_EQ(steps_forward, solution.size()); } }
Color HDRILight::eval(const DifferentialGeometry& dg, const Vec3f& wi) const { return Le(-wi); }
Spectrum f(const EmissionRecord &eRec) const { if (eRec.type == EmissionRecord::ENormal) return Le(-eRec.d) * INV_PI; else return Spectrum(INV_PI); }
void PhotonShootingTask::Run() { // Declare local variables for _PhotonShootingTask_ MemoryArena arena; RNG rng(31 * taskNum); vector<Photon> localDirectPhotons, localIndirectPhotons, localCausticPhotons; vector<RadiancePhoton> localRadiancePhotons; uint32_t totalPaths = 0; bool causticDone = (integrator->nCausticPhotonsWanted == 0); bool indirectDone = (integrator->nIndirectPhotonsWanted == 0); PermutedHalton halton(6, rng); vector<Spectrum> localRpReflectances, localRpTransmittances; while (true) { // Follow photon paths for a block of samples const uint32_t blockSize = 4096; for (uint32_t i = 0; i < blockSize; ++i) { float u[6]; halton.Sample(++totalPaths, u); // Choose light to shoot photon from float lightPdf; int lightNum = lightDistribution->SampleDiscrete(u[0], &lightPdf); const Light *light = scene.lights[lightNum]; // Generate _photonRay_ from light source and initialize _alpha_ LightSample ls(u[1], u[2], u[3]); LightInfo2 li = light->Sample_L(scene, ls, u[4], u[5], time); Spectrum Le(li.L); RayDifferential photonRay(li.ray); Normal Nl(li.N); if (li.pdf == 0.f || Le.IsBlack()) continue; Spectrum alpha = (AbsDot(Nl, photonRay.d) * Le) / (li.pdf * lightPdf); if (!alpha.IsBlack()) { // Follow photon path through scene and record intersections PBRT_PHOTON_MAP_STARTED_RAY_PATH(&photonRay, &alpha); bool specularPath = true; int nIntersections = 0; auto optPhotonIsect = scene.Intersect(photonRay); while (optPhotonIsect) { ++nIntersections; // Handle photon/surface intersection alpha *= renderer->Transmittance(scene, photonRay, NULL, rng, arena); BSDF *photonBSDF = optPhotonIsect->GetBSDF(photonRay, arena); BxDFType specularType = BxDFType(BSDF_REFLECTION | BSDF_TRANSMISSION | BSDF_SPECULAR); bool hasNonSpecular = (photonBSDF->NumComponents() > photonBSDF->NumComponents(specularType)); Vector wo = -photonRay.d; if (hasNonSpecular) { // Deposit photon at surface Photon photon(optPhotonIsect->dg.p, alpha, wo); bool depositedPhoton = false; if (specularPath && nIntersections > 1) { if (!causticDone) { PBRT_PHOTON_MAP_DEPOSITED_CAUSTIC_PHOTON(&optPhotonIsect->dg, &alpha, &wo); depositedPhoton = true; localCausticPhotons.push_back(photon); } } else { // Deposit either direct or indirect photon // stop depositing direct photons once indirectDone is true; don't // want to waste memory storing too many if we're going a long time // trying to get enough caustic photons desposited. if (nIntersections == 1 && !indirectDone && integrator->finalGather) { PBRT_PHOTON_MAP_DEPOSITED_DIRECT_PHOTON(&optPhotonIsect->dg, &alpha, &wo); depositedPhoton = true; localDirectPhotons.push_back(photon); } else if (nIntersections > 1 && !indirectDone) { PBRT_PHOTON_MAP_DEPOSITED_INDIRECT_PHOTON(&optPhotonIsect->dg, &alpha, &wo); depositedPhoton = true; localIndirectPhotons.push_back(photon); } } // Possibly create radiance photon at photon intersection point if (depositedPhoton && integrator->finalGather && rng.RandomFloat() < .125f) { Normal n = optPhotonIsect->dg.nn; n = Faceforward(n, -photonRay.d); localRadiancePhotons.push_back(RadiancePhoton(optPhotonIsect->dg.p, n)); Spectrum rho_r = photonBSDF->rho(rng, BSDF_ALL_REFLECTION); localRpReflectances.push_back(rho_r); Spectrum rho_t = photonBSDF->rho(rng, BSDF_ALL_TRANSMISSION); localRpTransmittances.push_back(rho_t); } } if (nIntersections >= integrator->maxPhotonDepth) break; // Sample new photon ray direction Vector wi; float pdf; BxDFType flags; Spectrum fr = photonBSDF->Sample_f(wo, &wi, BSDFSample(rng), &pdf, BSDF_ALL, &flags); if (fr.IsBlack() || pdf == 0.f) break; Spectrum anew = alpha * fr * AbsDot(wi, photonBSDF->dgShading.nn) / pdf; // Possibly terminate photon path with Russian roulette float continueProb = min(1.f, anew.y() / alpha.y()); if (rng.RandomFloat() > continueProb) break; alpha = anew / continueProb; specularPath &= ((flags & BSDF_SPECULAR) != 0); if (indirectDone && !specularPath) break; photonRay = RayDifferential(optPhotonIsect->dg.p, wi, photonRay, optPhotonIsect->rayEpsilon); optPhotonIsect = scene.Intersect(photonRay); } PBRT_PHOTON_MAP_FINISHED_RAY_PATH(&photonRay, &alpha); } arena.FreeAll(); } // Merge local photon data with data in _PhotonIntegrator_ { MutexLock lock(mutex); // Give up if we're not storing enough photons if (abortTasks) return; if (nshot > 500000 && (unsuccessful(integrator->nCausticPhotonsWanted, causticPhotons.size(), blockSize) || unsuccessful(integrator->nIndirectPhotonsWanted, indirectPhotons.size(), blockSize))) { Error("Unable to store enough photons. Giving up.\n"); causticPhotons.erase(causticPhotons.begin(), causticPhotons.end()); indirectPhotons.erase(indirectPhotons.begin(), indirectPhotons.end()); radiancePhotons.erase(radiancePhotons.begin(), radiancePhotons.end()); abortTasks = true; return; } progress.Update(localIndirectPhotons.size() + localCausticPhotons.size()); nshot += blockSize; // Merge indirect photons into shared array if (!indirectDone) { integrator->nIndirectPaths += blockSize; for (uint32_t i = 0; i < localIndirectPhotons.size(); ++i) indirectPhotons.push_back(localIndirectPhotons[i]); localIndirectPhotons.erase(localIndirectPhotons.begin(), localIndirectPhotons.end()); if (indirectPhotons.size() >= integrator->nIndirectPhotonsWanted) indirectDone = true; nDirectPaths += blockSize; for (uint32_t i = 0; i < localDirectPhotons.size(); ++i) directPhotons.push_back(localDirectPhotons[i]); localDirectPhotons.erase(localDirectPhotons.begin(), localDirectPhotons.end()); } // Merge direct, caustic, and radiance photons into shared array if (!causticDone) { integrator->nCausticPaths += blockSize; for (uint32_t i = 0; i < localCausticPhotons.size(); ++i) causticPhotons.push_back(localCausticPhotons[i]); localCausticPhotons.erase(localCausticPhotons.begin(), localCausticPhotons.end()); if (causticPhotons.size() >= integrator->nCausticPhotonsWanted) causticDone = true; } for (uint32_t i = 0; i < localRadiancePhotons.size(); ++i) radiancePhotons.push_back(localRadiancePhotons[i]); localRadiancePhotons.erase(localRadiancePhotons.begin(), localRadiancePhotons.end()); for (uint32_t i = 0; i < localRpReflectances.size(); ++i) rpReflectances.push_back(localRpReflectances[i]); localRpReflectances.erase(localRpReflectances.begin(), localRpReflectances.end()); for (uint32_t i = 0; i < localRpTransmittances.size(); ++i) rpTransmittances.push_back(localRpTransmittances[i]); localRpTransmittances.erase(localRpTransmittances.begin(), localRpTransmittances.end()); } // Exit task if enough photons have been found if (indirectDone && causticDone) break; } }
void Parser::executeAction(int production) try { if (d_token__ != _UNDETERMINED_) pushToken__(d_token__); // save an already available token // $insert defaultactionreturn // save default non-nested block $$ if (int size = s_productionInfo[production].d_size) d_val__ = d_vsp__[1 - size]; switch (production) { // $insert actioncases case 1: #line 43 "parser.yy" { d_val__.get<Tag__::basic>() = d_vsp__[0].data<Tag__::basic>(); res = d_val__.get<Tag__::basic>(); } break; case 2: #line 51 "parser.yy" { d_val__.get<Tag__::basic>() = add(d_vsp__[-2].data<Tag__::basic>(), d_vsp__[0].data<Tag__::basic>()); } break; case 3: #line 54 "parser.yy" { d_val__.get<Tag__::basic>() = sub(d_vsp__[-2].data<Tag__::basic>(), d_vsp__[0].data<Tag__::basic>()); } break; case 4: #line 57 "parser.yy" { d_val__.get<Tag__::basic>() = mul(d_vsp__[-2].data<Tag__::basic>(), d_vsp__[0].data<Tag__::basic>()); } break; case 5: #line 60 "parser.yy" { d_val__.get<Tag__::basic>() = div(d_vsp__[-2].data<Tag__::basic>(), d_vsp__[0].data<Tag__::basic>()); } break; case 6: #line 63 "parser.yy" { auto tup = parse_implicit_mul(d_vsp__[-2].data<Tag__::string>()); if (neq(*std::get<1>(tup), *one)) { d_val__.get<Tag__::basic>() = mul( std::get<0>(tup), pow(std::get<1>(tup), d_vsp__[0].data<Tag__::basic>())); } else { d_val__.get<Tag__::basic>() = pow(std::get<0>(tup), d_vsp__[0].data<Tag__::basic>()); } } break; case 7: #line 73 "parser.yy" { d_val__.get<Tag__::basic>() = pow(d_vsp__[-2].data<Tag__::basic>(), d_vsp__[0].data<Tag__::basic>()); } break; case 8: #line 76 "parser.yy" { d_val__.get<Tag__::basic>() = rcp_static_cast<const Basic>( Lt(d_vsp__[-2].data<Tag__::basic>(), d_vsp__[0].data<Tag__::basic>())); } break; case 9: #line 79 "parser.yy" { d_val__.get<Tag__::basic>() = rcp_static_cast<const Basic>( Gt(d_vsp__[-2].data<Tag__::basic>(), d_vsp__[0].data<Tag__::basic>())); } break; case 10: #line 82 "parser.yy" { d_val__.get<Tag__::basic>() = rcp_static_cast<const Basic>( Le(d_vsp__[-2].data<Tag__::basic>(), d_vsp__[0].data<Tag__::basic>())); } break; case 11: #line 85 "parser.yy" { d_val__.get<Tag__::basic>() = rcp_static_cast<const Basic>( Ge(d_vsp__[-2].data<Tag__::basic>(), d_vsp__[0].data<Tag__::basic>())); } break; case 12: #line 88 "parser.yy" { d_val__.get<Tag__::basic>() = rcp_static_cast<const Basic>( Eq(d_vsp__[-2].data<Tag__::basic>(), d_vsp__[0].data<Tag__::basic>())); } break; case 13: #line 91 "parser.yy" { set_boolean s; s.insert(rcp_static_cast<const Boolean>( d_vsp__[-2].data<Tag__::basic>())); s.insert(rcp_static_cast<const Boolean>( d_vsp__[0].data<Tag__::basic>())); d_val__.get<Tag__::basic>() = rcp_static_cast<const Basic>(logical_or(s)); } break; case 14: #line 99 "parser.yy" { set_boolean s; s.insert(rcp_static_cast<const Boolean>( d_vsp__[-2].data<Tag__::basic>())); s.insert(rcp_static_cast<const Boolean>( d_vsp__[0].data<Tag__::basic>())); d_val__.get<Tag__::basic>() = rcp_static_cast<const Basic>(logical_and(s)); } break; case 15: #line 107 "parser.yy" { vec_boolean s; s.push_back(rcp_static_cast<const Boolean>( d_vsp__[-2].data<Tag__::basic>())); s.push_back(rcp_static_cast<const Boolean>( d_vsp__[0].data<Tag__::basic>())); d_val__.get<Tag__::basic>() = rcp_static_cast<const Basic>(logical_xor(s)); } break; case 16: #line 115 "parser.yy" { d_val__.get<Tag__::basic>() = d_vsp__[-1].data<Tag__::basic>(); } break; case 17: #line 118 "parser.yy" { d_val__.get<Tag__::basic>() = neg(d_vsp__[0].data<Tag__::basic>()); } break; case 18: #line 121 "parser.yy" { d_val__.get<Tag__::basic>() = rcp_static_cast<const Basic>( logical_not(rcp_static_cast<const Boolean>( d_vsp__[0].data<Tag__::basic>()))); } break; case 19: #line 124 "parser.yy" { d_val__.get<Tag__::basic>() = rcp_static_cast<const Basic>(d_vsp__[0].data<Tag__::basic>()); } break; case 20: #line 129 "parser.yy" { d_val__.get<Tag__::basic>() = parse_identifier(d_vsp__[0].data<Tag__::string>()); } break; case 21: #line 134 "parser.yy" { auto tup = parse_implicit_mul(d_vsp__[0].data<Tag__::string>()); d_val__.get<Tag__::basic>() = mul(std::get<0>(tup), std::get<1>(tup)); } break; case 22: #line 140 "parser.yy" { d_val__.get<Tag__::basic>() = parse_numeric(d_vsp__[0].data<Tag__::string>()); } break; case 23: #line 145 "parser.yy" { d_val__.get<Tag__::basic>() = d_vsp__[0].data<Tag__::basic>(); } break; case 24: #line 152 "parser.yy" { d_val__.get<Tag__::basic>() = functionify(d_vsp__[-3].data<Tag__::string>(), d_vsp__[-1].data<Tag__::basic_vec>()); } break; case 25: #line 160 "parser.yy" { d_val__.get<Tag__::basic_vec>() = d_vsp__[-2].data<Tag__::basic_vec>(); d_val__.get<Tag__::basic_vec>().push_back( d_vsp__[0].data<Tag__::basic>()); } break; case 26: #line 166 "parser.yy" { d_val__.get<Tag__::basic_vec>() = vec_basic(1, d_vsp__[0].data<Tag__::basic>()); } break; } } catch (std::exception const &exc) { exceptionHandler__(exc); }
Spectrum Le(const LuminaireSamplingRecord &lRec) const { return Le(-lRec.d); }
inline Spectrum Le(const Ray &ray) const { return Le(normalize(ray.d)); }