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 "color.h"
00026 #include "spectrum.h"
00027 #include "mc.h"
00028 #include "sampling.h"
00029 #include "microfacetdistribution.h"
00030 #include <stdarg.h>
00031
00032 using namespace lux;
00033
00034 FresnelBlend::FresnelBlend(const SWCSpectrum &d,
00035 const SWCSpectrum &s,
00036 MicrofacetDistribution *dist)
00037 : BxDF(BxDFType(BSDF_REFLECTION | BSDF_GLOSSY)),
00038 Rd(d), Rs(s) {
00039 distribution = dist;
00040 }
00041 SWCSpectrum FresnelBlend::f(const Vector &wo,
00042 const Vector &wi) const {
00043 SWCSpectrum diffuse = (28.f/(23.f*M_PI)) * Rd *
00044 (SWCSpectrum(1.) - Rs) *
00045 (1 - powf(1 - .5f * fabsf(CosTheta(wi)), 5)) *
00046 (1 - powf(1 - .5f * fabsf(CosTheta(wo)), 5));
00047 Vector H = Normalize(wi + wo);
00048 SWCSpectrum specular = distribution->D(H) /
00049 (4.f * AbsDot(wi, H) *
00050 max(fabsf(CosTheta(wi)), fabsf(CosTheta(wo)))) *
00051 SchlickFresnel(Dot(wi, H));
00052 return diffuse + specular;
00053 }
00054
00055 SWCSpectrum FresnelBlend::Sample_f(const Vector &wo,
00056 Vector *wi, float u1, float u2, float *pdf, float *pdfBack) const
00057 {
00058 u1 *= 2.f;
00059 if (u1 < 1.f) {
00060
00061 *wi = CosineSampleHemisphere(u1, u2);
00062 if (wo.z < 0.) wi->z *= -1.f;
00063 }
00064 else {
00065 u1 -= 1.f;
00066 distribution->Sample_f(wo, wi, u1, u2, pdf);
00067 }
00068 *pdf = Pdf(wo, *wi);
00069 if (*pdf == 0.f) {
00070 if (pdfBack)
00071 *pdfBack = 0.f;
00072 return SWCSpectrum(0.f);
00073 }
00074 if (pdfBack)
00075 *pdfBack = Pdf(*wi, wo);
00076 return f(wo, *wi);
00077 }
00078 float FresnelBlend::Pdf(const Vector &wo,
00079 const Vector &wi) const {
00080 if (!SameHemisphere(wo, wi)) return 0.f;
00081 return .5f * (fabsf(wi.z) * INV_PI +
00082 distribution->Pdf(wo, wi));
00083 }
00084