@@ -135,6 +135,35 @@ 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 ) + Vec2 (-0 .6303f , -2 .323f ) * x
152+ + Vec2 (9 .748f , 2 .229f ) * y + Vec2 (-2 .038f , -3 .748f ) * x * y
153+ + Vec2 (29 .34f , 1 .424f ) * x2 + Vec2 (-8 .245f , -0 .7684f ) * y2
154+ + Vec2 (-26 .44f , 1 .436f ) * x2 * y
155+ + Vec2 (19 .99f , 0 .2913f ) * x * y2
156+ + Vec2 (-5 .448f , 0 .6286f ) * x2 * y2;
157+ Vec2 den = Vec2 (1 .0f , 1 .0f ) + Vec2 (-1 .765f , 0 .2281f ) * x
158+ + Vec2 (8 .263f , 15 .94f ) * y + Vec2 (11 .53f , -55 .83f ) * x * y
159+ + Vec2 (28 .96f , 13 .08f ) * x2 + Vec2 (-7 .507f , 41 .26f ) * y2
160+ + Vec2 (-36 .11f , 54 .9f ) * x2 * y
161+ + Vec2 (15 .86f , 300 .2f ) * x * y2
162+ + Vec2 (33 .37f , -285 .1f ) * x2 * y2;
163+ float a = OIIO::clamp (num.x / den.x , 0 .0f , 1 .0f );
164+ float b = OIIO::clamp (num.y / den.y , 0 .0f , 1 .0f );
165+ return reflection_tint * (f0 * a + f90 * b);
166+ }
138167};
139168
140169struct MxConductorParams : public MxMicrofacetBaseParams {
@@ -151,6 +180,13 @@ struct MxConductorParams : public MxMicrofacetBaseParams {
151180
152181 OSL_HOSTDEVICE Color3 evalT (float cos_theta) const { return Color3 (0 .0f ); }
153182
183+ OSL_HOSTDEVICE Color3 dirAlbedoR (float cos_theta) const
184+ {
185+ // TODO: Integrate the MaterialX fit for GGX directional albedo, which
186+ // may improve multiscatter compensation for conductors.
187+ return evalR (cos_theta);
188+ }
189+
154190 // Avoid function was declared but never referenced
155191 // float get_ior() const
156192 // {
@@ -180,6 +216,31 @@ struct MxGeneralizedSchlickParams : public MxMicrofacetBaseParams {
180216 * (Color3 (1 .0f )
181217 - fresnel_generalized_schlick (cos_theta, f0, f90, exponent));
182218 }
219+
220+ OSL_HOSTDEVICE Color3 dirAlbedoR (float cos_theta) const
221+ {
222+ // Rational quadratic fit for GGX directional albedo
223+ // https://github.com/AcademySoftwareFoundation/MaterialX/blob/main/libraries/pbrlib/genglsl/lib/mx_microfacet_specular.glsl
224+ float x = OIIO::clamp (cos_theta, 0 .0f , 1 .0f );
225+ float y = sqrtf (roughness_x * roughness_y); // average alpha
226+ float x2 = x * x;
227+ float y2 = y * y;
228+ Vec2 num = Vec2 (0 .1003f , 0 .9345f ) + Vec2 (-0 .6303f , -2 .323f ) * x
229+ + Vec2 (9 .748f , 2 .229f ) * y + Vec2 (-2 .038f , -3 .748f ) * x * y
230+ + Vec2 (29 .34f , 1 .424f ) * x2 + Vec2 (-8 .245f , -0 .7684f ) * y2
231+ + Vec2 (-26 .44f , 1 .436f ) * x2 * y
232+ + Vec2 (19 .99f , 0 .2913f ) * x * y2
233+ + Vec2 (-5 .448f , 0 .6286f ) * x2 * y2;
234+ Vec2 den = Vec2 (1 .0f , 1 .0f ) + Vec2 (-1 .765f , 0 .2281f ) * x
235+ + Vec2 (8 .263f , 15 .94f ) * y + Vec2 (11 .53f , -55 .83f ) * x * y
236+ + Vec2 (28 .96f , 13 .08f ) * x2 + Vec2 (-7 .507f , 41 .26f ) * y2
237+ + Vec2 (-36 .11f , 54 .9f ) * x2 * y
238+ + Vec2 (15 .86f , 300 .2f ) * x * y2
239+ + Vec2 (33 .37f , -285 .1f ) * x2 * y2;
240+ float a = OIIO::clamp (num.x / den.x , 0 .0f , 1 .0f );
241+ float b = OIIO::clamp (num.y / den.y , 0 .0f , 1 .0f );
242+ return reflection_tint * (f0 * a + f90 * b);
243+ }
183244};
184245
185246struct MxTranslucentParams {
0 commit comments