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