Skip to content

Commit afc09dd

Browse files
authored
Fix edge case behavior of dielectric_bsdf in MDL (#2910)
Address an issue that was discovered with OpenPBR. The specular lobe was still visible with specular_weight=0 and specular_ior=1. Improved the comment that explains the reasoning for chosing custom_curve over fresnel in the dielectric_bsdf.
1 parent 165a74a commit afc09dd

2 files changed

Lines changed: 12 additions & 8 deletions

File tree

source/MaterialXGenMdl/mdl/materialx/pbrlib_1_6.mdl

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -168,15 +168,17 @@ export material mx_dielectric_bsdf(
168168
]]
169169
= let {
170170
float coatIor = mxp_thinfilm_ior <= 0.0 ? 1.0 : mxp_thinfilm_ior;
171-
float grazing_refl = math::max((1.0 - math::average(mxp_roughness)), 0.0);
171+
// Fresnel layer does not work well if the base is a diffuse transmission. The energy loss is very high.
172+
// Therefore we use a custom curve that approximates the Fresnel effect and does not cause energy loss.
173+
// Make sure that IOR of 1.0 results in zero reflectance, independent of the roughness.
172174
float root_r = (mxp_ior-1)/(mxp_ior+1);
175+
float normal_refl = root_r*root_r;
176+
float grazing_refl = normal_refl <= 0.0 ? 0.0 : math::max((1.0 - math::average(mxp_roughness)), 0.0);
173177
bsdf bsdf_R = df::thin_film(
174178
thickness: mxp_thinfilm_thickness,
175179
ior: color(coatIor),
176-
// fresnel layer has issues if base is a diffuse transmission, use custom curve for now
177-
// this will break thin_film but improves standard_surface with diffuse transmission
178180
base: df::custom_curve_layer(
179-
normal_reflectivity: root_r*root_r,
181+
normal_reflectivity: normal_refl,
180182
grazing_reflectivity: grazing_refl,
181183
weight: mxp_weight,
182184
layer: df::microfacet_ggx_smith_bsdf(

source/MaterialXGenMdl/mdl/materialx/pbrlib_1_9.mdl

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -261,15 +261,17 @@ export material mx_dielectric_bsdf(
261261
]]
262262
= let {
263263
float coatIor = mxp_thinfilm_ior <= 0.0 ? 1.0 : mxp_thinfilm_ior;
264-
float grazing_refl = math::max((1.0 - math::average(mxp_roughness)), 0.0);
264+
// Fresnel layer does not work well if the base is a diffuse transmission. The energy loss is very high.
265+
// Therefore we use a custom curve that approximates the Fresnel effect and does not cause energy loss.
266+
// Make sure that IOR of 1.0 results in zero reflectance, independent of the roughness.
265267
float root_r = (mxp_ior-1)/(mxp_ior+1);
268+
float normal_refl = root_r*root_r;
269+
float grazing_refl = normal_refl <= 0.0 ? 0.0 : math::max((1.0 - math::average(mxp_roughness)), 0.0);
266270
bsdf bsdf_R = df::thin_film(
267271
thickness: mxp_thinfilm_thickness,
268272
ior: color(coatIor),
269-
// fresnel layer has issues if base is a diffuse transmission, use custom curve for now
270-
// this will break thin_film but improves standard_surface with diffuse transmission
271273
base: df::custom_curve_layer(
272-
normal_reflectivity: root_r*root_r,
274+
normal_reflectivity: normal_refl,
273275
grazing_reflectivity: grazing_refl,
274276
weight: mxp_weight,
275277
layer: df::microfacet_ggx_smith_bsdf(

0 commit comments

Comments
 (0)