Loading...
Searching...
No Matches
lambertian.h
Go to the documentation of this file.
1#ifndef _BBM_LAMBERTIAN_H_
2#define _BBM_LAMBERTIAN_H_
3
4#include "bbm/bsdfmodel.h"
5
6/**********************************************************************/
7/*! \file lambertian.h
8 \brief The classic diffuse Lambertian BSDF model.
9***********************************************************************/
10
11namespace bbm {
12
13 /**********************************************************************/
14 /*! \brief The classic diffuse Lambertian BSDF model.
15
16 \tparam CONF = type configuration to use.
17 \tparam NAME = name of the BSDF model.
18
19
20 Implements: concepts::bsdfmodel
21 ***********************************************************************/
22 template<typename CONF, string_literal NAME="Lambertian"> requires concepts::config<CONF>
24 {
25 public:
27 static constexpr string_literal name = NAME;
29
30
31 /********************************************************************/
32 /*! \brief Evaluate the BSDF for a given in and out direction
33
34 \param in = incident direction
35 \param out = outgoing direction
36 \param component = which reflectance component to eval
37 \param unit = unit of computation (ignored)
38 \param mask = masking of lanes (e.g., for Packet eval)
39 \returns Evaluation of the BSDF per spectrum.
40
41 Note: Evaluates the classic diffuse BSDF, i.e.. a constant independent
42 of in and out directions above the horizon. No foreshortning is
43 included.
44 *********************************************************************/
45 Spectrum eval(const Vec3d& in, const Vec3d& out, BsdfFlag component=bsdf_flag::All, unit_t /*unit*/=unit_t::Radiance, Mask mask=true) const
46 {
47 // diffuse?
48 mask &= is_set(component, bsdf_flag::Diffuse);
49
50 // above surface?
51 mask &= (vec::z(in) >= 0) && (vec::z(out) >= 0);
52
53 // Quick exit if mask is all negative
54 if(bbm::none(mask)) return Spectrum(0);
55
56 // compute reflectance
57 Spectrum result = albedo * Constants::InvPi();
58 return bbm::select(mask, result, 0);
59 }
60
61
62
63 /********************************************************************/
64 /*! \brief Sample the diffuse BSDF given a direction and two random variables.
65
66 \param out = outgoing direction
67 \param xi = two random variables stored in a Vec2d
68 \param component = which reflectance component to sample
69 \param unit = unit of computation (ignored)
70 \param mask = masking of lanes.
71 \returns A bsdfSample containing the sampled direction and the corresponding pdf.
72
73 Follows the convention of Veach; samples incoming directions
74 proportional to the cosine weighted solid angle.
75 *********************************************************************/
76 BsdfSample sample(const Vec3d& out, const Vec2d& xi, BsdfFlag component=bsdf_flag::All, unit_t unit=unit_t::Radiance, Mask mask=true) const
77 {
78 BsdfSample sample = {0,0,bsdf_flag::None};
79
80 // diffuse?
81 mask &= is_set(component, bsdf_flag::Diffuse);
82
83 // check for valid xi
84 mask &= (xi[0] >= 0) && (xi[1] >= 0) && (xi[0] <= 1) && (xi[1] <= 1);
85
86 // Quick exit if mask all negative
87 if(bbm::none(mask)) return sample;
88
89 // sample proportional to cosine weighted solid angle
90 Vec2d csp = bbm::cossin(xi[0] * Constants::Pi(2));
91 Value sinTheta = bbm::safe_sqrt(1.0 - xi[1]);
92
93 sample.direction = vec::expand( csp*sinTheta, bbm::safe_sqrt(xi[1]));
94
95 // compute pdf
96 sample.pdf = pdf(sample.direction, out, component, unit, mask);
97
98 // set component
99 sample.flag = bbm::select(mask, BsdfFlag(bsdf_flag::Diffuse), BsdfFlag(bsdf_flag::None));
100
101 // Done.
102 return sample;
103 }
104
105 /********************************************************************/
106 /*! \brief Compute the pdf given an in and out direction
107
108 \param in = the incoming (sampled) direction
109 \param out = the outgoing (given) direction
110 \param component = which reflectance component was sampled
111 \param unit = unit of computation (ignored)
112 \param mask = masking of lanes
113 \returns the PDF that the incoming direction would be sampled given the outgoing direction.
114 ***********************************************************************/
115 Value pdf(const Vec3d& in, const Vec3d& out, BsdfFlag component=bsdf_flag::All, unit_t /*unit*/=unit_t::Radiance, Mask mask=true) const
116 {
117 // diffuse?
118 mask &= is_set(component, bsdf_flag::Diffuse);
119
120 // above surface?
121 mask &= (vec::z(in) >= 0) && (vec::z(out) >= 0);
122
123 // compute PDF (~ cosine weighted solid angle)
124 return bbm::select(mask, vec::z(in) * Constants::InvPi(), 0);
125 }
126
127
128 /*******************************************************************/
129 /*! \brief Return the (approximate) hemispherical reflectance of the BSDF
130
131 \param out = the outgoing direction
132 \param component = which reflectance component to eval
133 \param unit = unit of computation (ignored)
134 \param mask = masking of lanes
135 \returns the approximate hemispherical reflectance of the BSDF for a given direction
136 ********************************************************************/
137 Spectrum reflectance(const Vec3d& /*out*/, BsdfFlag component=bsdf_flag::All, unit_t /*unit*/=unit_t::Radiance, Mask mask=true) const
138 {
139 return bbm::select(mask & is_set(component, bsdf_flag::Diffuse), albedo, 0);
140 }
141
142
143 ///////////////////////////////
144 //! @{ \name Class Attributes
145 ///////////////////////////////
147
149 //! @}
150
151 //! \brief Default constructor
153 };
154
156
157} // end bbm namespace
158
159#endif /* _BBM_LAMBERTIAN_H_ */
160
162
163
All includes and helpers needed for declaring new bsdfmodels.
#define BBM_EXPORT_BSDFMODEL(BsdfModel)
Definition: bbm_fromstring.h:49
bsdfmodel concept
Definition: bsdfmodel.h:33
#define BBM_CHECK_CONCEPT(CONCEPTNAME, CLASSNAME,...)
Check a class for a concept with bbm::concepts::archetypes in the namespace.
Definition: macro.h:35
constexpr const vec3d< T > expand(const vec2d< T > &v, V &&a)
Definition: vec.h:55
constexpr decltype(auto) z(bbm::vec3d< T > &v)
Definition: vec.h:26
Definition: aggregatebsdf.h:29
constexpr auto select(MASK &&mask, const A &a, const A &b)
Definition: backbone.h:255
constexpr auto is_set(const FLAGNAME &a, const FLAG &flag)
Check if all in 'flag' are also set in 'a'; compatible with packet types.
Definition: flags.h:100
unit_t
Light Unit.
Definition: unit.h:21
Base declaration of attribute; further specialized below.
Definition: attribute.h:26
The classic diffuse Lambertian BSDF model.
Definition: lambertian.h:24
Spectrum eval(const Vec3d &in, const Vec3d &out, BsdfFlag component=bsdf_flag::All, unit_t=unit_t::Radiance, Mask mask=true) const
Evaluate the BSDF for a given in and out direction.
Definition: lambertian.h:45
diffuse_scale< Spectrum > albedo
Definition: lambertian.h:146
BsdfSample sample(const Vec3d &out, const Vec2d &xi, BsdfFlag component=bsdf_flag::All, unit_t unit=unit_t::Radiance, Mask mask=true) const
Sample the diffuse BSDF given a direction and two random variables.
Definition: lambertian.h:76
BBM_IMPORT_CONFIG(CONF)
BBM_BSDF_FORWARD
Definition: lambertian.h:28
Value pdf(const Vec3d &in, const Vec3d &out, BsdfFlag component=bsdf_flag::All, unit_t=unit_t::Radiance, Mask mask=true) const
Compute the pdf given an in and out direction.
Definition: lambertian.h:115
BBM_ATTRIBUTES(albedo)
Spectrum reflectance(const Vec3d &, BsdfFlag component=bsdf_flag::All, unit_t=unit_t::Radiance, Mask mask=true) const
Return the (approximate) hemispherical reflectance of the BSDF.
Definition: lambertian.h:137
BBM_DEFAULT_CONSTRUCTOR(lambertian)
Default constructor.
Definition: lambertian.h:152
static constexpr string_literal name
Definition: lambertian.h:27
Definition: string_literal.h:16