diff --git a/source/MaterialXGenMdl/mdl/materialx/pbrlib.mdl b/source/MaterialXGenMdl/mdl/materialx/pbrlib.mdl index 9c166f7468..61234c4037 100644 --- a/source/MaterialXGenMdl/mdl/materialx/pbrlib.mdl +++ b/source/MaterialXGenMdl/mdl/materialx/pbrlib.mdl @@ -669,6 +669,27 @@ export material mx_displacement_vector3( ); +// helper function to mix two scattering volumes: +// - combined scattering coefficient is just the sum of the two +// - VDF mixer weight is the relative probability of encountering the corresponding +// particle type +// NOTE: mixer weight should be a color, but due to a bug in current MDL compilers +// the color mixers don't accept non-uniform weights yet +struct volume_mix_return { + color scattering_coefficient; + float mix_weight1; // mix_weight2 = 1.0 - mix_weight1, can use any mixer +}; +volume_mix_return volume_mix( + color scattering_coefficient1, + float weight1, + color scattering_coefficient2, + float weight2) +{ + color s1 = weight1 * scattering_coefficient1; + color s = s1 + weight2 * scattering_coefficient2; + return volume_mix_return(scattering_coefficient: s, mix_weight1: math::average(s1 / s)); +} + export material mx_mix_bsdf( material mxp_fg = material() [[ anno::usage( "materialx:bsdf") ]], material mxp_bg = material() [[ anno::usage( "materialx:bsdf") ]], @@ -676,7 +697,11 @@ export material mx_mix_bsdf( ) [[ anno::usage( "materialx:bsdf") ]] -= material( += let { + volume_mix_return v = volume_mix( + mxp_fg.volume.scattering_coefficient, mxp_mix, + mxp_bg.volume.scattering_coefficient, (1.0f - mxp_mix)); +} in material( surface: material_surface( scattering: df::weighted_layer( weight: mxp_mix, @@ -687,15 +712,14 @@ export material mx_mix_bsdf( // we need to carry volume properties along for SSS ior: mxp_fg.ior, // NOTE: IOR is uniform, cannot mix here volume: material_volume( - scattering: df::clamped_mix( + scattering: df::unbounded_mix( df::vdf_component[]( - df::vdf_component( mxp_mix, mxp_fg.volume.scattering), - df::vdf_component( 1.0 - mxp_mix, mxp_bg.volume.scattering)) + df::vdf_component(v.mix_weight1, mxp_fg.volume.scattering), + df::vdf_component(1.0 - v.mix_weight1, mxp_bg.volume.scattering)) ), absorption_coefficient: mxp_mix * mxp_fg.volume.absorption_coefficient + (1.0 - mxp_mix) * mxp_bg.volume.absorption_coefficient, - scattering_coefficient: mxp_mix * mxp_fg.volume.scattering_coefficient + - (1.0 - mxp_mix) * mxp_bg.volume.scattering_coefficient + scattering_coefficient: v.scattering_coefficient ) ); @@ -709,7 +733,7 @@ export material mx_mix_edf( = material( surface: material_surface( emission: material_emission( - emission: df::clamped_mix( + emission: df::unbounded_mix( // unbounded_mix is cheaper df::edf_component[]( df::edf_component( mxp_mix, mxp_fg.surface.emission.emission), df::edf_component( 1.0 - mxp_mix, mxp_bg.surface.emission.emission)) @@ -727,18 +751,21 @@ export material mx_mix_vdf( ) [[ anno::usage( "materialx:vdf") ]] -= material( += let { + volume_mix_return v = volume_mix( + mxp_fg.volume.scattering_coefficient, mxp_mix, + mxp_bg.volume.scattering_coefficient, (1.0f - mxp_mix)); +} in material( ior: mxp_fg.ior, // NOTE: IOR is uniform, cannot mix here volume: material_volume( - scattering: df::clamped_mix( + scattering: df::unbounded_mix( df::vdf_component[]( - df::vdf_component( mxp_mix, mxp_fg.volume.scattering), - df::vdf_component( 1.0 - mxp_mix, mxp_bg.volume.scattering)) + df::vdf_component( v.mix_weight1, mxp_fg.volume.scattering), + df::vdf_component( 1.0 - v.mix_weight1, mxp_bg.volume.scattering)) ), absorption_coefficient: mxp_mix * mxp_fg.volume.absorption_coefficient + (1.0 - mxp_mix) * mxp_bg.volume.absorption_coefficient, - scattering_coefficient: mxp_mix * mxp_fg.volume.scattering_coefficient + - (1.0 - mxp_mix) * mxp_bg.volume.scattering_coefficient + scattering_coefficient: v.scattering_coefficient ) ); @@ -751,7 +778,11 @@ export material mx_add_bsdf( ) [[ anno::usage( "materialx:bsdf") ]] -= material( += let { + volume_mix_return v = volume_mix( + mxp_in1.volume.scattering_coefficient, 1.0f, + mxp_in2.volume.scattering_coefficient, 1.0f); +} in material( surface: material_surface( scattering: df::unbounded_mix( df::bsdf_component[]( @@ -764,13 +795,12 @@ export material mx_add_bsdf( volume: material_volume( scattering: df::unbounded_mix( df::vdf_component[]( - df::vdf_component( 1.0, mxp_in1.volume.scattering), - df::vdf_component( 1.0, mxp_in2.volume.scattering)) + df::vdf_component( v.mix_weight1, mxp_in1.volume.scattering), + df::vdf_component( 1.0 - v.mix_weight1, mxp_in2.volume.scattering)) ), absorption_coefficient: mxp_in1.volume.absorption_coefficient + mxp_in2.volume.absorption_coefficient, - scattering_coefficient: mxp_in1.volume.scattering_coefficient + - mxp_in2.volume.scattering_coefficient + scattering_coefficient: v.scattering_coefficient ) ); @@ -806,19 +836,22 @@ export material mx_add_vdf( ) [[ anno::usage( "materialx:vdf") ]] -= material( += let { + volume_mix_return v = volume_mix( + mxp_in1.volume.scattering_coefficient, 1.0f, + mxp_in2.volume.scattering_coefficient, 1.0f); +} in material( // assuming mixing the IOR is the best we can do here ior: 0.5 * mxp_in1.ior + 0.5 * mxp_in2.ior, volume: material_volume( scattering: df::unbounded_mix( df::vdf_component[]( - df::vdf_component( 1.0, mxp_in1.volume.scattering), - df::vdf_component( 1.0, mxp_in2.volume.scattering)) + df::vdf_component( v.mix_weight1, mxp_in1.volume.scattering), + df::vdf_component( 1.0 - v.mix_weight1, mxp_in2.volume.scattering)) ), absorption_coefficient: mxp_in1.volume.absorption_coefficient + mxp_in2.volume.absorption_coefficient, - scattering_coefficient: mxp_in1.volume.scattering_coefficient + - mxp_in2.volume.scattering_coefficient + scattering_coefficient: v.scattering_coefficient ) ); diff --git a/source/MaterialXGenMdl/mdl/materialx/stdlib.mdl b/source/MaterialXGenMdl/mdl/materialx/stdlib.mdl index 2cb313221c..bce4a44ea5 100644 --- a/source/MaterialXGenMdl/mdl/materialx/stdlib.mdl +++ b/source/MaterialXGenMdl/mdl/materialx/stdlib.mdl @@ -2981,7 +2981,7 @@ export material mx_mix_surfaceshader( base: mxp_bg.surface.scattering ), emission: material_emission( - emission: df::clamped_mix( + emission: df::unbounded_mix( // unbounded_mix is cheaper df::edf_component[]( df::edf_component( mxp_mix, mxp_fg.surface.emission.emission), df::edf_component( 1.0 - mxp_mix, mxp_bg.surface.emission.emission)) @@ -2994,7 +2994,7 @@ export material mx_mix_surfaceshader( // we need to carry volume properties along for SSS ior: mxp_fg.ior, // NOTE: IOR is uniform, cannot mix here volume: material_volume( - scattering: df::clamped_mix( + scattering: df::unbounded_mix( // unbounded_mix is cheaper df::vdf_component[]( df::vdf_component( mxp_mix, mxp_fg.volume.scattering), df::vdf_component( 1.0 - mxp_mix, mxp_bg.volume.scattering))