WhittedRayTracer.cpp

Go to the documentation of this file.
00001 /**<!-------------------------------------------------------------------->
00002    @file   WhittedRayTracer.cpp
00003    @author Travis Fischer (fisch0920@gmail.com)
00004    @author Matthew Jacobs (jacobs.mh@gmail.com)
00005    @date   Fall 2008
00006 
00007    @brief
00008       Classic Whitted-style raytracer; for a concise introduction to 
00009    raytracing, see http://www.raytracing.co.uk/study/ray_intro.htm
00010    <!-------------------------------------------------------------------->**/
00011 
00012 #include "WhittedRayTracer.h"
00013 #include <DirectIllumination.h>
00014 #include <SurfacePoint.h>
00015 #include <Material.h>
00016 #include <Camera.h>
00017 #include <Scene.h>
00018 #include <QtCore>
00019 #include <Ray.h>
00020 
00021 void WhittedRayTracer::init() {
00022    m_noIndirectSamples = getValue<unsigned>("noIndirectSamples", 
00023                                             m_noIndirectSamples);
00024    
00025    m_maxDepth = getValue<unsigned>("maxDepth", m_maxDepth);
00026    m_ambient  = getValue<SpectralSampleSet>("ambient", m_ambient);
00027    
00028    RayTracer::init();
00029 }
00030 
00031 void WhittedRayTracer::_evaluate(const Ray &ray, SpectralSampleSet &outRadiance, 
00032                                  PropertyMap &data)
00033 {
00034    const unsigned depth = data.getValue<unsigned>("depth", 0u);
00035    
00036    // base case for recursion depth
00037    if (depth >= m_maxDepth)
00038       return;
00039    
00040    // find closest intersection
00041    SurfacePoint pt;
00042    const real_t t = m_scene->getIntersection(ray, pt);
00043    
00044    // lazily initialize SurfacePoint and return if no intersection
00045    // also return if we hit an emitter after the first bounce, 
00046    // ensuring we don't real_t-count direct illumination
00047    if (!pt.init(ray, t)) {
00048       outRadiance += m_scene->getBackgroundRadiance(ray.direction);
00049       return;
00050    }
00051    
00052    // evaluate emitted radiance from intersection point, making sure not to 
00053    // double-count direct illumination
00054    if (pt.emitter->isEmitter()) {
00055       if (depth == 0) {
00056          outRadiance += pt.emitter->getLe(-ray.direction);
00057       } else {
00058          const real_t emittedContribution = 
00059             data.getValue<real_t>("emittedContribution", 0);
00060          
00061          if (emittedContribution > EPSILON) {
00062             outRadiance += pt.emitter->getLe(-ray.direction) * 
00063                ((pt.shape->getSurfaceArea() * 
00064                  ABS(pt.normal.dot(-ray.direction) * emittedContribution)) / 
00065                 (t * t));
00066          }
00067       }
00068    }
00069    
00070    // estimate direct illumination
00071    outRadiance += m_directIllumination->evaluate(pt);
00072    
00073    // ambient term
00074    outRadiance += m_ambient;
00075    
00076    // estimate indirect illumination
00077    for(unsigned i = m_noIndirectSamples; i--;) {
00078       // sample the BSDF for an exitent direction
00079       const Event &event = pt.bsdf->sample();
00080       const Vector3 &wo  = event;
00081       if (wo == Vector3::zero())
00082          continue; // absorbed
00083       
00084       const SpectralSampleSet &fs = pt.bsdf->getBSDF(wo);
00085       const real_t pdf = pt.bsdf->getPdf(event);
00086       
00087       // if the surface has a non-zero bsdf for the given reflected vector
00088       if (!fs.isZero()) {
00089          SpectralSampleSet Li;
00090          
00091          // estimate indirect illumination by recurring
00092          data["depth"] = depth + 1;
00093          data["emittedContribution"] = (pt.bsdf->isSpecular() ? 
00094                                         pt.normal.dot(wo) : 0);
00095          
00096          _evaluate(Ray(pt.position, wo), Li, data);
00097          
00098          // attenuate incident illumination Li by reflectivity of surface 
00099          // in exitant direction (bsdf) and add its contribution to the 
00100          // exitant radiance
00101          outRadiance += (fs * Li / (pdf * m_noIndirectSamples));
00102       }
00103    }
00104 }
00105 

Generated on 28 Feb 2009 for Milton by doxygen 1.5.6