00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifndef LUX_BXDF_H
00024 #define LUX_BXDF_H
00025
00026 #include "lux.h"
00027 #include "geometry.h"
00028 #include "shape.h"
00029 #include "spectrum.h"
00030 #include "memory.h"
00031
00032 namespace lux
00033 {
00034
00035
00036 inline float CosTheta(const Vector &w) { return w.z; }
00037 inline float SinTheta(const Vector &w) {
00038 return sqrtf(max(0.f, 1.f - w.z*w.z));
00039 }
00040 inline float SinTheta2(const Vector &w) {
00041 return 1.f - CosTheta(w)*CosTheta(w);
00042 }
00043 inline float CosPhi(const Vector &w) {
00044 return w.x / SinTheta(w);
00045 }
00046 inline float SinPhi(const Vector &w) {
00047 return w.y / SinTheta(w);
00048 }
00049 inline bool SameHemisphere(const Vector &w,
00050 const Vector &wp) {
00051 return w.z * wp.z > 0.f;
00052 }
00053
00054 enum BxDFType {
00055 BSDF_REFLECTION = 1<<0,
00056 BSDF_TRANSMISSION = 1<<1,
00057 BSDF_DIFFUSE = 1<<2,
00058 BSDF_GLOSSY = 1<<3,
00059 BSDF_SPECULAR = 1<<4,
00060 BSDF_ALL_TYPES = BSDF_DIFFUSE |
00061 BSDF_GLOSSY |
00062 BSDF_SPECULAR,
00063 BSDF_ALL_REFLECTION = BSDF_REFLECTION |
00064 BSDF_ALL_TYPES,
00065 BSDF_ALL_TRANSMISSION = BSDF_TRANSMISSION |
00066 BSDF_ALL_TYPES,
00067 BSDF_ALL = BSDF_ALL_REFLECTION |
00068 BSDF_ALL_TRANSMISSION
00069 };
00070 class BSDF {
00071 public:
00072
00073 SWCSpectrum Sample_f(const Vector &o, Vector *wi, float u1, float u2,
00074 float u3, float *pdf, BxDFType flags = BSDF_ALL,
00075 BxDFType *sampledType = NULL, float *pdfBack = NULL) const;
00076 SWCSpectrum Sample_f(const Vector &wo, Vector *wi,
00077 BxDFType flags = BSDF_ALL,
00078 BxDFType *sampledType = NULL) const;
00079 float Pdf(const Vector &wo,
00080 const Vector &wi,
00081 BxDFType flags = BSDF_ALL) const;
00082 BSDF(const DifferentialGeometry &dgs,
00083 const Normal &ngeom,
00084 float eta = 1.f);
00085 inline void Add(BxDF *bxdf);
00086 int NumComponents() const { return nBxDFs; }
00087 int NumComponents(BxDFType flags) const;
00088 bool HasShadingGeometry() const {
00089 return (nn.x != ng.x || nn.y != ng.y || nn.z != ng.z);
00090 }
00091 Vector WorldToLocal(const Vector &v) const {
00092 return Vector(Dot(v, sn), Dot(v, tn), Dot(v, nn));
00093 }
00094 Vector LocalToWorld(const Vector &v) const {
00095 return Vector(sn.x * v.x + tn.x * v.y + nn.x * v.z,
00096 sn.y * v.x + tn.y * v.y + nn.y * v.z,
00097 sn.z * v.x + tn.z * v.y + nn.z * v.z);
00098 }
00099 SWCSpectrum f(const Vector &woW, const Vector &wiW,
00100 BxDFType flags = BSDF_ALL) const;
00101 SWCSpectrum rho(BxDFType flags = BSDF_ALL) const;
00102 SWCSpectrum rho(const Vector &wo,
00103 BxDFType flags = BSDF_ALL) const;
00104 static void *Alloc( u_int sz) { return arena->Alloc(sz); }
00105 static void FreeAll() { arena->FreeAll(); }
00106
00107 const DifferentialGeometry dgShading;
00108 const float eta;
00109
00110 friend class RenderThread;
00111 friend class Scene;
00112
00113 private:
00114
00115 ~BSDF() { }
00116 friend class NoSuchClass;
00117
00118 Normal nn, ng;
00119 Vector sn, tn;
00120 int nBxDFs;
00121 #define MAX_BxDFS 8
00122 BxDF * bxdfs[MAX_BxDFS];
00123 static boost::thread_specific_ptr<MemoryArena> arena;
00124
00125 };
00126 #define BSDF_ALLOC(T) new (BSDF::Alloc(sizeof(T))) T
00127
00128 class BxDF {
00129 public:
00130
00131 virtual ~BxDF() { }
00132 BxDF(BxDFType t) : type(t) { }
00133 bool MatchesFlags(BxDFType flags) const {
00134 return (type & flags) == type;
00135 }
00136 virtual SWCSpectrum f(const Vector &wo,
00137 const Vector &wi) const = 0;
00138 virtual SWCSpectrum Sample_f(const Vector &wo, Vector *wi,
00139 float u1, float u2, float *pdf, float *pdfBack = NULL) const;
00140 virtual SWCSpectrum rho(const Vector &wo,
00141 int nSamples = 16,
00142 float *samples = NULL) const;
00143 virtual SWCSpectrum rho(int nSamples = 16,
00144 float *samples = NULL) const;
00145 virtual float Pdf(const Vector &wi, const Vector &wo) const;
00146
00147 const BxDFType type;
00148 };
00149 class BRDFToBTDF : public BxDF {
00150 public:
00151
00152 BRDFToBTDF(BxDF *b)
00153 : BxDF(BxDFType(b->type ^
00154 (BSDF_REFLECTION | BSDF_TRANSMISSION))) {
00155 brdf = b;
00156 }
00157 static Vector otherHemisphere(const Vector &w) {
00158 return Vector(w.x, w.y, -w.z);
00159 }
00160 SWCSpectrum rho(const Vector &w, int nSamples,
00161 float *samples) const {
00162 return brdf->rho(otherHemisphere(w), nSamples, samples);
00163 }
00164 SWCSpectrum rho(int nSamples, float *samples) const {
00165 return brdf->rho(nSamples, samples);
00166 }
00167 SWCSpectrum f(const Vector &wo, const Vector &wi) const;
00168 SWCSpectrum Sample_f(const Vector &wo, Vector *wi,
00169 float u1, float u2, float *pdf, float *pdfBack = NULL) const;
00170 float Pdf(const Vector &wo, const Vector &wi) const;
00171 private:
00172 BxDF *brdf;
00173 };
00174
00175
00176 inline void BSDF::Add(BxDF *b) {
00177 BOOST_ASSERT(nBxDFs < MAX_BxDFS);
00178 bxdfs[nBxDFs++] = b;
00179 }
00180 inline int BSDF::NumComponents(BxDFType flags) const {
00181 int num = 0;
00182 for (int i = 0; i < nBxDFs; ++i)
00183 if (bxdfs[i]->MatchesFlags(flags)) ++num;
00184 return num;
00185 }
00186
00187 }
00188
00189 #endif // LUX_BXDF_H
00190