src/rcrt/materials/BSDFMaterial.cpp

Go to the documentation of this file.
00001 #include "BSDFMaterial.h"
00002 #include "../bxdf/fresnel.hpp"
00003 
00004 using namespace std;
00005 
00006 namespace rcrt
00007 {
00008 
00009 BSDFMaterial::BSDFMaterial(BSDF b, const std::complex<float>& ior):Material(ior),bsdf(b)
00010 {
00011 }
00012 
00013 BSDFMaterial::~BSDFMaterial()
00014 {
00015 }
00016 
00017 RGBColor BSDFMaterial::sample(const Vec3D& wOut, const Vec3D& wInc,
00018                                 Intersection& is)
00019 {
00020         return bsdf.eval(wOut,wInc,is.getGNormalW(), getShadingNormal(is));
00021 }
00022 
00023 
00024 bool BSDFMaterial::hasDiffuse() const
00025 {
00026         return bsdf.hasDiffuse();
00027 }
00028 
00029 bool BSDFMaterial::hasSpecular() const
00030 {
00031         return bsdf.hasSpecular();
00032 }
00033 
00034 bool BSDFMaterial::hasTransmissive() const
00035 {
00036         return bsdf.hasTransmissive();
00037 }
00038 
00039 RGBColor BSDFMaterial::getEmitted(const Vec3D& wOut, Intersection& is)
00040 {
00041         return 0;
00042 }
00043 
00044 RGBColor BSDFMaterial::sampleDiffuse(const Vec3D& wOut, const Vec3D& wInc, Intersection& is)
00045 {
00046         return bsdf.evalDiffuse(wOut, wInc, is.getGNormalW(), getShadingNormal(is));
00047 }
00048 
00049 RGBColor BSDFMaterial::sampleSpecular(const Vec3D& wOut, const Vec3D& wInc, Intersection& is)
00050 {
00051         return bsdf.evalSpecular(wOut, wInc, is.getGNormalW(), getShadingNormal(is));
00052 }
00053 
00054 ScatterEvent BSDFMaterial::scatterPhoton(Intersection& is, Photon* photon)
00055 {
00056         Vec3D normal(getShadingNormal(is));
00057         const RGBColor Kd(bsdf.getKdiffuse());
00058         const RGBColor Ks(bsdf.getKspecular());
00059         const RGBColor Kt(bsdf.getKtransmit());
00060         const RGBColor& P = photon->getPower();
00061         const float sD = Kd.r()*P.r() + Kd.g()*P.g() + Kd.b()*P.b();
00062         const float sS = Ks.r()*P.r() + Ks.g()*P.g() + Ks.b()*P.b();
00063         const float sT = Kt.r()*P.r() + Kt.g()*P.g() + Kt.b()*P.b(); 
00064         const float IsAll = 1.0f/(sD + sS + sT);
00065         const float Pd = sD * IsAll;
00066         const float Ps = sS * IsAll;
00067         const float Pt = sT * IsAll;
00068         const float xi = float(rand()) / float(RAND_MAX); 
00069         if(xi <= Pd){
00070                 photon->setPos(is.getPosition());
00071                 //diffuse reflection
00072                 photon->scalePower(Kd/Pd);
00073                 //cout << " scaling " << Kd/Pd << endl;
00074                 //get a random direction in the upper hemisphere
00075                 float xi1 = float(rand()) / float(RAND_MAX);
00076                 float xi2 = float(rand()) / float(RAND_MAX);
00077                 float z2 = xi2 * 2.0f * M_PI;
00078                 Vec3D u;
00079                 Vec3D v;
00080                 normal.getCS(u, v);
00081                 Vec3D outDir(u * cos(z2) + v * sin(z2) * sqrt(1-xi1) + normal * sqrt(xi1));
00082                 outDir.normalize();
00083                 photon->setDir(outDir);
00084                 return DIFFUSE;
00085         } else if(xi <= Ps+Pd) {
00086                 photon->setPos(is.getPosition());
00087                 //specular reflection
00088                 photon->scalePower(Ks/Ps);
00089                 Vec3D outDir(photon->getDir().reflect(normal));
00090                 photon->setDir(outDir);
00091                 return SPECULAR;
00092         } else if(xi <= Ps+Pd+Pt) {
00093                 photon->setPos(is.getPosition());
00094                 //if(float(rand()) / float(RAND_MAX) < (1.0f - Pt))
00095                         //return STORE;
00096                 //refraction with snells law
00097                 photon->scalePower(Kt/Pt);
00098                 float etaI = is.getLastIOR().real();
00099                 float etaT = 1.0;
00100                 if(!is.backSide())//we are entering this material
00101                         etaT = ior.real();
00102                 else {//we are leaving this material, we always assume to "air"
00103                         etaI = ior.real();
00104                 }
00105                 
00106                 float eta = etaI / etaT;
00107                 Vec3D wOut(snell(photon->getDir(), normal, eta));
00108                 float cosT = wOut * normal;
00109                 if(cosT <= 0.0f) {//total internal reflection
00110                         photon->setDir(photon->getDir().reflect(normal));
00111                         return SPECULAR;
00112                 }
00113                 photon->setDir(wOut);
00114                 return REFRACTED;               
00115         } else {
00116                 photon->setPos(is.getPosition());
00117                 return STORE;
00118         }
00119         
00120 }
00121 
00122 bool BSDFMaterial::refracts() const
00123 {
00124         return hasTransmissive();
00125 }
00126 
00127 }

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