BxDF 类
// BxDF Declarations
class BxDF {
public:
// BxDF Interface
virtual ~BxDF() { }
BxDF(BxDFType t) : type(t) { }
bool MatchesFlags(BxDFType flags) const {
return (type & flags) == type;
}
virtual Spectrum f(const Vector &wo, const Vector &wi) const = 0;
virtual Spectrum Sample_f(const Vector &wo, Vector *wi,
float u1, float u2, float *pdf) const;
virtual Spectrum rho(const Vector &wo, int nSamples,
const float *samples) const;
virtual Spectrum rho(int nSamples, const float *samples1,
const float *samples2) const;
virtual float Pdf(const Vector &wi, const Vector &wo) const;
// BxDF Public Data
const BxDFType type;
};
类的作用:
(BxDF 就是 BRDF 和 BTDF 的基类,就是为了保存一些 公用的 东西)
We will first define the interface for the individual BRDF and BTDF functions. BRDFs
and BTDFs share a common base class, BxDF. Because both have the exact same interface,
sharing the same base class reduces repeated code and allows some parts of the system to
work with BxDFs generically without distinguishing between BRDFs and BTDFs.
1. 构造函数
enum BxDFType {
BSDF_REFLECTION = 1 << 0,
BSDF_TRANSMISSION = 1 << 1,
BSDF_DIFFUSE = 1 << 2,
BSDF_GLOSSY = 1 << 3,
BSDF_SPECULAR = 1 << 4,
BSDF_ALL_TYPES = BSDF_DIFFUSE |
BSDF_GLOSSY |
BSDF_SPECULAR,
BSDF_ALL_REFLECTION = BSDF_REFLECTION |
BSDF_ALL_TYPES,
BSDF_ALL_TRANSMISSION = BSDF_TRANSMISSION |
BSDF_ALL_TYPES,
BSDF_ALL = BSDF_ALL_REFLECTION |
BSDF_ALL_TRANSMISSION
};
BxDF(BxDFType t) : type(t) { }
作用:
(构造函数需要传入 BxDFType 来区分到底是 BSDF还是BTDF)
Although we are hiding
the implementation details of the BxDF behind a common interface for reflective and
transmissive materials, some of the light transport algorithms in Chapter 15 will need
to distinguish between these two types. Therefore, all BxDFs have a BxDF::type member
that holds flags from BxDFType. For each BxDF, the flags should have exactly one of BSDF_
REFLECTION or BSDF_TRANSMISSION set, and exactly one of the diffuse, glossy, and specular
flags. Note that there is no retro-reflective flag; retro-reflection is treated as glossy reflection
in this categorization.
2. virtual Spectrum f(const Vector &wo, const Vector &wi) const = 0;
作用:
(传入 wo, wi,返回一个值,这个值用Spectrum来表示,
个人理解就是,这里的RGB(Spectrum) 其实代表的就是材质表面对光颜色的R,G,B的吸收程度,例如 返回的 RGB(Spectrum) = (1, 0.5, 0)的话,表示的就是,这个表面材质对 光线颜色的 R 不进行吸收,对G吸收一半, B全部吸收,光线到达这个表面时,因为R不吸收,所以R全部反射,因为G吸收一半,所以G就反射了一半,因为B全部吸收,所以B一点都不反射)
The key method that BxDFs provide is the BxDF::f() method. It returns the value of the
distribution function for the given pair of directions. This interface implicitly assumes
that light in different wavelengths is decoupled—energy at one wavelength will not be
reflected at a different wavelength.
3. virtual Spectrum Sample_f(const Vector &wo, Vector *wi,
float u1, float u2, float *pdf) const;
作用:
作用:(有 bsdf->f(), 为什么会有 bsdf->Sample_f(), 因为不是所有的 bsdf 都可以利用 wi, wo来获得一个反射值,像一些镜面反射只会反射某一个方向的,类似这样的镜面反射的BSDF用 delta distributions 来描述是最好的,所以,PBRT就专门用 Sample_f 来特殊处理这些 delta distributions 的 BSDF,Sample_f() 与f() 不同的还有的就是,Sample_f() 会计算wi)
Not all BxDFs can be evaluated with the f() method. For example, perfectly specular
objects like a mirror, glass, or water only scatter light from a single incident direction
into a single outgoing direction. Such BxDFs are best described with delta distributions
that are zero except for the single direction where light is scattered.
These BxDFs need special handling in pbrt, so we will also provide the meuothod BxDF::
Sample_f(). This method is used both for handling scattering that is described by delta
distributions as well as for randomly sampling directions from BxDFs that scatter light
along multiple directions;
BxDF::Sample_f() computes the direction of
incident light ωi given an outgoing direction ωo and returns the value of the BxDF for the
given pair of directions. For delta distributions, it is necessary for the BxDF to choose
the incident light direction in this way, since the caller has no chance of generating
the appropriate ωi direction.
This method returns the sampled direction in *wi and returns the value of p(ωi) in
*pdf. The value of the BSDF for the chosen direction is returned with a Spectrum return
value. The PDF value returned should be measured with respect to solid angle on the
hemisphere, and both the outgoing direction ωo and the sampled incident direction
ωi should be in the standard reflection coordinate system.
The default implementation of this method samples the unit hemisphere with a cosineweighted
distribution.
4. virtual Spectrum rho(const Vector &wo, int nSamples,
const float *samples) const;
作用:
(本来的fr 是 关于 wo,wi 的函数,但是这里的 ρhd(wo) 只是 关于wo的,对于fr 返回的值,意义就是,入射的wi 贡献了多少 光给wo,但是这里的 phd 的返回值的意思就是,对于所有的入射wi,一共贡献了多少光给wo这个方向上)
It can be useful to take the aggregate behavior of the 4D BRDF or BTDF, defined as a
function over pairs of directions, and reduce it to a 2D function over a single direction,
or even to a constant value that describes its overall scattering behavior.
The hemispherical-directional reflectance is a 2D function that gives the total reflection in
a given direction due to constant illumination over the hemisphere, or, equivalently, total
reflection over the hemisphere due to light from a given direction. It is defined as
The BxDF::rho() method computes the reflectance function ρhd. Some BxDFs can compute
this value in closed form, although most use Monte Carlo integration to compute
an approximation to it. For those BxDFs, the nSamples and samples parameters are used by
the implementation of the Monte Carlo algorithm; they are explained in Section 14.5.5.
5. virtual Spectrum rho(int nSamples, const float *samples1,
const float *samples2) const;
作用:
(ρhh 返回的是一个常量,描述的就是,一个表面总有反射了百分之多少的光)
The hemispherical-hemispherical reflectance of a surface, denoted by ρhh, is a constant
spectral value that gives the fraction of incident light reflected by a surface when the
incident light is the same from all directions. It is
The BxDF::rho() method computes ρhh if no direction ωo is provided. The remaining
parameters are again used when computing a Monte Carlo estimate, if needed.
BRDFToBTDF 类
class BRDFToBTDF : public BxDF {
public:
// BRDFToBTDF Public Methods
BRDFToBTDF(BxDF *b)
: BxDF(BxDFType(b->type ^ (BSDF_REFLECTION | BSDF_TRANSMISSION))) {
brdf = b;
}
static Vector otherHemisphere(const Vector &w) {
return Vector(w.x, w.y, -w.z);
}
Spectrum f(const Vector &wo, const Vector &wi) const;
Spectrum Sample_f(const Vector &wo, Vector *wi, float u1, float u2,
float *pdf) const;
Spectrum rho(const Vector &w, int nSamples, const float *samples) const {
return brdf->rho(otherHemisphere(w), nSamples, samples);
}
Spectrum rho(int nSamples, const float *samples1, const float *samples2) const {
return brdf->rho(nSamples, samples1, samples2);
}
float Pdf(const Vector &wo, const Vector &wi) const;
private:
BxDF *brdf;
};
类的作用:
(这个类 主要负责把 一个BRDF 转为一个 BTDF)
It’s handy to define an adapter class that makes it easy to reuse an already-defined BRDF
class as a BTDF, especially for phenomenological models that may be equally plausible
models of transmission.The BRDFToBTDF class takes a BRDF’s pointer in the constructor
and uses it to implement a BTDF. In particular, doing so involves forwarding method
calls on to the BRDF and switching the ωi direction to lie in the other hemisphere.
1. 构造函数
BRDFToBTDF(BxDF *b)
: BxDF(BxDFType(b->type ^ (BSDF_REFLECTION | BSDF_TRANSMISSION))) {
brdf = b; }
作用:
The constructor for the adapter class is simple. It switches the reflection and transmission
flags of the BxDF::type member.
2.
static Vector otherHemisphere(const Vector &w) {
return Vector(w.x, w.y, -w.z);
}
作用:
(直接 把 转换 wi 到相反的半球上)
The adapter needs to convert an incoming vector to the corresponding vector in the
opposite hemisphere. Fortunately, this is a simple calculation in the shading coordinate
system, just requiring negation of the vector’s z coordinate.
3. Spectrum BRDFToBTDF::f(const Vector &wo, const Vector &wi) const {
return brdf->f(wo, otherHemisphere(wi));
}
作用:
The BRDFToBTDF::otherHemisphere() method is used to reflect a ray into the other hemisphere
before calling the BRDF’s BxDF::f(), BxDF::rho(), and BxDF::Sample_f() methods.
We’ll only include f() here since the others are analogous.
ScaledBxDF 类
class ScaledBxDF : public BxDF {
public:
// ScaledBxDF Public Methods
ScaledBxDF(BxDF *b, const Spectrum &sc)
: BxDF(BxDFType(b->type)), bxdf(b), s(sc) {
}
Spectrum rho(const Vector &w, int nSamples, const float *samples) const {
return s * bxdf->rho(w, nSamples, samples);
}
Spectrum rho(int nSamples, const float *samples1,
const float *samples2) const {
return s * bxdf->rho(nSamples, samples1, samples2);
}
Spectrum f(const Vector &wo, const Vector &wi) const;
Spectrum Sample_f(const Vector &wo, Vector *wi,
float u1, float u2, float *pdf) const;
private:
BxDF *bxdf;
Spectrum s;
};
类的作用:
(缩放 一个BxDF用的)
It is also useful to take a given BxDF and scale its contribution with a Spectrum value. The
ScaledBxDF wrapper holds a BxDF * and a Spectrum and implements this functionality.
This class is used by the MixMaterial (defined in Section 9.2.3), which creates BSDFs based
on a weighted combination of two other materials.
1. 直接看代码就知道
ScaledBxDF(BxDF *b, const Spectrum &sc)
: BxDF(BxDFType(b->type)), bxdf(b), s(sc) {
}
Spectrum ScaledBxDF::f(const Vector &wo, const Vector &wi) const {
return s * bxdf->f(wo, wi);
}