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 "fresnelblend.h"
00025 #include "spectrum.h"
00026 #include "mc.h"
00027 #include "microfacetdistribution.h"
00028
00029 using namespace lux;
00030
00031 FresnelBlend::FresnelBlend(const SWCSpectrum &d,
00032 const SWCSpectrum &s,
00033 const SWCSpectrum &a,
00034 float dep,
00035 MicrofacetDistribution *dist)
00036 : BxDF(BxDFType(BSDF_REFLECTION | BSDF_GLOSSY)),
00037 Rd(d), Rs(s), Alpha(a), depth(dep)
00038 {
00039 distribution = dist;
00040 }
00041 void FresnelBlend::f(const TsPack *tspack, const Vector &wo,
00042 const Vector &wi, SWCSpectrum *const f_) const
00043 {
00044
00045 SWCSpectrum a(1.f);
00046
00047 if (depth > 0.f) {
00048 float depthfactor = depth * (1.f / fabsf(CosTheta(wi)) + 1.f / fabsf(CosTheta(wo)));
00049 a = Exp(Alpha * -depthfactor);
00050 }
00051
00052
00053 f_->AddWeighted((1.f - powf(1.f - .5f * fabsf(CosTheta(wi)), 5.f)) *
00054 (1.f - powf(1.f - .5f * fabsf(CosTheta(wo)), 5.f)) *
00055 (28.f/(23.f*M_PI)), a * Rd * (SWCSpectrum(1.f) - Rs));
00056
00057 Vector H = Normalize(wi + wo);
00058
00059 f_->AddWeighted(distribution->D(H) /
00060 (4.f * AbsDot(wi, H) *
00061 max(fabsf(CosTheta(wi)), fabsf(CosTheta(wo)))),
00062 SchlickFresnel(Dot(wi, H)));
00063 }
00064
00065 bool FresnelBlend::Sample_f(const TsPack *tspack, const Vector &wo, Vector *wi,
00066 float u1, float u2, SWCSpectrum *const f_, float *pdf,
00067 float *pdfBack, bool reverse) const
00068 {
00069 u1 *= 2.f;
00070 if (u1 < 1.f) {
00071
00072 *wi = CosineSampleHemisphere(u1, u2);
00073 if (wo.z < 0.f)
00074 wi->z *= -1.f;
00075 } else {
00076 u1 -= 1.f;
00077 distribution->Sample_f(wo, wi, u1, u2, pdf);
00078 }
00079 *pdf = Pdf(tspack, wo, *wi);
00080 if (*pdf == 0.f) {
00081 if (pdfBack)
00082 *pdfBack = 0.f;
00083 return false;
00084 }
00085 if (pdfBack)
00086 *pdfBack = Pdf(tspack, *wi, wo);
00087
00088 *f_ = SWCSpectrum(0.f);
00089 if (reverse)
00090 f(tspack, *wi, wo, f_);
00091 else
00092 f(tspack, wo, *wi, f_);
00093 return true;
00094 }
00095 float FresnelBlend::Pdf(const TsPack *tspack, const Vector &wo,
00096 const Vector &wi) const
00097 {
00098 if (!SameHemisphere(wo, wi))
00099 return 0.f;
00100 return .5f * (fabsf(wi.z) * INV_PI + distribution->Pdf(wo, wi));
00101 }
00102