示例#1
0
// generate sample in two dimension
void RegularSampler::Generate2D( float* sample , unsigned num , bool accept_uniform ) const
{
	Sort_Assert( sample != 0 );

	unsigned n = (unsigned)sqrt((float)num);
	Sort_Assert( n * n == num );
	unsigned dn = 2 * n;

	for( unsigned i = 0 ; i < n ; ++i )
	{
		unsigned offset = dn * i;
		for( unsigned j = 0 ; j < dn ; j+=2 )
		{
			// fall back to random sampling if uniform sampling is not accepted.
			// For certain cases, like sampling brdf and light, uniform sampling is not acceptable
			if( !accept_uniform )
			{
				sample[offset+j] = sort_canonical();
				sample[offset+j+1] = sort_canonical();
				continue;
			}

			sample[offset+j] = ( (float)j/2 + 0.5f ) / (float)n ;
			sample[offset+j+1] = ( (float)i + 0.5f ) / (float)n ;
		}
	}
}
示例#2
0
文件: ir.cpp 项目: JerryCao1985/SORT
// 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);
			}
		}
	}
}
示例#3
0
文件: random.cpp 项目: tincann/SORT
// generate sample in two dimension
void RandomSampler::Generate2D( float* sample , unsigned num , bool accept_uniform ) const
{
	Sort_Assert( sample != 0 );

	int count = 2 * num;
	for( int i = 0 ; i < count ; i += 2 )
	{
		sample[i] = sort_canonical();
		sample[i+1] = sort_canonical();
	}
}
示例#4
0
// sample a ray from light
void Square::sample_l( const LightSample& ls , Ray& r , Vector& n , float* pdf ) const
{
	float u = 2 * ls.u - 1.0f;
	float v = 2 * ls.v - 1.0f;
	r.m_fMin = 0.0f;
	r.m_fMax = FLT_MAX;
	r.m_Ori = transform( Point( radius * u , 0.0f , radius * v ) );
	r.m_Dir = transform( UniformSampleHemisphere( sort_canonical() , sort_canonical() ) );
	n = transform.invMatrix.Transpose()( Vector( 0.0f , 1.0f , 0.0f ) );

	if( pdf ) *pdf = 1.0f / ( SurfaceArea() * TWO_PI );
}
示例#5
0
文件: random.cpp 项目: tincann/SORT
// generate sample in one dimension
void RandomSampler::Generate1D( float* sample , unsigned num , bool accept_uniform ) const
{
	Sort_Assert( sample != 0 );

	for( unsigned i = 0 ; i < num ; ++i )
		sample[i] = sort_canonical();
}
示例#6
0
// generate sample in one dimension
void StratifiedSampler::Generate1D( float* sample , unsigned num , bool accept_uniform ) const
{
    Sort_Assert( sample != 0 );

    for( unsigned i = 0 ; i < num ; ++i )
        sample[i] = ( (float)i + sort_canonical() ) / (float)num ;
}
示例#7
0
// generate sample in two dimension
void StratifiedSampler::Generate2D( float* sample , unsigned num , bool accept_uniform ) const
{
    Sort_Assert( sample != 0 );

    unsigned n = (unsigned)sqrt((float)num);
    Sort_Assert( n * n == num );
    unsigned dn = 2 * n;

    for( unsigned i = 0 ; i < n ; ++i )
    {
        unsigned offset = dn * i;
        for( unsigned j = 0 ; j < dn ; j+=2 )
        {
            sample[offset+j] = ( (float)j/2 + sort_canonical() ) / (float)n ;
            sample[offset+j+1] = ( (float)i + sort_canonical() ) / (float)n ;
        }
    }
}
示例#8
0
// generate sample in one dimension
void RegularSampler::Generate1D( float* sample , unsigned num , bool accept_uniform ) const
{
	Sort_Assert( sample != 0 );

	for( unsigned i = 0 ; i < num ; ++i )
	{
		// fall back to random sampling if uniform sampling is not accepted.
		// For certain cases, like sampling brdf and light, uniform sampling is not acceptable
		if( !accept_uniform )
			sample[i] = sort_canonical();
		else
			sample[i] = ( (float)i + 0.5f ) / (float)num ;
	}
}
示例#9
0
文件: ir.cpp 项目: JerryCao1985/SORT
// 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;
}
示例#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;
}