DirectIllumination.cpp

Go to the documentation of this file.
00001 /**<!-------------------------------------------------------------------->
00002    @file   DirectIllumination.cpp
00003    @author Travis Fischer (fisch0920@gmail.com)
00004    @author Matthew Jacobs (jacobs.mh@gmail.com)
00005    @date   Fall 2008
00006    
00007    @brief
00008       Interface for estimating direct illumination from all luminaires in 
00009    a scene to a given surface point on a surface
00010    <!-------------------------------------------------------------------->**/
00011 
00012 #include "DirectIllumination.h"
00013 #include <generators.h>
00014 
00015 #include <SurfacePoint.h>
00016 #include <PointSample.h>
00017 #include <Material.h>
00018 #include <Renderer.h>
00019 #include <ShapeSet.h>
00020 #include <Scene.h>
00021 #include <QtCore>
00022 #include <BSDF.h>
00023 #include <Ray.h>
00024 
00025 DirectIllumination::~DirectIllumination() {
00026    safeDelete(m_generator);
00027 }
00028 
00029 void DirectIllumination::init() {
00030    ASSERT(m_renderer);
00031    
00032    m_noDirectSamples = getValue<unsigned>("noDirectSamples", 1);
00033    
00034    const std::string &directSampleGenerator = 
00035       getValue<std::string>("directSampleGenerator", std::string("jittered"));
00036    
00037    m_generator = SampleGenerator::create(directSampleGenerator);
00038    m_generator->init();
00039 }
00040 
00041 SpectralSampleSet DirectIllumination::evaluate(SurfacePoint &pt) {
00042    return evaluate(pt, m_noDirectSamples);
00043 }
00044 
00045 SpectralSampleSet DirectIllumination::evaluate(SurfacePoint &pt, 
00046                                       unsigned reqNoDirectSamples)
00047 {
00048    ASSERT(reqNoDirectSamples > 0);
00049    
00050    Scene *scene = m_renderer->getScene();
00051    ShapeSet &lights = *scene->getLights();
00052    SpectralSampleSet Li;
00053    
00054    // with probability 1, a specular surface's BSDF will be zero for all random
00055    // rays shot towards light sources, so don't bother
00056    if (pt.bsdf->isSpecular())
00057       return SpectralSampleSet::black();
00058    /*{
00059       const Event &event = pt.bsdf->sample();
00060       const Vector3 &wo  = event;
00061       
00062       if (wo == Vector3::zero())
00063          return SpectralSampleSet::black();
00064       
00065       Ray ray(pt.position, wo);
00066       SurfacePoint pt2;
00067       
00068       const real_t t = scene->getIntersection(ray, pt2);
00069       
00070       if (!pt2.init(ray, t))
00071          return SpectralSampleSet::black();
00072       
00073       Shape *light = pt2.shape;
00074       
00075       if (!pt2.emitter->isEmitter())
00076          return SpectralSampleSet::black();
00077       
00078       const real_t lightSurfaceArea = light->getSurfaceArea();
00079       
00080       const real_t cosWo = ABS(pt.normal.dot(wo));
00081       const real_t cosWi = ABS(pt2.normal.dot(-wo));
00082       
00083       const real_t pdf   = pt.bsdf->getPdf(event);
00084       const SpectralSampleSet &fs = pt.bsdf->getBSDF(wo) / pdf;
00085       
00086       return lightSurfaceArea * pt2.emitter->getLe(-wo) * (cosWo * cosWi) / (t * t);
00087    }*/
00088    
00089    for(unsigned i = lights.size(); i--;) {
00090       Shape *light = lights[i];
00091       SpectralSampleSet direct;
00092       
00093       // unless we were to have rally oddly-shaped lights, this should be fine
00094       if (pt.shape == light)
00095          continue;
00096       
00097       const real_t lightSurfaceArea = light->getSurfaceArea();
00098       const bool isPoint = (lightSurfaceArea <= EPSILON);
00099       unsigned noDirectSamples = (isPoint ? 1 : reqNoDirectSamples);
00100       
00101       PointSampleList samples;
00102       m_generator->generate(samples, Viewport(noDirectSamples));
00103       ASSERT(samples.size() == noDirectSamples);
00104       
00105       // average incident radiance from current light source over N samples
00106       FOREACH(PointSampleListIter, samples, sample) {
00107          SurfacePoint lightPt;
00108          light->getPoint(lightPt, UV(sample->position[0], 
00109                                      sample->position[1]));
00110          ASSERT(lightPt.emitter);
00111          
00112          Vector3 wo     = (lightPt.position - pt.position);
00113          const real_t t = wo.normalize();
00114          
00115          const real_t cosWo = ABS(pt.normal.dot(wo));
00116          const real_t cosWi = ABS(lightPt.normal.dot(-wo));
00117          const SpectralSampleSet &fr = pt.bsdf->getBSDF(wo);
00118          
00119          // if point is not in shadow with respect to the current surface point
00120          // on the current light source, then add its contribution
00121          if (cosWo > 0 && cosWi > 0 && fr != SpectralSampleSet::black()
00122              && !scene->intersects(Ray(pt.position, wo), t - EPSILON))
00123          {
00124             const SpectralSampleSet &frLi = fr * lightPt.emitter->getLe(-wo);
00125             
00126             direct += (frLi * cosWo * cosWi) / (t * t);
00127          }
00128       }
00129       
00130       if (!isPoint)
00131          direct *= (lightSurfaceArea / noDirectSamples);
00132       
00133       Li += direct;
00134    }
00135    
00136    return Li;
00137 }
00138 

Generated on 28 Feb 2009 for Milton by doxygen 1.5.6