Loading...
Searching...
No Matches
phong.h
Go to the documentation of this file.
1#ifndef _BBM_PHONG_H_
2#define _BBM_PHONG_H_
3
4#include "bbm/bsdfmodel.h"
5
6/************************************************************************/
7/*! \file phong.h
8
9 \brief Implements: "The Modifed Phong BSDF model for physically based rendering"
10 [Lafortune 1994]: http://www.lafortune.eu/publications/Phong.html
11
12*************************************************************************/
13
14namespace bbm {
15
16 /**********************************************************************/
17 /*! \brief The modified Phong BSDF model. This is the classic Phong BSDF
18 model with appropriate normalization and sampling methods.
19
20 \tparam CONF = bbm configuration
21 \tparam NAME = name of the BSDF model (Default: 'Phong')
22
23 Implements: concepts::bsdfmodel
24 ***********************************************************************/
25 template<typename CONF, string_literal NAME="Phong"> requires concepts::config<CONF>
26 class phong
27 {
28 public:
30 static constexpr string_literal name = NAME;
32
33 /********************************************************************/
34 /*! \brief Evaluate the BSDF for a given in and out direction
35
36 \param in = incident direction
37 \param out = outgoing direction
38 \param component = which reflectance component to eval
39 \param unit = unit of computation (ignored)
40 \param mask = masking of lanes (e.g., for Packet eval)
41 \returns Evaluation of the BSDF per spectrum.
42 *********************************************************************/
43 Spectrum eval(const Vec3d& in, const Vec3d& out, BsdfFlag component=bsdf_flag::All, unit_t /*unit*/=unit_t::Radiance, Mask mask=true) const
44 {
45 // specular?
46 mask &= is_set(component, bsdf_flag::Specular);
47
48 // above surface?
49 mask &= (vec::z(in) >= 0) && (vec::z(out) >= 0);
50
51 // Quick exit if mask is all negative
52 if(bbm::none(mask)) return Spectrum(0);
53
54 // cos(Alpha) between reflected and outgoing direction
55 Value cosAlpha = bbm::max(bbm::dot(reflect(in), out), 0);
56
57 // Evaluate BSDF
58 auto result = albedo;
59 result *= (sharpness + 2) * Constants::InvPi(0.5) * bbm::pow(cosAlpha, sharpness);
60
61 // Done.
62 return bbm::select(mask, result, 0);
63 }
64
65
66 /********************************************************************/
67 /*! \brief Sample the BSDF given a direction and two random variables.
68
69 \param out = outgoing direction
70 \param xi = two random variables stored in a Vec2d
71 \param component = which reflectance component to sample
72 \param unit = unit of computation (ignored)
73 \param mask = masking of lanes.
74 \returns A bsdfSample containing the sampled direction and the corresponding pdf.
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 // specular?
81 mask &= is_set(component, bsdf_flag::Specular);
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 pow(cos(alpha), sharpness)
90 Vec2d csp = bbm::cossin(xi[0] * Constants::Pi(2));
91 Value cosTheta = bbm::pow(xi[1], 1.0 / (sharpness + 1));
92 Value sinTheta = bbm::safe_sqrt( 1.0 - cosTheta*cosTheta );
93
94 Vec3d in = vec::expand(csp * sinTheta, cosTheta);
95 sample.direction = bbm::select(mask, toGlobalShadingFrame(reflect(out)) * in, 0);
96
97 // compute pdf
98 sample.pdf = pdf(sample.direction, out, component, unit, mask);
99
100 // set component
101 sample.flag = bbm::select(mask, BsdfFlag(bsdf_flag::Specular), BsdfFlag(bsdf_flag::None));
102
103 // Done.
104 return sample;
105 }
106
107
108 /********************************************************************/
109 /*! \brief Compute the pdf given an in and out direction
110
111 \param in = the incoming (sampled) direction
112 \param out = the outgoing (given) direction
113 \param component = which reflectance component was sampled
114 \param unit = unit of computation (ignored)
115 \param mask = masking of lanes
116 \returns the PDF that the incoming direction would be sampled given the outgoing direction.
117 ***********************************************************************/
118 Value pdf(const Vec3d& in, const Vec3d& out, BsdfFlag component=bsdf_flag::All, unit_t /*unit*/=unit_t::Radiance, Mask mask=true) const
119 {
120 // specular?
121 mask &= is_set(component, bsdf_flag::Specular);
122
123 // above surface?
124 mask &= (vec::z(in) >= 0) && (vec::z(out) >= 0);
125
126 // Quick bailout
127 if(bbm::none(mask)) return 0;
128
129 // compute PDF: (sharpness+1)/2PI * pow(cos(alpha), sharpness)
130 Value cosAlpha = bbm::max(bbm::dot(reflect(in), out), 0);
131 Value pdf = (sharpness + 1) * Constants::InvPi(0.5) * bbm::pow(cosAlpha, sharpness);
132
133 // Done.
134 return bbm::select(mask, pdf, 0);
135 }
136
137 /*******************************************************************/
138 /*! \brief Return the (approximate) hemispherical reflectance of the BSDF
139
140 \param out = the outgoing direction
141 \param component = which reflectance component to eval
142 \param unit = unit of computation (ignored)
143 \param mask = masking of lanes
144 \returns the approximate hemispherical reflectance of the BSDF for a given direction
145 ********************************************************************/
146 Spectrum reflectance(const Vec3d& /*out*/, BsdfFlag component=bsdf_flag::All, unit_t /*unit*/=unit_t::Radiance, Mask mask=true) const
147 {
148 return bbm::select(mask & is_set(component, bsdf_flag::Specular), albedo, Spectrum(0));
149 }
150
151
152 ///////////////////////////////
153 //! @{ \name Class Attributes
154 ///////////////////////////////
157
159 //! @}
160
161 //! \brief Default constructor
163 };
164
166
167} // end bbm namespace
168
169#endif /* _BBM_PHONG_H_ */
170
All includes and helpers needed for declaring new bsdfmodels.
#define BBM_EXPORT_BSDFMODEL(BsdfModel)
Definition: bbm_fromstring.h:49
The modified Phong BSDF model. This is the classic Phong BSDF model with appropriate normalization an...
Definition: phong.h:27
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: phong.h:43
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: phong.h:76
BBM_ATTRIBUTES(albedo, sharpness)
BBM_IMPORT_CONFIG(CONF)
specular_sharpness< Value > sharpness
Definition: phong.h:156
BBM_BSDF_FORWARD
Definition: phong.h:31
BBM_DEFAULT_CONSTRUCTOR(phong)
Default constructor.
Definition: phong.h:162
specular_scale< Spectrum > albedo
Definition: phong.h:155
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: phong.h:118
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: phong.h:146
static constexpr string_literal name
Definition: phong.h:30
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
mat3d< std::decay_t< T > > toGlobalShadingFrame(const vec3d< T > &normal)
Construct a local shading frame to global frame transformation given a normal direction.
Definition: shading_frame.h:26
vec3d< T > reflect(const vec3d< T > &v, const vec3d< T > &normal)
Reflects a 3D vector.
Definition: vec_transform.h:44
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
Definition: string_literal.h:16