Exemplo n.º 1
0
// Integrator Utility Functions
Spectrum UniformSampleAllLights(const Scene *scene,
        const Renderer *renderer, MemoryArena &arena, const Point &p,
        const Normal &n, const Vector &wo, float rayEpsilon,
        float time, BSDF *bsdf, const Sample *sample, RNG &rng,
        const LightSampleOffsets *lightSampleOffsets,
        const BSDFSampleOffsets *bsdfSampleOffsets) {
    Spectrum L(0.);
    for (uint32_t i = 0; i < scene->lights.size(); ++i) {
        Light *light = scene->lights[i];
        int nSamples = lightSampleOffsets ?
                       lightSampleOffsets[i].nSamples : 1;
        // Estimate direct lighting from _light_ samples
        Spectrum Ld(0.);
        for (int j = 0; j < nSamples; ++j) {
            // Find light and BSDF sample values for direct lighting estimate
            LightSample lightSample;
            BSDFSample bsdfSample;
            if (lightSampleOffsets != NULL && bsdfSampleOffsets != NULL) {
                lightSample = LightSample(sample, lightSampleOffsets[i], j);
                bsdfSample = BSDFSample(sample, bsdfSampleOffsets[i], j);
            }
            else {
                lightSample = LightSample(rng);
                bsdfSample = BSDFSample(rng);
            }
            Ld += EstimateDirect(scene, renderer, arena, light, p, n, wo,
                rayEpsilon, time, bsdf, rng, lightSample, bsdfSample,
                BxDFType(BSDF_ALL & ~BSDF_SPECULAR));
        }
        L += Ld / nSamples;
    }
    return L;
}
Exemplo n.º 2
0
Spectrum UniformSampleOneLight(const Scene *scene,
        const Renderer *renderer, MemoryArena &arena, const Point &p,
        const Normal &n, const Vector &wo, float rayEpsilon, float time,
        BSDF *bsdf, const Sample *sample, RNG &rng, int lightNumOffset,
        const LightSampleOffsets *lightSampleOffset,
        const BSDFSampleOffsets *bsdfSampleOffset) {
    // Randomly choose a single light to sample, _light_
    int nLights = int(scene->lights.size());
    if (nLights == 0) return Spectrum(0.);
    int lightNum;
    if (lightNumOffset != -1)
        lightNum = Floor2Int(sample->oneD[lightNumOffset][0] * nLights);
    else
        lightNum = Floor2Int(rng.RandomFloat() * nLights);
    lightNum = min(lightNum, nLights-1);
    Light *light = scene->lights[lightNum];

    // Initialize light and bsdf samples for single light sample
    LightSample lightSample;
    BSDFSample bsdfSample;
    if (lightSampleOffset != NULL && bsdfSampleOffset != NULL) {
        lightSample = LightSample(sample, *lightSampleOffset, 0);
        bsdfSample = BSDFSample(sample, *bsdfSampleOffset, 0);
    }
    else {
        lightSample = LightSample(rng);
        bsdfSample = BSDFSample(rng);
    }
    return (float)nLights *
        EstimateDirect(scene, renderer, arena, light, p, n, wo,
                       rayEpsilon, time, bsdf, rng, lightSample,
                       bsdfSample, BxDFType(BSDF_ALL & ~BSDF_SPECULAR));
}
Exemplo n.º 3
0
// Preprocess
void InstantRadiosity::PreProcess()
{
	m_pVirtualLightSources = new list<VirtualLightSource>[m_nLightPathSet];

	for( int k = 0 ; k < m_nLightPathSet ; ++k )
	{
		for( int i = 0 ; i < m_nLightPaths ; ++i )
		{
			// pick a light first
			float light_pick_pdf;
			const Light* light = scene.SampleLight( sort_canonical() , &light_pick_pdf );

			// sample a ray from the light source
			float	light_emission_pdf = 0.0f;
			float	light_pdfa = 0.0f;
			Ray		ray;
			float   cosAtLight = 1.0f;
			Spectrum le = light->sample_l( LightSample(true) , ray , &light_emission_pdf , &light_pdfa , &cosAtLight );

			Spectrum throughput = le * cosAtLight / ( light_pick_pdf * light_emission_pdf );

			int current_depth = 0;
			Intersection intersect;
			while( true )
			{
				if (false == scene.GetIntersect(ray, &intersect))
					break;

				VirtualLightSource ls;
				ls.power = throughput;
				ls.intersect = intersect;
				ls.wi = -ray.m_Dir;
				ls.depth = ++current_depth;
				m_pVirtualLightSources[k].push_back( ls );

				float bsdf_pdf;
				Vector wo;
				Bsdf* bsdf = intersect.primitive->GetMaterial()->GetBsdf(&intersect);
				Spectrum bsdf_value = bsdf->sample_f(ls.wi, wo, BsdfSample(true), &bsdf_pdf, BXDF_ALL);

				if( bsdf_pdf == 0.0f )
					break;

				// apply russian roulette
				float continueProperbility = min( 1.0f , throughput.GetIntensity() );
				if( sort_canonical() > continueProperbility )
					break;
				throughput /= continueProperbility;

				// update throughput
				throughput *= bsdf_value * ( AbsDot(wo, intersect.normal) / bsdf_pdf );

				// update next ray
				ray = Ray(intersect.intersect, wo, 0, 0.001f);
			}
		}
	}
}
Exemplo n.º 4
0
// generate samples
void PathTracing::GenerateSample( const Sampler* sampler , PixelSample* samples , unsigned ps , const Scene& scene ) const
{
	Integrator::GenerateSample( sampler , samples , ps , scene );

	if( sampler->RoundSize( ps ) == ps )
	{
		float* data_1d = samples[0].data;
		float* data_2d = samples[0].data + ps;

		sampler->Generate1D( data_1d , ps );
		sampler->Generate2D( data_2d , ps );
		for( unsigned k = 0 ; k < ps ; ++k )
		{
			int two_k = 2*k;
			samples[k].bsdf_sample[0].t = data_1d[k];
			samples[k].bsdf_sample[0].u = data_2d[two_k];
			samples[k].bsdf_sample[0].v = data_2d[two_k+1];
		}

		sampler->Generate1D( data_1d , ps );
		sampler->Generate2D( data_2d , ps );
		for( unsigned k = 0 ; k < ps ; ++k )
		{
			int two_k = 2*k;
			samples[k].bsdf_sample[1].t = data_1d[k];
			samples[k].bsdf_sample[1].u = data_2d[two_k];
			samples[k].bsdf_sample[1].v = data_2d[two_k+1];
		}

		sampler->Generate1D( data_1d , ps );
		sampler->Generate2D( data_2d , ps );
		for( unsigned k = 0 ; k < ps ; ++k )
		{
			int two_k = 2*k;
			samples[k].light_sample[0].t = data_1d[k];
			samples[k].light_sample[0].u = data_2d[two_k];
			samples[k].light_sample[0].v = data_2d[two_k+1];
		}
	}else
	{
		for (unsigned k = 0; k < ps; ++k) 
		{
			samples[k].bsdf_sample[0] = BsdfSample(true);
			samples[k].bsdf_sample[1] = BsdfSample(true);
			samples[k].light_sample[0] = LightSample(true);
		}
	}
}
Exemplo n.º 5
0
    void PointLight::illuminate(const glm::vec3 & point,
                    unsigned,
                    LightSamples & samples) const
    {
        glm::vec3 dir = m_position - point;

        const real d = glm::length(dir);
        const real normInv = real(1) / (d*d);

        dir *= (1 / d);

        const glm::vec3 radiance = m_intensity * normInv;

        samples.resize(1);
        samples[0] = LightSample(m_position, dir, d, real(1), radiance);
    }
Exemplo n.º 6
0
// WhittedIntegrator Method Definitions
Spectrum WhittedIntegrator::Li(const Scene *scene,
        const Renderer *renderer, const RayDifferential &ray,
        const Intersection &isect, const Sample *sample,
        MemoryArena &arena) const {
    Spectrum L(0.);
    // Compute emitted and reflected light at ray intersection point

    // Evaluate BSDF at hit point
    BSDF *bsdf = isect.GetBSDF(ray, arena);

    // Initialize common variables for Whitted integrator
    const Point &p = bsdf->dgShading.p;
    const Normal &n = bsdf->dgShading.nn;
    Vector wo = -ray.d;

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

    // Add contribution of each light source
    Vector wi;
    for (u_int i = 0; i < scene->lights.size(); ++i) {
        VisibilityTester visibility;
        float pdf;
        Spectrum Li = scene->lights[i]->Sample_L(p, isect.rayEpsilon,
            LightSample(*sample->rng), sample->time, &wi, &pdf, &visibility);
        if (Li.IsBlack() || pdf == 0.f) continue;
        Li /= pdf;
        Spectrum f = bsdf->f(wo, wi);
        if (!f.IsBlack() && visibility.Unoccluded(scene))
            L += f * Li * AbsDot(wi, n) *
                visibility.Transmittance(scene, renderer,
                                         sample, NULL, arena);
    }
    if (ray.depth + 1 < maxDepth) {
        // Trace rays for specular reflection and refraction
        L += SpecularReflect(ray, bsdf, *sample->rng, isect, renderer,
                             scene, sample, arena);
        L += SpecularTransmit(ray, bsdf, *sample->rng, isect, renderer,
                              scene, sample, arena);
    }
    return L;
}
Exemplo n.º 7
0
// radiance along a specific ray direction
Spectrum DirectLight::Li( const Ray& r , const PixelSample& ps ) const
{
	if( r.m_Depth > max_recursive_depth )
		return 0.0f;

	// get the intersection between the ray and the scene
	Intersection ip;
	// evaluate light directly
	if( false == scene.GetIntersect( r , &ip ) )
		return scene.Le( r );

	Spectrum li = ip.Le( -r.m_Dir );

	// eavluate direct light
	unsigned light_num = scene.LightNum();
	for( unsigned i = 0 ; i < light_num ; ++i )
	{
		const Light* light = scene.GetLight(i);
		li += EvaluateDirect( r , scene , light , ip , LightSample(true) , BsdfSample(true), BXDF_TYPE( BXDF_ALL ) );
	}

	return li;
}
Exemplo n.º 8
0
// private method of li
Spectrum InstantRadiosity::_li( const Ray& r , bool ignoreLe , float* first_intersect_dist ) const
{
	// return if it is larger than the maximum depth
    if( r.m_Depth > max_recursive_depth )
		return 0.0f;

	// get intersection from camera ray
	Intersection ip;
	if( false == scene.GetIntersect( r , &ip ) )
		return ignoreLe?0.0f:scene.Le( r );

	// eavluate light path less than two vertices
	Spectrum radiance = ignoreLe?0.0f:ip.Le( -r.m_Dir );
	unsigned light_num = scene.LightNum();
	for( unsigned i = 0 ; i < light_num ; ++i )
	{
		const Light* light = scene.GetLight(i);
		radiance += EvaluateDirect( r , scene , light , ip , LightSample(true) , BsdfSample(true) , BXDF_TYPE( BXDF_ALL ) );
	}
	
	if( first_intersect_dist )
		*first_intersect_dist = ip.t;

	// pick a virtual light source randomly
	const unsigned lps_id = min( m_nLightPathSet - 1 , (int)(sort_canonical() * m_nLightPathSet) );
	list<VirtualLightSource> vps = m_pVirtualLightSources[lps_id];

	Bsdf*	bsdf = ip.primitive->GetMaterial()->GetBsdf(&ip);

	// evaluate indirect illumination
	Spectrum indirectIllum;
	list<VirtualLightSource>::const_iterator it = vps.begin();
	while( it != vps.end() )
	{
		if( r.m_Depth + it->depth > max_recursive_depth )
		{
			++it;
			continue;
		}

		Vector	delta = ip.intersect - it->intersect.intersect;
		float	sqrLen = delta.SquaredLength();
		float	len = sqrt( sqrLen );
		Vector	n_delta = delta / len;

		Bsdf* bsdf1 = it->intersect.primitive->GetMaterial()->GetBsdf(&(it->intersect));

		float		gterm = AbsDot( n_delta , ip.normal ) * AbsDot( n_delta , it->intersect.normal ) / max( m_fMinSqrDist , sqrLen );
		Spectrum	f0 = bsdf->f( -r.m_Dir , -n_delta );
		Spectrum	f1 = bsdf1->f( n_delta , it->wi );

		Spectrum	contr = gterm * f0 * f1 * it->power;
		if( !contr.IsBlack() )
		{
			Visibility vis(scene);
			vis.ray = Ray( it->intersect.intersect , n_delta , 0 , 0.001f , len - 0.001f );

			if( vis.IsVisible() )
				indirectIllum += contr;
		}

		++it;
	}
	radiance += indirectIllum / (float)m_nLightPaths;

	if( m_fMinDist > 0.0f )
	{
		Vector	wi;
		float	bsdf_pdf;
		Spectrum f = bsdf->sample_f( -r.m_Dir , wi , BsdfSample( true ) , &bsdf_pdf );

		if( !f.IsBlack() && bsdf_pdf != 0.0f )
		{
			PixelSample ps;
			float gather_dist;
			Ray gather_ray( ip.intersect , wi , r.m_Depth + 1 , 0.001f , m_fMinDist - 0.001f );
			Spectrum li = _li( gather_ray , true , &gather_dist );

			if( !li.IsBlack() )
			{
				float dgterm = AbsDot( wi , ip.normal ) * max( 0.0f , 1.0f - gather_dist * gather_dist / m_fMinSqrDist );
				radiance += f * li * dgterm / bsdf_pdf;
			}
		}
	}

	return radiance;
}
Exemplo n.º 9
0
LightSample LightSample::Zero()
{
	return LightSample(Vector3::Zero(),Color::Black());
}
Exemplo n.º 10
0
// return the radiance of a specific direction
// note : there are one factor makes the method biased.
//		there is a limitation on the number of vertexes in the path
Spectrum PathTracing::Li( const Ray& ray , const PixelSample& ps ) const
{
	Spectrum	L = 0.0f;
	Spectrum	throughput = 1.0f;

	int			bounces = 0;
	Ray	r = ray;
	while(true)
	{
		Intersection inter;

		// get the intersection between the ray and the scene
		// if it's a light , accumulate the radiance and break
		if( false == scene.GetIntersect( r , &inter ) )
		{
			if( bounces == 0 )
				return scene.Le( r );
			break;
		}

		if( bounces == 0 ) L+=inter.Le(-r.m_Dir);

		// make sure there is intersected primitive
		Sort_Assert( inter.primitive != 0 );

		// evaluate the light
		Bsdf*			bsdf = inter.primitive->GetMaterial()->GetBsdf(&inter);
		float			light_pdf = 0.0f;
		LightSample		light_sample = (bounces==0)?ps.light_sample[0]:LightSample(true);
		BsdfSample		bsdf_sample = (bounces==0)?ps.bsdf_sample[0]:BsdfSample(true);
		const Light*	light = scene.SampleLight( light_sample.t , &light_pdf );
		if( light_pdf > 0.0f )
			L += throughput * EvaluateDirect(	r  , scene , light , inter , light_sample , 
												bsdf_sample , BXDF_TYPE(BXDF_ALL) ) / light_pdf;

		// sample the next direction using bsdf
		float		path_pdf;
		Vector		wi;
		BXDF_TYPE	bxdf_type;
		Spectrum f;
		BsdfSample	_bsdf_sample = (bounces==0)?ps.bsdf_sample[1]:BsdfSample(true);
		f = bsdf->sample_f( -r.m_Dir , wi , _bsdf_sample , &path_pdf , BXDF_ALL , &bxdf_type );
		if( f.IsBlack() || path_pdf == 0.0f )
			break;

		// update path weight
		throughput *= f * AbsDot( wi , inter.normal ) / path_pdf;

		if( throughput.GetIntensity() == 0.0f )
			break;
		if( bounces > 4 )
		{
			float continueProperbility = min( 0.5f , throughput.GetIntensity() );
			if( sort_canonical() > continueProperbility )
				break;
			throughput /= continueProperbility;
		}

		r.m_Ori = inter.intersect;
		r.m_Dir = wi;
		r.m_fMin = 0.001f;

		++bounces;

		// note :	the following code makes the method biased
		//			'path_per_pixel' could be set very large to reduce the side-effect.
		if( bounces >= max_recursive_depth )
			break;
	}

	return L;
}
Exemplo n.º 11
0
// WhittedIntegrator [ surface integrator ] Method Definitions
Spectrum WhittedIntegrator::Li(const Scene *scene,
        const Renderer *renderer, const RayDifferential &ray,
        const Intersection &isect, const Sample *sample, RNG &rng,
        MemoryArena &arena) const {
    Spectrum L(0.);
    // Compute emitted and reflected light at ray intersection point

    // Evaluate BSDF at hit point
    BSDF *bsdf = isect.GetBSDF(ray, arena); // return BSDF of the material of the hit primitive


    // Initialize common variables for Whitted integrator
    const pbrt::Point &p = bsdf->dgShading.p;
    const Normal &n = bsdf->dgShading.nn;
    Vector wo = -ray.d;

    // Compute emitted light at the intersection point. The emiited light exists if 
	// the intersection occured at an area light source; otherwise, it is zero. 

    L += isect.Le(wo);

    // Add contribution of each light source
    for (uint32_t i = 0; i < scene->lights.size(); ++i) {

        Vector wi;
        float pdf;
        VisibilityTester visibility;

        Spectrum Li = scene->lights[i]->Sample_L(p, isect.rayEpsilon,
            LightSample(rng), ray.time, &wi, &pdf, &visibility);

		// if light is a delta light, then "reflection" direction wi is set to the light direction with pdf =1

        if (Li.IsBlack() || pdf == 0.f) continue;

        Spectrum f = bsdf->f(wo, wi); 
		//
		// compute the fraction of light to be reflected from wi to wo.
		// ONLY non-delta BXDF, e.g. Lambertian (diffuse reflection)  contributes to f here.  
		
		

        if (!f.IsBlack() && visibility.Unoccluded(scene)) 
			// bsdf indicates that some of the incident
			// light from direction wi is in fact scattered to the direction wo

            L += f * Li * AbsDot(wi, n) *
                 visibility.Transmittance(scene, renderer,
                                          sample, rng, arena) / pdf;
    }

	// consider the specular reflection and the specular transmission;
	// you can get this component only when the light sources are NOT delta distribution.
	 // there's no possible way that the peaks of the two delta distributions (the glass 
     // and the point light) match.  it is not possible 
     // to get a highlight of a point light source in a mirror.

    if (ray.depth + 1 < maxDepth) {
        // Trace rays for specular reflection and refraction
        L += SpecularReflect(ray, bsdf, rng, isect, renderer, scene, sample,
                             arena);
        L += SpecularTransmit(ray, bsdf, rng, isect, renderer, scene, sample,
                              arena);
    }
    return L;
}