src/rcrt/tracing/SimpleTracer.cpp

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

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