From b0800d1060a283a7bf0be04804ca01dd48f44fd0 Mon Sep 17 00:00:00 2001 From: Kai Rohmer Date: Mon, 26 Jun 2023 10:01:07 +0200 Subject: [PATCH] MDL: Fix volume mixes. --- .../MaterialXGenMdl/mdl/materialx/pbrlib.mdl | 79 +++++++++++++------ .../MaterialXGenMdl/mdl/materialx/stdlib.mdl | 4 +- 2 files changed, 58 insertions(+), 25 deletions(-) diff --git a/source/MaterialXGenMdl/mdl/materialx/pbrlib.mdl b/source/MaterialXGenMdl/mdl/materialx/pbrlib.mdl index 3f64767491..b0e9b4964d 100644 --- a/source/MaterialXGenMdl/mdl/materialx/pbrlib.mdl +++ b/source/MaterialXGenMdl/mdl/materialx/pbrlib.mdl @@ -659,6 +659,27 @@ export float3 mx_displacement_vector3( + mxp_displacement.z * state::normal()); } +// 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") ]], @@ -666,7 +687,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, @@ -677,15 +702,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 ) ); @@ -699,7 +723,7 @@ export material mx_mix_edf( = material( surface: material_surface( emission: material_emission( - emission: df::clamped_mix( + emission: df::unbounded_mix( // unbounded_mix is cheeper 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)) @@ -717,18 +741,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 ) ); @@ -741,7 +768,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[]( @@ -754,13 +785,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 ) ); @@ -796,19 +826,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 b73e881fcb..3664523d1c 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 cheeper 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 cheeper df::vdf_component[]( df::vdf_component( mxp_mix, mxp_fg.volume.scattering), df::vdf_component( 1.0 - mxp_mix, mxp_bg.volume.scattering))