Spectrum PathTracer::Integration ( 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, 0.99 ); 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 emission; Objects * obj = intersectionInfo.object; if ( obj->emitter ) { emission = obj->emission; } BRDFModels * brdf = obj->brdf_model; // Get surface (macro) normal direction Vector geometryNormalDirection ( 0 , 0 , 0 ); Vector sampledNextDirection ( 0 , 0 , 0 ); geometryNormalDirection = intersectionInfo.normal; double pdf = 0; Attenuation attenuationFactor = brdf->SampleBRDF( ray.direction, sampledNextDirection, geometryNormalDirection, pdf ); Ray newRay( intersectionInfo.intersectionPoint, sampledNextDirection ); Spectrum Li = Integration( thisScene, newRay, currentDepth + 1 ); if ( !Li.isEmpty() ) { attenuationFactor.Scaled_by_Spectrum_Value( obj->material_type->color ); double cos_i = AbsDot( sampledNextDirection, geometryNormalDirection ); intensity += Attenuate_Light_Spectrum( attenuationFactor, Li ) * cos_i / pdf; } // weight the radiance back after Ruassian Roulette intensity = ( currentDepth > 5 ) ? ( intensity / ( 1 - rr ) ) : intensity; ASSERT_NAN( intensity ); return emission + intensity; }
// 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; }