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
1.5.6