Loading...
Searching...
No Matches
low.h
Go to the documentation of this file.
1#ifndef _BBM_LOW_NDF_H_
2#define _BBM_LOW_NDF_H_
3
4#include "bbm/ndf.h"
5
6/************************************************************************/
7/*! \file low.h
8
9 \brief Implements Low et al.'s Microfacet Normal Distribution from "BRDF
10 models for accurate and efficient rendering of glossy surfaces" [Low 2012]:
11 https://doi.org/10.1145/2077341.2077350
12
13***********************************************************************/
14
15namespace bbm {
16 namespace ndf {
17
18 /**********************************************************************/
19 /*! \brief The Low Microfacet distribution
20
21 \tparam CONF = bbm configuration
22 \tparam NAME = ndf name (default = Low)
23
24 The NDF is parameterized by two unnormalized parameters 'B' and 'C'. The
25 'A' scale parameter is not included. Note: this is not a true NDF, as the
26 eval function is not normalized!
27
28 Implements: concepts::ndf
29 ************************************************************************/
30 template<typename CONF, string_literal NAME="Low"> requires concepts::config<CONF>
31 class low
32 {
33 public:
35 static constexpr string_literal name = NAME;
36
37 /********************************************************************/
38 /*! \brief Evaluate the NDF
39
40 \param halfway = vector to eval the NDF for
41 \param mask = enable/disbale lanes [default = true]
42 \returns the resulting evaluation of the NDF
43 *********************************************************************/
44 Value eval(const Vec3d& halfway, Mask mask=true) const
45 {
46 // above surface?
47 mask &= (vec::z(halfway) > 0);
48
49 // Quick exit
50 if(bbm::none(mask)) return 0;
51
52 // eval NDF
53 Value S = bbm::pow(1.0 + B*(1.0 - vec::z(halfway)), -C);
54
55 // Done.
56 return bbm::select(mask, S, 0);
57 }
58
59 /********************************************************************/
60 /*! \brief Sample the NDF
61
62 \param view = view direction (ignored)
63 \param xi = 2D uniform random variables in [0..1] range
64 \param Mask = enable/disbale lanes
65 \returns A sampled microfacet normal.
66 ********************************************************************/
67 Vec3d sample(const Vec3d& /*view*/, const Vec2d& xi, Mask mask=true) const
68 {
69 // check valid xi
70 mask &= (xi[0] >= 0) && (xi[1] >= 0) && (xi[0] <= 1) && (xi[1] <= 1);
71
72 // quick exit
73 if(bbm::none(mask)) return 0.0;
74
75 // sample microfacet normal
76 Value term = bbm::select( bbm::abs(C-1) < Constants::Epsilon(),
77 bbm::exp( xi[0] * bbm::log(1.0 + B) ), // C ~ 1
78 bbm::pow(1.0 + xi[0] * (bbm::pow(1.0+B, 1.0-C) - 1.0), -1.0 / (C - 1.0)) // C != 1
79 );
80 Value cosTheta = (1.0 + B - term) / B;
81 Value sinTheta = bbm::safe_sqrt( 1.0 - cosTheta*cosTheta );
82 Vec2d csp = bbm::cossin( xi[1] * Constants::Pi(2) );
83
84 // Done.
85 return bbm::select(mask, vec::expand(csp*sinTheta, cosTheta), 0.0);
86 }
87
88 /********************************************************************/
89 /*! \brief PDF of sampling the NDF
90
91 \param view = view direction (ignored)
92 \param m = sampled microfacet normal
93 \param mask = enable/disable lanes [default = true]
94 \returns the PDF of sampling 'm' using the sample method.
95 *********************************************************************/
96 Value pdf(const Vec3d& /*view*/, const Vec3d& m, Mask mask=true) const
97 {
98 // m above surface?
99 mask &= (vec::z(m) > 0);
100
101 // quick bail out
102 if(bbm::none(mask)) return 0;
103
104 // eval PDF: D(m) * normalization
105 Value normalization = bbm::select( bbm::abs(C-1) < Constants::Epsilon(),
106 1.0f / bbm::log(1.0+B), // C ~ 1
107 (C-1.0) / (1.0 - bbm::pow(1.0+B, 1.0-C)) // C != 1
108 );
109 Value pdf = eval(m, mask) * B * (Constants::InvPi(0.5) * normalization);
110
111
112 // ignore negative values (round off errors)
113 mask &= (pdf > 0);
114
115 // Done.
116 return bbm::select(mask, pdf, 0);
117 }
118
119 /********************************************************************/
120 /*! \brief Monodirectional shadowing and masking factor
121
122 \param v = incident/exitant direction of transport
123 \param m = microfacet normal.
124 \param mask = enable/disable lanes [default = true]
125
126 Low et al. did not propose a shadowing and masking function based on
127 the NDF, and used the v-groove model instead
128 *********************************************************************/
129 Value G1(const Vec3d& /*v*/, const Vec3d& /*m*/, Mask /*mask*/=true) const
130 {
131 return 1;
132 }
133
134 ///////////////////////////////
135 //! @{ \name Class Attributes
136 ///////////////////////////////
139
141 //! @}
142
143 //! \brief Default constructor
145 };
146
148
149 } // end ndf namespace
150} // end bbm namespace
151
152#endif /* _BBM_LOW_NDF_H_ */
All includes and helpers needed for declaring new ndfs.
The Low Microfacet distribution.
Definition: low.h:32
bsdf_parameter< Value, bsdf_attr::SpecularParameter > B
Definition: low.h:137
BBM_IMPORT_CONFIG(CONF)
Value pdf(const Vec3d &, const Vec3d &m, Mask mask=true) const
PDF of sampling the NDF.
Definition: low.h:96
Value eval(const Vec3d &halfway, Mask mask=true) const
Evaluate the NDF.
Definition: low.h:44
Vec3d sample(const Vec3d &, const Vec2d &xi, Mask mask=true) const
Sample the NDF.
Definition: low.h:67
bsdf_parameter< Value, bsdf_attr::SpecularParameter > C
Definition: low.h:138
Value G1(const Vec3d &, const Vec3d &, Mask=true) const
Monodirectional shadowing and masking factor.
Definition: low.h:129
BBM_ATTRIBUTES(B, C)
static constexpr string_literal name
Definition: low.h:35
BBM_DEFAULT_CONSTRUCTOR(low)
Default constructor.
Definition: low.h:144
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
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
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
Definition: string_literal.h:16