Loading...
Searching...
No Matches
wardduergeislermoroder.h
Go to the documentation of this file.
1#ifndef _BBM_WARD_DUER_GEISLER_MORODER_H_
2#define _BBM_WARD_DUER_GEISLER_MORODER_H_
3
4#include "bsdfmodel/ward.h"
5
6/************************************************************************/
7/*! \file wardduergeislermoroder.h
8
9 \brief Implements: "A New Ward BRDF Model with Bounded Albedo",
10 [Geisler-Moroder and Duer 2010]:
11 https://doi.org/10.1111/j.1467-8659.2010.01735.x
12
13*************************************************************************/
14
15namespace bbm {
16
17 /**********************************************************************/
18 /*! \brief The anisotropic Ward-Duer-Geisler-Moroder BSDF model.
19
20 \tparam CONF = bbm configuration
21 \tparam Symmetry = isotropic or anisotropic (default: symmetry_v::anisotropic)
22 \tparam NAME = name of the BSDF model (Default: 'WardDuerGeislerMoroder')
23
24 This model differs from the Ward-Duer BRDF model in that it includes a
25 scaling term to preserve energy conservation at grazing angles.
26
27 Implements: concepts::bsdfmodel
28 **********************************************************************/
29 template<typename CONF, symmetry_v Symmetry = symmetry_v::Anisotropic, string_literal NAME="WardDuerGeislerMoroder"> requires concepts::config<CONF>
30 class wardduergeislermoroder : public ward<CONF, Symmetry>
31 {
34 public:
36 static constexpr string_literal name = NAME;
38
39 // Copy sample, pdf, and reflectance unchanged from ward
40 using base::sample;
41 using base::pdf;
43
44 /********************************************************************/
45 /*! \brief Evaluate the BSDF for a given in and out direction
46
47 \param in = incident direction
48 \param out = outgoing direction
49 \param component = which reflectance component to eval
50 \param unit = unit of computation (ignored)
51 \param mask = masking of lanes (e.g., for Packet eval)
52 \returns Evaluation of the BSDF per spectrum.
53 *********************************************************************/
54 Spectrum eval(const Vec3d& in, const Vec3d& out, BsdfFlag component=bsdf_flag::All, unit_t /*unit*/=unit_t::Radiance, Mask mask=true) const
55 {
56 // specular?
57 mask &= is_set(component, bsdf_flag::Specular);
58
59 // above surface?
60 mask &= (vec::z(in) >= 0) && (vec::z(out) >= 0);
61
62 // Quick exit if mask is all negative
63 if(bbm::none(mask)) return Spectrum(0);
64
65 // Evaluate BRDF
66 Vec2d r(base::roughness); // copy anisotropic | map isotropic to Vec2d.
67 Vec3d H = in + out;
68 Value zH2 = vec::z(H)*vec::z(H);
69 Value normalizationFactor = Constants::Pi(4) * vec::x(r) * vec::y(r) * bbm::pow(zH2, 2.0) / bbm::dot(H, H);
70 auto exponent = bbm::squared_norm(vec::xy(H) / r) / zH2;
71
72 auto result = base::albedo;
73 result *= bbm::exp(-exponent) / normalizationFactor;
74
75 // Done.
76 return bbm::select(mask, result, 0);
77 }
78
79 //! \brief Default constructor
81 };
82
84
85} // end bbm namespace
86
87#endif /* _BBM_WARD_DUER_GEISLER_MORODER_H_ */
88
#define BBM_EXPORT_BSDFMODEL(BsdfModel)
Definition: bbm_fromstring.h:49
The anisotropic Ward BSDF model.
Definition: ward.h:28
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 BSDF given a direction and two random variables.
Definition: ward.h:79
specular_roughness< symmetry_t< Symmetry, Value > > roughness
Definition: ward.h:161
specular_scale< Spectrum > albedo
Definition: ward.h:160
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: ward.h:120
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: ward.h:152
The anisotropic Ward-Duer-Geisler-Moroder BSDF model.
Definition: wardduergeislermoroder.h:31
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: wardduergeislermoroder.h:54
BBM_DEFAULT_CONSTRUCTOR(wardduergeislermoroder)
Default constructor.
Definition: wardduergeislermoroder.h:80
BBM_BSDF_FORWARD
Definition: wardduergeislermoroder.h:37
static constexpr string_literal name
Definition: wardduergeislermoroder.h:36
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 decltype(auto) y(bbm::vec3d< T > &v)
Definition: vec.h:23
constexpr decltype(auto) z(bbm::vec3d< T > &v)
Definition: vec.h:26
constexpr decltype(auto) x(bbm::vec3d< T > &v)
Definition: vec.h:20
constexpr const vec2d< T > xy(const vec3d< T > &v)
Definition: vec.h:47
Definition: aggregatebsdf.h:29
symmetry_v
symmetry variants.
Definition: bsdf_symmetry.h:19
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
Definition: string_literal.h:16
Implements: "Measuring and modeling anisotropic reflection" [Ward 1992]: https://doi....