Nori  23
diffuse.cpp
1 /*
2  This file is part of Nori, a simple educational ray tracer
3 
4  Copyright (c) 2015 by Wenzel Jakob, Romain Prévost
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 #include <nori/texture.h>
23 
24 NORI_NAMESPACE_BEGIN
25 
29 class Diffuse : public BSDF {
30 public:
31  Diffuse(const PropertyList &propList) : m_albedo(nullptr) {
32  if(propList.has("albedo")) {
33  PropertyList l;
34  l.setColor("value", propList.getColor("albedo"));
35  m_albedo = static_cast<Texture<Color3f> *>(NoriObjectFactory::createInstance("constant_color", l));
36  }
37  }
38  virtual ~Diffuse() {
39  delete m_albedo;
40  }
41 
43  virtual void addChild(NoriObject *obj) override {
44  switch (obj->getClassType()) {
45  case ETexture:
46  if(obj->getIdName() == "albedo") {
47  if (m_albedo)
48  throw NoriException("There is already an albedo defined!");
49  m_albedo = static_cast<Texture<Color3f> *>(obj);
50  }
51  else {
52  throw NoriException("The name of this texture does not match any field!");
53  }
54  break;
55 
56  default:
57  throw NoriException("Diffuse::addChild(<%s>) is not supported!",
58  classTypeName(obj->getClassType()));
59  }
60  }
61 
62  virtual void activate() override {
63  if(!m_albedo) {
64  PropertyList l;
65  l.setColor("value", Color3f(0.5f));
66  m_albedo = static_cast<Texture<Color3f> *>(NoriObjectFactory::createInstance("constant_color", l));
67  m_albedo->activate();
68  }
69  }
70 
72  virtual Color3f eval(const BSDFQueryRecord &bRec) const override {
73  /* This is a smooth BRDF -- return zero if the measure
74  is wrong, or when queried for illumination on the backside */
75  if (bRec.measure != ESolidAngle
76  || Frame::cosTheta(bRec.wi) <= 0
77  || Frame::cosTheta(bRec.wo) <= 0)
78  return Color3f(0.0f);
79 
80  /* The BRDF is simply the albedo / pi */
81  return m_albedo->eval(bRec.uv) * INV_PI;
82  }
83 
85  virtual float pdf(const BSDFQueryRecord &bRec) const override {
86  /* This is a smooth BRDF -- return zero if the measure
87  is wrong, or when queried for illumination on the backside */
88  if (bRec.measure != ESolidAngle
89  || Frame::cosTheta(bRec.wi) <= 0
90  || Frame::cosTheta(bRec.wo) <= 0)
91  return 0.0f;
92 
93 
94  /* Importance sampling density wrt. solid angles:
95  cos(theta) / pi.
96 
97  Note that the directions in 'bRec' are in local coordinates,
98  so Frame::cosTheta() actually just returns the 'z' component.
99  */
100  return INV_PI * Frame::cosTheta(bRec.wo);
101  }
102 
104  virtual Color3f sample(BSDFQueryRecord &bRec, const Point2f &sample) const override {
105  if (Frame::cosTheta(bRec.wi) <= 0)
106  return Color3f(0.0f);
107 
108  bRec.measure = ESolidAngle;
109 
110  /* Warp a uniformly distributed sample on [0,1]^2
111  to a direction on a cosine-weighted hemisphere */
113 
114  /* Relative index of refraction: no change */
115  bRec.eta = 1.0f;
116 
117  /* eval() / pdf() * cos(theta) = albedo. There
118  is no need to call these functions. */
119  return m_albedo->eval(bRec.uv);
120  }
121 
122  bool isDiffuse() const {
123  return true;
124  }
125 
127  virtual std::string toString() const override {
128  return tfm::format(
129  "Diffuse[\n"
130  " albedo = %s\n"
131  "]",
132  m_albedo ? indent(m_albedo->toString()) : std::string("null")
133  );
134  }
135 
136  virtual EClassType getClassType() const override { return EBSDF; }
137 
138 private:
139  Texture<Color3f> * m_albedo;
140 };
141 
142 NORI_REGISTER_CLASS(Diffuse, "diffuse");
143 NORI_NAMESPACE_END
Superclass of all bidirectional scattering distribution functions.
Definition: bsdf.h:63
Diffuse / Lambertian BRDF model.
Definition: diffuse.cpp:29
virtual EClassType getClassType() const override
Return the type of object (i.e. Mesh/BSDF/etc.) provided by this instance.
Definition: diffuse.cpp:136
virtual Color3f eval(const BSDFQueryRecord &bRec) const override
Evaluate the BRDF model.
Definition: diffuse.cpp:72
virtual std::string toString() const override
Return a human-readable summary.
Definition: diffuse.cpp:127
virtual void activate() override
Perform some action associated with the object.
Definition: diffuse.cpp:62
virtual float pdf(const BSDFQueryRecord &bRec) const override
Compute the density of sample() wrt. solid angles.
Definition: diffuse.cpp:85
bool isDiffuse() const
Return whether or not this BRDF is diffuse. This is primarily used by photon mapping to decide whethe...
Definition: diffuse.cpp:122
virtual Color3f sample(BSDFQueryRecord &bRec, const Point2f &sample) const override
Draw a a sample from the BRDF model.
Definition: diffuse.cpp:104
virtual void addChild(NoriObject *obj) override
Add texture for the albedo.
Definition: diffuse.cpp:43
Simple exception class, which stores a human-readable error description.
Definition: common.h:148
static NoriObject * createInstance(const std::string &name, const PropertyList &propList)
Construct an instance from the class of the given name.
Definition: object.h:158
Base class of all objects.
Definition: object.h:32
virtual void activate()
Perform some action associated with the object.
Definition: object.h:107
virtual std::string toString() const =0
Return a brief string summary of the instance (for debugging purposes)
static std::string classTypeName(EClassType type)
Turn a class type into a human-readable string.
Definition: object.h:51
virtual EClassType getClassType() const =0
Return the type of object (i.e. Mesh/BSDF/etc.) provided by this instance.
This is an associative container used to supply the constructors of NoriObject subclasses with parame...
Definition: proplist.h:32
void setColor(const std::string &name, const Color3f &value)
Set a color property.
Color3f getColor(const std::string &name) const
Get a color property, and throw an exception if it does not exist.
static Vector3f squareToCosineHemisphere(const Point2f &sample)
Uniformly sample a vector on the unit hemisphere around the pole (0,0,1) with respect to projected so...
Definition: warp.cpp:81
Convenience data structure used to pass multiple parameters to the evaluation and sampling routines i...
Definition: bsdf.h:30
Vector3f wo
Outgoing direction (in the local frame)
Definition: bsdf.h:35
Vector3f wi
Incident direction (in the local frame)
Definition: bsdf.h:32
EMeasure measure
Measure associated with the sample.
Definition: bsdf.h:41
Point2f uv
Definition: bsdf.h:55
float eta
Relative refractive index in the sampled direction.
Definition: bsdf.h:38
Represents a linear RGB color value.
Definition: color.h:29
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