00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "cooktorrance.h"
00025 #include "spectrum.h"
00026 #include "mc.h"
00027 #include "microfacetdistribution.h"
00028 #include "fresnel.h"
00029
00030 using namespace lux;
00031
00032 CookTorrance::CookTorrance(const SWCSpectrum &ks, MicrofacetDistribution *dist,
00033 Fresnel *fres) : BxDF(BxDFType(BSDF_REFLECTION | BSDF_SPECULAR)), KS(ks), distribution(dist), fresnel(fres)
00034 {
00035 }
00036
00037 void CookTorrance::f(const TsPack *tspack, const Vector &wo, const Vector &wi, SWCSpectrum *const f_) const {
00038 const float cosThetaO = fabsf(CosTheta(wo));
00039 const float cosThetaI = fabsf(CosTheta(wi));
00040 const Vector wh(Normalize(wi + wo));
00041 const float cosThetaH = Dot(wi, wh);
00042 const float cG = G(wo, wi, wh);
00043
00044 SWCSpectrum F;
00045 fresnel->Evaluate(tspack, cosThetaH, &F);
00046 f_->AddWeighted(distribution->D(wh) * cG / (M_PI * cosThetaI * cosThetaO), KS * F);
00047 }
00048
00049 float CookTorrance::G(const Vector &wo, const Vector &wi, const Vector &wh) const
00050 {
00051 const float NdotWh = fabsf(CosTheta(wh));
00052 const float NdotWo = fabsf(CosTheta(wo));
00053 const float NdotWi = fabsf(CosTheta(wi));
00054 const float WodotWh = AbsDot(wo, wh);
00055 return min(1.f, min((2.f * NdotWh * NdotWo / WodotWh), (2.f * NdotWh * NdotWi / WodotWh)));
00056 }
00057
00058 bool CookTorrance::Sample_f(const TsPack *tspack, const Vector &wo, Vector *wi, float u1, float u2, SWCSpectrum *const f_, float *pdf, float *pdfBack, bool reverse) const
00059 {
00060 distribution->Sample_f(wo, wi, u1, u2, pdf);
00061 if (*pdf == 0.f) {
00062 if (pdfBack)
00063 *pdfBack = 0.f;
00064 return false;
00065 }
00066 if (pdfBack)
00067 *pdfBack = Pdf(tspack, *wi, wo);
00068
00069 *f_ = SWCSpectrum(0.f);
00070 if (reverse)
00071 f(tspack, *wi, wo, f_);
00072 else
00073 f(tspack, wo, *wi, f_);
00074 return true;
00075 }
00076
00077 float CookTorrance::Pdf(const TsPack *tspack, const Vector &wo, const Vector &wi) const
00078 {
00079 if (!SameHemisphere(wo, wi))
00080 return 0.f;
00081
00082 return distribution->Pdf(wo, wi);
00083 }
00084