PathTracer.cpp

Go to the documentation of this file.
00001 /**<!-------------------------------------------------------------------->
00002    @file   PathTracer.cpp
00003    @author Travis Fischer (fisch0920@gmail.com)
00004    @author Matthew Jacobs (jacobs.mh@gmail.com)
00005    @date   Fall 2008
00006 
00007    @brief
00008       Unbiased path tracer with support for efficient direct illumination
00009    <!-------------------------------------------------------------------->**/
00010 
00011 #include "PathTracer.h"
00012 #include <DirectIllumination.h>
00013 #include <SurfacePoint.h>
00014 #include <Material.h>
00015 #include <Camera.h>
00016 #include <Scene.h>
00017 #include <QtCore>
00018 #include <Ray.h>
00019 
00020 void PathTracer::init() {
00021    m_efficientDirect = getValue<bool>("efficientDirect", true);
00022    
00023    RayTracer::init();
00024 }
00025 
00026 void PathTracer::_evaluate(const Ray &ray, SpectralSampleSet &outRadiance, 
00027                            PropertyMap &data)
00028 {
00029    unsigned depth = data.getValue<unsigned>("depth", 0);
00030    
00031    // find closest intersection
00032    SurfacePoint pt;
00033    const real_t t = m_scene->getIntersection(ray, pt);
00034    
00035    // lazily initialize SurfacePoint and return if no intersection
00036    if (!pt.init(ray, t)) {
00037       outRadiance += m_scene->getBackgroundRadiance(ray.direction);
00038       return;
00039    }
00040    
00041    // evaluate emitted radiance from intersection point, making sure 
00042    // not to double-count direct illumination
00043    if (pt.emitter->isEmitter()) {
00044       if (!m_efficientDirect || (depth == 0)) {
00045          outRadiance += pt.emitter->getLe(-ray.direction);
00046       } else {
00047          const real_t emittedContribution = 
00048             data.getValue<real_t>("emittedContribution", 0);
00049          
00050          // note: this is a bit messy and really belongs in DirectIllumination, 
00051          // but it is an optimization to place it here s.t. the reflected 
00052          // ray from a specular surface only needs to be traced through the 
00053          // scene once (we're in this case only if a specular bounce landed on 
00054          // a light source)
00055          if (emittedContribution > EPSILON) {
00056             outRadiance += pt.emitter->getLe(-ray.direction) * 
00057                (pt.shape->getSurfaceArea() / 
00058                 (t * t));
00059                  //ABS(pt.normal.dot(-ray.direction)/* * emittedContribution*/)
00060          }
00061       }
00062    }
00063    
00064    // estimate direct illumination
00065    if (m_efficientDirect)
00066       outRadiance += m_directIllumination->evaluate(pt);
00067    
00068    // sample the BSDF for an exitant direction
00069    const Event &event = pt.bsdf->sample();
00070    const Vector3 &wo  = event;
00071    
00072    if (wo == Vector3::zero())
00073       return; // absorbed
00074    
00075    const real_t pdf = pt.bsdf->getPdf(event);
00076    const SpectralSampleSet &fs = pt.bsdf->getBSDF(wo) / pdf;
00077    
00078    // record russian roulette probability for terminating random walk
00079    // note: russian roulette increases variance noticeably, so don't 
00080    // use it until several bounces have passed
00081    const real_t pCont = 
00082       (depth < 2 ? !fs.isZero() : MIN(.95, fs[fs.getMaxSample()].value));
00083    
00084    // russian roulette to terminate walk depending on albedo of surface
00085    if (Random::sample(0, 1) < pCont) {
00086       SpectralSampleSet Li;
00087       
00088       // estimate indirect illumination by recurring
00089       data["depth"] = depth + 1;
00090       data["emittedContribution"] = (pt.bsdf->isSpecular() ? 
00091                                      pt.normal.dot(wo) : 0);
00092       
00093       _evaluate(Ray(pt.position, wo), Li, data);
00094       
00095       // attenuate indirect illumination estimate Li by reflectivity of surface 
00096       // in exitant direction according to the bsdf and add its contribution to 
00097       // the exitant radiance
00098       outRadiance += fs * Li / pCont;
00099    }
00100 }
00101 

Generated on 28 Feb 2009 for Milton by doxygen 1.5.6