PBRT
|
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