Loading...
Searching...
No Matches
sgd.h
Go to the documentation of this file.
1#ifndef _BBM_SGD_NDF_H_
2#define _BBM_SGD_NDF_H_
3
4#include "bbm/ndf.h"
5#include "ndf/ggx.h"
6
7/************************************************************************/
8/*! \file sgd.h
9
10 \brief Implements the Shifted Gamma Distribution:
11
12 M. M. Bagher, C. Soler, and N. Holzschuch "Accurate fitting of measured
13 reflectances using a Shifted Gamma micro-facet distribution", Computer
14 Graphics Forum 31, 4, 2012: https://doi.org/10.1111/j.1467-8659.2012.03147.x
15
16 Includes different variants:
17 + sgd_base : unnormalized NDF without shadowing or masking
18 + sgd : NDF with fitted normalization and and approximate shadowing and masking
19
20*************************************************************************/
21
22namespace bbm {
23 namespace ndf {
24
25 /********************************************************************/
26 /*! \brief The unnormalized SGD microfacet distribution and
27 without shadowing and masking
28
29 \tparam CONF = bbm configuration
30 \tparam NAME = ndf name (default = SGD_unnormalized)
31
32 Implements: concepts::ndf
33 *********************************************************************/
34 template<typename CONF, string_literal NAME="SGD_base"> requires concepts::config<CONF>
36 {
37 public:
39 static constexpr string_literal name = NAME;
40
41 /******************************************************************/
42 /*! \brief Evaluate the NDF
43
44 \param halfway = vector to eval the NDF for
45 \param mask = enable/disbale lanes [default = true]
46 \returns the resulting evaluation of the NDF
47 *******************************************************************/
48 Spectrum eval(const Vec3d& halfway, Mask mask=true) const
49 {
50 // above surface?
51 mask &= (vec::z(halfway) > 0);
52
53 // Quick exit
54 if(bbm::none(mask)) return 0;
55
56 // Eval
57 Spectrum temp = alpha + Spectrum(spherical::tanTheta2(halfway)) / alpha;
58 Spectrum denum = bbm::pow(temp, p);
59 Spectrum P22 = bbm::select(denum > Constants::Epsilon(), bbm::exp( -temp ) / denum, 0);
60
61 // Done.
62 return bbm::select(mask, P22 / (Constants::Pi() * bbm::pow(spherical::cosTheta(halfway), 4.0)), 0);
63 }
64
65 /******************************************************************/
66 /*! \brief Sample the NDF
67
68 \param view = view direction
69 \param xi = 2D uniform random variables in [0..1] range
70 \param Mask = enable/disbale lanes
71 \returns A sampled microfacet normal.
72 *******************************************************************/
73 Vec3d sample(const Vec3d& view, const Vec2d& xi, Mask mask=true) const
74 {
75 // Use GGX for sampling with average alpha
76 Value avg_alpha = bbm::hsum(alpha) / bbm::hsum(Spectrum(1));
77 return ggx<Config>( avg_alpha ).sample(view, xi, mask);
78 }
79
80 /******************************************************************/
81 /*! \brief PDF of sampling the NDF
82
83 \param view = view direction
84 \param m = sampled microfacet normal
85 \param mask = enable/disable lanes [default = true]
86 \returns the PDF of sampling 'm' using the sample method.
87 *******************************************************************/
88 Value pdf(const Vec3d& view, const Vec3d& m, Mask mask=true) const
89 {
90 // Use GGX for pdf with average alpha
91 Value avg_alpha = bbm::hsum(alpha) / bbm::hsum(Spectrum(1));
92 return ggx<Config>( avg_alpha ).pdf(view, m, mask);
93 }
94
95
96 /******************************************************************/
97 /*! \brief Monodirectional shadowing and masking factor
98
99 \param v = incident/exitant direction of transport
100 \param m = microfacet normal.
101 \param mask = enable/disable lanes [default = true]
102
103 Bagher et al. did not present an analytical solution and instead
104 relied on a fitted rational approximation of the shadowing and masking
105 function.
106 *******************************************************************/
107 Value G1(const Vec3d& /*v*/, const Vec3d& /*m*/, Mask /*mask*/=true) const
108 {
109 return 1.0;
110 }
111
112 ///////////////////////////////
113 //! @{ \name Class Attributes
114 ///////////////////////////////
117
119 //! @}
120
121 //! \brief Default Constructor
123 };
124
126
127
128 /********************************************************************/
129 /*! \brief The SGD microfacet distribution with fitted shadowing and masking
130
131 \tparam CONF = bbm configuration
132 \tparam NAME = ndf name (default = SGD)
133
134 Implements: concepts::ndf
135 *********************************************************************/
136 template<typename CONF, string_literal NAME="SGD"> requires concepts::config<CONF>
137 class sgd : public sgd_base<CONF>
138 {
141 public:
143 static constexpr string_literal name = NAME;
144
145 //! @{ \name From base
146 using base::sample;
147 using base::pdf;
148 //! @}
149
150 /******************************************************************/
151 /*! \brief Evaluate the NDF
152
153 \param halfway = vector to eval the NDF for
154 \param mask = enable/disbale lanes [default = true]
155 \returns the resulting evaluation of the NDF
156 *******************************************************************/
157 Spectrum eval(const Vec3d& halfway, Mask mask=true) const
158 {
159 // above surface?
160 mask &= (vec::z(halfway) > 0);
161
162 // Quick exit
163 if(bbm::none(mask)) return 0;
164
165 // Eval
166 return base::eval(halfway, mask) * K;
167 }
168
169 /******************************************************************/
170 /*! \brief Monodirectional shadowing and masking term
171
172 \param v = incident/outgoing vector
173 \param m = microfacet normal
174 \\param mask = enable/disable lanes
175 \returns the monodirectional shadowing and masking attentuation factor
176 *******************************************************************/
177 Spectrum G1(const Vec3d& v, const Vec3d& m, Mask mask=true) const
178 {
179 // check (dot(v,m) / dot(v,n)) > 0.
180 mask &= (vec::z(v) > 0) && (bbm::dot(v, m) > 0);
181
182 // Quick exit
183 if(bbm::none(mask)) return 0;
184
185 // compute theta
186 Value theta = spherical::theta(v);
187
188 // Eval
189 Spectrum g = bbm::select((theta > theta0), Scalar(1.0) + Lambda*(Scalar(1.0) - bbm::exp(c*bbm::pow(theta-theta0, k))), 1.0);
190
191 // Done.
192 return bbm::select(mask, g, 0);
193 }
194
195 ///////////////////////////////
196 //! @{ \name Class Attributes
197 ///////////////////////////////
203
205 //! @}
206
207 //! \brief Default Constructor
209 };
210
212
213 } // end ndf namespace
214} // end bbm namespace
215
216#endif /* _BBM_SDF_NDF_H_ */
All includes and helpers needed for declaring new ndfs.
The GGX Microfacet distribution.
Definition: ggx.h:38
Value pdf(const Vec3d &view, const Vec3d &m, Mask mask=true) const
PDF of sampling the NDF.
Definition: ggx.h:142
Vec3d sample(const Vec3d &view, const Vec2d &xi, Mask mask=true) const
Sample the NDF.
Definition: ggx.h:75
The unnormalized SGD microfacet distribution and without shadowing and masking.
Definition: sgd.h:36
Value pdf(const Vec3d &view, const Vec3d &m, Mask mask=true) const
PDF of sampling the NDF.
Definition: sgd.h:88
Vec3d sample(const Vec3d &view, const Vec2d &xi, Mask mask=true) const
Sample the NDF.
Definition: sgd.h:73
BBM_ATTRIBUTES(alpha, p)
Value G1(const Vec3d &, const Vec3d &, Mask=true) const
Monodirectional shadowing and masking factor.
Definition: sgd.h:107
bsdf_parameter< Spectrum, bsdf_attr::SpecularParameter, 0.64 > p
Definition: sgd.h:116
specular_roughness< Spectrum > alpha
Definition: sgd.h:115
static constexpr string_literal name
Definition: sgd.h:39
BBM_DEFAULT_CONSTRUCTOR(sgd_base)
Default Constructor.
Definition: sgd.h:122
Spectrum eval(const Vec3d &halfway, Mask mask=true) const
Evaluate the NDF.
Definition: sgd.h:48
The SGD microfacet distribution with fitted shadowing and masking.
Definition: sgd.h:138
bsdf_parameter< Spectrum, bsdf_attr::Dependent, constants< Scalar >::Pi(0.5)> theta0
Definition: sgd.h:202
BBM_IMPORT_CONFIG(CONF)
bsdf_parameter< Spectrum, bsdf_attr::Dependent > Lambda
Definition: sgd.h:199
Spectrum G1(const Vec3d &v, const Vec3d &m, Mask mask=true) const
Monodirectional shadowing and masking term.
Definition: sgd.h:177
bsdf_parameter< Spectrum, bsdf_attr::Dependent > c
Definition: sgd.h:200
bsdf_parameter< Spectrum, bsdf_attr::Dependent, 7.5 > K
Definition: sgd.h:198
BBM_DEFAULT_CONSTRUCTOR(sgd)
Default Constructor.
Definition: sgd.h:208
BBM_BASETYPES(base)
static constexpr string_literal name
Definition: sgd.h:143
Spectrum eval(const Vec3d &halfway, Mask mask=true) const
Evaluate the NDF.
Definition: sgd.h:157
BBM_ATTRIBUTES(K, Lambda, c, theta0, k)
bsdf_parameter< Spectrum, bsdf_attr::Dependent > k
Definition: sgd.h:201
config concept
Definition: config.h:31
ndf concept
Definition: ndf.h:29
#define BBM_CHECK_CONCEPT(CONCEPTNAME, CLASSNAME,...)
Check a class for a concept with bbm::concepts::archetypes in the namespace.
Definition: macro.h:35
T tanTheta2(const vec2d< T > &v)
Definition: spherical.h:183
T cosTheta(const vec2d< T > &v)
Definition: spherical.h:109
T & theta(vec2d< T > &v)
Definition: spherical.h:23
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
vec3d< T > halfway(const vec3d< T > &a, const vec3d< T > &b)
Halfway vector (3D)
Definition: vec_transform.h:77
Base declaration of attribute; further specialized below.
Definition: attribute.h:26
Implements the GGX Microfacet Normal Distribution from: "Microfacet Models for Refraction through Rou...
Definition: string_literal.h:16