Nori  23
microfacet.cpp
1 /*
2  This file is part of Nori, a simple educational ray tracer
3 
4  Copyright (c) 2015 by Wenzel Jakob
5 
6  Nori is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License Version 3
8  as published by the Free Software Foundation.
9 
10  Nori is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18 
19 #include <nori/bsdf.h>
20 #include <nori/frame.h>
21 #include <nori/warp.h>
22 
23 NORI_NAMESPACE_BEGIN
24 
25 class Microfacet : public BSDF {
26 public:
27  Microfacet(const PropertyList &propList) {
28  /* RMS surface roughness */
29  m_alpha = propList.getFloat("alpha", 0.1f);
30 
31  /* Interior IOR (default: BK7 borosilicate optical glass) */
32  m_intIOR = propList.getFloat("intIOR", 1.5046f);
33 
34  /* Exterior IOR (default: air) */
35  m_extIOR = propList.getFloat("extIOR", 1.000277f);
36 
37  /* Albedo of the diffuse base material (a.k.a "kd") */
38  m_kd = propList.getColor("kd", Color3f(0.5f));
39 
40  /* To ensure energy conservation, we must scale the
41  specular component by 1-kd.
42 
43  While that is not a particularly realistic model of what
44  happens in reality, this will greatly simplify the
45  implementation. Please see the course staff if you're
46  interested in implementing a more realistic version
47  of this BRDF. */
48  m_ks = 1 - m_kd.maxCoeff();
49  }
50 
52  float evalBeckmann(const Normal3f &m) const {
53  float temp = Frame::tanTheta(m) / m_alpha,
54  ct = Frame::cosTheta(m), ct2 = ct*ct;
55 
56  return std::exp(-temp*temp)
57  / (M_PI * m_alpha * m_alpha * ct2 * ct2);
58  }
59 
61  float smithBeckmannG1(const Vector3f &v, const Normal3f &m) const {
62  float tanTheta = Frame::tanTheta(v);
63 
64  /* Perpendicular incidence -- no shadowing/masking */
65  if (tanTheta == 0.0f)
66  return 1.0f;
67 
68  /* Can't see the back side from the front and vice versa */
69  if (m.dot(v) * Frame::cosTheta(v) <= 0)
70  return 0.0f;
71 
72  float a = 1.0f / (m_alpha * tanTheta);
73  if (a >= 1.6f)
74  return 1.0f;
75  float a2 = a * a;
76 
77  /* Use a fast and accurate (<0.35% rel. error) rational
78  approximation to the shadowing-masking function */
79  return (3.535f * a + 2.181f * a2)
80  / (1.0f + 2.276f * a + 2.577f * a2);
81  }
82 
84  virtual Color3f eval(const BSDFQueryRecord &bRec) const override {
85  throw NoriException("MicrofacetBRDF::eval(): not implemented!");
86  }
87 
89  virtual float pdf(const BSDFQueryRecord &bRec) const override {
90  throw NoriException("MicrofacetBRDF::pdf(): not implemented!");
91  }
92 
94  virtual Color3f sample(BSDFQueryRecord &bRec, const Point2f &_sample) const override {
95  throw NoriException("MicrofacetBRDF::sample(): not implemented!");
96  }
97 
98  virtual std::string toString() const override {
99  return tfm::format(
100  "Microfacet[\n"
101  " alpha = %f,\n"
102  " intIOR = %f,\n"
103  " extIOR = %f,\n"
104  " kd = %s,\n"
105  " ks = %f\n"
106  "]",
107  m_alpha,
108  m_intIOR,
109  m_extIOR,
110  m_kd.toString(),
111  m_ks
112  );
113  }
114 private:
115  float m_alpha;
116  float m_intIOR, m_extIOR;
117  float m_ks;
118  Color3f m_kd;
119 };
120 
121 NORI_REGISTER_CLASS(Microfacet, "microfacet");
122 NORI_NAMESPACE_END
Superclass of all bidirectional scattering distribution functions.
Definition: bsdf.h:63
virtual Color3f eval(const BSDFQueryRecord &bRec) const override
Evaluate the BRDF for the given pair of directions.
Definition: microfacet.cpp:84
virtual std::string toString() const override
Return a brief string summary of the instance (for debugging purposes)
Definition: microfacet.cpp:98
float evalBeckmann(const Normal3f &m) const
Evaluate the microfacet normal distribution D.
Definition: microfacet.cpp:52
float smithBeckmannG1(const Vector3f &v, const Normal3f &m) const
Evaluate Smith's shadowing-masking function G1.
Definition: microfacet.cpp:61
virtual float pdf(const BSDFQueryRecord &bRec) const override
Evaluate the sampling density of sample() wrt. solid angles.
Definition: microfacet.cpp:89
virtual Color3f sample(BSDFQueryRecord &bRec, const Point2f &_sample) const override
Sample the BRDF.
Definition: microfacet.cpp:94
Simple exception class, which stores a human-readable error description.
Definition: common.h:148
This is an associative container used to supply the constructors of NoriObject subclasses with parame...
Definition: proplist.h:32
float getFloat(const std::string &name) const
Get a float property, and throw an exception if it does not exist.
Color3f getColor(const std::string &name) const
Get a color property, and throw an exception if it does not exist.
Convenience data structure used to pass multiple parameters to the evaluation and sampling routines i...
Definition: bsdf.h:30
Represents a linear RGB color value.
Definition: color.h:29
std::string toString() const
Return a human-readable string summary.
Definition: color.h:79
static float tanTheta(const Vector3f &v)
Assuming that the given direction is in the local coordinate system, return the tangent of the angle ...
Definition: frame.h:82
static float cosTheta(const Vector3f &v)
Assuming that the given direction is in the local coordinate system, return the cosine of the angle b...
Definition: frame.h:67
3-dimensional surface normal representation
Definition: vector.h:133