00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifndef PBRT_REFLECTION_H
00025 #define PBRT_REFLECTION_H
00026
00027 #include "pbrt.h"
00028 #include "geometry.h"
00029 #include "shape.h"
00030
00031 inline float CosTheta(const Vector &w) { return w.z; }
00032 inline float SinTheta(const Vector &w) {
00033 return sqrtf(max(0.f, 1.f - w.z*w.z));
00034 }
00035 inline float SinTheta2(const Vector &w) {
00036 return 1.f - CosTheta(w)*CosTheta(w);
00037 }
00038 inline float CosPhi(const Vector &w) {
00039 return w.x / SinTheta(w);
00040 }
00041 inline float SinPhi(const Vector &w) {
00042 return w.y / SinTheta(w);
00043 }
00044 inline bool SameHemisphere(const Vector &w,
00045 const Vector &wp) {
00046 return w.z * wp.z > 0.f;
00047 }
00048
00049 enum BxDFType {
00050 BSDF_REFLECTION = 1<<0,
00051 BSDF_TRANSMISSION = 1<<1,
00052 BSDF_DIFFUSE = 1<<2,
00053 BSDF_GLOSSY = 1<<3,
00054 BSDF_SPECULAR = 1<<4,
00055 BSDF_ALL_TYPES = BSDF_DIFFUSE |
00056 BSDF_GLOSSY |
00057 BSDF_SPECULAR,
00058 BSDF_ALL_REFLECTION = BSDF_REFLECTION |
00059 BSDF_ALL_TYPES,
00060 BSDF_ALL_TRANSMISSION = BSDF_TRANSMISSION |
00061 BSDF_ALL_TYPES,
00062 BSDF_ALL = BSDF_ALL_REFLECTION |
00063 BSDF_ALL_TRANSMISSION
00064 };
00065 class COREDLL BSDF {
00066 public:
00067
00068 Spectrum Sample_f(const Vector &o, Vector *wi, float u1, float u2,
00069 float u3, float *pdf, BxDFType flags = BSDF_ALL,
00070 BxDFType *sampledType = NULL) const;
00071 Spectrum Sample_f(const Vector &wo, Vector *wi,
00072 BxDFType flags = BSDF_ALL,
00073 BxDFType *sampledType = NULL) const;
00074 float Pdf(const Vector &wo,
00075 const Vector &wi,
00076 BxDFType flags = BSDF_ALL) const;
00077 BSDF(const DifferentialGeometry &dgs,
00078 const Normal &ngeom,
00079 float eta = 1.f);
00080 inline void Add(BxDF *bxdf);
00081 int NumComponents() const { return nBxDFs; }
00082 int NumComponents(BxDFType flags) const;
00083 bool HasShadingGeometry() const {
00084 return (nn.x != ng.x || nn.y != ng.y || nn.z != ng.z);
00085 }
00086 Vector WorldToLocal(const Vector &v) const {
00087 return Vector(Dot(v, sn), Dot(v, tn), Dot(v, nn));
00088 }
00089 Vector LocalToWorld(const Vector &v) const {
00090 return Vector(sn.x * v.x + tn.x * v.y + nn.x * v.z,
00091 sn.y * v.x + tn.y * v.y + nn.y * v.z,
00092 sn.z * v.x + tn.z * v.y + nn.z * v.z);
00093 }
00094 Spectrum f(const Vector &woW, const Vector &wiW,
00095 BxDFType flags = BSDF_ALL) const;
00096 Spectrum rho(BxDFType flags = BSDF_ALL) const;
00097 Spectrum rho(const Vector &wo,
00098 BxDFType flags = BSDF_ALL) const;
00099 static void *Alloc(u_int sz) { return arena.Alloc(sz); }
00100 static void FreeAll() { arena.FreeAll(); }
00101
00102 const DifferentialGeometry dgShading;
00103 const float eta;
00104 private:
00105
00106 ~BSDF() { }
00107 friend class NoSuchClass;
00108
00109 Normal nn, ng;
00110 Vector sn, tn;
00111 int nBxDFs;
00112 #define MAX_BxDFS 8
00113 BxDF * bxdfs[MAX_BxDFS];
00114 static MemoryArena arena;
00115 };
00116 #define BSDF_ALLOC(T) new (BSDF::Alloc(sizeof(T))) T
00117
00118 class COREDLL BxDF {
00119 public:
00120
00121 virtual ~BxDF() { }
00122 BxDF(BxDFType t) : type(t) { }
00123 bool MatchesFlags(BxDFType flags) const {
00124 return (type & flags) == type;
00125 }
00126 virtual Spectrum f(const Vector &wo,
00127 const Vector &wi) const = 0;
00128 virtual Spectrum Sample_f(const Vector &wo, Vector *wi,
00129 float u1, float u2, float *pdf) const;
00130 virtual Spectrum rho(const Vector &wo,
00131 int nSamples = 16,
00132 float *samples = NULL) const;
00133 virtual Spectrum rho(int nSamples = 16,
00134 float *samples = NULL) const;
00135 virtual float Pdf(const Vector &wi, const Vector &wo) const;
00136
00137 const BxDFType type;
00138 };
00139 class COREDLL BRDFToBTDF : public BxDF {
00140 public:
00141
00142 BRDFToBTDF(BxDF *b)
00143 : BxDF(BxDFType(b->type ^
00144 (BSDF_REFLECTION | BSDF_TRANSMISSION))) {
00145 brdf = b;
00146 }
00147 static Vector otherHemisphere(const Vector &w) {
00148 return Vector(w.x, w.y, -w.z);
00149 }
00150 Spectrum rho(const Vector &w, int nSamples,
00151 float *samples) const {
00152 return brdf->rho(otherHemisphere(w), nSamples, samples);
00153 }
00154 Spectrum rho(int nSamples, float *samples) const {
00155 return brdf->rho(nSamples, samples);
00156 }
00157 Spectrum f(const Vector &wo, const Vector &wi) const;
00158 Spectrum Sample_f(const Vector &wo, Vector *wi,
00159 float u1, float u2, float *pdf) const;
00160 float Pdf(const Vector &wo, const Vector &wi) const;
00161 private:
00162 BxDF *brdf;
00163 };
00164 class COREDLL Fresnel {
00165 public:
00166
00167 virtual ~Fresnel();
00168 virtual Spectrum Evaluate(float cosi) const = 0;
00169 };
00170 class COREDLL FresnelConductor : public Fresnel {
00171 public:
00172
00173 Spectrum Evaluate(float cosi) const;
00174 FresnelConductor(const Spectrum &e, const Spectrum &kk)
00175 : eta(e), k(kk) {
00176 }
00177 private:
00178
00179 Spectrum eta, k;
00180 };
00181 class COREDLL FresnelDielectric : public Fresnel {
00182 public:
00183
00184 Spectrum Evaluate(float cosi) const;
00185 FresnelDielectric(float ei, float et) {
00186 eta_i = ei;
00187 eta_t = et;
00188 }
00189 private:
00190
00191 float eta_i, eta_t;
00192 };
00193 class COREDLL FresnelNoOp : public Fresnel {
00194 public:
00195 Spectrum Evaluate(float) const { return Spectrum(1.); }
00196 };
00197 class COREDLL SpecularReflection : public BxDF {
00198 public:
00199
00200 SpecularReflection(const Spectrum &r, Fresnel *f)
00201 : BxDF(BxDFType(BSDF_REFLECTION | BSDF_SPECULAR)),
00202 R(r), fresnel(f) {
00203 }
00204 Spectrum f(const Vector &, const Vector &) const {
00205 return Spectrum(0.);
00206 }
00207 Spectrum Sample_f(const Vector &wo, Vector *wi,
00208 float u1, float u2, float *pdf) const;
00209 float Pdf(const Vector &wo, const Vector &wi) const {
00210 return 0.;
00211 }
00212 private:
00213
00214 Spectrum R;
00215 Fresnel *fresnel;
00216 };
00217 class COREDLL SpecularTransmission : public BxDF {
00218 public:
00219
00220 SpecularTransmission(const Spectrum &t, float ei, float et)
00221 : BxDF(BxDFType(BSDF_TRANSMISSION | BSDF_SPECULAR)),
00222 fresnel(ei, et) {
00223 T = t;
00224 etai = ei;
00225 etat = et;
00226 }
00227 Spectrum f(const Vector &, const Vector &) const {
00228 return Spectrum(0.);
00229 }
00230 Spectrum Sample_f(const Vector &wo, Vector *wi, float u1, float u2, float *pdf) const;
00231 float Pdf(const Vector &wo, const Vector &wi) const {
00232 return 0.;
00233 }
00234 private:
00235
00236 Spectrum T;
00237 float etai, etat;
00238 FresnelDielectric fresnel;
00239 };
00240 class COREDLL Lambertian : public BxDF {
00241 public:
00242
00243 Lambertian(const Spectrum &reflectance)
00244 : BxDF(BxDFType(BSDF_REFLECTION | BSDF_DIFFUSE)),
00245 R(reflectance), RoverPI(reflectance * INV_PI) {
00246 }
00247 Spectrum f(const Vector &wo, const Vector &wi) const;
00248 Spectrum rho(const Vector &, int, float *) const {
00249 return R;
00250 }
00251 Spectrum rho(int, float *) const { return R; }
00252 private:
00253
00254 Spectrum R, RoverPI;
00255 };
00256 class COREDLL OrenNayar : public BxDF {
00257 public:
00258
00259 Spectrum f(const Vector &wo, const Vector &wi) const;
00260 OrenNayar(const Spectrum &reflectance, float sig)
00261 : BxDF(BxDFType(BSDF_REFLECTION | BSDF_DIFFUSE)),
00262 R(reflectance) {
00263 float sigma = Radians(sig);
00264 float sigma2 = sigma*sigma;
00265 A = 1.f - (sigma2 / (2.f * (sigma2 + 0.33f)));
00266 B = 0.45f * sigma2 / (sigma2 + 0.09f);
00267 }
00268 private:
00269
00270 Spectrum R;
00271 float A, B;
00272 };
00273 class COREDLL MicrofacetDistribution {
00274 public:
00275
00276 virtual ~MicrofacetDistribution() { }
00277 virtual float D(const Vector &wh) const = 0;
00278 virtual void Sample_f(const Vector &wo, Vector *wi,
00279 float u1, float u2, float *pdf) const = 0;
00280 virtual float Pdf(const Vector &wo,
00281 const Vector &wi) const = 0;
00282 };
00283 class COREDLL Microfacet : public BxDF {
00284 public:
00285
00286 Microfacet(const Spectrum &reflectance, Fresnel *f,
00287 MicrofacetDistribution *d);
00288 Spectrum f(const Vector &wo, const Vector &wi) const;
00289 float G(const Vector &wo, const Vector &wi,
00290 const Vector &wh) const {
00291 float NdotWh = fabsf(CosTheta(wh));
00292 float NdotWo = fabsf(CosTheta(wo));
00293 float NdotWi = fabsf(CosTheta(wi));
00294 float WOdotWh = AbsDot(wo, wh);
00295 return min(1.f, min((2.f * NdotWh * NdotWo / WOdotWh),
00296 (2.f * NdotWh * NdotWi / WOdotWh)));
00297 }
00298 Spectrum Sample_f(const Vector &wo, Vector *wi,
00299 float u1, float u2, float *pdf) const;
00300 float Pdf(const Vector &wo, const Vector &wi) const;
00301 private:
00302
00303 Spectrum R;
00304 MicrofacetDistribution *distribution;
00305 Fresnel *fresnel;
00306 };
00307 class COREDLL Blinn : public MicrofacetDistribution {
00308 public:
00309 Blinn(float e) { if (e > 1000.f || isnan(e)) e = 1000.f; exponent = e; }
00310
00311 float D(const Vector &wh) const {
00312 float costhetah = fabsf(CosTheta(wh));
00313 return (exponent+2) *
00314 INV_TWOPI *
00315 powf(costhetah, exponent);
00316 }
00317 virtual void Sample_f(const Vector &wi, Vector *sampled_f, float u1, float u2, float *pdf) const;
00318 virtual float Pdf(const Vector &wi, const Vector &wo) const;
00319 private:
00320 float exponent;
00321 };
00322 class COREDLL Anisotropic : public MicrofacetDistribution {
00323 public:
00324
00325 Anisotropic(float x, float y) { ex = x; ey = y;
00326 if (ex > 1000.f || isnan(ex)) ex = 1000.f;
00327 if (ey > 1000.f || isnan(ey)) ey = 1000.f;
00328 }
00329 float D(const Vector &wh) const {
00330 float costhetah = fabsf(CosTheta(wh));
00331 float e = (ex * wh.x * wh.x + ey * wh.y * wh.y) /
00332 (1.f - costhetah * costhetah);
00333 return sqrtf((ex+1)*(ey+1)) * INV_TWOPI * powf(costhetah, e);
00334 }
00335 void Sample_f(const Vector &wo, Vector *wi, float u1, float u2, float *pdf) const;
00336 float Pdf(const Vector &wo, const Vector &wi) const;
00337 void sampleFirstQuadrant(float u1, float u2, float *phi, float *costheta) const;
00338 private:
00339 float ex, ey;
00340 };
00341 class COREDLL Lafortune : public BxDF {
00342 public:
00343
00344 Lafortune(const Spectrum &r, u_int nl,
00345 const Spectrum *x, const Spectrum *y, const Spectrum *z,
00346 const Spectrum *e, BxDFType t);
00347 Spectrum f(const Vector &wo, const Vector &wi) const;
00348 private:
00349
00350 Spectrum R;
00351 u_int nLobes;
00352 const Spectrum *x, *y, *z, *exponent;
00353 };
00354 class COREDLL FresnelBlend : public BxDF {
00355 public:
00356
00357 FresnelBlend(const Spectrum &Rd,
00358 const Spectrum &Rs,
00359 MicrofacetDistribution *dist);
00360 Spectrum f(const Vector &wo, const Vector &wi) const;
00361 Spectrum SchlickFresnel(float costheta) const {
00362 return
00363 Rs + powf(1 - costheta, 5.f) * (Spectrum(1.) - Rs);
00364 }
00365 Spectrum Sample_f(const Vector &wi, Vector *sampled_f, float u1, float u2, float *pdf) const;
00366 float Pdf(const Vector &wi, const Vector &wo) const;
00367 private:
00368
00369 Spectrum Rd, Rs;
00370 MicrofacetDistribution *distribution;
00371 };
00372
00373 inline void BSDF::Add(BxDF *b) {
00374 Assert(nBxDFs < MAX_BxDFS);
00375 bxdfs[nBxDFs++] = b;
00376 }
00377 inline int BSDF::NumComponents(BxDFType flags) const {
00378 int num = 0;
00379 for (int i = 0; i < nBxDFs; ++i)
00380 if (bxdfs[i]->MatchesFlags(flags)) ++num;
00381 return num;
00382 }
00383 #endif // PBRT_REFLECTION_H