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
1.5.6