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 "anisotropic.h"
00025
00026 using namespace lux;
00027
00028 void Anisotropic::Sample_f(const Vector &wo, Vector *wi,
00029 float u1, float u2, float *pdf) const {
00030
00031 float phi, costheta;
00032 if (u1 < .25f) {
00033 sampleFirstQuadrant(4.f * u1, u2, &phi, &costheta);
00034 } else if (u1 < .5f) {
00035 u1 = 4.f * (.5f - u1);
00036 sampleFirstQuadrant(u1, u2, &phi, &costheta);
00037 phi = M_PI - phi;
00038 } else if (u1 < .75f) {
00039 u1 = 4.f * (u1 - .5f);
00040 sampleFirstQuadrant(u1, u2, &phi, &costheta);
00041 phi += M_PI;
00042 } else {
00043 u1 = 4.f * (1.f - u1);
00044 sampleFirstQuadrant(u1, u2, &phi, &costheta);
00045 phi = 2.f * M_PI - phi;
00046 }
00047 const float sintheta = sqrtf(max(0.f, 1.f - costheta*costheta));
00048 Vector H = SphericalDirection(sintheta, costheta, phi);
00049 if (Dot(wo, H) < 0.f) H = -H;
00050
00051 *wi = -wo + 2.f * Dot(wo, H) * H;
00052
00053 const float e = (ex * H.x * H.x + ey * H.y * H.y) /
00054 (sintheta * sintheta);
00055 const float d = sqrtf((ex + 1.f) * (ey + 1.f)) * INV_TWOPI *
00056 powf(costheta, e);
00057 const float anisotropic_pdf = d / (4.f * Dot(wo, H));
00058 *pdf = anisotropic_pdf;
00059 }
00060 void Anisotropic::sampleFirstQuadrant(float u1, float u2,
00061 float *phi, float *costheta) const {
00062 if (ex == ey)
00063 *phi = M_PI * u1 * 0.5f;
00064 else
00065 *phi = atanf(sqrtf((ex + 1.f)/(ey + 1.f)) *
00066 tanf(M_PI * u1 * 0.5f));
00067 const float cosphi = cosf(*phi), sinphi = sinf(*phi);
00068 *costheta = powf(u2, 1.f / (ex * cosphi * cosphi +
00069 ey * sinphi * sinphi + 1.f));
00070 }
00071 float Anisotropic::Pdf(const Vector &wo,
00072 const Vector &wi) const {
00073 Vector H = Normalize(wo + wi);
00074
00075 const float e = (ex * H.x * H.x + ey * H.y * H.y) /
00076 (1.f - CosTheta(H) * CosTheta(H));
00077 const float d = sqrtf((ex + 1.f) * (ey + 1.f)) * INV_TWOPI *
00078 powf(fabsf(CosTheta(H)), e);
00079 const float anisotropic_pdf = d / (4.f * Dot(wo, H));
00080 return anisotropic_pdf;
00081 }
00082