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
00072 photon->scalePower(Kd/Pd);
00073
00074
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
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
00095
00096
00097 photon->scalePower(Kt/Pt);
00098 float etaI = is.getLastIOR().real();
00099 float etaT = 1.0;
00100 if(!is.backSide())
00101 etaT = ior.real();
00102 else {
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) {
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 }