Spectrum PhotonMap::estimate_radiance(const Point& p, const Normal& nn, const Vector& wo, const Bsdf& bsdf, float radius) const { (void)nn; Spectrum power(0.f); this->photon_tree.lookup(p, square(radius), [&](const Photon& photon, float dist_square, float radius_square) { (void)dist_square; if(dot(photon.nn, nn) >= 0.7f) { power += photon.power * bsdf.f(wo, photon.wi, BSDF_ALL); } return radius_square; }); return power / (float(this->emitted_count) * PI * square(radius)); }
// 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; }