Skip to content

Commit

Permalink
MDL: Fix volume mixes.
Browse files Browse the repository at this point in the history
  • Loading branch information
krohmerNV committed Jun 26, 2023
1 parent da444d5 commit b0800d1
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 25 deletions.
79 changes: 56 additions & 23 deletions source/MaterialXGenMdl/mdl/materialx/pbrlib.mdl
Original file line number Diff line number Diff line change
Expand Up @@ -659,14 +659,39 @@ 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") ]],
float mxp_mix = 0.0
) [[
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,
Expand All @@ -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
)
);

Expand All @@ -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))
Expand All @@ -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
)
);

Expand All @@ -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[](
Expand All @@ -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
)
);

Expand Down Expand Up @@ -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
)
);

Expand Down
4 changes: 2 additions & 2 deletions source/MaterialXGenMdl/mdl/materialx/stdlib.mdl
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand All @@ -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))
Expand Down

0 comments on commit b0800d1

Please sign in to comment.