PBRT
/home/felix/UBC/projects/AdaptiveLightfieldSampling/pbrt_v2/src/core/reflection.h
00001 
00002 /*
00003     pbrt source code Copyright(c) 1998-2012 Matt Pharr and Greg Humphreys.
00004 
00005     This file is part of pbrt.
00006 
00007     Redistribution and use in source and binary forms, with or without
00008     modification, are permitted provided that the following conditions are
00009     met:
00010 
00011     - Redistributions of source code must retain the above copyright
00012       notice, this list of conditions and the following disclaimer.
00013 
00014     - Redistributions in binary form must reproduce the above copyright
00015       notice, this list of conditions and the following disclaimer in the
00016       documentation and/or other materials provided with the distribution.
00017 
00018     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
00019     IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
00020     TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00021     PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
00022     HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00023     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00024     LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00025     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00026     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00027     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00028     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029 
00030  */
00031 
00032 #if defined(_MSC_VER)
00033 #pragma once
00034 #endif
00035 
00036 #ifndef PBRT_CORE_REFLECTION_H
00037 #define PBRT_CORE_REFLECTION_H
00038 
00039 // core/reflection.h*
00040 #include "pbrt.h"
00041 #include "geometry.h"
00042 #include "shape.h"
00043 #include "rng.h"
00044 #include "spectrum.h"
00045 #include "kdtree.h"
00046 
00047 // Reflection Declarations
00048 Spectrum FrDiel(float cosi, float cost, const Spectrum &etai,
00049                 const Spectrum &etat);
00050 Spectrum FrCond(float cosi, const Spectrum &n, const Spectrum &k);
00051 
00052 Point BRDFRemap(const Vector &wo, const Vector &wi);
00053 struct IrregIsotropicBRDFSample {
00054     IrregIsotropicBRDFSample(const Point &pp, const Spectrum &vv)
00055         : p(pp), v(vv) { }
00056     IrregIsotropicBRDFSample() { }
00057     Point p;
00058     Spectrum v;
00059 };
00060 
00061 
00062 inline float Fdr(float eta) {
00063     if (eta >= 1)
00064         return -1.4399f / (eta*eta) + 0.7099f / eta + 0.6681f +
00065             0.0636f * eta;
00066     else
00067         return -0.4399f + .7099f / eta - .3319f / (eta * eta) +
00068             .0636f / (eta*eta*eta);
00069 }
00070 
00071 
00072 
00073 // BSDF Inline Functions
00074 inline float CosTheta(const Vector &w) { return w.z; }
00075 inline float AbsCosTheta(const Vector &w) { return fabsf(w.z); }
00076 inline float SinTheta2(const Vector &w) {
00077     return max(0.f, 1.f - CosTheta(w)*CosTheta(w));
00078 }
00079 
00080 
00081 inline float SinTheta(const Vector &w) {
00082     return sqrtf(SinTheta2(w));
00083 }
00084 
00085 
00086 inline float CosPhi(const Vector &w) {
00087     float sintheta = SinTheta(w);
00088     if (sintheta == 0.f) return 1.f;
00089     return Clamp(w.x / sintheta, -1.f, 1.f);
00090 }
00091 
00092 
00093 inline float SinPhi(const Vector &w) {
00094     float sintheta = SinTheta(w);
00095     if (sintheta == 0.f) return 0.f;
00096     return Clamp(w.y / sintheta, -1.f, 1.f);
00097 }
00098 
00099 
00100 inline bool SameHemisphere(const Vector &w, const Vector &wp) {
00101     return w.z * wp.z > 0.f;
00102 }
00103 
00104 
00105 
00106 // BSDF Declarations
00107 enum BxDFType {
00108     BSDF_REFLECTION   = 1<<0,
00109     BSDF_TRANSMISSION = 1<<1,
00110     BSDF_DIFFUSE      = 1<<2,
00111     BSDF_GLOSSY       = 1<<3,
00112     BSDF_SPECULAR     = 1<<4,
00113     BSDF_ALL_TYPES        = BSDF_DIFFUSE |
00114                             BSDF_GLOSSY |
00115                             BSDF_SPECULAR,
00116     BSDF_ALL_REFLECTION   = BSDF_REFLECTION |
00117                             BSDF_ALL_TYPES,
00118     BSDF_ALL_TRANSMISSION = BSDF_TRANSMISSION |
00119                             BSDF_ALL_TYPES,
00120     BSDF_ALL              = BSDF_ALL_REFLECTION |
00121                             BSDF_ALL_TRANSMISSION
00122 };
00123 
00124 
00125 struct BSDFSample {
00126    // BSDFSample Public Methods
00127    BSDFSample(float up0, float up1, float ucomp) {
00128        Assert(up0 >= 0.f && up0 < 1.f);
00129        Assert(up1 >= 0.f && up1 < 1.f);
00130        Assert(ucomp >= 0.f && ucomp < 1.f);
00131        uDir[0] = up0;
00132        uDir[1] = up1;
00133        uComponent = ucomp;
00134    }
00135    BSDFSample(RNG &rng) {
00136       uDir[0] = rng.RandomFloat();
00137       uDir[1] = rng.RandomFloat();
00138       uComponent = rng.RandomFloat();
00139    }
00140    BSDFSample(const Sample *sample, const BSDFSampleOffsets &offsets, uint32_t num);
00141    BSDFSample() { }
00142    float uDir[2], uComponent;
00143 };
00144 
00145 
00146 struct BSDFSampleOffsets {
00147     BSDFSampleOffsets() { }
00148     BSDFSampleOffsets(int count, Sample *sample);
00149     int nSamples, componentOffset, dirOffset;
00150 };
00151 
00152 
00153 class BSDF {
00154 public:
00155     // BSDF Public Methods
00156     Spectrum Sample_f(const Vector &wo, Vector *wi, const BSDFSample &bsdfSample,
00157                       float *pdf, BxDFType flags = BSDF_ALL,
00158                       BxDFType *sampledType = NULL) const;
00159     float Pdf(const Vector &wo, const Vector &wi,
00160               BxDFType flags = BSDF_ALL) const;
00161     BSDF(const DifferentialGeometry &dgs, const Normal &ngeom,
00162          float eta = 1.f);
00163     inline void Add(BxDF *bxdf);
00164     int NumComponents() const { return nBxDFs; }
00165     int NumComponents(BxDFType flags) const;
00166     Vector WorldToLocal(const Vector &v) const {
00167         return Vector(Dot(v, sn), Dot(v, tn), Dot(v, nn));
00168     }
00169     Vector LocalToWorld(const Vector &v) const {
00170         return Vector(sn.x * v.x + tn.x * v.y + nn.x * v.z,
00171                       sn.y * v.x + tn.y * v.y + nn.y * v.z,
00172                       sn.z * v.x + tn.z * v.y + nn.z * v.z);
00173     }
00174     Spectrum f(const Vector &woW, const Vector &wiW, BxDFType flags = BSDF_ALL) const;
00175     Spectrum rho(RNG &rng, BxDFType flags = BSDF_ALL,
00176                  int sqrtSamples = 6) const;
00177     Spectrum rho(const Vector &wo, RNG &rng, BxDFType flags = BSDF_ALL,
00178                  int sqrtSamples = 6) const;
00179 
00180     // BSDF Public Data
00181     const DifferentialGeometry dgShading;
00182     const float eta;
00183 private:
00184     // BSDF Private Methods
00185     ~BSDF() { }
00186 
00187     // BSDF Private Data
00188     Normal nn, ng;
00189     Vector sn, tn;
00190     int nBxDFs;
00191 #define MAX_BxDFS 8
00192     BxDF *bxdfs[MAX_BxDFS];
00193     friend class MixMaterial;
00194 };
00195 
00196 
00197 #define BSDF_ALLOC(arena, Type) new (arena.Alloc(sizeof(Type))) Type
00198 
00199 // BxDF Declarations
00200 class BxDF {
00201 public:
00202     // BxDF Interface
00203     virtual ~BxDF() { }
00204     BxDF(BxDFType t) : type(t) { }
00205     bool MatchesFlags(BxDFType flags) const {
00206         return (type & flags) == type;
00207     }
00208     virtual Spectrum f(const Vector &wo, const Vector &wi) const = 0;
00209     virtual Spectrum Sample_f(const Vector &wo, Vector *wi,
00210                               float u1, float u2, float *pdf) const;
00211     virtual Spectrum rho(const Vector &wo, int nSamples,
00212                          const float *samples) const;
00213     virtual Spectrum rho(int nSamples, const float *samples1,
00214                          const float *samples2) const;
00215     virtual float Pdf(const Vector &wi, const Vector &wo) const;
00216 
00217     // BxDF Public Data
00218     const BxDFType type;
00219 };
00220 
00221 
00222 class BRDFToBTDF : public BxDF {
00223 public:
00224     // BRDFToBTDF Public Methods
00225     BRDFToBTDF(BxDF *b)
00226         : BxDF(BxDFType(b->type ^ (BSDF_REFLECTION | BSDF_TRANSMISSION))) {
00227         brdf = b;
00228     }
00229     static Vector otherHemisphere(const Vector &w) {
00230         return Vector(w.x, w.y, -w.z);
00231     }
00232     Spectrum f(const Vector &wo, const Vector &wi) const;
00233     Spectrum Sample_f(const Vector &wo, Vector *wi, float u1, float u2,
00234                       float *pdf) const;
00235     Spectrum rho(const Vector &w, int nSamples, const float *samples) const {
00236         return brdf->rho(otherHemisphere(w), nSamples, samples);
00237     }
00238     Spectrum rho(int nSamples, const float *samples1, const float *samples2) const {
00239         return brdf->rho(nSamples, samples1, samples2);
00240     }
00241     float Pdf(const Vector &wo, const Vector &wi) const;
00242 private:
00243     BxDF *brdf;
00244 };
00245 
00246 
00247 class ScaledBxDF : public BxDF {
00248 public:
00249     // ScaledBxDF Public Methods
00250     ScaledBxDF(BxDF *b, const Spectrum &sc)
00251         : BxDF(BxDFType(b->type)), bxdf(b), s(sc) {
00252     }
00253     Spectrum rho(const Vector &w, int nSamples, const float *samples) const {
00254         return s * bxdf->rho(w, nSamples, samples);
00255     }
00256     Spectrum rho(int nSamples, const float *samples1,
00257         const float *samples2) const {
00258         return s * bxdf->rho(nSamples, samples1, samples2);
00259     }
00260     Spectrum f(const Vector &wo, const Vector &wi) const;
00261     Spectrum Sample_f(const Vector &wo, Vector *wi,
00262         float u1, float u2, float *pdf) const;
00263 private:
00264     BxDF *bxdf;
00265     Spectrum s;
00266 };
00267 
00268 
00269 class Fresnel {
00270 public:
00271     // Fresnel Interface
00272     virtual ~Fresnel();
00273     virtual Spectrum Evaluate(float cosi) const = 0;
00274 };
00275 
00276 
00277 class FresnelConductor : public Fresnel {
00278 public:
00279     // FresnelConductor Public Methods
00280     Spectrum Evaluate(float cosi) const;
00281     FresnelConductor(const Spectrum &e, const Spectrum &kk)
00282         : eta(e), k(kk) {
00283     }
00284 
00285 private:
00286     Spectrum eta, k;
00287 };
00288 
00289 
00290 class FresnelDielectric : public Fresnel {
00291 public:
00292     // FresnelDielectric Public Methods
00293     Spectrum Evaluate(float cosi) const;
00294     FresnelDielectric(float ei, float et) : eta_i(ei), eta_t(et) { }
00295 private:
00296     float eta_i, eta_t;
00297 };
00298 
00299 
00300 class FresnelNoOp : public Fresnel {
00301 public:
00302     Spectrum Evaluate(float) const { return Spectrum(1.); }
00303 };
00304 
00305 
00306 class SpecularReflection : public BxDF {
00307 public:
00308     // SpecularReflection Public Methods
00309     SpecularReflection(const Spectrum &r, Fresnel *f)
00310         : BxDF(BxDFType(BSDF_REFLECTION | BSDF_SPECULAR)),
00311           R(r), fresnel(f) {
00312     }
00313     Spectrum f(const Vector &, const Vector &) const {
00314         return Spectrum(0.);
00315     }
00316     Spectrum Sample_f(const Vector &wo, Vector *wi,
00317                       float u1, float u2, float *pdf) const;
00318     float Pdf(const Vector &wo, const Vector &wi) const {
00319         return 0.;
00320     }
00321 private:
00322     // SpecularReflection Private Data
00323     Spectrum R;
00324     Fresnel *fresnel;
00325 };
00326 
00327 
00328 class SpecularTransmission : public BxDF {
00329 public:
00330     // SpecularTransmission Public Methods
00331     SpecularTransmission(const Spectrum &t, float ei, float et)
00332         : BxDF(BxDFType(BSDF_TRANSMISSION | BSDF_SPECULAR)),
00333           fresnel(ei, et) {
00334         T = t;
00335         etai = ei;
00336         etat = et;
00337     }
00338     Spectrum f(const Vector &, const Vector &) const {
00339         return Spectrum(0.);
00340     }
00341     Spectrum Sample_f(const Vector &wo, Vector *wi, float u1, float u2, float *pdf) const;
00342     float Pdf(const Vector &wo, const Vector &wi) const {
00343         return 0.;
00344     }
00345 private:
00346     // SpecularTransmission Private Data
00347     Spectrum T;
00348     float etai, etat;
00349     FresnelDielectric fresnel;
00350 };
00351 
00352 
00353 class Lambertian : public BxDF {
00354 public:
00355     // Lambertian Public Methods
00356     Lambertian(const Spectrum &reflectance)
00357         : BxDF(BxDFType(BSDF_REFLECTION | BSDF_DIFFUSE)), R(reflectance) { }
00358     Spectrum f(const Vector &wo, const Vector &wi) const;
00359     Spectrum rho(const Vector &, int, const float *) const { return R; }
00360     Spectrum rho(int, const float *, const float *) const { return R; }
00361 private:
00362     // Lambertian Private Data
00363     Spectrum R;
00364 };
00365 
00366 
00367 class OrenNayar : public BxDF {
00368 public:
00369     // OrenNayar Public Methods
00370     Spectrum f(const Vector &wo, const Vector &wi) const;
00371     OrenNayar(const Spectrum &reflectance, float sig)
00372         : BxDF(BxDFType(BSDF_REFLECTION | BSDF_DIFFUSE)),
00373           R(reflectance) {
00374         float sigma = Radians(sig);
00375         float sigma2 = sigma*sigma;
00376         A = 1.f - (sigma2 / (2.f * (sigma2 + 0.33f)));
00377         B = 0.45f * sigma2 / (sigma2 + 0.09f);
00378     }
00379 private:
00380     // OrenNayar Private Data
00381     Spectrum R;
00382     float A, B;
00383 };
00384 
00385 
00386 class MicrofacetDistribution {
00387 public:
00388     // MicrofacetDistribution Interface
00389     virtual ~MicrofacetDistribution() { }
00390     virtual float D(const Vector &wh) const = 0;
00391     virtual void Sample_f(const Vector &wo, Vector *wi,
00392                           float u1, float u2, float *pdf) const = 0;
00393     virtual float Pdf(const Vector &wo, const Vector &wi) const = 0;
00394 };
00395 
00396 
00397 class Microfacet : public BxDF {
00398 public:
00399     // Microfacet Public Methods
00400     Microfacet(const Spectrum &reflectance, Fresnel *f,
00401         MicrofacetDistribution *d);
00402     Spectrum f(const Vector &wo, const Vector &wi) const;
00403     float G(const Vector &wo, const Vector &wi, const Vector &wh) const {
00404         float NdotWh = AbsCosTheta(wh);
00405         float NdotWo = AbsCosTheta(wo);
00406         float NdotWi = AbsCosTheta(wi);
00407         float WOdotWh = AbsDot(wo, wh);
00408         return min(1.f, min((2.f * NdotWh * NdotWo / WOdotWh),
00409                             (2.f * NdotWh * NdotWi / WOdotWh)));
00410     }
00411     Spectrum Sample_f(const Vector &wo, Vector *wi,
00412                               float u1, float u2, float *pdf) const;
00413     float Pdf(const Vector &wo, const Vector &wi) const;
00414 private:
00415     // Microfacet Private Data
00416     Spectrum R;
00417     MicrofacetDistribution *distribution;
00418     Fresnel *fresnel;
00419 };
00420 
00421 
00422 class Blinn : public MicrofacetDistribution {
00423 public:
00424     Blinn(float e) { if (e > 10000.f || isnan(e)) e = 10000.f;
00425                      exponent = e; }
00426     // Blinn Public Methods
00427     float D(const Vector &wh) const {
00428         float costhetah = AbsCosTheta(wh);
00429         return (exponent+2) * INV_TWOPI * powf(costhetah, exponent);
00430     }
00431     virtual void Sample_f(const Vector &wi, Vector *sampled_f, float u1, float u2, float *pdf) const;
00432     virtual float Pdf(const Vector &wi, const Vector &wo) const;
00433 private:
00434     float exponent;
00435 };
00436 
00437 
00438 class Anisotropic : public MicrofacetDistribution {
00439 public:
00440     // Anisotropic Public Methods
00441     Anisotropic(float x, float y) {
00442         ex = x; ey = y;
00443         if (ex > 10000.f || isnan(ex)) ex = 10000.f;
00444         if (ey > 10000.f || isnan(ey)) ey = 10000.f;
00445     }
00446     float D(const Vector &wh) const {
00447         float costhetah = AbsCosTheta(wh);
00448         float d = 1.f - costhetah * costhetah;
00449         if (d == 0.f) return 0.f;
00450         float e = (ex * wh.x * wh.x + ey * wh.y * wh.y) / d;
00451         return sqrtf((ex+2.f) * (ey+2.f)) * INV_TWOPI * powf(costhetah, e);
00452     }
00453     void Sample_f(const Vector &wo, Vector *wi, float u1, float u2, float *pdf) const;
00454     float Pdf(const Vector &wo, const Vector &wi) const;
00455     void sampleFirstQuadrant(float u1, float u2, float *phi, float *costheta) const;
00456 private:
00457     float ex, ey;
00458 };
00459 
00460 
00461 class FresnelBlend : public BxDF {
00462 public:
00463     // FresnelBlend Public Methods
00464     FresnelBlend(const Spectrum &Rd,
00465                  const Spectrum &Rs,
00466                  MicrofacetDistribution *dist);
00467     Spectrum f(const Vector &wo, const Vector &wi) const;
00468     Spectrum SchlickFresnel(float costheta) const {
00469         return Rs + powf(1 - costheta, 5.f) * (Spectrum(1.) - Rs);
00470     }
00471     Spectrum Sample_f(const Vector &wi, Vector *sampled_f, float u1, float u2, float *pdf) const;
00472     float Pdf(const Vector &wi, const Vector &wo) const;
00473 private:
00474     // FresnelBlend Private Data
00475     Spectrum Rd, Rs;
00476     MicrofacetDistribution *distribution;
00477 };
00478 
00479 
00480 class IrregIsotropicBRDF : public BxDF {
00481 public:
00482     // IrregIsotropicBRDF Public Methods
00483     IrregIsotropicBRDF(const KdTree<IrregIsotropicBRDFSample> *d)
00484         : BxDF(BxDFType(BSDF_REFLECTION | BSDF_GLOSSY)), isoBRDFData(d) { }
00485     Spectrum f(const Vector &wo, const Vector &wi) const;
00486 private:
00487     // IrregIsotropicBRDF Private Data
00488     const KdTree<IrregIsotropicBRDFSample> *isoBRDFData;
00489 };
00490 
00491 
00492 class RegularHalfangleBRDF : public BxDF {
00493 public:
00494     // RegularHalfangleBRDF Public Methods
00495     RegularHalfangleBRDF(const float *d, uint32_t nth, uint32_t ntd,
00496                          uint32_t npd)
00497         : BxDF(BxDFType(BSDF_REFLECTION | BSDF_GLOSSY)), brdf(d),
00498           nThetaH(nth), nThetaD(ntd), nPhiD(npd) { }
00499     Spectrum f(const Vector &wo, const Vector &wi) const;
00500 private:
00501     // RegularHalfangleBRDF Private Data
00502     const float *brdf;
00503     const uint32_t nThetaH, nThetaD, nPhiD;
00504 };
00505 
00506 
00507 
00508 // BSSRDF Declarations
00509 class BSSRDF {
00510 public:
00511     // BSSRDF Public Methods
00512     BSSRDF(const Spectrum &sa, const Spectrum &sps, float et)
00513         : e(et), sig_a(sa), sigp_s(sps) { }
00514     float eta() const { return e; }
00515     Spectrum sigma_a() const { return sig_a; }
00516     Spectrum sigma_prime_s() const { return sigp_s; }
00517 private:
00518     // BSSRDF Private Data
00519     float e;
00520     Spectrum sig_a, sigp_s;
00521 };
00522 
00523 
00524 
00525 // BSDF Inline Method Definitions
00526 inline void BSDF::Add(BxDF *b) {
00527     Assert(nBxDFs < MAX_BxDFS);
00528     bxdfs[nBxDFs++] = b;
00529 }
00530 
00531 
00532 inline int BSDF::NumComponents(BxDFType flags) const {
00533     int num = 0;
00534     for (int i = 0; i < nBxDFs; ++i)
00535         if (bxdfs[i]->MatchesFlags(flags)) ++num;
00536     return num;
00537 }
00538 
00539 
00540 
00541 #endif // PBRT_CORE_REFLECTION_H