src/rcrt/tracing/PhotonTracer.cpp

Go to the documentation of this file.
00001 #include "PhotonTracer.h"
00002 #include "../materials/Material.h"
00003 #include "../bxdf/fresnel.hpp"
00004 
00005 using namespace std;
00006 
00007 namespace rcrt
00008 {
00009 
00010 PhotonTracer::PhotonTracer(Scene* s, PhotonMap* photonM, const int& noPhotG, const int& noPhotC):
00011         TracingStrategy(s), photonMap(photonM), noGPhotons(noPhotG), noCPhotons(noPhotC)
00012 {
00013         
00014 }
00015 
00016 PhotonTracer::~PhotonTracer()
00017 {
00018 }
00019 
00020 RGBColor PhotonTracer::directLight(Intersection& is, const Vec3D& rayDir) const
00021 {
00022         RGBColor result(0);
00023         Material* mat = is.getPrimitive()->getParent()->getMaterial();
00024         vector<Light*>* const lights = scene->getLights();
00025         for(unsigned int i = 0; i < lights->size(); i++){
00026                 Light* const light = lights->at(i);
00027                 RGBColor Lr(0);
00028                 std::vector<LightSample> samples;
00029                 if(light->hasSampler())
00030                         //use a more specialized sampling strategy for lighting
00031                         light->getSampler()->sample(is.getPosition(), is.getSNormalW(), samples, light->getMinSamples(), scene);
00032                 else
00033                         //get a number of light samples from the light
00034                         light->illuminate(is.getPosition(), is.getSNormalW(), samples, light->getMinSamples());
00035                 
00036                 for(unsigned int s = 0; s < samples.size(); s++){
00037                         const LightSample& sample = samples[s];
00038                         
00039                         if(sample.weight() == 0)
00040                                 continue;
00041                         //only cast shadows for manually sampled lights
00042                         //light samplers should check for shadows themselves
00043                         if(!light->hasSampler() && scene->castShadows() && 
00044                                         scene->isOccluded(is.getPosition(), sample.dirToLight(), sample.dist())){
00045                                 continue;
00046                         }
00047                         const Vec3D dirFromLight = (sample.dirToLight()*-1).normalize();
00048                         //get the reflectance value from the material
00049                         RGBColor fr = mat->sample(rayDir*-1,dirFromLight, is);
00050                         float angle = dirFromLight*is.getSNormalW();
00051                         RGBColor power = sample.power();
00052                         float weight = sample.weight();
00053                         //compute this samples contribution
00054                         Lr = Lr + power * fr * fabs(angle) * weight;
00055                 }
00056                 result = result + Lr;
00057         }
00058         return result;
00059 }
00060 
00061 RGBColor PhotonTracer::trace(Ray& r) const
00062 {
00063         static const float MAXRAYDEPTH = 7;
00064         static const float THRESHOLD = 0.00001f;
00065         if(r.getDepth() > MAXRAYDEPTH)
00066                 return RGBColor::BLACK;
00067         
00068         Intersection is = scene->intersect(r);
00069         if(is.isValid())//setting distance for beer's law
00070                 r.setCurrDist(is.getDistance());                
00071 
00072         RGBColor result(0);
00073         
00074         if(is.isValid()){
00075                 Material* mat = is.getPrimitive()->getParent()->getMaterial();
00076                 Vec3D normal(mat->getShadingNormal(is));
00077                 if(!is.backSide()){
00078                         //get emitted light
00079                         result = result + mat->getEmitted(r.dir()*-1, is);
00080                         
00081                         //get direct light contribution
00082                         RGBColor direct(directLight(is, r.dir()));
00083                         
00084                         result = result + direct;
00085                         
00086                         //get radiance estimate
00087                         RGBColor radiance(photonMap->getRadiance(r.dir()*-1, noGPhotons, noCPhotons, is));
00088                         
00089                         result = result + radiance;
00090                         
00091                         if(false){
00092                                 RGBColor indir(0);
00093                                 for(int i = 0; i < 1; i++){
00094                                         float xi1 = float(rand()) / float(RAND_MAX);
00095                                         float xi2 = float(rand()) / float(RAND_MAX);
00096                                         float z2 = xi2 * 2.0f * M_PI;
00097                                         Vec3D u;
00098                                         Vec3D v;
00099                                         normal.getCS(u, v);
00100                                         Vec3D sampleDir(u * cos(z2) + v * sin(z2) * sqrt(1-xi1) + normal * sqrt(xi1));
00101                                         sampleDir.normalize();
00102                                         RGBColor fr = mat->sample(r.dir()*-1,sampleDir*-1,is);
00103                                         float weight = fr.avg() * r.getWeight();
00104                                         Ray indRay(is.getPosition(),sampleDir,r.getDepth()+1,weight);
00105                                         RGBColor sample = trace(indRay);
00106                                         indir = indir + fr * sample / (4 * M_PI * indRay.currDist() * indRay.currDist());
00107                                 }
00108                                 result = result + indir;
00109                         }
00110                         
00111                         //trace specular reflection
00112                         if(mat->hasSpecular()){
00113                                 //compute reflection
00114                                 Vec3D reflDir(r.dir().reflect(normal));
00115                                 RGBColor fr = mat->sampleSpecular(r.dir()*-1,reflDir*-1,is);
00116                                 float weight = fr.avg()*r.getWeight();
00117                                 //do not trace further reflections if
00118                                 //it doesn't change that much
00119                                 if(weight > THRESHOLD && r.getDepth()+1 <= MAXRAYDEPTH){
00120                                         Ray reflRay(is.getPosition(),reflDir,r.getDepth()+1,weight);
00121                                         RGBColor reflColor = trace(reflRay);                    
00122                                         result = result + reflColor * fr;
00123                                 }
00124                         }
00125                         
00126                 }
00127                 
00128                 //trace fresnel refraction
00129                 if(mat->refracts()){
00130                         float etaT = mat->getRealIORPart();
00131                         float etaI = r.getLastIOR().real();
00132                         bool leaving = false;
00133                         if(is.backSide()){
00134                                 //ray is leaving the object again
00135                                 etaT = 1;//we always assume we're leaving to vaccuum
00136                                 leaving = true;
00137                         }
00138                         //compute direction based on Snells law
00139                         float eta = etaI / etaT;
00140                         float cosI = r.dir() * normal;
00141                         float cosT = 1.0 - (eta * eta) * (1.0 - cosI * cosI);
00142                         
00143                         if (leaving && cosT <= 0.0f) {
00144                                 //total internal reflection
00145                                 //TODO may not work yet, look into this
00146                                 /*
00147                                 Vec3D reflDir(r.dir().reflect(is.getSNormalW()));                               
00148                                 cosT = reflDir * normal;
00149                                 float fresnel = frRDielectric(cosI, cosT, etaI, etaT);
00150                                 float weight = fresnel * r.getWeight();
00151                                 if(weight > THRESHOLD && r.getDepth()+1 <= MAXRAYDEPTH){
00152                                         Ray reflRay(is.getPosition(),reflDir,r.getDepth()+1,weight);
00153                                         reflRay.setLastIOR(r.getLastIOR());
00154                                         reflRay.setLastObject(r.getLastObject());
00155                                         RGBColor reflColor = trace(reflRay);
00156                                         RGBColor absorb(mat->getAbsorbance());
00157                                         float dist = reflRay.currDist();
00158                                         if(dist < std::numeric_limits<float>::infinity() && dist > 0){
00159                                                 absorb = RGBColor(exp(-dist * absorb.r()),
00160                                                                 exp(-dist * absorb.g()),
00161                                                                 exp(-dist * absorb.b()));
00162                                         }
00163                                 
00164                                         result = result + reflColor * absorb * fresnel;
00165                                         
00166                                 }
00167                                 return result;
00168                                 */
00169                         }
00170                         cosT = sqrt(cosT);
00171                         float k = eta * cosI + cosT;
00172                         
00173                         Vec3D refrDir = r.dir() * eta + normal * -k;
00174                         cosT = refrDir * normal;
00175                         
00176                         float fresnel(frTDielectric(cosI, cosT,
00177                                         r.getLastIOR().real(), etaT));
00178                         //do not trace further refractions if
00179                         //it doesn't change that much
00180                         float weight = fresnel *r.getWeight();
00181                         if(weight > THRESHOLD && r.getDepth()+1 <= MAXRAYDEPTH){
00182                                 //cout << "[SimpleTracer] getting refraction" << endl;
00183                                 Ray refrRay(is.getPosition()+refrDir * 0.0001f,refrDir,r.getDepth()+1, weight);
00184                                 if(leaving)
00185                                         refrRay.setLastObject(0);
00186                                 else
00187                                         refrRay.setLastObject(is.getPrimitive()->getParent());
00188                                 
00189                                 refrRay.setLastIOR(complex<float>(etaT,0));             
00190 
00191                                 RGBColor refrColor = trace(refrRay);
00192                                 
00193                                 float dist = refrRay.currDist();
00194                         
00195                                 RGBColor absorb(mat->getAbsorbance());
00196                                 if(dist < std::numeric_limits<float>::infinity() && dist > 0){
00197                                         absorb = RGBColor(exp(-dist * absorb.r()),
00198                                                         exp(-dist * absorb.g()),
00199                                                         exp(-dist * absorb.b()));
00200                                 }
00201                                 
00202                                 result = result + refrColor * absorb * fresnel;
00203                         }
00204                 }
00205         }
00206                 
00207         return result.clamped();
00208         
00209 }
00210 
00211 }

Generated on Thu Jan 31 19:26:20 2008 for RenderingCompetitionRayTracer by  doxygen 1.5.3