Spectrum SampleIntegrator::E(const Scene *scene, const Point &p, const Normal &n, Float time,
		const Medium *medium, Sampler *sampler, int nSamples, bool handleIndirect) const {
	Spectrum E(0.0f);
	LuminaireSamplingRecord lRec;
	RadianceQueryRecord rRec(scene, sampler);
	Frame frame(n);

	sampler->generate();
	for (int i=0; i<nSamples; i++) {
		rRec.newQuery(RadianceQueryRecord::ERadianceNoEmission, medium);

		/* Direct */
		if (scene->sampleAttenuatedLuminaire(p, time, medium, lRec, rRec.nextSample2D())) {
			Float dp = dot(lRec.d, n);
			if (dp < 0) 
				E -= lRec.value * dp;
		}

		/* Indirect */
		if (handleIndirect) {
			Vector d = frame.toWorld(squareToHemispherePSA(rRec.nextSample2D()));
			++rRec.depth;
			E += Li(RayDifferential(p, d, time), rRec) * M_PI;
		}
		sampler->advance();
	}
	return E / (Float) nSamples;
}
Exemple #2
0
Spectrum DirectLightingIntegrator::Li(const RayDifferential &ray,
                                      const Scene &scene, Sampler &sampler,
                                      MemoryArena &arena, int depth) const {
    ProfilePhase p(Prof::SamplerIntegratorLi);
    Spectrum L(0.f);
    // Find closest ray intersection or return background radiance
    SurfaceInteraction isect;
    if (!scene.Intersect(ray, &isect)) {
        for (const auto &light : scene.lights) L += light->Le(ray);
        return L;
    }

    // Compute scattering functions for surface interaction
    isect.ComputeScatteringFunctions(ray, arena);
    if (!isect.bsdf)
        return Li(isect.SpawnRay(ray.d), scene, sampler, arena, depth);
    Vector3f wo = isect.wo;
    // Compute emitted light if ray hit an area light source
    L += isect.Le(wo);
    if (scene.lights.size() > 0) {
        // Compute direct lighting for _DirectLightingIntegrator_ integrator
        if (strategy == LightStrategy::UniformSampleAll)
            L += UniformSampleAllLights(isect, scene, arena, sampler,
                                        nLightSamples);
        else
            L += UniformSampleOneLight(isect, scene, arena, sampler);
    }
    if (depth + 1 < maxDepth) {
        Vector3f wi;
        // Trace rays for specular reflection and refraction
        L += SpecularReflect(ray, isect, scene, sampler, arena, depth);
        L += SpecularTransmit(ray, isect, scene, sampler, arena, depth);
    }
    return L;
}
Exemple #3
0
Spectrum SamplingIntegrator::E(const Scene *scene, const Intersection &its,
		const Medium *medium, Sampler *sampler, int nSamples, bool handleIndirect) const {
	Spectrum E(0.0f);
	RadianceQueryRecord query(scene, sampler);
	DirectSamplingRecord dRec(its);
	Frame frame(its.shFrame.n);

	sampler->generate(Point2i(0));
	for (int i=0; i<nSamples; i++) {
		/* Sample the direct illumination component */
		int maxIntermediateInteractions = -1;
		Spectrum directRadiance = scene->sampleAttenuatedEmitterDirect(
			dRec, its, medium, maxIntermediateInteractions, query.nextSample2D());

		if (!directRadiance.isZero()) {
			Float dp = dot(dRec.d, its.shFrame.n);
			if (dp > 0)
				E += directRadiance * dp;
		}

		/* Sample the indirect illumination component */
		if (handleIndirect) {
			query.newQuery(RadianceQueryRecord::ERadianceNoEmission, medium);
			Vector d = frame.toWorld(Warp::squareToCosineHemisphere(query.nextSample2D()));
			++query.depth;
			query.medium = medium;
			E += Li(RayDifferential(its.p, d, its.time), query) * M_PI;
		}

		sampler->advance();
	}

	return E / (Float) nSamples;
}
void Rubik::turnCubeDown() { //White to red
	R(false);
	Li(false);
	this->shift(this->middle, 0, 2, 5, 1);
	this->shift(this->edges, 4, 0, 14, 17);
	this->shift(this->edges, 12, 2, 5, 16);

	std::map<std::string, std::string> tempMap(movesDictionary);

	//Dictionary
	/*movesDictionary[movesDictionary[_R]] = movesDictionary[_R];
	movesDictionary[movesDictionary[_Ri]] = movesDictionary[_Ri];
	movesDictionary[movesDictionary[_R2]] = movesDictionary[_R2];
	movesDictionary[movesDictionary[_L]] = movesDictionary[_L];
	movesDictionary[movesDictionary[_Li]] = movesDictionary[_Li];
	movesDictionary[movesDictionary[_L2]] = movesDictionary[_L2];*/
	movesDictionary[_U] = tempMap[_F];
	movesDictionary[_Ui] = tempMap[_Fi];
	movesDictionary[_U2] = tempMap[_F2];
	movesDictionary[_B] = tempMap[_U];
	movesDictionary[_Bi] = tempMap[_Ui];
	movesDictionary[_B2] = tempMap[_U2];
	movesDictionary[_F] = tempMap[_D];
	movesDictionary[_Fi] = tempMap[_Di];
	movesDictionary[_F2] = tempMap[_D2];
	movesDictionary[_D] = tempMap[_B];
	movesDictionary[_Di] = tempMap[_Bi];
	movesDictionary[_D2] = tempMap[_B2];

}
// Scene Methods
void Scene::Render() {
	// Allocate and initialize _sample_
	Sample *sample = new Sample(surfaceIntegrator,
	                            volumeIntegrator,
	                            this);
	// Allow integrators to do pre-processing for the scene
	surfaceIntegrator->Preprocess(this);
	volumeIntegrator->Preprocess(this);
	// Trace rays: The main loop
	ProgressReporter progress(sampler->TotalSamples(), "Rendering");
	while (sampler->GetNextSample(sample)) {
		// Find camera ray for _sample_
		RayDifferential ray;
		float rayWeight = camera->GenerateRay(*sample, &ray);
		// Generate ray differentials for camera ray
		++(sample->imageX);
		camera->GenerateRay(*sample, &ray.rx);
		--(sample->imageX);
		++(sample->imageY);
		camera->GenerateRay(*sample, &ray.ry);
		ray.hasDifferentials = true;
		--(sample->imageY);
		// Evaluate radiance along camera ray
		float alpha;
		Spectrum Ls = 0.f;
		if (rayWeight > 0.f)
			Ls = rayWeight * Li(ray, sample, &alpha);
		// Issue warning if unexpected radiance value returned
		if (Ls.IsNaN()) {
			Error("Not-a-number radiance value returned "
		          "for image sample.  Setting to black.");
			Ls = Spectrum(0.f);
		}
		else if (Ls.y() < -1e-5) {
			Error("Negative luminance value, %g, returned "
		          "for image sample.  Setting to black.", Ls.y());
			Ls = Spectrum(0.f);
		}
		else if (isinf(Ls.y())) {
			Error("Infinite luminance value returned "
		          "for image sample.  Setting to black.");
			Ls = Spectrum(0.f);
		}
		// Add sample contribution to image
		camera->film->AddSample(*sample, ray, Ls, alpha);
		// Free BSDF memory from computing image sample value
		BSDF::FreeAll();
		// Report rendering progress
		static StatsCounter cameraRaysTraced("Camera", "Camera Rays Traced");
		++cameraRaysTraced;
		progress.Update();
	}
	// Clean up after rendering and store final image
	delete sample;
	progress.Done();
	camera->film->WriteImage();
}
Exemple #6
0
	Color RayTracer::TraceSpecularTransmit(const Scene *scene, const Ray& ray, const LocalGeo& geom, int depth, const CameraSample& samplebuf){
		Vec3 wo = -ray.dir, wi;
		float pdf;
		Color color;
		Color f = geom.bsdf->SampleDirect(wo, geom, Sample(), &wi, &pdf, BSDFType(BSDF_TRANSMISSION | BSDF_SPECULAR));
		float absdot_wi_n = Math::AbsDot(wi, geom.normal);
		if (pdf > 0.f && f != Color::BLACK && absdot_wi_n != 0.f){
			Ray refracted(geom.point, wi);
			//TODO differential
			color = f * Li(scene, refracted, depth, samplebuf) * absdot_wi_n / pdf;
		}
		return color;
	}
Exemple #7
0
void SamplingIntegrator::renderBlock(const Scene *scene,
		const Sensor *sensor, Sampler *sampler, ImageBlock *block,
		const bool &stop, const std::vector< TPoint2<uint8_t> > &points) const {

	Float diffScaleFactor = 1.0f /
		std::sqrt((Float) sampler->getSampleCount());

	bool needsApertureSample = sensor->needsApertureSample();
	bool needsTimeSample = sensor->needsTimeSample();

	RadianceQueryRecord rRec(scene, sampler);
	Point2 apertureSample(0.5f);
	Float timeSample = 0.5f;
	RayDifferential sensorRay;

	block->clear();

	uint32_t queryType = RadianceQueryRecord::ESensorRay;

	if (!sensor->getFilm()->hasAlpha()) /* Don't compute an alpha channel if we don't have to */
		queryType &= ~RadianceQueryRecord::EOpacity;

	for (size_t i = 0; i<points.size(); ++i) {
		Point2i offset = Point2i(points[i]) + Vector2i(block->getOffset());
		if (stop)
			break;

		sampler->generate(offset);

		for (size_t j = 0; j<sampler->getSampleCount(); j++) {
			rRec.newQuery(queryType, sensor->getMedium());
			Point2 samplePos(Point2(offset) + Vector2(rRec.nextSample2D()));

			if (needsApertureSample)
				apertureSample = rRec.nextSample2D();
			if (needsTimeSample)
				timeSample = rRec.nextSample1D();

			Spectrum spec = sensor->sampleRayDifferential(
				sensorRay, samplePos, apertureSample, timeSample);

			sensorRay.scaleDifferential(diffScaleFactor);

			spec *= Li(sensorRay, rRec);
			block->put(samplePos, spec, rRec.alpha);
			sampler->advance();
		}
	}
}
Exemple #8
0
/*
 * Calculate coefficients of B-spline representing a multivariate polynomial
 *
 * The polynomial f(x), with x in R^n, has m terms on the form
 * f(x) = c(0)*x(0)^E(0,0)*x(1)^E(0,1)*...*x(n-1)^E(0,n-1)
 *       +c(1)*x(0)^E(1,0)*x(1)^E(1,1)*...*x(n-1)^E(1,n-1)
 *       +...
 *       +c(m-1)*x(0)^E(m-1,0)*x(1)^E(m-1,1)*...*x(n-1)^E(m-1,n-1)
 * where c in R^m is a vector with coefficients for each of the m terms,
 * and E in N^(mxn) is a matrix with the exponents of each variable in each of the m terms,
 * e.g. the first row of E defines the first term with variable exponents E(0,0) to E(0,n-1).
 *
 * Note: E must be a matrix of nonnegative integers
 */
DenseMatrix getBSplineBasisCoefficients(DenseVector c, DenseMatrix E, std::vector<double> lb, std::vector<double> ub)
{
    unsigned int dim = E.cols();
    unsigned int terms = E.rows();
    assert(dim >= 1); // At least one variable
    assert(terms >= 1); // At least one term (assumes that c is a column vector)
    assert(terms == c.rows());
    assert(dim == lb.size());
    assert(dim == ub.size());

    // Get highest power of each variable
    DenseVector powers = E.colwise().maxCoeff();

    // Store in std vector
    std::vector<unsigned int> powers2;
    for (unsigned int i = 0; i < powers.size(); ++i)
        powers2.push_back(powers(i));

    // Calculate tensor product transformation matrix T
    DenseMatrix T = getTransformationMatrix(powers2, lb, ub);

    // Compute power basis coefficients (lambda vector)
    SparseMatrix L(T.cols(),1);
    L.setZero();

    for (unsigned int i = 0; i < terms; i++)
    {
        SparseMatrix Li(1,1);
        Li.insert(0,0) = 1;

        for (unsigned int j = 0; j < dim; j++)
        {
            int e = E(i,j);
            SparseVector li(powers(j)+1);
            li.reserve(1);
            li.insert(e) = 1;

            SparseMatrix temp = Li;
            Li = kroneckerProduct(temp, li);
        }

        L += c(i)*Li;
    }

    // Compute B-spline coefficients
    DenseMatrix C = T*L;

    return C;
}
Exemple #9
0
void Cube::RotateUp()
{
    Li();
    SaveState();
    subCubes[1][0][0] = ROTATE_UP(oldSubCubes[1][2][0]);
    subCubes[1][0][1] = ROTATE_UP(oldSubCubes[1][1][0]);
    subCubes[1][0][2] = ROTATE_UP(oldSubCubes[1][0][0]);
    subCubes[1][1][0] = ROTATE_UP(oldSubCubes[1][2][1]);
    subCubes[1][1][1] = ROTATE_UP(oldSubCubes[1][1][1]);
    subCubes[1][1][2] = ROTATE_UP(oldSubCubes[1][0][1]);
    subCubes[1][2][0] = ROTATE_UP(oldSubCubes[1][2][2]);
    subCubes[1][2][1] = ROTATE_UP(oldSubCubes[1][1][2]);
    subCubes[1][2][2] = ROTATE_UP(oldSubCubes[1][0][2]);
    R();
}
Exemple #10
0
Spectrum SamplerIntegrator::SpecularTransmit(
    const RayDifferential &ray, const SurfaceInteraction &isect,
    const Scene &scene, Sampler &sampler, MemoryArena &arena, int depth) const {
    Vector3f wo = isect.wo, wi;
    Float pdf;
    const Point3f &p = isect.p;
    const Normal3f &ns = isect.shading.n;
    const BSDF &bsdf = *isect.bsdf;
    Spectrum f = bsdf.Sample_f(wo, &wi, sampler.Get2D(), &pdf,
                               BxDFType(BSDF_TRANSMISSION | BSDF_SPECULAR));
    Spectrum L = Spectrum(0.f);
    if (pdf > 0.f && !f.IsBlack() && AbsDot(wi, ns) != 0.f) {
        // Compute ray differential _rd_ for specular transmission
        RayDifferential rd = isect.SpawnRay(wi);
        if (ray.hasDifferentials) {
            rd.hasDifferentials = true;
            rd.rxOrigin = p + isect.dpdx;
            rd.ryOrigin = p + isect.dpdy;

            Float eta = bsdf.eta;
            Vector3f w = -wo;
            if (Dot(wo, ns) < 0) eta = 1.f / eta;

            Normal3f dndx = isect.shading.dndu * isect.dudx +
                            isect.shading.dndv * isect.dvdx;
            Normal3f dndy = isect.shading.dndu * isect.dudy +
                            isect.shading.dndv * isect.dvdy;

            Vector3f dwodx = -ray.rxDirection - wo,
                     dwody = -ray.ryDirection - wo;
            Float dDNdx = Dot(dwodx, ns) + Dot(wo, dndx);
            Float dDNdy = Dot(dwody, ns) + Dot(wo, dndy);

            Float mu = eta * Dot(w, ns) - Dot(wi, ns);
            Float dmudx =
                (eta - (eta * eta * Dot(w, ns)) / Dot(wi, ns)) * dDNdx;
            Float dmudy =
                (eta - (eta * eta * Dot(w, ns)) / Dot(wi, ns)) * dDNdy;

            rd.rxDirection =
                wi + eta * dwodx - Vector3f(mu * dndx + dmudx * ns);
            rd.ryDirection =
                wi + eta * dwody - Vector3f(mu * dndy + dmudy * ns);
        }
        L = f * Li(rd, scene, sampler, arena, depth + 1) * AbsDot(wi, ns) / pdf;
    }
    return L;
}
Exemple #11
0
Spectrum VolumePatIntegrator::Li_Multiple(const Scene *scene, const Renderer *renderer,
        const RayDifferential &r, const Sample *sample, RNG &rng,
        Spectrum *T, MemoryArena &arena) const {

    // Do eye and light random walks
    VolumeVertexList eyeVertexList;
    EyeRandomWalk(scene, r, eyeVertexList, rng);

    // Do multiple scattering
    Spectrum Li(0.f);
    for (uint64_t i = 0; i < eyeVertexList.size(); i++) {
        Li += EvaluatePath(scene, eyeVertexList, i, rng, renderer, arena);
    }

    return Li;
}
Exemple #12
0
// WhittedIntegrator Method Definitions
Spectrum WhittedIntegrator::Li(const RayDifferential &ray, const Scene &scene,
                               Sampler &sampler, MemoryArena &arena,
                               int depth) const {
    Spectrum L(0.);
    // Find closest ray intersection or return background radiance
    SurfaceInteraction isect;
    if (!scene.Intersect(ray, &isect)) {
        for (const auto &light : scene.lights) L += light->Le(ray);
        return L;
    }

    // Compute emitted and reflected light at ray intersection point

    // Initialize common variables for Whitted integrator
    const Normal3f &n = isect.shading.n;
    Vector3f wo = isect.wo;

    // Compute scattering functions for surface interaction
    isect.ComputeScatteringFunctions(ray, arena);
    if (!isect.bsdf)
        return Li(isect.SpawnRay(ray.d), scene, sampler, arena, depth);

    // Compute emitted light if ray hit an area light source
    L += isect.Le(wo);

    // Add contribution of each light source
    for (const auto &light : scene.lights) {
        Vector3f wi;
        Float pdf;
        VisibilityTester visibility;
        Spectrum Li =
            light->Sample_Li(isect, sampler.Get2D(), &wi, &pdf, &visibility);
        if (Li.IsBlack() || pdf == 0) continue;
        Spectrum f = isect.bsdf->f(wo, wi);
        if (!f.IsBlack() && visibility.Unoccluded(scene))
            L += f * Li * AbsDot(wi, n) / pdf;
    }
    if (depth + 1 < maxDepth) {
        // Trace rays for specular reflection and refraction
        L += SpecularReflect(ray, isect, scene, sampler, arena, depth);
        L += SpecularTransmit(ray, isect, scene, sampler, arena, depth);
    }
    return L;
}
Exemple #13
0
maxint_t S2_hard(maxint_t x, int threads)
{
  if (x < 1)
    return 0;

  if (print_status())
    set_print_variables(true);

  double alpha = get_alpha(x, 0.0017154, -0.0508992, 0.483613, 0.0672202);
  int64_t y = (int64_t) (iroot<3>(x) * alpha);
  int64_t z = (int64_t) (x / y);
  int64_t c = PhiTiny::get_c(y);

  // TODO: find better S2_hard approximation formula
  maxint_t s2_hard_approx = Li(x);

  if (x <= numeric_limits<int64_t>::max())
    return S2_hard((int64_t) x, y, z, c, (int64_t) s2_hard_approx, threads);
  else
    return S2_hard(x, y, z, c, s2_hard_approx, threads);
}
Exemple #14
0
// check if a clause subsumes another clause. subsumed clause
// must have MORE elements than the subsuming clause.
//
int
ST(Array<Literal> &C, Array<Literal> &D, int i, int j, Substitutions &theta)
{
	// check if clause D literals are exhausted
	if (j > D.getSize())
	{
		return(NOMATCH);
	}

	// search for a possible unifying literal
	int a = j;
	Literal Li(C[i]);
	if (theta.applyTo(Li) != OK)
	{
		ERROR("applyTo failed.", errno);
		return(NOTOK);
	}
	Substitutions mu;
	for ( ; a <= D.getSize(); a++)
	{
		mu.clear();
		Literal Ka(D[a]);
		if (unify(Li, Ka, mu) == OK)
			break;
	}
	if (a > D.getSize())
	{
		return(NOMATCH);
	}

	// attempt to extend the matching
	Substitutions theta_mu(theta*mu);
	// if (i == C.getSize() || ST(C, D, i+1, 1, theta*mu) == OK)
	if (i == C.getSize() || ST(C, D, i+1, 1, theta_mu) == OK)
	{
		return(OK);
	}
	else
		return(ST(C, D, i, a+1, theta));
}
Exemple #15
0
Spectrum SamplerIntegrator::SpecularReflect(
    const RayDifferential &ray, const SurfaceInteraction &isect,
    const Scene &scene, Sampler &sampler, MemoryArena &arena, int depth) const {
    // Compute specular reflection direction _wi_ and BSDF value
    Vector3f wo = isect.wo, wi;
    Float pdf;
    BxDFType type = BxDFType(BSDF_REFLECTION | BSDF_SPECULAR);
    Spectrum f = isect.bsdf->Sample_f(wo, &wi, sampler.Get2D(), &pdf, type);

    // Return contribution of specular reflection
    const Normal3f &ns = isect.shading.n;
    if (pdf > 0.f && !f.IsBlack() && AbsDot(wi, ns) != 0.f) {
        // Compute ray differential _rd_ for specular reflection
        RayDifferential rd = isect.SpawnRay(wi);
        if (ray.hasDifferentials) {
            rd.hasDifferentials = true;
            rd.rxOrigin = isect.p + isect.dpdx;
            rd.ryOrigin = isect.p + isect.dpdy;
            // Compute differential reflected directions
            Normal3f dndx = isect.shading.dndu * isect.dudx +
                            isect.shading.dndv * isect.dvdx;
            Normal3f dndy = isect.shading.dndu * isect.dudy +
                            isect.shading.dndv * isect.dvdy;
            Vector3f dwodx = -ray.rxDirection - wo,
                     dwody = -ray.ryDirection - wo;
            Float dDNdx = Dot(dwodx, ns) + Dot(wo, dndx);
            Float dDNdy = Dot(dwody, ns) + Dot(wo, dndy);
            rd.rxDirection =
                wi - dwodx + 2.f * Vector3f(Dot(wo, ns) * dndx + dDNdx * ns);
            rd.ryDirection =
                wi - dwody + 2.f * Vector3f(Dot(wo, ns) * dndy + dDNdy * ns);
        }
        return f * Li(rd, scene, sampler, arena, depth + 1) * AbsDot(wi, ns) /
               pdf;
    } else
        return Spectrum(0.f);
}
Exemple #16
0
    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
            Vector3f d = ray.d;
            return distantsDisk->sampleL(d);
        }

        //get the Number of lights from the scene
        const  std::vector<Emitter *> lights = scene->getEmitters();
        uint32_t nLights = lights.size();

        Color3f tp(1.0f, 1.0f, 1.0f);
        Color3f L(0.0f, 0.0f, 0.0f);
        Ray3f pathRay(ray.o, ray.d);

        bool deltaFlag = true;

        while(true) {

            if (its.mesh->isEmitter() && deltaFlag) {
                const Emitter* areaLightEM = its.mesh->getEmitter();
                const areaLight* aEM = static_cast<const areaLight *> (areaLightEM);
                L += tp * aEM->sampleL(-pathRay.d, its.shFrame.n, its);
            }

            //Light sampling
            //randomly select a lightsource
            uint32_t var = uint32_t(std::min(sampler->next1D()*nLights, float(nLights) - 1.0f));

            //init the light color
            Color3f Li(0.0f, 0.0f, 0.0f);
            Color3f Ld(1.0f, 1.0f, 1.0f);

            //create a sample for the light
            const BSDF* curBSDF = its.mesh->getBSDF();
            const Point2f lightSample = sampler->next2D();
            VisibilityTester vis;
            Vector3f wo;
            float lightpdf;
            float bsdfpdf;
            Normal3f n = its.shFrame.n;

            deltaFlag = curBSDF->isDeltaBSDF();

            //sample the light

            {
                Li = lights[var]->sampleL(its.p, Epsilon, lightSample , &wo, &lightpdf, &vis);
                lightpdf /= float(nLights);
                //check if the pdf of the sample is greater than 0 and if the color is not black
                if(lightpdf > 0 && Li.maxCoeff() != 0.0f) {
                    //calculate the cosine term wi in my case the vector to the light
                    float cosTerm = std::abs(n.dot(wo));
                    const BSDFQueryRecord queryEM = BSDFQueryRecord(its.toLocal(- pathRay.d), its.toLocal(wo), EMeasure::ESolidAngle, sampler);
                    Color3f f = curBSDF->eval(queryEM);

                    if(f.maxCoeff() > 0.0f && f.minCoeff() >= 0.0f && vis.Unoccluded(scene)) {
                        bsdfpdf = curBSDF->pdf(queryEM);
                        float weight = BalanceHeuristic(float(1), lightpdf, float(1), bsdfpdf);
                        if(curBSDF->isDeltaBSDF())  weight = 1.0f;
                        if(bsdfpdf > 0.0f) {
                            Ld = (weight * f * Li * cosTerm) / lightpdf;
                            L += tp * Ld;
                        } else {
                            //cout << "bsdfpdf = " << bsdfpdf  << endl;
                            //cout << "f = " << f  << endl;
                        }
                    }
                }
            }

            //Material part
            BSDFQueryRecord queryMats = BSDFQueryRecord(its.toLocal(-pathRay.d), Vector3f(0.0f), EMeasure::ESolidAngle, sampler);

            Color3f fi =  curBSDF->sample(queryMats, sampler->next2D());
            bsdfpdf = curBSDF->pdf(queryMats);
            lightpdf = 0.0f;
            if(fi.maxCoeff() > 0.0f && fi.minCoeff() >= 0.0f) {
                if(bsdfpdf > 0.0f) {
                    Ray3f shadowRay(its.p, its.toWorld(queryMats.wo));
                    Intersection lightIsect;

                     if (scene->rayIntersect(shadowRay, lightIsect)) {
                         if(lightIsect.mesh->isEmitter()){
                            const Emitter* areaLightEMcur = lightIsect.mesh->getEmitter();
                            const areaLight* aEMcur = static_cast<const areaLight *> (areaLightEMcur);

                            Li = aEMcur->sampleL(-shadowRay.d, lightIsect.shFrame.n, lightIsect);
                            lightpdf = aEMcur->pdf(its.p, (lightIsect.p - its.p).normalized(), lightIsect.p, Normal3f(lightIsect.shFrame.n));
                         }
                     } else {
                         const Emitter* distantsDisk = scene->getDistantEmitter();
                         if(distantsDisk != nullptr ) {
                             //check if THIS is right!
                             Li = distantsDisk->sampleL(lightIsect.toWorld(queryMats.wo));
                             lightpdf = distantsDisk->pdf(Point3f(0.0f), wo, Point3f(0.0f), Normal3f(0.0f));
                         }
                     }
                     lightpdf /= float(nLights);
                     //calculate the weights
                     float weight = BalanceHeuristic(float(1), bsdfpdf, float(1), lightpdf);


                     //check if the lightcolor is not black
                     if(Li.maxCoeff() > 0.0f  && lightpdf > 0.0f ) {
                         //wo in my case the vector to the light
                         Ld = weight * Li * fi;
                         L += tp * Ld;
                     }
                }



                 tp *= fi;
            } else {
                break;
            }

            wo = its.toWorld(queryMats.wo);
            pathRay = Ray3f(its.p, wo);

            if (!scene->rayIntersect(pathRay, its)) {
                const Emitter* distantsDisk = scene->getDistantEmitter();
                if(distantsDisk != nullptr ) {
                    //sample the distant disk light
                    Vector3f d = pathRay.d;
                    L += tp * distantsDisk->sampleL(d);
                }


                break;
            }

            float maxCoeff = tp.maxCoeff();
            float q = std::min(0.99f, maxCoeff);
            if(q < sampler->next1D()){
                break;
            }
            tp /= q;
        }

        return L;

    }
 Color vplIntegrator::Li(Ray& ray, const Ref<BackendScene>& scene, IntegratorState& state) {
   LightPath path(ray); return Li(path,scene,state);
 }
Exemple #18
0
 Col3f PathTraceIntegrator::Li(const Ray& ray, const Ref<BackendScene>& scene, const PrecomputedSample& sample, size_t& numRays) {
   return Li(LightPath(ray),scene,sample,numRays);
 }
Exemple #19
0
Spectrum SamplingIntegrator::Li(const RayDifferential &ray, RadianceQueryRecord &rRec, RenderLogger* logger ) const
{
	return Li(ray, rRec);
}
Exemple #20
0
int main(int argc, char * argv[]) {

	std::string file;

	int RDN = 0;

	char c;
	while ((c = getopt(argc, argv, "A:R:")) != -1) {
		switch (c) {
		case 'A':
			file = optarg;
			break;
		case 'R':
			RDN = atoi(optarg);
			break;
		}
	}

//	file= "../../SVM/epsilon_normalized";
//	file = "data/dense.svm";
//	file = "data/a1a";
//	file = "../../SVM/random_dense";

	stringstream ss("");
	ss << file << "_log";

	ofstream logFile;
	logFile.open(ss.str().c_str());

	omp_set_num_threads(1);

	const int MAXIMUM_THREADS = 64;
	std::vector<gsl_rng *> rs = randomNumberUtil::inittializeRandomSeeds(
			MAXIMUM_THREADS);

	int n = 1000; // this value was used for experiments
	int m = n * 2;

	randomNumberUtil::init_random_seeds(rs);
//--------------------- run experiment - one can change precission here

//	string inputFile, int file, int totalFiles,
//			ProblemData<L, D> & part, bool zeroBased

	ProblemData<int, double> part;
	std::vector<double> A;
	std::vector<double> b;

	if (RDN == 0) {
		loadDistributedSparseSVMRowData(file, -1, -1, part, false);
		m = part.m;
		n = part.n;
//		std::vector<double> &A = part.A_csr_values;
//		std::vector<double> &b = part.b;
	} else {

		switch (RDN) {
		case 1:

			n = 2048;
			m = n / 2;

			break;

		case 2:

			n = 2048;
			m = n * 2;

			break;

		case 3:

			n = 2048;
			m = n;

			break;

		default:
			break;
		}

		A.resize(m * n, 0);
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < m; j++) {
				A[i * m + j] = -1 + 2 * rand() / (0.0 + RAND_MAX);
			}
			double norm = cblas_l2_norm(m, &A[m * i], 1);
			cblas_vector_scale(m, &A[m * i], 1 / norm);
		}
		b.resize(n);
		for (int i = 0; i < b.size(); i++) {
			b[i] = -1 + 2 * round(rand() / (0.0 + RAND_MAX));
		}
	}
	std::vector<double> Li(n, 0);
	std::vector<double> LiSqInv(n, 0);

	bool dense = (m * n == A.size());

	if (dense) {
		cout << "Input data is dense!!!" << endl;
		for (int i = 0; i < n; i++) {
			Li[i] = 0;
			LiSqInv[i] = 0;
			for (int j = 0; j < m; j++) {
				Li[i] += A[i * m + j] * A[i * m + j];
			}
			if (Li[i] > 0) {
				LiSqInv[i] = 1 / sqrt(Li[i]);
			}
		}

	} else {
		cout << "Input data is sparse!!!  " << part.A_csr_row_ptr.size()
				<< endl;

		for (int i = 0; i < n; i++) {
			Li[i] = 0;
			LiSqInv[i] = 0;
			for (int j = part.A_csr_row_ptr[i]; j < part.A_csr_row_ptr[i + 1];
					j++) {
				Li[i] += part.A_csr_values[j] * part.A_csr_values[j];
			}
			if (Li[i] > 0) {
				LiSqInv[i] = 1 / sqrt(Li[i]);
			}
		}

	}
	cout << "Stage 2" << endl;

	std::vector<double> x(n);
	std::vector<double> y(m);

	for (int i = 0; i < n; i++) {
		x[i] = rand() / (0.0 + RAND_MAX);
	}
	double norm = cblas_l2_norm(n, &x[0], 1);
	cblas_vector_scale(n, &x[0], 1 / norm);

	double maxEig = 1;

	for (int PM = 0; PM < 20; PM++) {

		if (dense) {
			for (int j = 0; j < m; j++) {
				y[j] = 0;

				for (int i = 0; i < n; i++) {
					y[j] += A[i * m + j] * LiSqInv[i] * x[i];
				}
			}

		} else {
			for (int j = 0; j < m; j++) {
				y[j] = 0;
			}
			for (int i = 0; i < n; i++) {
				for (int j = part.A_csr_row_ptr[i];
						j < part.A_csr_row_ptr[i + 1]; j++) {
					y[part.A_csr_col_idx[j]] += part.A_csr_values[j]
							* LiSqInv[i] * x[i];
				}

			}

		}

		for (int i = 0; i < n; i++) {
			x[i] = 0;
			if (dense) {
				for (int j = 0; j < m; j++) {
					x[i] += A[i * m + j] * LiSqInv[i] * y[j];
				}
			} else {
				for (int j = part.A_csr_row_ptr[i];
						j < part.A_csr_row_ptr[i + 1]; j++) {
					x[i] += part.A_csr_values[j] * LiSqInv[i]
							* y[part.A_csr_col_idx[j]];
				}

			}

		}

		maxEig = cblas_l2_norm(n, &x[0], 1);
		cout << maxEig << endl;
		cblas_vector_scale(n, &x[0], 1 / maxEig);

	}

	cout << "Max eigenvalue estimated " << endl;

	x.resize(0);
	y.resize(0);
	LiSqInv.resize(0);

	double lambda = 1 / (n + 0.0);

	double maxTime = 1000;

	std::vector<double> Hessian;
	if (n < 10000) {
		Hessian.resize(n * n);

		if (dense) {

			cblas_dgemm(CblasColMajor, CblasTrans, CblasNoTrans, n, n, m, 1.0,
					&A[0], m, &A[0], m, 0, &Hessian[0], n);

		} else {

			std::vector<double>& vals = part.A_csr_values;
			std::vector<int> &rowPtr = part.A_csr_row_ptr;
			std::vector<int> &colIdx = part.A_csr_col_idx;

			for (int row = 0; row < n; row++) {
				for (int col = row; col < n; col++) {

					double tmp = 0;

					int id1 = rowPtr[row];
					int id2 = rowPtr[col];

					while (id1 < rowPtr[row + 1] && id2 < rowPtr[col + 1]) {

						if (colIdx[id1] == colIdx[id2]) {
							tmp += vals[id1] * vals[id2];
							id1++;
							id2++;
						} else if (colIdx[id1] < colIdx[id2]) {
							id1++;
						} else {
							id2++;
						}

					}

					Hessian[row * n + col] = tmp;
					Hessian[col * n + row] = tmp;

				}
			}
		}
	}

	int MAXTAU = n / 2;
	if (MAXTAU > 1024 * 8) {
		MAXTAU = 1024 * 8;
	}

	for (int tau = 1; tau <= MAXTAU; tau = tau * 2) {
//		int tau = 1;
//		omp_set_num_threads(tau);

		double sigma = 1 + (tau - 1) * (maxEig - 1) / (n - 1.0);

		if (dense) {
			randomNumberUtil::init_random_seeds(rs);

			runPCDMExperiment(m, n, A, b, lambda, tau, logFile, Li, sigma,
					maxTime);
			randomNumberUtil::init_random_seeds(rs);

			runCDNExperiment(m, n, A, b, lambda, tau, logFile, 1, maxTime,
					Hessian);
			randomNumberUtil::init_random_seeds(rs);

			runCDNExperiment(m, n, A, b, lambda, tau, logFile, 2, maxTime,
					Hessian);
		} else {

			randomNumberUtil::init_random_seeds(rs);
			runPCDMExperimentSparse(m, n, part, part.b, lambda, tau, logFile,
					Li, sigma, maxTime);
			randomNumberUtil::init_random_seeds(rs);
			runCDNExperimentSparse(m, n, part, part.b, lambda, tau, logFile, 1,
					maxTime, Hessian);
			randomNumberUtil::init_random_seeds(rs);
			runCDNExperimentSparse(m, n, part, part.b, lambda, tau, logFile, 2,
					maxTime, Hessian);

		}
	}

	logFile.close();

//	histogramLogFile.close();
//	experimentLogFile.close();
	return 0;
}
	Spectrum Li(const RayDifferential &r, RadianceQueryRecord &rRec) const {
		/* Some aliases and local variables */
		const Scene *scene = rRec.scene;
		Intersection &its = rRec.its;
		RayDifferential ray(r);
		Spectrum Li(0.0f);
		bool scattered = false;

		/* Perform the first ray intersection (or ignore if the
		   intersection has already been provided). */
		rRec.rayIntersect(ray);
		ray.mint = Epsilon;

		Spectrum throughput(1.0f);
		Float eta = 1.0f;

		while (rRec.depth <= m_maxDepth || m_maxDepth < 0) {
			if (!its.isValid()) {
				/* If no intersection could be found, potentially return
				   radiance from a environment luminaire if it exists */
				if ((rRec.type & RadianceQueryRecord::EEmittedRadiance)
					&& (!m_hideEmitters || scattered))
					Li += throughput * scene->evalEnvironment(ray);
				break;
			}

			const BSDF *bsdf = its.getBSDF(ray);

			/* Possibly include emitted radiance if requested */
			if (its.isEmitter() && (rRec.type & RadianceQueryRecord::EEmittedRadiance)
				&& (!m_hideEmitters || scattered))
				Li += throughput * its.Le(-ray.d);

			/* Include radiance from a subsurface scattering model if requested */
			if (its.hasSubsurface() && (rRec.type & RadianceQueryRecord::ESubsurfaceRadiance))
				Li += throughput * its.LoSub(scene, rRec.sampler, -ray.d, rRec.depth);

			if ((rRec.depth >= m_maxDepth && m_maxDepth > 0)
				|| (m_strictNormals && dot(ray.d, its.geoFrame.n)
					* Frame::cosTheta(its.wi) >= 0)) {

				/* Only continue if:
				   1. The current path length is below the specifed maximum
				   2. If 'strictNormals'=true, when the geometric and shading
				      normals classify the incident direction to the same side */
				break;
			}

			/* ==================================================================== */
			/*                     Direct illumination sampling                     */
			/* ==================================================================== */

			/* Estimate the direct illumination if this is requested */
			DirectSamplingRecord dRec(its);

			if (rRec.type & RadianceQueryRecord::EDirectSurfaceRadiance &&
				(bsdf->getType() & BSDF::ESmooth)) {
				Spectrum value = scene->sampleEmitterDirect(dRec, rRec.nextSample2D());
				if (!value.isZero()) {
					const Emitter *emitter = static_cast<const Emitter *>(dRec.object);

					/* Allocate a record for querying the BSDF */
					BSDFSamplingRecord bRec(its, its.toLocal(dRec.d), ERadiance);

					/* Evaluate BSDF * cos(theta) */
					const Spectrum bsdfVal = bsdf->eval(bRec);

					/* Prevent light leaks due to the use of shading normals */
					if (!bsdfVal.isZero() && (!m_strictNormals
							|| dot(its.geoFrame.n, dRec.d) * Frame::cosTheta(bRec.wo) > 0)) {

						/* Calculate prob. of having generated that direction
						   using BSDF sampling */
						Float bsdfPdf = (emitter->isOnSurface() && dRec.measure == ESolidAngle)
							? bsdf->pdf(bRec) : 0;

						/* Weight using the power heuristic */
						Float weight = miWeight(dRec.pdf, bsdfPdf);
						Li += throughput * value * bsdfVal * weight;
					}
				}
			}

			/* ==================================================================== */
			/*                            BSDF sampling                             */
			/* ==================================================================== */

			/* Sample BSDF * cos(theta) */
			Float bsdfPdf;
			BSDFSamplingRecord bRec(its, rRec.sampler, ERadiance);
			Spectrum bsdfWeight = bsdf->sample(bRec, bsdfPdf, rRec.nextSample2D());
			if (bsdfWeight.isZero())
				break;

			scattered |= bRec.sampledType != BSDF::ENull;

			/* Prevent light leaks due to the use of shading normals */
			const Vector wo = its.toWorld(bRec.wo);
			Float woDotGeoN = dot(its.geoFrame.n, wo);
			if (m_strictNormals && woDotGeoN * Frame::cosTheta(bRec.wo) <= 0)
				break;

			bool hitEmitter = false;
			Spectrum value;

			/* Trace a ray in this direction */
			ray = Ray(its.p, wo, ray.time);
			if (scene->rayIntersect(ray, its)) {
				/* Intersected something - check if it was a luminaire */
				if (its.isEmitter()) {
					value = its.Le(-ray.d);
					dRec.setQuery(ray, its);
					hitEmitter = true;
				}
			} else {
				/* Intersected nothing -- perhaps there is an environment map? */
				const Emitter *env = scene->getEnvironmentEmitter();

				if (env) {
					if (m_hideEmitters && !scattered)
						break;

					value = env->evalEnvironment(ray);
					if (!env->fillDirectSamplingRecord(dRec, ray))
						break;
					hitEmitter = true;
				} else {
					break;
				}
			}

			/* Keep track of the throughput and relative
			   refractive index along the path */
			throughput *= bsdfWeight;
			eta *= bRec.eta;

			/* If a luminaire was hit, estimate the local illumination and
			   weight using the power heuristic */
			if (hitEmitter &&
				(rRec.type & RadianceQueryRecord::EDirectSurfaceRadiance)) {
				/* Compute the prob. of generating that direction using the
				   implemented direct illumination sampling technique */
				const Float lumPdf = (!(bRec.sampledType & BSDF::EDelta)) ?
					scene->pdfEmitterDirect(dRec) : 0;
				Li += throughput * value * miWeight(bsdfPdf, lumPdf);
			}

			/* ==================================================================== */
			/*                         Indirect illumination                        */
			/* ==================================================================== */

			/* Set the recursive query type. Stop if no surface was hit by the
			   BSDF sample or if indirect illumination was not requested */
			if (!its.isValid() || !(rRec.type & RadianceQueryRecord::EIndirectSurfaceRadiance))
				break;
			rRec.type = RadianceQueryRecord::ERadianceNoEmission;

			if (rRec.depth++ >= m_rrDepth) {
				/* Russian roulette: try to keep path weights equal to one,
				   while accounting for the solid angle compression at refractive
				   index boundaries. Stop with at least some probability to avoid
				   getting stuck (e.g. due to total internal reflection) */

				Float q = std::min(throughput.max() * eta * eta, (Float) 0.95f);
				if (rRec.nextSample1D() >= q)
					break;
				throughput /= q;
			}
		}

		/* Store statistics */
		avgPathLength.incrementBase();
		avgPathLength += rRec.depth;

		return Li;
	}
  Color PathTraceIntegrator::Li(LightPath& lightPath, const Ref<BackendScene>& scene, IntegratorState& state)
  {
    /*! Terminate path if too long or contribution too low. */
    if (lightPath.depth >= maxDepth || reduce_max(lightPath.throughput) < minContribution)
      return zero;

    /*! Traverse ray. */
    DifferentialGeometry dg;
    //scene->intersector->intersect(lightPath.lastRay);
    rtcIntersect(scene->scene,(RTCRay&)lightPath.lastRay);
    scene->postIntersect(lightPath.lastRay,dg);
    state.numRays++;
    //return Color(dg.st.x,dg.st.y,0.0f);

    Color L = zero;
    const Vector3f wo = -lightPath.lastRay.dir;
    BRDFType directLightingBRDFTypes = (BRDFType)(DIFFUSE); 
    BRDFType giBRDFTypes = (BRDFType)(ALL);
    if (sampleLightForGlossy) {
      directLightingBRDFTypes = (BRDFType)(DIFFUSE|GLOSSY); 
      giBRDFTypes = (BRDFType)(SPECULAR);
    }

    /*! Environment shading when nothing hit. */
    if (!lightPath.lastRay)
    {
      if (backplate && lightPath.unbend) {
        const int x = clamp(int(state.pixel.x * backplate->width ), 0, int(backplate->width )-1);
        const int y = clamp(int(state.pixel.y * backplate->height), 0, int(backplate->height)-1);
        L = backplate->get(x, y);
      }
      else {
        if (!lightPath.ignoreVisibleLights)
          for (size_t i=0; i<scene->envLights.size(); i++)
            L += scene->envLights[i]->Le(wo);
      }
      return L;
    }

    /*! face forward normals */
    bool backfacing = false;
    if (dot(dg.Ng, lightPath.lastRay.dir) > 0) {
      backfacing = true; dg.Ng = -dg.Ng; dg.Ns = -dg.Ns;
    }

    /*! Shade surface. */
    CompositedBRDF brdfs;
    if (dg.material) dg.material->shade(lightPath.lastRay, lightPath.lastMedium, dg, brdfs);

    /*! Add light emitted by hit area light source. */
    if (!lightPath.ignoreVisibleLights && dg.light && !backfacing)
      L += dg.light->Le(dg,wo);

    /*! Global illumination. Pick one BRDF component and sample it. */
    if (lightPath.depth < maxDepth)
    {
      /*! sample brdf */
      Sample3f wi; BRDFType type;
      Vec2f s  = state.sample->getVec2f(firstScatterSampleID     + lightPath.depth);
      float ss = state.sample->getFloat(firstScatterTypeSampleID + lightPath.depth);
      Color c = brdfs.sample(wo, dg, wi, type, s, ss, giBRDFTypes);

      /*! Continue only if we hit something valid. */
      if (c != Color(zero) && wi.pdf > 0.0f)
      {
        /*! Compute  simple volumetric effect. */
        const Color& transmission = lightPath.lastMedium.transmission;
        if (transmission != Color(one)) c *= pow(transmission,lightPath.lastRay.tfar);

        /*! Tracking medium if we hit a medium interface. */
        Medium nextMedium = lightPath.lastMedium;
        if (type & TRANSMISSION) nextMedium = dg.material->nextMedium(lightPath.lastMedium);

        /*! Continue the path. */
        LightPath scatteredPath = lightPath.extended(Ray(dg.P, wi, dg.error*epsilon, inf, lightPath.lastRay.time), 
                                                     nextMedium, c, (type & directLightingBRDFTypes) != NONE);
        L += c * Li(scatteredPath, scene, state) * rcp(wi.pdf);
      }
    }

    /*! Check if any BRDF component uses direct lighting. */
    bool useDirectLighting = false;
    for (size_t i=0; i<brdfs.size(); i++)
      useDirectLighting |= (brdfs[i]->type & directLightingBRDFTypes) != NONE;

    /*! Direct lighting. Shoot shadow rays to all light sources. */
    if (useDirectLighting)
    {
      for (size_t i=0; i<scene->allLights.size(); i++)
      {
        if ((scene->allLights[i]->illumMask & dg.illumMask) == 0)
          continue;

        /*! Either use precomputed samples for the light or sample light now. */
        LightSample ls;
        if (scene->allLights[i]->precompute()) ls = state.sample->getLightSample(precomputedLightSampleID[i]);
        else ls.L = scene->allLights[i]->sample(dg, ls.wi, ls.tMax, state.sample->getVec2f(lightSampleID));

        /*! Ignore zero radiance or illumination from the back. */
        //if (ls.L == Color(zero) || ls.wi.pdf == 0.0f || dot(dg.Ns,Vector3f(ls.wi)) <= 0.0f) continue; 
        if (ls.L == Color(zero) || ls.wi.pdf == 0.0f) continue;

        /*! Evaluate BRDF */
        Color brdf = brdfs.eval(wo, dg, ls.wi, directLightingBRDFTypes);
        if (brdf == Color(zero)) continue;

        /*! Test for shadows. */
        Ray shadowRay(dg.P, ls.wi, dg.error*epsilon, ls.tMax-dg.error*epsilon, lightPath.lastRay.time,dg.shadowMask);
        rtcOccluded(scene->scene,(RTCRay&)shadowRay);
        state.numRays++;
        if (shadowRay) continue;

        /*! Evaluate BRDF. */
        L += ls.L * brdf * rcp(ls.wi.pdf);
      }
    }
    
    return L;
  }
Exemple #23
0
// SamplerIntegrator Method Definitions
void SamplerIntegrator::Render(const Scene &scene) {
    ProfilePhase p(Prof::IntegratorRender);
    Preprocess(scene, *sampler);
    // Render image tiles in parallel

    // Compute number of tiles, _nTiles_, to use for parallel rendering
    Bounds2i sampleBounds = camera->film->GetSampleBounds();
    Vector2i sampleExtent = sampleBounds.Diagonal();
    const int tileSize = 16;
    Point2i nTiles((sampleExtent.x + tileSize - 1) / tileSize,
                   (sampleExtent.y + tileSize - 1) / tileSize);
    ProgressReporter reporter(nTiles.x * nTiles.y, "Rendering");
    {
        StatTimer timer(&renderingTime);
        ParallelFor2D([&](Point2i tile) {
            // Render section of image corresponding to _tile_

            // Allocate _MemoryArena_ for tile
            MemoryArena arena;

            // Get sampler instance for tile
            int seed = tile.y * nTiles.x + tile.x;
            std::unique_ptr<Sampler> tileSampler = sampler->Clone(seed);

            // Compute sample bounds for tile
            int x0 = sampleBounds.pMin.x + tile.x * tileSize;
            int x1 = std::min(x0 + tileSize, sampleBounds.pMax.x);
            int y0 = sampleBounds.pMin.y + tile.y * tileSize;
            int y1 = std::min(y0 + tileSize, sampleBounds.pMax.y);
            Bounds2i tileBounds(Point2i(x0, y0), Point2i(x1, y1));

            // Get _FilmTile_ for tile
            std::unique_ptr<FilmTile> filmTile =
                camera->film->GetFilmTile(tileBounds);

            // Loop over pixels in tile to render them
            for (Point2i pixel : tileBounds) {
                {
                    ProfilePhase pp(Prof::StartPixel);
                    tileSampler->StartPixel(pixel);
                }
                do {
                    // Initialize _CameraSample_ for current sample
                    CameraSample cameraSample =
                        tileSampler->GetCameraSample(pixel);

                    // Generate camera ray for current sample
                    RayDifferential ray;
                    Float rayWeight =
                        camera->GenerateRayDifferential(cameraSample, &ray);
                    ray.ScaleDifferentials(
                        1 / std::sqrt((Float)tileSampler->samplesPerPixel));
                    ++nCameraRays;

                    // Evaluate radiance along camera ray
                    Spectrum L(0.f);
                    if (rayWeight > 0) L = Li(ray, scene, *tileSampler, arena);

                    // Issue warning if unexpected radiance value returned
                    if (L.HasNaNs()) {
                        Error(
                            "Not-a-number radiance value returned "
                            "for image sample.  Setting to black.");
                        L = Spectrum(0.f);
                    } else if (L.y() < -1e-5) {
                        Error(
                            "Negative luminance value, %f, returned "
                            "for image sample.  Setting to black.",
                            L.y());
                        L = Spectrum(0.f);
                    } else if (std::isinf(L.y())) {
                        Error(
                            "Infinite luminance value returned "
                            "for image sample.  Setting to black.");
                        L = Spectrum(0.f);
                    }

                    // Add camera ray's contribution to image
                    filmTile->AddSample(cameraSample.pFilm, L, rayWeight);

                    // Free _MemoryArena_ memory from computing image sample
                    // value
                    arena.Reset();
                } while (tileSampler->StartNextSample());
            }

            // Merge image tile into _Film_
            camera->film->MergeFilmTile(std::move(filmTile));
            reporter.Update();
        }, nTiles);
        reporter.Done();
    }

    // Save final image after rendering
    camera->film->WriteImage();
}
Exemple #24
0
	void RayTracer::Trace(const Scene *scene, const Ray& ray, const CameraSample& samples, RNG& rng, Color *color)
	{
		rng_ = &rng;
		*color = Li(scene, ray, maxdepth_, samples);
	}
Exemple #25
0
    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)) {
            return Color3f(0.0f);
        }

        Color3f tp(1.0f, 1.0f, 1.0f);
        Color3f L(0.0f, 0.0f, 0.0f);
        Ray3f pathRay(ray.o, ray.d);
        while(true) {

            //get the radiance of hitten object

            if (its.mesh->isEmitter() ) {
                const Emitter* areaLightEM = its.mesh->getEmitter();
                const areaLight* aEM = static_cast<const areaLight *> (areaLightEM);
                L += tp * aEM->sampleL(-pathRay.d, its.shFrame.n, its);
            }

            //get the asigned BSDF
            const BSDF* curBSDF = its.mesh->getBSDF();

            //transform to the local frame
            BSDFQueryRecord query = BSDFQueryRecord(its.toLocal(-pathRay.d), Vector3f(0.0f), EMeasure::ESolidAngle);

            //Normal3f n = its.shFrame.n;



            if(curBSDF->isDiffuse()) {
                std::vector<uint32_t> results;
                m_photonMap->search(its.p, m_photonRadius, results);
                Color3f Li(0.0f, 0.0f, 0.0f);
                int k = results.size();
                //cout << k << endl;

                if(k > 0) {

                    //cout << results.size() << " Photons found!" << endl;
                    //get the power from all photons
                    //for (uint32_t i : results)
                    //const Photon &photonk = (*m_photonMap)[k-1];
                    Color3f Lindir(0.0f, 0.0f, 0.0f);
                    for (int i = 0; i < k; ++i)
                    {
                        const Photon &photon = (*m_photonMap)[results[i]];
                        Vector3f wi = its.toLocal(photon.getDirection());
                        Vector3f wo = its.toLocal(its.shFrame.n);
                        BSDFQueryRecord dummy = BSDFQueryRecord(wi, wo, EMeasure::ESolidAngle);
                        Color3f f = curBSDF->eval(dummy);


                        Lindir += (tp * f) * photon.getPower() / (M_PI * m_photonRadius * m_photonRadius);


                    }

                    Li += Lindir;

                    //cout << "Li = " <<  Li.toString() << endl;
                    if(Li.maxCoeff() > 0.0f)
                        L +=  Li  / m_shootedRays;

                }
                break;
            }

            //sample the BRDF
            Color3f fi =  curBSDF->sample(query, sampler->next2D());
            //check for black brdf
            if(fi.maxCoeff() > 0.0f) {
                tp *= fi;
            } else {
                //stop
                // hit a black brdf
                break;
            }
            Vector3f wo = its.toWorld(query.wo);
            pathRay = Ray3f(its.p, wo);

            //ray escapes the scene
            if (!scene->rayIntersect(pathRay, its)) break;


            //stop critirium russian roulette
            float maxCoeff = tp.maxCoeff();
            float q = std::min(0.99f, maxCoeff);
            if(q < sampler->next1D()) break;
            tp /= q;
        }
        return L;
    }
Exemple #26
0
void Cube::DoMethod(CubeRotateMethod method)
{
    switch (method)
    {
    case ROTATE_NONE:
    case ROTATE_NONEi:
        break;
    case ROTATE_FRONT:
        F();
        break;
    case ROTATE_BACK:
        B();
        break;
    case ROTATE_LEFT:
        L();
        break;
    case ROTATE_RIGHT:
        R();
        break;
    case ROTATE_UP:
        U();
        break;
    case ROTATE_DOWN:
        D();
        break;
    case ROTATE_FRONTi:
        Fi();
        break;
    case ROTATE_BACKi:
        Bi();
        break;
    case ROTATE_LEFTi:
        Li();
        break;
    case ROTATE_RIGHTi:
        Ri();
        break;
    case ROTATE_UPi:
        Ui();
        break;
    case ROTATE_DOWNi:
        Di();
        break;
    case ROTATE_WHOLEX:
        RotateUp();
        break;
    case ROTATE_WHOLEY:
        RotateLeft();
        break;
    case ROTATE_WHOLEZ:
        RotateClockwise();
        break;
    case ROTATE_WHOLEXi:
        RotateDown();
        break;
    case ROTATE_WHOLEYi:
        RotateRight();
        break;
    case ROTATE_WHOLEZi:
        RotateCounterClockwise();
        break;
    default:
        break;
    }
}
Exemple #27
0
INT16 CGmm_PrecalcD(CGmm* _this, BOOL bCleanup)
#endif
{
  INT32      i       = 0;                                                        /* Triangular inv. cov. matrix cntr. */
  INT32      c       = 0;                                                        /* Index of inv. covariance matrix   */
  INT32      k       = 0;                                                        /* Gaussian loop counter             */
  INT32      n       = 0;                                                        /* Dimension loop counter            */
  INT32      m       = 0;                                                        /* Dimension loop counter            */
  INT32      K       = 0;                                                        /* Number of single Gaussians        */
  INT32      N       = 0;                                                        /* Feature space dimensionality      */
  GMM_FTYPE nDelta1 = 0.;                                                       /* Class indep. term of delta const. */
#ifdef __TMS
  GMM_FTYPE *mean = (GMM_FTYPE*)CData_XAddr(AS(CData,_this->m_idMean),0,0);
#endif


  /* Clean up precalculated data */                                             /* --------------------------------- */
  dlp_free(_this->m_lpAlpha);                                                   /* Clear alpha vector                */
  dlp_free(_this->m_lpBeta );                                                   /* Clear beta vectors                */
  dlp_free(_this->m_lpGamma);                                                   /* Clear gamma vector                */
  dlp_free(_this->m_lpDelta);                                                   /* Clear delta vector                */
  dlp_free(_this->m_lpI    );                                                   /* Clear inv. cov. pointer array     */
  dlp_free(_this->m_lpV    );                                                   /* Clear inverse variance array      */
  if(_this->m_idSse2Icov){
    CData *idSse2Icov=AS(CData,_this->m_idSse2Icov);
    IDESTROY(idSse2Icov);                                                     /* Destroy inv.covs. for SSE2 opt.   */
    _this->m_idSse2Icov=NULL;
  }
  dlp_free(_this->m_lpSse2Buf);                                                 /* Clear aux. buffer for SSE2 opt.   */
  dlp_free(_this->m_lpLdlL);                                                    /* Clear L-matrix buffer for LDL     */
  dlp_free(_this->m_lpLdlD);                                                    /* Clear D-vector buffer for LDL     */
  _this->m_nN = 0;                                                              /* Clear feature space dimensionality*/
  _this->m_nK = 0;                                                              /* Clear number of single Gaussians  */
  if (bCleanup) return O_K;                                                     /* When cleaning up that's it        */

  /* Initialize */                                                              /* --------------------------------- */
  K       = CGmm_GetNGauss(_this);                                              /* Get nuumber of single Gaussians   */
  N       = CGmm_GetDim(_this);                                                 /* Get feature space dimensionality  */
  nDelta1 = -N/2*log(2*F_PI);                                                   /* Compute part of delta term        */

  /* Basic validation */                                                        /* --------------------------------- */
  IF_NOK(CGmm_CheckMean(_this)) DLPTHROW(GMM_NOTSETUP);                         /* Check mean vectors                */
  IF_NOK(CGmm_CheckIvar(_this)) DLPTHROW(GMM_NOTSETUP);                         /* Check inverse variance vectors    */
  IF_NOK(CGmm_CheckCdet(_this)) DLPTHROW(GMM_NOTSETUP);                         /* Check (co-)variance determinants  */

  /* Basic dimensions */                                                        /* --------------------------------- */
  _this->m_nN = N;                                                              /* Feature space dimensionality      */
  _this->m_nK = K;                                                              /* Number of single Gaussians        */

  /* Create inverse covariance matrix map */                                    /* --------------------------------- */
  if (_this->m_idIcov)                                                          /* If using covariances              */
  {                                                                             /* >>                                */
    IF_NOK(CGmm_CheckIcov(_this)) DLPTHROW(GMM_NOTSETUP);                       /*   Inverse covariance data corrupt */
    _this->m_lpI = dlp_calloc(K,sizeof(GMM_FTYPE*));                            /*   Allocate map                    */
    if (!_this->m_lpI) DLPTHROW(ERR_NOMEM);                                     /*   Out of memory                   */
    for (k=0; k<K; k++)                                                         /*   Loop over Gaussians             */
    {                                                                           /*   >>                              */
      c=_this->m_idCmap ? (INT32)CData_Dfetch(AS(CData,_this->m_idCmap),k,0) : k;/*     Cov. mat. idx. for Gaussian k */
      I[k] = (GMM_FTYPE*)CData_XAddr(AS(CData,_this->m_idIcov),c,0);            /*     Store ptr. to inv. cov. matrix*/
    }                                                                           /*   <<                              */
  }                                                                             /* <<                                */

  /* Create inverse variance vector map */                                      /* --------------------------------- */
  IF_NOK(CGmm_CheckIvar(_this)) DLPTHROW(GMM_NOTSETUP);                         /*   Inverse covariance data corrupt */
  _this->m_lpV = dlp_calloc(K,sizeof(GMM_FTYPE*));                              /*   Allocate map                    */
  if (!_this->m_lpV) DLPTHROW(ERR_NOMEM);                                       /*   Out of memory                   */
  for (k=0; k<K; k++)                                                           /*   Loop over Gaussians             */
    V[k] = (GMM_FTYPE*)CData_XAddr(AS(CData,_this->m_idIvar),k,0);              /*     Store ptr. to inv. cov. matrix*/

  /* LDL-factorization */                                                       /* --------------------------------- */
  if(_this->m_nLDL)                                                             /* LDL factorization used            */
  {                                                                             /* >>                                */
    /* TODO: GMM_TYPE is float => dlm_factldl in float */                       /*   ------------------------------- */
    _this->m_lpLdlL = dlp_malloc(K*N*(N-1)/2*sizeof(GMM_FTYPE));                /*   Alloc L matrix                  */
    _this->m_lpLdlD = dlp_malloc(K*N*sizeof(GMM_FTYPE));                        /*   Alloc D vector                  */
    if (!_this->m_lpLdlL || !_this->m_lpLdlD) DLPTHROW(ERR_NOMEM);              /*   Out of memory                   */
    {
    FLOAT64 *lpAux1 = (FLOAT64 *)dlp_malloc(N*N*sizeof(FLOAT64));                  /*   Alloc auxilary matrix #1        */
    FLOAT64 *lpAux2 = (FLOAT64 *)dlp_malloc(N*N*sizeof(FLOAT64));                  /*   Alloc auxilary matrix #2        */
    if (!lpAux1 || !lpAux2) DLPTHROW(ERR_NOMEM);                                /*   Out of memory                   */
    for(k=0;k<K;k++)                                                            /*   Loop over all Gaussians         */
    {                                                                           /*   >>                              */
      for(n=0;n<N;n++)                                                          /*     Loop over Gaussian dimension  */
      {                                                                         /*     >>                            */
        lpAux1[n*N+n] = V[k][n];                                                /*       Copy inverse variance values*/
        for(m=0;m<n;m++) lpAux1[n*N+m] = lpAux1[m*N+n] =                        /*       Copy inverse covariance val.*/
          I?I[k][m*N-2*m-m*(m-1)/2+n-1]:0.;                                     /*       |                           */
      }                                                                         /*     <<                            */
      dlm_factldl(lpAux1,lpAux2,N);                                             /*     Factorize matrix              */
      for(n=0;n<N;n++)                                                          /*     Loop over Gaussian dimension  */
      {                                                                         /*     >>                            */
        for(m=n+1;m<N;m++) Li(N,k,n,m) = lpAux1[n*N+m];                         /*       Store L matrix values       */
        D(N,k,n) = lpAux2[n*N+n];                                               /*       Store D vector values       */
      }                                                                         /*     <<                            */
      if(_this->m_nLdlCoef>=0 && _this->m_nLdlCoef<N*(N-1)/2)
      {
        FLOAT64 nMinAbs;
        memcpy(lpAux1,&L(N,k,0),N*(N-1)/2);
#if GMM_FTYPE_CODE == T_FLOAT
        qsort(lpAux1,N*(N-1)/2,sizeof(FLOAT64),cf_absfloat_down);
#else
        qsort(lpAux1,N*(N-1)/2,sizeof(FLOAT64),cf_absdouble_down);
#endif
        nMinAbs=fabs(lpAux1[_this->m_nLdlCoef]);
        for(n=0;n<N*(N-1)/2;n++) if(fabs(L(N,k,n))<=nMinAbs) L(N,k,n)=0.;
      }
    }                                                                           /*   <<                              */
    dlp_free(lpAux1);                                                           /*   Free auxilary matrix #1         */
    dlp_free(lpAux2);                                                           /*   Free auxilary matrix #2         */
    }
  }                                                                             /* <<                                */

  /* Precalculate alpha and beta vectors */                                     /* --------------------------------- */
  if(!_this->m_nLDL)                                                            /* No LDL factorization used         */
  {                                                                             /* >>                                */
    _this->m_lpAlpha = dlp_calloc(K,sizeof(GMM_FTYPE));                         /*   Allocate buffer                 */
    _this->m_lpBeta  = dlp_calloc(K*N,sizeof(GMM_FTYPE));                       /*   Allocate buffer                 */
    if (!_this->m_lpAlpha || !_this->m_lpBeta) DLPTHROW(ERR_NOMEM);             /*   Out of memory                   */
    for (k=0; k<K; k++)                                                         /*   Loop over Gaussians             */
      for (n=0; n<N; n++)                                                       /*     Loop over dimensions          */
        for (m=0; m<N; m++)                                                     /*       Loop over dimensions        */
          if (m==n)                                                             /*         Main diagonal (variances)?*/
          {                                                                     /*         >>                        */
            alpha[k]     += V[k][n]*mu(k,m)*mu(k,n);                            /*           Sum up alpha val. (n==m)*/
            beta [k*N+n] += V[k][n]*mu(k,m);                                    /*           Sum up beta value (n==m)*/
          }                                                                     /*         <<                        */
          else if (_this->m_lpI)                                                /*         Otherwise cov.(if present)*/
          {                                                                     /*         >>                        */
            if (m>n) i = n*N - 2*n - n*(n-1)/2 + m - 1;                         /*           Calc index if I[n,m] in */
            else     i = m*N - 2*m - m*(m-1)/2 + n - 1;                         /*           | triangular icov. mat. */
            alpha[k]     += I[k][i]*mu(k,m)*mu(k,n);                            /*           Sum up alpha val. (n!=m)*/
            beta [k*N+n] += I[k][i]*mu(k,m);                                    /*           Sum up beta value (n!=m)*/
          }                                                                     /*         <<                        */
  }                                                                             /* <<                                */
  else                                                                          /* LDL factorization used            */
  {                                                                             /* >>                                */
    _this->m_lpAlpha = NULL;                                                    /*   No alpha needed here            */
    _this->m_lpBeta  = dlp_calloc(K*N,sizeof(GMM_FTYPE));                       /*   Allocate buffer                 */
    if (!_this->m_lpBeta) DLPTHROW(ERR_NOMEM);                                  /*   Out of memory                   */
    for(k=0;k<K;k++) for(n=0;n<N;n++)                                           /*   Loop over Gaussians & dimensions*/
    {                                                                           /*   >>                              */
      beta[k*N+n] = mu(k,n);                                                    /*     Init beta with mean value     */
      for(m=n+1;m<N;m++) beta[k*N+n] += mu(k,m)*Li(N,k,n,m);                    /*     Calculate beta from L*mu      */
    }                                                                           /*   <<                              */
  }                                                                             /* <<                                */

  /* Allocate gamma vector */                                                   /* --------------------------------- */
  /* NOTE: If this fails there will just be no lazy computation -> no big deal*//*                                   */
  if (_this->m_idCmap && _this->m_idIcov && _this->m_lpI)                       /* Wanna do lazy computation?        */
    if (CData_GetDescr(AS(CData,_this->m_idIvar),0)==0.)                        /*   Only if variances are tied too  */
      _this->m_lpGamma = dlp_calloc(K,sizeof(GMM_FTYPE));                       /*     Allocate buffer               */

  /* Precalculate delta vector */                                               /* --------------------------------- */
  _this->m_lpDelta = dlp_calloc(K,sizeof(GMM_FTYPE));                           /* Allocate buffer                   */
  if (!_this->m_lpDelta) DLPTHROW(ERR_NOMEM);                                   /* Out of memory                     */
  for (k=0; k<K; k++)                                                           /* Loop over Gaussians               */
    delta[k] = nDelta1-(GMM_FTYPE)(0.5*log(                                     /*   Calculate delta[k]              */
      CData_Dfetch(AS(CData,_this->m_idCdet),k,0)));                            /*   |                               */

  /* SSE2 precalculated objects */                                              /* --------------------------------- */
#ifdef GMM_SSE2                                                                 /* Use SSE2?                         */
  IFIELD_RESET(CData,"sse2_icov");                                              /* Create/reset SSE2 inv.cov. matrs. */
  CGmm_Extract(_this,NULL,_this->m_idSse2Icov);                                 /* ... and go get 'em                */
  _this->m_lpSse2Buf = dlp_calloc(2*N,sizeof(GMM_FTYPE));                       /* Allocate auxilary buffer          */
  if (!_this->m_lpSse2Buf) DLPTHROW(ERR_NOMEM);                                 /* Out of memory                     */
#endif                                                                          /* #ifdef GMM_SSE2                   */

  /* Final checkup */                                                           /* --------------------------------- */
#ifndef __NOXALLOC
  IF_NOK(CGmm_CheckPrecalc(_this)) DLPTHROW(GMM_NOTSETUP);                      /* Check precalculated data          */
#endif
  return O_K;                                                                   /* That's it folks ...               */

DLPCATCH(GMM_NOTSETUP)                                                          /* On NOT_EXEC exception             */
DLPCATCH(ERR_NOMEM)                                                             /* On ERR_NOMEM exception            */
#if GMM_FTYPE_CODE == T_FLOAT
  CGmm_PrecalcF(_this,TRUE);                                                    /* - Free memory of precalc'd. data  */
#else
  CGmm_PrecalcD(_this,TRUE);                                                    /* - Free memory of precalc'd. data  */
#endif
  return NOT_EXEC;                                                              /* - Indicate failure                */
}
 Col3f PathTraceIntegrator::Li(const Ray& ray, const Ref<BackendScene>& scene, Sampler* sampler, size_t& numRays) {
   return Li(LightPath(ray),scene,sampler,numRays);
 }
void SampleIntegrator::renderBlock(const Scene *scene,
	const Camera *camera, Sampler *sampler, ImageBlock *block, 
	const bool &stop, const std::vector<Point2i> *points) const {
	Point2 sample, lensSample;
	RayDifferential eyeRay;
	Float timeSample = 0;
	Spectrum spec;


	block->clear();
	RadianceQueryRecord rRec(scene, sampler);
	bool needsLensSample = camera->needsLensSample();
	bool needsTimeSample = camera->needsTimeSample();
	const TabulatedFilter *filter = camera->getFilm()->getTabulatedFilter();
	Float scaleFactor = 1.0f/std::sqrt((Float) sampler->getSampleCount());

	if (points) {
		/* Use a prescribed traversal order (e.g. using a space-filling curve) */
		if (!block->collectStatistics()) {
			for (size_t i=0; i<points->size(); ++i) {
				Point2i offset = (*points)[i] + Vector2i(block->getOffset());
				if (stop) 
					break;
				sampler->generate();
				for (size_t j = 0; j<sampler->getSampleCount(); j++) {
					rRec.newQuery(RadianceQueryRecord::ECameraRay, camera->getMedium());
					if (needsLensSample)
						lensSample = rRec.nextSample2D();
					if (needsTimeSample)
						timeSample = rRec.nextSample1D();
					sample = rRec.nextSample2D();
					sample.x += offset.x; sample.y += offset.y;
					camera->generateRayDifferential(sample, 
						lensSample, timeSample, eyeRay);
					eyeRay.scaleDifferential(scaleFactor);
					spec = Li(eyeRay, rRec);
					block->putSample(sample, spec, rRec.alpha, filter);
					sampler->advance();
				}
			}
		} else {
			Spectrum mean, meanSqr;
			for (size_t i=0; i<points->size(); ++i) {
				Point2i offset = (*points)[i] + Vector2i(block->getOffset());
				if (stop) 
					break;
				sampler->generate();
				mean = meanSqr = Spectrum(0.0f);
				for (size_t j = 0; j<sampler->getSampleCount(); j++) {
					rRec.newQuery(RadianceQueryRecord::ECameraRay, camera->getMedium());
					if (needsLensSample)
						lensSample = rRec.nextSample2D();
					if (needsTimeSample)
						timeSample = rRec.nextSample1D();
					sample = rRec.nextSample2D();
					sample.x += offset.x; sample.y += offset.y;
					camera->generateRayDifferential(sample, 
						lensSample, timeSample, eyeRay);
					eyeRay.scaleDifferential(scaleFactor);
					spec = Li(eyeRay, rRec);

					/* Numerically robust online variance estimation using an
						algorithm proposed by Donald Knuth (TAOCP vol.2, 3rd ed., p.232) */
					const Spectrum delta = spec - mean;
					mean += delta / ((Float) j+1);
					meanSqr += delta * (spec - mean);
					block->putSample(sample, spec, rRec.alpha, filter);
					block->setVariance(offset.x, offset.y,
						meanSqr / (Float) j, (int) j+1);
					sampler->advance();
				}
			}
		}
	} else {
		/* Simple scanline traversal order */
		const int
			sx = block->getOffset().x,
			sy = block->getOffset().y,
			ex = sx + block->getSize().x,
			ey = sy + block->getSize().y;
		if (!block->collectStatistics()) {
			for (int y = sy; y < ey; y++) {
				for (int x = sx; x < ex; x++) {
					if (stop) 
						break;
					sampler->generate();
					for (size_t j = 0; j<sampler->getSampleCount(); j++) {
						rRec.newQuery(RadianceQueryRecord::ECameraRay, camera->getMedium());
						if (needsLensSample)
							lensSample = rRec.nextSample2D();
						if (needsTimeSample)
							timeSample = rRec.nextSample1D();
						sample = rRec.nextSample2D();
						sample.x += x; sample.y += y;
						camera->generateRayDifferential(sample, 
							lensSample, timeSample, eyeRay);
						eyeRay.scaleDifferential(scaleFactor);
						spec = Li(eyeRay, rRec);
						block->putSample(sample, spec, rRec.alpha, filter);
						sampler->advance();
					}
				}
			}
		} else {
			Spectrum mean, meanSqr;
			for (int y = sy; y < ey; y++) {
				for (int x = sx; x < ex; x++) {
					if (stop) 
						break;
					sampler->generate();
					mean = meanSqr = Spectrum(0.0f);
					for (size_t j = 0; j<sampler->getSampleCount(); j++) {
						rRec.newQuery(RadianceQueryRecord::ECameraRay, camera->getMedium());
						if (needsLensSample)
							lensSample = rRec.nextSample2D();
						if (needsTimeSample)
							timeSample = rRec.nextSample1D();
						sample = rRec.nextSample2D();
						sample.x += x; sample.y += y;
						camera->generateRayDifferential(sample, 
							lensSample, timeSample, eyeRay);
						eyeRay.scaleDifferential(scaleFactor);
						spec = Li(eyeRay, rRec);

						/* Numerically robust online variance estimation using an
						   algorithm proposed by Donald Knuth (TAOCP vol.2, 3rd ed., p.232) */
						const Spectrum delta = spec - mean;
						mean += delta / ((Float) j+1);
						meanSqr += delta * (spec - mean);
						block->putSample(sample, spec, rRec.alpha, filter);
						block->setVariance(x, y, meanSqr / (Float) j, (int) j+1);
						sampler->advance();
					}
				}
			}
		}
	}
}
	Spectrum Li(const RayDifferential &r, RadianceQueryRecord &rRec) const {
		/* Some aliases and local variables */
		const Scene *scene = rRec.scene;
		Intersection &its = rRec.its;
		MediumSamplingRecord mRec;
		RayDifferential ray(r);
		Spectrum Li(0.0f);
		bool nullChain = true, scattered = false;
		Float eta = 1.0f;

		/* Perform the first ray intersection (or ignore if the
		   intersection has already been provided). */
		rRec.rayIntersect(ray);
		Spectrum throughput(1.0f);

		if (m_maxDepth == 1)
			rRec.type &= RadianceQueryRecord::EEmittedRadiance;

		/**
		 * Note: the logic regarding maximum path depth may appear a bit
		 * strange. This is necessary to get this integrator's output to
		 * exactly match the output of other integrators under all settings
		 * of this parameter.
		 */
		while (rRec.depth <= m_maxDepth || m_maxDepth < 0) {
			/* ==================================================================== */
			/*                 Radiative Transfer Equation sampling                 */
			/* ==================================================================== */
			if (rRec.medium && rRec.medium->sampleDistance(Ray(ray, 0, its.t), mRec, rRec.sampler)) {
				/* Sample the integral
				   \int_x^y tau(x, x') [ \sigma_s \int_{S^2} \rho(\omega,\omega') L(x,\omega') d\omega' ] dx'
				*/
				const PhaseFunction *phase = rRec.medium->getPhaseFunction();

				throughput *= mRec.sigmaS * mRec.transmittance / mRec.pdfSuccess;

				/* ==================================================================== */
				/*                     Direct illumination sampling                     */
				/* ==================================================================== */

				/* Estimate the single scattering component if this is requested */
				if (rRec.type & RadianceQueryRecord::EDirectMediumRadiance) {
					DirectSamplingRecord dRec(mRec.p, mRec.time);
					int maxInteractions = m_maxDepth - rRec.depth - 1;

					Spectrum value = scene->sampleAttenuatedEmitterDirect(
							dRec, rRec.medium, maxInteractions,
							rRec.nextSample2D(), rRec.sampler);

					if (!value.isZero())
						Li += throughput * value * phase->eval(
								PhaseFunctionSamplingRecord(mRec, -ray.d, dRec.d));
				}

				/* Stop if multiple scattering was not requested, or if the path gets too long */
				if ((rRec.depth + 1 >= m_maxDepth && m_maxDepth > 0) ||
					!(rRec.type & RadianceQueryRecord::EIndirectMediumRadiance))
					break;

				/* ==================================================================== */
				/*             Phase function sampling / Multiple scattering            */
				/* ==================================================================== */

				PhaseFunctionSamplingRecord pRec(mRec, -ray.d);
				Float phaseVal = phase->sample(pRec, rRec.sampler);
				if (phaseVal == 0)
					break;
				throughput *= phaseVal;

				/* Trace a ray in this direction */
				ray = Ray(mRec.p, pRec.wo, ray.time);
				ray.mint = 0;
				scene->rayIntersect(ray, its);
				nullChain = false;
				scattered = true;
			} else {
				/* Sample
					tau(x, y) * (Surface integral). This happens with probability mRec.pdfFailure
					Account for this and multiply by the proper per-color-channel transmittance.
				*/

				if (rRec.medium)
					throughput *= mRec.transmittance / mRec.pdfFailure;

				if (!its.isValid()) {
					/* If no intersection could be found, possibly return
					   attenuated radiance from a background luminaire */
					if ((rRec.type & RadianceQueryRecord::EEmittedRadiance)
						&& (!m_hideEmitters || scattered)) {
						Spectrum value = throughput * scene->evalEnvironment(ray);
						if (rRec.medium)
							value *= rRec.medium->evalTransmittance(ray);
						Li += value;
					}
					break;
				}

				/* Possibly include emitted radiance if requested */
				if (its.isEmitter() && (rRec.type & RadianceQueryRecord::EEmittedRadiance)
					&& (!m_hideEmitters || scattered))
					Li += throughput * its.Le(-ray.d);

				/* Include radiance from a subsurface integrator if requested */
				if (its.hasSubsurface() && (rRec.type & RadianceQueryRecord::ESubsurfaceRadiance))
					Li += throughput * its.LoSub(scene, rRec.sampler, -ray.d, rRec.depth);

				/* Prevent light leaks due to the use of shading normals */
				Float wiDotGeoN = -dot(its.geoFrame.n, ray.d),
					  wiDotShN  = Frame::cosTheta(its.wi);
				if (m_strictNormals && wiDotGeoN * wiDotShN < 0)
					break;

				/* ==================================================================== */
				/*                     Direct illumination sampling                     */
				/* ==================================================================== */

				const BSDF *bsdf = its.getBSDF(ray);

				/* Estimate the direct illumination if this is requested */
				if (rRec.type & RadianceQueryRecord::EDirectSurfaceRadiance &&
						(bsdf->getType() & BSDF::ESmooth)) {
					DirectSamplingRecord dRec(its);
					int maxInteractions = m_maxDepth - rRec.depth - 1;

					Spectrum value = scene->sampleAttenuatedEmitterDirect(
							dRec, its, rRec.medium, maxInteractions,
							rRec.nextSample2D(), rRec.sampler);

					if (!value.isZero()) {
						/* Allocate a record for querying the BSDF */
						BSDFSamplingRecord bRec(its, its.toLocal(dRec.d));
						bRec.sampler = rRec.sampler;

						Float woDotGeoN = dot(its.geoFrame.n, dRec.d);
						/* Prevent light leaks due to the use of shading normals */
						if (!m_strictNormals ||
							woDotGeoN * Frame::cosTheta(bRec.wo) > 0)
							Li += throughput * value * bsdf->eval(bRec);
					}
				}

				/* ==================================================================== */
				/*                   BSDF sampling / Multiple scattering                */
				/* ==================================================================== */

				/* Sample BSDF * cos(theta) */
				BSDFSamplingRecord bRec(its, rRec.sampler, ERadiance);
				Spectrum bsdfVal = bsdf->sample(bRec, rRec.nextSample2D());
				if (bsdfVal.isZero())
					break;

				/* Recursively gather indirect illumination? */
				int recursiveType = 0;
				if ((rRec.depth + 1 < m_maxDepth || m_maxDepth < 0) &&
					(rRec.type & RadianceQueryRecord::EIndirectSurfaceRadiance))
					recursiveType |= RadianceQueryRecord::ERadianceNoEmission;

				/* Recursively gather direct illumination? This is a bit more
				   complicated by the fact that this integrator can create connection
				   through index-matched medium transitions (ENull scattering events) */
				if ((rRec.depth < m_maxDepth || m_maxDepth < 0) &&
					(rRec.type & RadianceQueryRecord::EDirectSurfaceRadiance) &&
					(bRec.sampledType & BSDF::EDelta) &&
					(!(bRec.sampledType & BSDF::ENull) || nullChain)) {
					recursiveType |= RadianceQueryRecord::EEmittedRadiance;
					nullChain = true;
				} else {
					nullChain &= bRec.sampledType == BSDF::ENull;
				}

				/* Potentially stop the recursion if there is nothing more to do */
				if (recursiveType == 0)
					break;
				rRec.type = recursiveType;

				/* Prevent light leaks due to the use of shading normals */
				const Vector wo = its.toWorld(bRec.wo);
				Float woDotGeoN = dot(its.geoFrame.n, wo);
				if (woDotGeoN * Frame::cosTheta(bRec.wo) <= 0 && m_strictNormals)
					break;

				/* Keep track of the throughput, medium, and relative
				   refractive index along the path */
				throughput *= bsdfVal;
				eta *= bRec.eta;
				if (its.isMediumTransition())
					rRec.medium = its.getTargetMedium(wo);

				/* In the next iteration, trace a ray in this direction */
				ray = Ray(its.p, wo, ray.time);
				scene->rayIntersect(ray, its);
				scattered |= bRec.sampledType != BSDF::ENull;
			}

			if (rRec.depth++ >= m_rrDepth) {
				/* Russian roulette: try to keep path weights equal to one,
				   while accounting for the solid angle compression at refractive
				   index boundaries. Stop with at least some probability to avoid
				   getting stuck (e.g. due to total internal reflection) */

				Float q = std::min(throughput.max() * eta * eta, (Float) 0.95f);
				if (rRec.nextSample1D() >= q)
					break;
				throughput /= q;
			}
		}
		avgPathLength.incrementBase();
		avgPathLength += rRec.depth;
		return Li;
	}