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
00043 light->getSampler()->sample(is.getPosition(), normal, samples, light->getMinSamples(), scene);
00044 else
00045
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
00054
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
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
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())
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
00091 result = result + mat->getEmitted(r.dir()*-1, is);
00092
00093
00094 RGBColor direct(directLight(is, r.dir()));
00095 result = result + direct;
00096
00097
00098 if( false){
00099
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
00104
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
00114 if(mat->refracts()){
00115 float etaT = mat->getRealIORPart();
00116 float etaI = r.getLastIOR().real();
00117 bool leaving = false;
00118 if(is.backSide()){
00119
00120 etaT = 1;
00121 leaving = true;
00122 }
00123
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
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
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
00164
00165 float weight = fresnel *r.getWeight();
00166 if(weight > THRESHOLD && r.getDepth()+1 <= MAXRAYDEPTH){
00167
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 }