Example #1
0
float ComputeHeuristic(float fpdf, float gpdf)
{
#if 0
    return BalanceHeuristic(fpdf, gpdf);
#else
    return PowerHeuristic(fpdf, gpdf);
#endif
}
Example #2
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;

    }
// with direct illumination
// this one actually does not do the right things on DI with MIS
// left only for reference
Spectrum PathTracer::IntegrationWithDI (
	const Scene * thisScene,
	const Ray & ray,
	size_t currentDepth
) const
{
	// Russian Roulette
	// probility to stop this path
	double rr = 0.01;
	double randnum = getUniformRandomNumber( 0.0, 1.0 );
	if ( randnum < rr && currentDepth > 5 )
		return Spectrum();

	if ( currentDepth == maxDepth )
		return Spectrum();

	Intersection intersectionInfo;

	// check intersection between ray and scene
	if ( !thisScene->IntersectionWithScene( ray, intersectionInfo ) )
		return Spectrum();

	// if there is an intersection
	Spectrum intensity;
	Spectrum lightSourceSamplingContribution;
	Spectrum brdfSamplingContribution;

	double brdf_pdf = 0;
	double light_pdf = 0;

	double brdf_weight = 0;
	double light_weight = 0;

	Objects * obj = intersectionInfo.object;

	if ( obj->emitter )
	{
		intensity += obj->emission;
	}


	BRDFModels * brdf = obj->brdf_model;


	// **************** evaluate direction illumination ******
	if ( !obj->emitter )
		EstimateDirectIllumination(
			thisScene,
			& intersectionInfo,
			ray,
			light_pdf,
			lightSourceSamplingContribution
		);

	// ******************** end of direct illumination **********************

	// BRDF sampling is evaluated twice????

	Vector geometryNormalDirection;

	geometryNormalDirection = intersectionInfo.normal;

	Vector sampledNextDirection( 0, 0, 0 );
	Attenuation attenuationFactor;

	attenuationFactor = brdf->SampleBRDF(
		ray.direction,
		sampledNextDirection,
		geometryNormalDirection,
		brdf_pdf
	);

	Ray newRay(
		intersectionInfo.intersectionPoint,
		sampledNextDirection
	);

	Spectrum Li =
		IntegrationWithDI(
			thisScene,
			newRay,
			currentDepth + 1
		);

	if ( !Li.isEmpty() )
	{
		attenuationFactor.Scaled_by_Spectrum_Value( obj->material_type->color );

		double cos_i = AbsDot( sampledNextDirection, geometryNormalDirection );

		brdfSamplingContribution += Attenuate_Light_Spectrum( attenuationFactor, Li ) * cos_i;
	}


	if ( light_pdf == 0 && brdf_pdf == 0 )
	{
		return intensity;
	}
	// MIS weight
	BalanceHeuristic( 1, light_pdf, 1, brdf_pdf, light_weight, brdf_weight );

	intensity += lightSourceSamplingContribution * light_weight;
	intensity += brdfSamplingContribution * brdf_weight;

	intensity = ( currentDepth > 5 ) ? ( intensity / ( 1 - rr ) ) : intensity;


	ASSERT_NAN( intensity );

	return intensity;
}