@@ -135,6 +135,41 @@ struct MxDielectricParams : public MxMicrofacetBaseParams {
135135 {
136136 return transmission_tint * (1 .0f - fresnel_dielectric (cos_theta, ior));
137137 }
138+
139+ OSL_HOSTDEVICE Color3 dirAlbedoR (float cos_theta) const
140+ {
141+ float iorRatio = (ior - 1 .0f ) / (ior + 1 .0f );
142+ Color3 f0 (iorRatio * iorRatio);
143+ Color3 f90 (1 .0f );
144+
145+ // Rational quadratic fit for GGX directional albedo
146+ // https://github.com/AcademySoftwareFoundation/MaterialX/blob/main/libraries/pbrlib/genglsl/lib/mx_microfacet_specular.glsl
147+ float x = OIIO::clamp (cos_theta, 0 .0f , 1 .0f );
148+ float y = sqrtf (roughness_x * roughness_y); // average alpha
149+ float x2 = x * x;
150+ float y2 = y * y;
151+ Vec2 num = Vec2 (0 .1003f , 0 .9345f ) +
152+ Vec2 (-0 .6303f , -2 .323f ) * x +
153+ Vec2 (9 .748f , 2 .229f ) * y +
154+ Vec2 (-2 .038f , -3 .748f ) * x * y +
155+ Vec2 (29 .34f , 1 .424f ) * x2 +
156+ Vec2 (-8 .245f , -0 .7684f ) * y2 +
157+ Vec2 (-26 .44f , 1 .436f ) * x2 * y +
158+ Vec2 (19 .99f , 0 .2913f ) * x * y2 +
159+ Vec2 (-5 .448f , 0 .6286f ) * x2 * y2;
160+ Vec2 den = Vec2 (1 .0f , 1 .0f ) +
161+ Vec2 (-1 .765f , 0 .2281f ) * x +
162+ Vec2 (8 .263f , 15 .94f ) * y +
163+ Vec2 (11 .53f , -55 .83f ) * x * y +
164+ Vec2 (28 .96f , 13 .08f ) * x2 +
165+ Vec2 (-7 .507f , 41 .26f ) * y2 +
166+ Vec2 (-36 .11f , 54 .9f ) * x2 * y +
167+ Vec2 (15 .86f , 300 .2f ) * x * y2 +
168+ Vec2 (33 .37f , -285 .1f ) * x2 * y2;
169+ float a = OIIO::clamp (num.x / den.x , 0 .0f , 1 .0f );
170+ float b = OIIO::clamp (num.y / den.y , 0 .0f , 1 .0f );
171+ return reflection_tint * (f0 * a + f90 * b);
172+ }
138173};
139174
140175struct MxConductorParams : public MxMicrofacetBaseParams {
@@ -151,6 +186,13 @@ struct MxConductorParams : public MxMicrofacetBaseParams {
151186
152187 OSL_HOSTDEVICE Color3 evalT (float cos_theta) const { return Color3 (0 .0f ); }
153188
189+ OSL_HOSTDEVICE Color3 dirAlbedoR (float cos_theta) const
190+ {
191+ // TODO: Integrate the MaterialX fit for GGX directional albedo, which
192+ // may improve multiscatter compensation for conductors.
193+ return evalR (cos_theta);
194+ }
195+
154196 // Avoid function was declared but never referenced
155197 // float get_ior() const
156198 // {
@@ -180,6 +222,37 @@ struct MxGeneralizedSchlickParams : public MxMicrofacetBaseParams {
180222 * (Color3 (1 .0f )
181223 - fresnel_generalized_schlick (cos_theta, f0, f90, exponent));
182224 }
225+
226+ OSL_HOSTDEVICE Color3 dirAlbedoR (float cos_theta) const
227+ {
228+ // Rational quadratic fit for GGX directional albedo
229+ // https://github.com/AcademySoftwareFoundation/MaterialX/blob/main/libraries/pbrlib/genglsl/lib/mx_microfacet_specular.glsl
230+ float x = OIIO::clamp (cos_theta, 0 .0f , 1 .0f );
231+ float y = sqrtf (roughness_x * roughness_y); // average alpha
232+ float x2 = x * x;
233+ float y2 = y * y;
234+ Vec2 num = Vec2 (0 .1003f , 0 .9345f ) +
235+ Vec2 (-0 .6303f , -2 .323f ) * x +
236+ Vec2 (9 .748f , 2 .229f ) * y +
237+ Vec2 (-2 .038f , -3 .748f ) * x * y +
238+ Vec2 (29 .34f , 1 .424f ) * x2 +
239+ Vec2 (-8 .245f , -0 .7684f ) * y2 +
240+ Vec2 (-26 .44f , 1 .436f ) * x2 * y +
241+ Vec2 (19 .99f , 0 .2913f ) * x * y2 +
242+ Vec2 (-5 .448f , 0 .6286f ) * x2 * y2;
243+ Vec2 den = Vec2 (1 .0f , 1 .0f ) +
244+ Vec2 (-1 .765f , 0 .2281f ) * x +
245+ Vec2 (8 .263f , 15 .94f ) * y +
246+ Vec2 (11 .53f , -55 .83f ) * x * y +
247+ Vec2 (28 .96f , 13 .08f ) * x2 +
248+ Vec2 (-7 .507f , 41 .26f ) * y2 +
249+ Vec2 (-36 .11f , 54 .9f ) * x2 * y +
250+ Vec2 (15 .86f , 300 .2f ) * x * y2 +
251+ Vec2 (33 .37f , -285 .1f ) * x2 * y2;
252+ float a = OIIO::clamp (num.x / den.x , 0 .0f , 1 .0f );
253+ float b = OIIO::clamp (num.y / den.y , 0 .0f , 1 .0f );
254+ return reflection_tint * (f0 * a + f90 * b);
255+ }
183256};
184257
185258struct MxTranslucentParams {
0 commit comments