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 "lafortune.h"
00025 #include "color.h"
00026 #include "spectrum.h"
00027 #include "mc.h"
00028 #include "sampling.h"
00029 #include <stdarg.h>
00030
00031 using namespace lux;
00032
00033 Lafortune::Lafortune(const SWCSpectrum &r, u_int nl,
00034 const SWCSpectrum *xx,
00035 const SWCSpectrum *yy,
00036 const SWCSpectrum *zz,
00037 const SWCSpectrum *e, BxDFType t)
00038 : BxDF(t), R(r) {
00039 nLobes = nl;
00040 x = xx;
00041 y = yy;
00042 z = zz;
00043 exponent = e;
00044 }
00045 SWCSpectrum Lafortune::f(const Vector &wo,
00046 const Vector &wi) const {
00047 SWCSpectrum ret = R * INV_PI;
00048 for (u_int i = 0; i < nLobes; ++i) {
00049
00050 SWCSpectrum v = x[i] * wo.x * wi.x + y[i] * wo.y * wi.y +
00051 z[i] * wo.z * wi.z;
00052 ret += v.Pow(exponent[i]);
00053 }
00054 return ret;
00055 }
00056
00057 SWCSpectrum Lafortune::Sample_f(const Vector &wo, Vector *wi,
00058 float u1, float u2, float *pdf, float *pdfBack) const {
00059 u_int comp = lux::random::uintValue() % (nLobes+1);
00060 if (comp == nLobes) {
00061
00062 *wi = CosineSampleHemisphere(u1, u2);
00063 if (wo.z < 0.) wi->z *= -1.f;
00064 }
00065 else {
00066
00067 float xlum = x[comp].y();
00068 float ylum = y[comp].y();
00069 float zlum = z[comp].y();
00070 float costheta = powf(u1, 1.f / (.8f * exponent[comp].y() + 1));
00071 float sintheta = sqrtf(max(0.f, 1.f - costheta*costheta));
00072 float phi = u2 * 2.f * M_PI;
00073 Vector lobeCenter = Normalize(Vector(xlum * wo.x, ylum * wo.y, zlum * wo.z));
00074 Vector lobeX, lobeY;
00075 CoordinateSystem(lobeCenter, &lobeX, &lobeY);
00076 *wi = SphericalDirection(sintheta, costheta, phi, lobeX, lobeY,
00077 lobeCenter);
00078 }
00079 *pdf = Pdf(wo, *wi);
00080 if (pdfBack)
00081 *pdfBack = Pdf(*wi, wo);
00082 if (!SameHemisphere(wo, *wi)) return SWCSpectrum(0.f);
00083 return f(wo, *wi);
00084 }
00085 float Lafortune::Pdf(const Vector &wo, const Vector &wi) const {
00086 if (!SameHemisphere(wo, wi)) return 0.f;
00087 float pdfSum = fabsf(wi.z) * INV_PI;
00088 for (u_int i = 0; i < nLobes; ++i) {
00089 float xlum = x[i].y();
00090 float ylum = y[i].y();
00091 float zlum = z[i].y();
00092 Vector lobeCenter =
00093 Normalize(Vector(wo.x * xlum, wo.y * ylum, wo.z * zlum));
00094 float e = .8f * exponent[i].y();
00095 pdfSum += (e + 1.f) * powf(max(0.f, Dot(wi, lobeCenter)), e);
00096 }
00097 return pdfSum / (1.f + nLobes);
00098 }
00099