Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix volume mixes in MDL #1395

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 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))
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 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))
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 cheaper
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