Loading...
Searching...
No Matches
vanginneken.h
Go to the documentation of this file.
1#ifndef _BBM_MASKINGSHADOWING_VANGINNEKEN_H_
2#define _BBM_MASKINGSHADOWING_VANGINNEKEN_H_
3
5
6/************************************************************************/
7/*! \file ginneken.h
8
9 \brief Height-direction correlated joint masking and shadowing following the
10 empirical factor from "Diffuse and Specular Reflectance from Rough
11 Surfaces," by Bram van Ginneken, Marigo Stavridi, and Jan J. Koenderink,
12 Appl. Opt. 37, 130-139 (1998):
13 https://opg.optica.org/ao/abstract.cfm?URI=ao-37-1-130
14
15 See also Eq. 101 from "Understanding the Masking-Shadowing Function in
16 Microfacet-Based BRDFs" [Heitz 2014]: https://jcgt.org/published/0003/02/03/
17
18*************************************************************************/
19
20namespace bbm {
21 namespace maskingshadowing {
22
23 /********************************************************************/
24 /*! \brief Heigh correlated joint masking and shadowing following
25 Vanginneken et al.
26
27 See also Eq. 101 from "Understanding the Masking-Shadowing Function in
28 Microfacet-Based BRDFs" [Heitz 2014]:
29 https://jcgt.org/published/0003/02/03/
30 ********************************************************************/
31 template<typename CONF> requires concepts::config<CONF>
33 {
35
36 template<typename NDF> requires concepts::ndf<NDF> && concepts::matching_config<CONF, NDF>
37 static constexpr auto eval(const NDF& ndf, const Vec3d& in, const Vec3d& out, const Vec3d& m, Mask mask=true)
38 {
39 using return_t = decltype(ndf.G1(in, m, mask));
40
41 // check dot
42 mask &= (bbm::dot(in, m) > 0) && (bbm::dot(out, m) > 0);
43
44 // Quick bailout
45 if(bbm::none(mask)) return return_t(0);
46
47 // Van Ginnekin empirical factor:
48 // lambda = 4.41 phi / (4.441 phi + 1)
49 // with phi = the azimuthal angle between in and out.
50 auto phi = bbm::abs(spherical::phi(in) - spherical::phi(out));
51 return_t lambda = 4.41 * phi / (4.41 * phi + 1.0);
52
53 // Compute Eq. 101
54 auto gi = ndf.G1(in, m, mask);
55 auto go = ndf.G1(out, m, mask);
56 auto gio = gi*go;
57
58 // min/max(delta_i, delta_o) = min/max(1/gi - 1, 1/go - 1)
59 // = 1 / (max/min(gi,go)) - 1
60 // = min/max(gi,go) / gio - 1
61 auto maxg = bbm::max(gi, go);
62 auto ming = bbm::min(gi, go);
63
64 // denom = 1 + max(delta_i, delta_o) + lambda * min(delta_i, delta_o)
65 // = 1 + (max(gi, go)/gio - 1) + lambda*( min(gi,go)/gio - 1)
66 // = (max(gi,go)+ lambda*(min(gi,go) - gio)) / gio
67 auto denom = maxg + lambda*(ming - gio);
68
69 // check for division by zero
70 mask &= (denom > Constants::Epsilon());
71
72 // Done.
73 return bbm::select(mask, gio / denom, 0);
74 }
75 };
76
78
79 } // end maskingshadowing namespace
80} // end bbm namespace
81
82#endif /* _BBM_MASKINGSHADOWING_VANGINNEKEN_H_ */
All necessary include files for defining new joint masking and shadowing functions.
maskingshadowing concept
Definition: maskingshadowing.h:24
matching_config concept
Definition: config.h:63
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 & phi(vec2d< T > &v)
Definition: spherical.h:39
Definition: aggregatebsdf.h:29
constexpr auto select(MASK &&mask, const A &a, const A &b)
Definition: backbone.h:255
Heigh correlated joint masking and shadowing following Vanginneken et al.
Definition: vanginneken.h:33
static constexpr auto eval(const NDF &ndf, const Vec3d &in, const Vec3d &out, const Vec3d &m, Mask mask=true)
Definition: vanginneken.h:37