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
1.5.6