diff --git a/libraries/pbrlib/genglsl/mx_conductor_bsdf.glsl b/libraries/pbrlib/genglsl/mx_conductor_bsdf.glsl index 532550554a..04bbe42dbb 100644 --- a/libraries/pbrlib/genglsl/mx_conductor_bsdf.glsl +++ b/libraries/pbrlib/genglsl/mx_conductor_bsdf.glsl @@ -1,6 +1,6 @@ #include "lib/mx_microfacet_specular.glsl" -void mx_conductor_bsdf_reflection(vec3 L, vec3 V, vec3 P, float occlusion, float weight, vec3 ior_n, vec3 ior_k, vec2 roughness, vec3 N, vec3 X, int distribution, inout BSDF bsdf) +void mx_conductor_bsdf_reflection(vec3 L, vec3 V, vec3 P, float occlusion, float weight, vec3 ior_n, vec3 ior_k, vec2 roughness, float thinfilm_thickness, float thinfilm_ior, vec3 N, vec3 X, int distribution, inout BSDF bsdf) { bsdf.throughput = vec3(0.0); @@ -24,8 +24,8 @@ void mx_conductor_bsdf_reflection(vec3 L, vec3 V, vec3 P, float occlusion, float vec3 Ht = vec3(dot(H, X), dot(H, Y), dot(H, N)); FresnelData fd; - if (bsdf.thickness > 0.0) - fd = mx_init_fresnel_conductor_airy(ior_n, ior_k, bsdf.thickness, bsdf.ior); + if (thinfilm_thickness > 0.0) + fd = mx_init_fresnel_conductor_airy(ior_n, ior_k, thinfilm_thickness, thinfilm_ior); else fd = mx_init_fresnel_conductor(ior_n, ior_k); @@ -39,7 +39,7 @@ void mx_conductor_bsdf_reflection(vec3 L, vec3 V, vec3 P, float occlusion, float bsdf.response = D * F * G * comp * occlusion * weight / (4.0 * NdotV); } -void mx_conductor_bsdf_indirect(vec3 V, float weight, vec3 ior_n, vec3 ior_k, vec2 roughness, vec3 N, vec3 X, int distribution, inout BSDF bsdf) +void mx_conductor_bsdf_indirect(vec3 V, float weight, vec3 ior_n, vec3 ior_k, vec2 roughness, float thinfilm_thickness, float thinfilm_ior, vec3 N, vec3 X, int distribution, inout BSDF bsdf) { bsdf.throughput = vec3(0.0); @@ -53,8 +53,8 @@ void mx_conductor_bsdf_indirect(vec3 V, float weight, vec3 ior_n, vec3 ior_k, ve float NdotV = clamp(dot(N, V), M_FLOAT_EPS, 1.0); FresnelData fd; - if (bsdf.thickness > 0.0) - fd = mx_init_fresnel_conductor_airy(ior_n, ior_k, bsdf.thickness, bsdf.ior); + if (thinfilm_thickness > 0.0) + fd = mx_init_fresnel_conductor_airy(ior_n, ior_k, thinfilm_thickness, thinfilm_ior); else fd = mx_init_fresnel_conductor(ior_n, ior_k); diff --git a/libraries/pbrlib/genglsl/mx_dielectric_bsdf.glsl b/libraries/pbrlib/genglsl/mx_dielectric_bsdf.glsl index dcaaadf1fa..826b9c24e5 100644 --- a/libraries/pbrlib/genglsl/mx_dielectric_bsdf.glsl +++ b/libraries/pbrlib/genglsl/mx_dielectric_bsdf.glsl @@ -1,6 +1,6 @@ #include "lib/mx_microfacet_specular.glsl" -void mx_dielectric_bsdf_reflection(vec3 L, vec3 V, vec3 P, float occlusion, float weight, vec3 tint, float ior, vec2 roughness, vec3 N, vec3 X, int distribution, int scatter_mode, inout BSDF bsdf) +void mx_dielectric_bsdf_reflection(vec3 L, vec3 V, vec3 P, float occlusion, float weight, vec3 tint, float ior, vec2 roughness, float thinfilm_thickness, float thinfilm_ior, vec3 N, vec3 X, int distribution, int scatter_mode, inout BSDF bsdf) { if (weight < M_FLOAT_EPS) { @@ -22,9 +22,9 @@ void mx_dielectric_bsdf_reflection(vec3 L, vec3 V, vec3 P, float occlusion, floa vec3 Ht = vec3(dot(H, X), dot(H, Y), dot(H, N)); FresnelData fd; - if (bsdf.thickness > 0.0) + if (thinfilm_thickness > 0.0) { - fd = mx_init_fresnel_dielectric_airy(ior, bsdf.thickness, bsdf.ior); + fd = mx_init_fresnel_dielectric_airy(ior, thinfilm_thickness, thinfilm_ior); } else { @@ -43,7 +43,7 @@ void mx_dielectric_bsdf_reflection(vec3 L, vec3 V, vec3 P, float occlusion, floa bsdf.response = D * F * G * comp * tint * occlusion * weight / (4.0 * NdotV); } -void mx_dielectric_bsdf_transmission(vec3 V, float weight, vec3 tint, float ior, vec2 roughness, vec3 N, vec3 X, int distribution, int scatter_mode, inout BSDF bsdf) +void mx_dielectric_bsdf_transmission(vec3 V, float weight, vec3 tint, float ior, vec2 roughness, float thinfilm_thickness, float thinfilm_ior, vec3 N, vec3 X, int distribution, int scatter_mode, inout BSDF bsdf) { if (weight < M_FLOAT_EPS) { @@ -54,9 +54,9 @@ void mx_dielectric_bsdf_transmission(vec3 V, float weight, vec3 tint, float ior, float NdotV = clamp(dot(N, V), M_FLOAT_EPS, 1.0); FresnelData fd; - if (bsdf.thickness > 0.0) + if (thinfilm_thickness > 0.0) { - fd = mx_init_fresnel_dielectric_airy(ior, bsdf.thickness, bsdf.ior); + fd = mx_init_fresnel_dielectric_airy(ior, thinfilm_thickness, thinfilm_ior); } else { @@ -78,7 +78,7 @@ void mx_dielectric_bsdf_transmission(vec3 V, float weight, vec3 tint, float ior, } } -void mx_dielectric_bsdf_indirect(vec3 V, float weight, vec3 tint, float ior, vec2 roughness, vec3 N, vec3 X, int distribution, int scatter_mode, inout BSDF bsdf) +void mx_dielectric_bsdf_indirect(vec3 V, float weight, vec3 tint, float ior, vec2 roughness, float thinfilm_thickness, float thinfilm_ior, vec3 N, vec3 X, int distribution, int scatter_mode, inout BSDF bsdf) { if (weight < M_FLOAT_EPS) { @@ -90,9 +90,9 @@ void mx_dielectric_bsdf_indirect(vec3 V, float weight, vec3 tint, float ior, vec float NdotV = clamp(dot(N, V), M_FLOAT_EPS, 1.0); FresnelData fd; - if (bsdf.thickness > 0.0) + if (thinfilm_thickness > 0.0) { - fd = mx_init_fresnel_dielectric_airy(ior, bsdf.thickness, bsdf.ior); + fd = mx_init_fresnel_dielectric_airy(ior, thinfilm_thickness, thinfilm_ior); } else { diff --git a/libraries/pbrlib/genglsl/mx_generalized_schlick_bsdf.glsl b/libraries/pbrlib/genglsl/mx_generalized_schlick_bsdf.glsl index ebeaa66f7a..4aa7e9efe6 100644 --- a/libraries/pbrlib/genglsl/mx_generalized_schlick_bsdf.glsl +++ b/libraries/pbrlib/genglsl/mx_generalized_schlick_bsdf.glsl @@ -1,6 +1,6 @@ #include "lib/mx_microfacet_specular.glsl" -void mx_generalized_schlick_bsdf_reflection(vec3 L, vec3 V, vec3 P, float occlusion, float weight, vec3 color0, vec3 color90, float exponent, vec2 roughness, vec3 N, vec3 X, int distribution, int scatter_mode, inout BSDF bsdf) +void mx_generalized_schlick_bsdf_reflection(vec3 L, vec3 V, vec3 P, float occlusion, float weight, vec3 color0, vec3 color90, float exponent, vec2 roughness, float thinfilm_thickness, float thinfilm_ior, vec3 N, vec3 X, int distribution, int scatter_mode, inout BSDF bsdf) { if (weight < M_FLOAT_EPS) { @@ -22,9 +22,9 @@ void mx_generalized_schlick_bsdf_reflection(vec3 L, vec3 V, vec3 P, float occlus vec3 Ht = vec3(dot(H, X), dot(H, Y), dot(H, N)); FresnelData fd; - if (bsdf.thickness > 0.0) + if (thinfilm_thickness > 0.0) { - fd = mx_init_fresnel_schlick_airy(color0, color90, exponent, bsdf.thickness, bsdf.ior); + fd = mx_init_fresnel_schlick_airy(color0, color90, exponent, thinfilm_thickness, thinfilm_ior); } else { @@ -43,7 +43,7 @@ void mx_generalized_schlick_bsdf_reflection(vec3 L, vec3 V, vec3 P, float occlus bsdf.response = D * F * G * comp * occlusion * weight / (4.0 * NdotV); } -void mx_generalized_schlick_bsdf_transmission(vec3 V, float weight, vec3 color0, vec3 color90, float exponent, vec2 roughness, vec3 N, vec3 X, int distribution, int scatter_mode, inout BSDF bsdf) +void mx_generalized_schlick_bsdf_transmission(vec3 V, float weight, vec3 color0, vec3 color90, float exponent, vec2 roughness, float thinfilm_thickness, float thinfilm_ior, vec3 N, vec3 X, int distribution, int scatter_mode, inout BSDF bsdf) { if (weight < M_FLOAT_EPS) { @@ -54,9 +54,9 @@ void mx_generalized_schlick_bsdf_transmission(vec3 V, float weight, vec3 color0, float NdotV = clamp(dot(N, V), M_FLOAT_EPS, 1.0); FresnelData fd; - if (bsdf.thickness > 0.0) + if (thinfilm_thickness > 0.0) { - fd = mx_init_fresnel_schlick_airy(color0, color90, exponent, bsdf.thickness, bsdf.ior); + fd = mx_init_fresnel_schlick_airy(color0, color90, exponent, thinfilm_thickness, thinfilm_thickness); } else { @@ -80,7 +80,7 @@ void mx_generalized_schlick_bsdf_transmission(vec3 V, float weight, vec3 color0, } } -void mx_generalized_schlick_bsdf_indirect(vec3 V, float weight, vec3 color0, vec3 color90, float exponent, vec2 roughness, vec3 N, vec3 X, int distribution, int scatter_mode, inout BSDF bsdf) +void mx_generalized_schlick_bsdf_indirect(vec3 V, float weight, vec3 color0, vec3 color90, float exponent, vec2 roughness, float thinfilm_thickness, float thinfilm_ior, vec3 N, vec3 X, int distribution, int scatter_mode, inout BSDF bsdf) { if (weight < M_FLOAT_EPS) { @@ -91,9 +91,9 @@ void mx_generalized_schlick_bsdf_indirect(vec3 V, float weight, vec3 color0, vec float NdotV = clamp(dot(N, V), M_FLOAT_EPS, 1.0); FresnelData fd; - if (bsdf.thickness > 0.0) + if (thinfilm_thickness > 0.0) { - fd = mx_init_fresnel_schlick_airy(color0, color90, exponent, bsdf.thickness, bsdf.ior); + fd = mx_init_fresnel_schlick_airy(color0, color90, exponent, thinfilm_thickness, thinfilm_ior); } else { diff --git a/libraries/pbrlib/genglsl/pbrlib_genglsl_impl.mtlx b/libraries/pbrlib/genglsl/pbrlib_genglsl_impl.mtlx index fa4617375f..5980b1f02c 100644 --- a/libraries/pbrlib/genglsl/pbrlib_genglsl_impl.mtlx +++ b/libraries/pbrlib/genglsl/pbrlib_genglsl_impl.mtlx @@ -28,9 +28,6 @@ - - - diff --git a/libraries/pbrlib/genmdl/pbrlib_genmdl_impl.mtlx b/libraries/pbrlib/genmdl/pbrlib_genmdl_impl.mtlx index 800e32edd0..429e103b84 100644 --- a/libraries/pbrlib/genmdl/pbrlib_genmdl_impl.mtlx +++ b/libraries/pbrlib/genmdl/pbrlib_genmdl_impl.mtlx @@ -11,13 +11,13 @@ - + - + - + @@ -25,9 +25,6 @@ - - - diff --git a/libraries/pbrlib/genmsl/pbrlib_genmsl_impl.mtlx b/libraries/pbrlib/genmsl/pbrlib_genmsl_impl.mtlx index 8d1d2a4729..51f0ba14b8 100644 --- a/libraries/pbrlib/genmsl/pbrlib_genmsl_impl.mtlx +++ b/libraries/pbrlib/genmsl/pbrlib_genmsl_impl.mtlx @@ -28,9 +28,6 @@ - - - diff --git a/libraries/pbrlib/genosl/legacy/mx_conductor_bsdf.osl b/libraries/pbrlib/genosl/legacy/mx_conductor_bsdf.osl index 850ff58f62..82cb6f32be 100644 --- a/libraries/pbrlib/genosl/legacy/mx_conductor_bsdf.osl +++ b/libraries/pbrlib/genosl/legacy/mx_conductor_bsdf.osl @@ -1,6 +1,6 @@ #include "../lib/mx_microfacet_specular.osl" -void mx_conductor_bsdf(float weight, color ior_n, color ior_k, vector2 roughness, normal N, vector U, string distribution, output BSDF bsdf) +void mx_conductor_bsdf(float weight, color ior_n, color ior_k, vector2 roughness, float thinfilm_thickness, float thinfilm_ior, normal N, vector U, string distribution, output BSDF bsdf) { bsdf.throughput = color(0.0); diff --git a/libraries/pbrlib/genosl/legacy/mx_dielectric_bsdf.osl b/libraries/pbrlib/genosl/legacy/mx_dielectric_bsdf.osl index a17fdd40cf..5e50834746 100644 --- a/libraries/pbrlib/genosl/legacy/mx_dielectric_bsdf.osl +++ b/libraries/pbrlib/genosl/legacy/mx_dielectric_bsdf.osl @@ -1,6 +1,6 @@ #include "../lib/mx_microfacet_specular.osl" -void mx_dielectric_bsdf(float weight, color tint, float ior, vector2 roughness, normal N, vector U, string distribution, string scatter_mode, output BSDF bsdf) +void mx_dielectric_bsdf(float weight, color tint, float ior, vector2 roughness, float thinfilm_thickness, float thinfilm_ior, normal N, vector U, string distribution, string scatter_mode, output BSDF bsdf) { if (scatter_mode == "T") { diff --git a/libraries/pbrlib/genosl/legacy/mx_generalized_schlick_bsdf.osl b/libraries/pbrlib/genosl/legacy/mx_generalized_schlick_bsdf.osl index ee34727ec1..59fc64bfd4 100644 --- a/libraries/pbrlib/genosl/legacy/mx_generalized_schlick_bsdf.osl +++ b/libraries/pbrlib/genosl/legacy/mx_generalized_schlick_bsdf.osl @@ -1,6 +1,6 @@ #include "../lib/mx_microfacet_specular.osl" -void mx_generalized_schlick_bsdf(float weight, color color0, color color90, float exponent, vector2 roughness, normal N, vector U, string distribution, string scatter_mode, output BSDF bsdf) +void mx_generalized_schlick_bsdf(float weight, color color0, color color90, float exponent, vector2 roughness, float thinfilm_thickness, float thinfilm_ior, normal N, vector U, string distribution, string scatter_mode, output BSDF bsdf) { float avgF0 = dot(color0, color(1.0 / 3.0)); float ior = mx_f0_to_ior(avgF0); diff --git a/libraries/pbrlib/genosl/mx_dielectric_bsdf.osl b/libraries/pbrlib/genosl/mx_dielectric_bsdf.osl index 69773b3ced..fe570e1546 100644 --- a/libraries/pbrlib/genosl/mx_dielectric_bsdf.osl +++ b/libraries/pbrlib/genosl/mx_dielectric_bsdf.osl @@ -1,15 +1,15 @@ -void mx_dielectric_bsdf(float weight, color tint, float ior, vector2 roughness, normal N, vector U, string distribution, string scatter_mode, output BSDF bsdf) +void mx_dielectric_bsdf(float weight, color tint, float ior, vector2 roughness, float thinfilm_thickness, float thinfilm_ior, normal N, vector U, string distribution, string scatter_mode, output BSDF bsdf) { if (scatter_mode == "R") { - bsdf = weight * dielectric_bsdf(N, U, tint, color(0.0), roughness.x, roughness.y, ior, distribution); + bsdf = weight * dielectric_bsdf(N, U, tint, color(0.0), roughness.x, roughness.y, ior, distribution, "thinfilm_thickness", thinfilm_thickness, "thinfilm_ior", thinfilm_ior); } else if (scatter_mode == "T") { - bsdf = weight * dielectric_bsdf(N, U, color(0.0), tint, roughness.x, roughness.y, ior, distribution); + bsdf = weight * dielectric_bsdf(N, U, color(0.0), tint, roughness.x, roughness.y, ior, distribution, "thinfilm_thickness", thinfilm_thickness, "thinfilm_ior", thinfilm_ior); } else { - bsdf = weight * dielectric_bsdf(N, U, tint, tint, roughness.x, roughness.y, ior, distribution); + bsdf = weight * dielectric_bsdf(N, U, tint, tint, roughness.x, roughness.y, ior, distribution, "thinfilm_thickness", thinfilm_thickness, "thinfilm_ior", thinfilm_ior); } } diff --git a/libraries/pbrlib/genosl/mx_generalized_schlick_bsdf.osl b/libraries/pbrlib/genosl/mx_generalized_schlick_bsdf.osl index 955de3c1fa..80431b5af2 100644 --- a/libraries/pbrlib/genosl/mx_generalized_schlick_bsdf.osl +++ b/libraries/pbrlib/genosl/mx_generalized_schlick_bsdf.osl @@ -1,15 +1,15 @@ -void mx_generalized_schlick_bsdf(float weight, color color0, color color90, float exponent, vector2 roughness, normal N, vector U, string distribution, string scatter_mode, output BSDF bsdf) +void mx_generalized_schlick_bsdf(float weight, color color0, color color90, float exponent, vector2 roughness, float thinfilm_thickness, float thinfilm_ior, normal N, vector U, string distribution, string scatter_mode, output BSDF bsdf) { if (scatter_mode == "R") { - bsdf = weight * generalized_schlick_bsdf(N, U, color(1.0), color(0.0), roughness.x, roughness.y, color0, color90, exponent, distribution); + bsdf = weight * generalized_schlick_bsdf(N, U, color(1.0), color(0.0), roughness.x, roughness.y, color0, color90, exponent, distribution, "thinfilm_thickness", thinfilm_thickness, "thinfilm_ior", thinfilm_ior); } else if (scatter_mode == "T") { - bsdf = weight * generalized_schlick_bsdf(N, U, color(0.0), color(1.0), roughness.x, roughness.y, color0, color90, exponent, distribution); + bsdf = weight * generalized_schlick_bsdf(N, U, color(0.0), color(1.0), roughness.x, roughness.y, color0, color90, exponent, distribution, "thinfilm_thickness", thinfilm_thickness, "thinfilm_ior", thinfilm_ior); } else { - bsdf = weight * generalized_schlick_bsdf(N, U, color(1.0), color(1.0), roughness.x, roughness.y, color0, color90, exponent, distribution); + bsdf = weight * generalized_schlick_bsdf(N, U, color(1.0), color(1.0), roughness.x, roughness.y, color0, color90, exponent, distribution, "thinfilm_thickness", thinfilm_thickness, "thinfilm_ior", thinfilm_ior); } } diff --git a/libraries/pbrlib/genosl/pbrlib_genosl_impl.legacy b/libraries/pbrlib/genosl/pbrlib_genosl_impl.legacy index 6ab7cc9e61..e4a424e1ac 100644 --- a/libraries/pbrlib/genosl/pbrlib_genosl_impl.legacy +++ b/libraries/pbrlib/genosl/pbrlib_genosl_impl.legacy @@ -28,9 +28,6 @@ - - - diff --git a/libraries/pbrlib/genosl/pbrlib_genosl_impl.mtlx b/libraries/pbrlib/genosl/pbrlib_genosl_impl.mtlx index 7a38f0fb12..69e4574e45 100644 --- a/libraries/pbrlib/genosl/pbrlib_genosl_impl.mtlx +++ b/libraries/pbrlib/genosl/pbrlib_genosl_impl.mtlx @@ -14,7 +14,7 @@ - + @@ -28,9 +28,6 @@ - - - diff --git a/libraries/pbrlib/pbrlib_defs.mtlx b/libraries/pbrlib/pbrlib_defs.mtlx index e63625a45d..47fa249b08 100644 --- a/libraries/pbrlib/pbrlib_defs.mtlx +++ b/libraries/pbrlib/pbrlib_defs.mtlx @@ -63,6 +63,8 @@ + + @@ -79,6 +81,8 @@ + + @@ -95,6 +99,8 @@ + + @@ -127,16 +133,6 @@ - - - - - - - diff --git a/resources/Materials/TestSuite/pbrlib/bsdf/thin_film_bsdf.mtlx b/resources/Materials/TestSuite/pbrlib/bsdf/thin_film_bsdf.mtlx index a6bc23bfa2..68bd46b52f 100644 --- a/resources/Materials/TestSuite/pbrlib/bsdf/thin_film_bsdf.mtlx +++ b/resources/Materials/TestSuite/pbrlib/bsdf/thin_film_bsdf.mtlx @@ -1,5 +1,10 @@ + + + diff --git a/resources/Materials/TestSuite/pbrlib/bsdf/vertical_layering.mtlx b/resources/Materials/TestSuite/pbrlib/bsdf/vertical_layering.mtlx index 206f6b1f00..657b9a6462 100644 --- a/resources/Materials/TestSuite/pbrlib/bsdf/vertical_layering.mtlx +++ b/resources/Materials/TestSuite/pbrlib/bsdf/vertical_layering.mtlx @@ -17,129 +17,36 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + - - + + - + - - - - - - - - - - - - - - - - - - - - + + + + + + - - - - - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -183,7 +90,7 @@ - + @@ -205,7 +112,7 @@ - + @@ -234,7 +141,7 @@ - + @@ -274,7 +181,7 @@ - + diff --git a/source/MaterialXCore/Document.cpp b/source/MaterialXCore/Document.cpp index a5ecbf733b..46d0552250 100644 --- a/source/MaterialXCore/Document.cpp +++ b/source/MaterialXCore/Document.cpp @@ -46,6 +46,44 @@ NodeDefPtr getShaderNodeDef(ElementPtr shaderRef) return NodeDefPtr(); } +void copyConnectionOrValue(NodePtr srcNode, const string& srcInput, NodePtr dstNode, const string& dstInput) +{ + InputPtr src = srcNode->getInput(srcInput); + if (src) + { + InputPtr dst = dstNode->getInput(dstInput); + if (!dst) + { + dst = dstNode->addInput(dstInput, src->getType()); + } + + if (src->hasNodeName()) + { + dst->setNodeName(src->getNodeName()); + if (src->hasOutputString()) + { + dst->setOutputString(src->getOutputString()); + } + } + else if (src->hasNodeGraphString()) + { + dst->setNodeGraphString(src->getNodeGraphString()); + if (src->hasOutputString()) + { + dst->setOutputString(src->getOutputString()); + } + } + else if (src->hasInterfaceName()) + { + dst->setInterfaceName(src->getInterfaceName()); + } + else if (src->hasValueString()) + { + dst->setValueString(src->getValueString()); + } + } +} + } // anonymous namespace // @@ -1396,6 +1434,53 @@ void Document::upgradeVersion() // Upgrade from 1.38 to 1.39 if (majorVersion == 1 && minorVersion == 38) { + const StringSet BSDF_WITH_THINFILM = { "dielectric_bsdf", "conductor_bsdf", "generalized_schlick_bsdf" }; + const string LAYER = "layer"; + const string TOP = "top"; + const string BASE = "base"; + const string THIN_FILM_BSDF = "thin_film_bsdf"; + const string THICKNESS = "thickness"; + const string IOR = "ior"; + const string THINFILM_THICKNESS = "thinfilm_thickness"; + const string THINFILM_IOR = "thinfilm_ior"; + + // Convert layering of thin_film_bsdf nodes to thin-film parameters on the affected BSDF nodes. + for (ElementPtr elem : traverseTree()) + { + if (elem->isA(LAYER)) + { + NodePtr layer = elem->asA(); + NodePtr top = layer->getConnectedNode(TOP); + NodePtr base = layer->getConnectedNode(BASE); + if (top && base && top->getCategory() == THIN_FILM_BSDF) + { + // Apply thin-film parameters to all supported BSDF's upstream. + for (Edge edge : layer->traverseGraph()) + { + NodePtr upstream = edge.getUpstreamElement()->asA(); + if (upstream && BSDF_WITH_THINFILM.count(upstream->getCategory())) + { + copyConnectionOrValue(top, THICKNESS, upstream, THINFILM_THICKNESS); + copyConnectionOrValue(top, IOR, upstream, THINFILM_IOR); + } + } + + // Bypass the thin-film layer operator. + vector downstreamPorts = layer->getDownstreamPorts(); + for (auto port : downstreamPorts) + { + port->setNodeName(base->getName()); + } + + // Remove the now unused nodes. + removeNode(layer->getName()); + removeNode(top->getName()); + } + } + } + + removeNodeDef("ND_thin_film_bsdf"); + minorVersion = 39; } diff --git a/source/MaterialXGenGlsl/GlslSyntax.cpp b/source/MaterialXGenGlsl/GlslSyntax.cpp index afd6f033dc..bf9964642e 100644 --- a/source/MaterialXGenGlsl/GlslSyntax.cpp +++ b/source/MaterialXGenGlsl/GlslSyntax.cpp @@ -281,10 +281,10 @@ GlslSyntax::GlslSyntax() Type::BSDF, std::make_shared( "BSDF", - "BSDF(vec3(0.0),vec3(1.0), 0.0, 0.0)", + "BSDF(vec3(0.0),vec3(1.0))", EMPTY_STRING, EMPTY_STRING, - "struct BSDF { vec3 response; vec3 throughput; float thickness; float ior; };")); + "struct BSDF { vec3 response; vec3 throughput; };")); registerTypeSyntax( Type::EDF, @@ -299,7 +299,7 @@ GlslSyntax::GlslSyntax() Type::VDF, std::make_shared( "BSDF", - "BSDF(vec3(0.0),vec3(1.0), 0.0, 0.0)", + "BSDF(vec3(0.0),vec3(1.0))", EMPTY_STRING)); registerTypeSyntax( diff --git a/source/MaterialXGenMdl/MdlShaderGenerator.cpp b/source/MaterialXGenMdl/MdlShaderGenerator.cpp index dddf1f2f13..2977f83f56 100644 --- a/source/MaterialXGenMdl/MdlShaderGenerator.cpp +++ b/source/MaterialXGenMdl/MdlShaderGenerator.cpp @@ -168,22 +168,11 @@ MdlShaderGenerator::MdlShaderGenerator() : registerImplementation("IM_layer_bsdf_" + MdlShaderGenerator::TARGET, ClosureLayerNodeMdl::create); registerImplementation("IM_layer_vdf_" + MdlShaderGenerator::TARGET, ClosureLayerNodeMdl::create); - registerImplementation("IM_mix_bsdf_" + MdlShaderGenerator::TARGET, MixBsdfNodeMdl::create); - registerImplementation("IM_add_bsdf_" + MdlShaderGenerator::TARGET, AddOrMultiplyBsdfNodeMdl::create); - registerImplementation("IM_multiply_bsdfC_" + MdlShaderGenerator::TARGET, AddOrMultiplyBsdfNodeMdl::create); - registerImplementation("IM_multiply_bsdfF_" + MdlShaderGenerator::TARGET, AddOrMultiplyBsdfNodeMdl::create); - - // - registerImplementation("IM_thin_film_bsdf_" + MdlShaderGenerator::TARGET, ClosureLayerNodeMdl::create); - // - registerImplementation("IM_dielectric_bsdf_" + MdlShaderGenerator::TARGET, ThinFilmReceiverNodeMdl::create); - - // - registerImplementation("IM_conductor_bsdf_" + MdlShaderGenerator::TARGET, ThinFilmReceiverNodeMdl::create); + registerImplementation("IM_dielectric_bsdf_" + MdlShaderGenerator::TARGET, LayerableNodeMdl::create); // - registerImplementation("IM_generalized_schlick_bsdf_" + MdlShaderGenerator::TARGET, ThinFilmReceiverNodeMdl::create); + registerImplementation("IM_generalized_schlick_bsdf_" + MdlShaderGenerator::TARGET, LayerableNodeMdl::create); // registerImplementation("IM_sheen_bsdf_" + MdlShaderGenerator::TARGET, LayerableNodeMdl::create); diff --git a/source/MaterialXGenMdl/Nodes/ClosureLayerNodeMdl.cpp b/source/MaterialXGenMdl/Nodes/ClosureLayerNodeMdl.cpp index fd27d5e547..1dfa45317f 100644 --- a/source/MaterialXGenMdl/Nodes/ClosureLayerNodeMdl.cpp +++ b/source/MaterialXGenMdl/Nodes/ClosureLayerNodeMdl.cpp @@ -16,17 +16,6 @@ MATERIALX_NAMESPACE_BEGIN const string StringConstantsMdl::TOP = "top"; const string StringConstantsMdl::BASE = "base"; -const string StringConstantsMdl::FG = "fg"; -const string StringConstantsMdl::BG = "bg"; -const string StringConstantsMdl::IN1 = "in1"; -const string StringConstantsMdl::IN2 = "in2"; - -const string StringConstantsMdl::THICKNESS = "thickness"; -const string StringConstantsMdl::IOR = "ior"; -const string StringConstantsMdl::THIN_FILM_THICKNESS = "thinfilm_thickness"; -const string StringConstantsMdl::THIN_FILM_IOR = "thinfilm_ior"; - -const string StringConstantsMdl::EMPTY = ""; ShaderNodeImplPtr ClosureLayerNodeMdl::create() { @@ -109,69 +98,11 @@ void ClosureLayerNodeMdl::emitFunctionCall(const ShaderNode& _node, GenContext& return; } - // Special composition based on the layers. - - // Handle the layering of thin film onto another node separately. - // This reads the parameters from the thin film bsdf and passes them to base. - if (top->hasClassification(ShaderNode::Classification::THINFILM)) - { - emitBsdfOverBsdfFunctionCalls_thinFilm(node, context, stage, shadergen, top, base, output); - return; - } - - // Otherwise, if the layer is carrying thin film parameters already, - // they are pushed further down to the top and base node if they supported it. - ShaderInput* layerNodeThicknessInput = node.getInput(StringConstantsMdl::THIN_FILM_THICKNESS); - ShaderInput* layerNodeIorInput = node.getInput(StringConstantsMdl::THIN_FILM_IOR); - - ShaderInput* topNodeThicknessInput = top->getInput(StringConstantsMdl::THIN_FILM_THICKNESS); - ShaderInput* topNodeIorInput = top->getInput(StringConstantsMdl::THIN_FILM_IOR); - bool breakTopConnection = false; - if (layerNodeThicknessInput && layerNodeIorInput && topNodeThicknessInput && topNodeIorInput) - { - topNodeThicknessInput->makeConnection(layerNodeThicknessInput->getConnection()); - topNodeIorInput->makeConnection(layerNodeIorInput->getConnection()); - breakTopConnection = true; - } - ShaderInput* baseNodeThicknessInput = base->getInput(StringConstantsMdl::THIN_FILM_THICKNESS); - ShaderInput* baseNodeIorInput = base->getInput(StringConstantsMdl::THIN_FILM_IOR); - bool breakBaseConnection = false; - if (layerNodeThicknessInput && layerNodeIorInput && baseNodeThicknessInput && baseNodeIorInput) - { - baseNodeThicknessInput->makeConnection(layerNodeThicknessInput->getConnection()); - baseNodeIorInput->makeConnection(layerNodeIorInput->getConnection()); - breakBaseConnection = true; - } - - // note, this called for all layering operations independent of thin film - emitBsdfOverBsdfFunctionCalls(node, context, stage, shadergen, top, base, output); - - if (breakTopConnection) - { - topNodeThicknessInput->breakConnection(); - topNodeIorInput->breakConnection(); - } - if (breakBaseConnection) - { - baseNodeThicknessInput->breakConnection(); - baseNodeIorInput->breakConnection(); - } -} - -void ClosureLayerNodeMdl::emitBsdfOverBsdfFunctionCalls( - const ShaderNode& node, - GenContext& context, - ShaderStage& stage, - const ShaderGenerator& shadergen, - ShaderNode* top, - ShaderNode* base, - ShaderOutput* output) const -{ - // transport the base bsdf further than one layer + // Transport the base bsdf further than one layer ShaderNode* baseReceiverNode = top; while (true) { - // if the top node is again a layer, we don't want to override the base + // If the top node is again a layer, we don't want to override the base // parameter but instead aim for the base parameter of layers base if (baseReceiverNode->hasClassification(ShaderNode::Classification::LAYER)) { @@ -230,58 +161,6 @@ void ClosureLayerNodeMdl::emitBsdfOverBsdfFunctionCalls( topNodeBaseInput->breakConnection(); } -void ClosureLayerNodeMdl::emitBsdfOverBsdfFunctionCalls_thinFilm( - const ShaderNode& node, - GenContext& context, - ShaderStage& stage, - const ShaderGenerator& shadergen, - ShaderNode* top, - ShaderNode* base, - ShaderOutput* output) const -{ - ShaderInput* thinFilmThicknessInput = top->getInput(StringConstantsMdl::THICKNESS); - ShaderInput* thinFilmIorInput = top->getInput(StringConstantsMdl::IOR); - - ShaderInput* baseNodeThicknessInput = base->getInput(StringConstantsMdl::THIN_FILM_THICKNESS); - ShaderInput* baseNodeIorInput = base->getInput(StringConstantsMdl::THIN_FILM_IOR); - - // Make sure the base node has thickness and IOR inputs for thin film. - if (!baseNodeThicknessInput || !baseNodeIorInput) - { - shadergen.emitComment("Warning: The base node does not have parameters to transport thin-film thickness and IOR.", stage); - - // Change the state so we emit the base BSDF function without thin film - // with output variable name from the layer node itself. - ScopedSetVariableName setVariable(output->getVariable(), base->getOutput()); - - // Make the call. - if (base->getParent() == node.getParent()) - { - base->getImplementation().emitFunctionCall(*base, context, stage); - } - return; - } - - // Emit the base operation with the thin-film parameters of the top node - // pushed down to the base node. - baseNodeThicknessInput->makeConnection(thinFilmThicknessInput->getConnection()); - baseNodeIorInput->makeConnection(thinFilmIorInput->getConnection()); - - // Change the output of this node to the output of base. - // This basically removes the top as it is not needed anymore. - ScopedSetVariableName setVariable(output->getVariable(), base->getOutput()); - - // Make the call. - if (base->getParent() == node.getParent()) - { - base->getImplementation().emitFunctionCall(*base, context, stage); - } - - // Restore state. - baseNodeThicknessInput->breakConnection(); - baseNodeIorInput->breakConnection(); -} - ShaderNodeImplPtr LayerableNodeMdl::create() { return std::make_shared(); @@ -293,106 +172,4 @@ void LayerableNodeMdl::addInputs(ShaderNode& node, GenContext& /*context*/) cons node.addInput(StringConstantsMdl::BASE, Type::BSDF); } -ShaderNodeImplPtr ThinFilmReceiverNodeMdl::create() -{ - return std::make_shared(); -} - -void ThinFilmCombineNodeMdl::emitFunctionCall(const ShaderNode& _node, GenContext& context, ShaderStage& stage) const -{ - const ShaderGenerator& shadergen = context.getShaderGenerator(); - ShaderNode& node = const_cast(_node); - - ShaderInput* topInput = node.getInput(getOperatorName(0)); - ShaderInput* baseInput = node.getInput(getOperatorName(1)); - - ShaderNode* top = topInput->getConnection()->getNode(); - ShaderNode* base = baseInput->getConnection()->getNode(); - - // Otherwise, if the combine node is carrying thin film parameters already, - // they are pushed further down to the top and base node if they supported it. - ShaderInput* layerNodeThicknessInput = node.getInput(StringConstantsMdl::THIN_FILM_THICKNESS); - ShaderInput* layerNodeIorInput = node.getInput(StringConstantsMdl::THIN_FILM_IOR); - - ShaderInput* topNodeThicknessInput = top->getInput(StringConstantsMdl::THIN_FILM_THICKNESS); - ShaderInput* topNodeIorInput = top->getInput(StringConstantsMdl::THIN_FILM_IOR); - bool breakTopConnection = false; - if (layerNodeThicknessInput && layerNodeIorInput && topNodeThicknessInput && topNodeIorInput) - { - topNodeThicknessInput->makeConnection(layerNodeThicknessInput->getConnection()); - topNodeIorInput->makeConnection(layerNodeIorInput->getConnection()); - breakTopConnection = true; - } - ShaderInput* baseNodeThicknessInput = base->getInput(StringConstantsMdl::THIN_FILM_THICKNESS); - ShaderInput* baseNodeIorInput = base->getInput(StringConstantsMdl::THIN_FILM_IOR); - bool breakBaseConnection = false; - if (layerNodeThicknessInput && layerNodeIorInput && baseNodeThicknessInput && baseNodeIorInput) - { - baseNodeThicknessInput->makeConnection(layerNodeThicknessInput->getConnection()); - baseNodeIorInput->makeConnection(layerNodeIorInput->getConnection()); - breakBaseConnection = true; - } - - // Emit the fore and background calls. - // Make sure it's a sibling node and not the graph interface. - if (top->getParent() == node.getParent()) - { - shadergen.emitFunctionCall(*top, context, stage); - } - if (base->getParent() == node.getParent()) - { - shadergen.emitFunctionCall(*base, context, stage); - } - - // Note, this is called for all combine operations independent of thin film. - Base::emitFunctionCall(_node, context, stage); - - if (breakTopConnection) - { - topNodeThicknessInput->breakConnection(); - topNodeIorInput->breakConnection(); - } - if (breakBaseConnection) - { - baseNodeThicknessInput->breakConnection(); - baseNodeIorInput->breakConnection(); - } -} - -ShaderNodeImplPtr MixBsdfNodeMdl::create() -{ - return std::make_shared(); -} - -const string& MixBsdfNodeMdl::getOperatorName(size_t index) const -{ - switch (index) - { - case 0: - return StringConstantsMdl::FG; - case 1: - return StringConstantsMdl::BG; - default: - return StringConstantsMdl::EMPTY; - } -} - -ShaderNodeImplPtr AddOrMultiplyBsdfNodeMdl::create() -{ - return std::make_shared(); -} - -const string& AddOrMultiplyBsdfNodeMdl::getOperatorName(size_t index) const -{ - switch (index) - { - case 0: - return StringConstantsMdl::IN1; - case 1: - return StringConstantsMdl::IN2; - default: - return StringConstantsMdl::EMPTY; - } -} - MATERIALX_NAMESPACE_END diff --git a/source/MaterialXGenMdl/Nodes/ClosureLayerNodeMdl.h b/source/MaterialXGenMdl/Nodes/ClosureLayerNodeMdl.h index 75ea46046c..729b835560 100644 --- a/source/MaterialXGenMdl/Nodes/ClosureLayerNodeMdl.h +++ b/source/MaterialXGenMdl/Nodes/ClosureLayerNodeMdl.h @@ -23,75 +23,15 @@ class MX_GENMDL_API StringConstantsMdl /// String constants static const string TOP; ///< layer parameter name of the top component static const string BASE; ///< layer parameter name of the base component - static const string FG; ///< parameter of the mix node - static const string BG; ///< parameter of the mix node - static const string IN1; ///< parameter of the add and multiply nodes - static const string IN2; ///< parameter of the add and multiply nodes - - static const string THICKNESS; ///< thickness parameter name of the thin_film_bsdf - static const string IOR; ///< ior parameter name of the thin_film_bsdf - - static const string THIN_FILM_THICKNESS; ///< helper parameter name for transporting thickness - static const string THIN_FILM_IOR; ///< helper parameter name for transporting ior - - static const string EMPTY; ///< the empty string "" -}; - -/// Helper class to be injected into nodes that need to carry thin film parameters from the -/// thin_film_bsdf through layers and mixers, etc., to the elemental bsdfs that support thin film. -/// Because thin-film can not be layered on any BSDF in MDL, we try to push down the parameters to -/// the nodes that support thin-film. -template class CarryThinFilmParameters : public TBase -{ - public: - /// Add the thin film inputs for transporting the parameter. - /// `addInputs` for the injected base class is called first. - void addInputs(ShaderNode& node, GenContext& context) const override - { - TBase::addInputs(node, context); - node.addInput(StringConstantsMdl::THIN_FILM_THICKNESS, Type::FLOAT); - node.addInput(StringConstantsMdl::THIN_FILM_IOR, Type::FLOAT); - } - - /// Mark the thin film parameters as not editable because connections are - /// created while emitting the MDL code and the default values should not - /// get exposed to the public material interface. - bool isEditable(const ShaderInput& input) const override - { - if (input.getName() == StringConstantsMdl::THIN_FILM_THICKNESS || - input.getName() == StringConstantsMdl::THIN_FILM_IOR) - { - return false; - } - return TBase::isEditable(input); - } }; /// Closure layer node implementation for MDL. -class MX_GENMDL_API ClosureLayerNodeMdl : public CarryThinFilmParameters +class MX_GENMDL_API ClosureLayerNodeMdl : public ShaderNodeImpl { public: static ShaderNodeImplPtr create(); void emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const override; - - void emitBsdfOverBsdfFunctionCalls( - const ShaderNode& node, - GenContext& context, - ShaderStage& stage, - const ShaderGenerator& shadergen, - ShaderNode* top, - ShaderNode* base, - ShaderOutput* output) const; - - void emitBsdfOverBsdfFunctionCalls_thinFilm( - const ShaderNode& node, - GenContext& context, - ShaderStage& stage, - const ShaderGenerator& shadergen, - ShaderNode* top, - ShaderNode* base, - ShaderOutput* output) const; }; /// Layerable BSDF node. @@ -107,49 +47,6 @@ class MX_GENMDL_API LayerableNodeMdl : public SourceCodeNodeMdl void addInputs(ShaderNode& node, GenContext&) const override; }; -/// Used for elemental nodes that can consume thin film. -class MX_GENMDL_API ThinFilmReceiverNodeMdl : public CarryThinFilmParameters -{ - using Base = CarryThinFilmParameters; - - public: - static ShaderNodeImplPtr create(); -}; - -/// Base class for operators that on bsdfs that need to transport the thin film parameters -class ThinFilmCombineNodeMdl : public CarryThinFilmParameters -{ - using Base = CarryThinFilmParameters; - - public: - virtual ~ThinFilmCombineNodeMdl() = default; - - void emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const override; - - protected: - virtual const string& getOperatorName(size_t index) const = 0; -}; - -/// Used for mix_bsdf nodes. -class MX_GENMDL_API MixBsdfNodeMdl : public ThinFilmCombineNodeMdl -{ - public: - static ShaderNodeImplPtr create(); - - protected: - virtual const string& getOperatorName(size_t index) const final; -}; - -/// Used for add_bsdf and multpli_bsdf nodes. -class MX_GENMDL_API AddOrMultiplyBsdfNodeMdl : public ThinFilmCombineNodeMdl -{ - public: - static ShaderNodeImplPtr create(); - - protected: - virtual const string& getOperatorName(size_t index) const final; -}; - MATERIALX_NAMESPACE_END #endif diff --git a/source/MaterialXGenMdl/mdl/materialx/pbrlib.mdl b/source/MaterialXGenMdl/mdl/materialx/pbrlib.mdl index 61234c4037..3f285890bd 100644 --- a/source/MaterialXGenMdl/mdl/materialx/pbrlib.mdl +++ b/source/MaterialXGenMdl/mdl/materialx/pbrlib.mdl @@ -147,13 +147,13 @@ export material mx_dielectric_bsdf( color mxp_tint = color(1.0), float mxp_ior = 1.5, float2 mxp_roughness = float2(0.0), + float mxp_thinfilm_thickness = 0.0, + float mxp_thinfilm_ior = 1.0, float3 mxp_normal = state::normal(), float3 mxp_tangent = state::texture_tangent_u(0), uniform mx_distribution_type mxp_distribution = mx_distribution_type_ggx [[ anno::unused() ]], uniform mx_scatter_mode mxp_scatter_mode = mx_scatter_mode_R, - material mxp_base = material() [[ anno::usage( "materialx:bsdf") ]], - float mxp_thinfilm_thickness = 0.0, - float mxp_thinfilm_ior = 1.0 + material mxp_base = material() [[ anno::usage( "materialx:bsdf") ]] ) [[ anno::usage( "materialx:bsdf") ]] @@ -220,11 +220,11 @@ export material mx_conductor_bsdf( color mxp_ior = color(0.18, 0.42, 1.37), color mxp_extinction = color(3.42, 2.35, 1.77), float2 mxp_roughness = float2(0.0), + float mxp_thinfilm_thickness = 0.0, + float mxp_thinfilm_ior = 1.0, float3 mxp_normal = state::normal(), float3 mxp_tangent = state::texture_tangent_u(0), - uniform mx_distribution_type mxp_distribution = mx_distribution_type_ggx [[ anno::unused() ]], - float mxp_thinfilm_thickness = 0.0, - float mxp_thinfilm_ior = 1.0 + uniform mx_distribution_type mxp_distribution = mx_distribution_type_ggx [[ anno::unused() ]] ) [[ anno::usage( "materialx:bsdf") ]] @@ -261,13 +261,13 @@ export material mx_generalized_schlick_bsdf( color mxp_color90 = color(1.0), float mxp_exponent = 5.0, float2 mxp_roughness = float2(0.05), + float mxp_thinfilm_thickness = 0.0, + float mxp_thinfilm_ior = 1.0, float3 mxp_normal = state::normal(), float3 mxp_tangent = state::texture_tangent_u(0), uniform mx_distribution_type mxp_distribution = mx_distribution_type_ggx [[ anno::unused() ]], uniform mx_scatter_mode mxp_scatter_mode = mx_scatter_mode_R, - material mxp_base = material() [[ anno::usage( "materialx:bsdf") ]], - float mxp_thinfilm_thickness = 0.0, - float mxp_thinfilm_ior = 1.0 + material mxp_base = material() [[ anno::usage( "materialx:bsdf") ]] ) [[ anno::usage( "materialx:bsdf") ]] @@ -399,26 +399,6 @@ export material mx_sheen_bsdf( volume: mxp_base.volume ); -export material mx_thin_film_bsdf( - float mxp_thickness = 1000.0, - float mxp_ior = 1.5, - material mxp_base = material() [[ anno::usage( "materialx:bsdf") ]] -) [[ - anno::usage( "materialx:bsdf") -]] -= material( - surface: material_surface( - scattering: df::thin_film( - thickness: mxp_thickness, - ior: color(mxp_ior), - base: mxp_base.surface.scattering - ) - ), - // we need to carry volume properties along for SSS - ior: mxp_base.ior, - volume: mxp_base.volume -); - // EDF Nodes export material mx_uniform_edf( diff --git a/source/MaterialXGenOsl/Nodes/ClosureLayerNodeOsl.cpp b/source/MaterialXGenOsl/Nodes/ClosureLayerNodeOsl.cpp index 7c3f9d460c..b77eebbd86 100644 --- a/source/MaterialXGenOsl/Nodes/ClosureLayerNodeOsl.cpp +++ b/source/MaterialXGenOsl/Nodes/ClosureLayerNodeOsl.cpp @@ -41,111 +41,68 @@ void ClosureLayerNodeOsl::emitFunctionCall(const ShaderNode& _node, GenContext& ClosureContext* cct = context.getClosureContext(); - if (top->hasClassification(ShaderNode::Classification::THINFILM)) + // Evaluate top and base nodes and combine their result + // according to throughput. + // + // TODO: In the BSDF over BSDF case should we emit code + // to check the top throughput amount before calling + // the base BSDF? + + // Make sure the connections are sibling nodes and not the graph interface. + if (top->getParent() == node.getParent()) { - // This is a layer node with thin-film as top layer. - // Call only the base BSDF but with thin-film parameters set. - - // Make sure the connection to base is a sibling node and not the graph interface. - if (base->getParent() != node.getParent()) - { - throw ExceptionShaderGenError("Thin-film can only be applied to a sibling node, not through a graph interface"); - } - - // Set the extra parameters for thin-film. - ClosureContext::ClosureParams params; - params[THICKNESS] = top->getInput(THICKNESS); - params[IOR] = top->getInput(IOR); - ScopedSetClosureParams setParams(¶ms, base, cct); + // If this layer node has closure parameters set, + // we pass this on to the top component only. + ScopedSetClosureParams setParams(&node, top, cct); + shadergen.emitFunctionCall(*top, context, stage); + } + if (base->getParent() == node.getParent()) + { + shadergen.emitFunctionCall(*base, context, stage); + } - // Store the base result in the layer result variable. - ScopedSetVariableName setVariable(output->getVariable(), base->getOutput()); + // Get the result variables. + const string& topResult = topInput->getConnection()->getVariable(); + const string& baseResult = baseInput->getConnection()->getVariable(); - // Emit the function call. - shadergen.emitFunctionCall(*base, context, stage); + // Calculate the layering result. + emitOutputVariables(node, context, stage); + if (base->getOutput()->getType() == Type::VDF) + { + // Combining a surface closure with a volumetric closure is simply done with the add operator in OSL. + shadergen.emitLine(output->getVariable() + ".response = " + topResult + ".response + " + baseResult, stage); + // Just pass the throughput along. + shadergen.emitLine(output->getVariable() + ".throughput = " + topResult + ".throughput", stage); } else { - // Evaluate top and base nodes and combine their result - // according to throughput. - // - // TODO: In the BSDF over BSDF case should we emit code - // to check the top throughput amount before calling - // the base BSDF? - - // Make sure the connections are sibling nodes and not the graph interface. - if (top->getParent() == node.getParent()) - { - // If this layer node has closure parameters set, - // we pass this on to the top component only. - ScopedSetClosureParams setParams(&node, top, cct); - shadergen.emitFunctionCall(*top, context, stage); - } - if (base->getParent() == node.getParent()) - { - shadergen.emitFunctionCall(*base, context, stage); - } - - // Get the result variables. - const string& topResult = topInput->getConnection()->getVariable(); - const string& baseResult = baseInput->getConnection()->getVariable(); - - // Calculate the layering result. - emitOutputVariables(node, context, stage); - if (base->getOutput()->getType() == Type::VDF) - { - // Combining a surface closure with a volumetric closure is simply done with the add operator in OSL. - shadergen.emitLine(output->getVariable() + ".response = " + topResult + ".response + " + baseResult, stage); - // Just pass the throughput along. - shadergen.emitLine(output->getVariable() + ".throughput = " + topResult + ".throughput", stage); - } - else - { - shadergen.emitLine(output->getVariable() + ".response = " + topResult + ".response + " + baseResult + ".response * " + topResult + ".throughput", stage); - shadergen.emitLine(output->getVariable() + ".throughput = " + topResult + ".throughput * " + baseResult + ".throughput", stage); - } + shadergen.emitLine(output->getVariable() + ".response = " + topResult + ".response + " + baseResult + ".response * " + topResult + ".throughput", stage); + shadergen.emitLine(output->getVariable() + ".throughput = " + topResult + ".throughput * " + baseResult + ".throughput", stage); } #else - if (top->hasClassification(ShaderNode::Classification::THINFILM)) + // Emit the function call for top and base layer. + // Make sure the connections are sibling nodes and not the graph interface. + if (top->getParent() == node.getParent()) { - // Make sure the connection to base is a sibling node and not the graph interface. - if (base->getParent() != node.getParent()) - { - throw ExceptionShaderGenError("Thin-film can only be applied to a sibling node, not through a graph interface"); - } - - // TODO: Thin-film is not supported yet. - // Emit the function call for base layer but - // store the base result in the layer result variable. - ScopedSetVariableName setVariable(output->getVariable(), base->getOutput()); - shadergen.emitFunctionCall(*base, context, stage); + shadergen.emitFunctionCall(*top, context, stage); } - else + if (base->getParent() == node.getParent()) { - // Emit the function call for top and base layer. - // Make sure the connections are sibling nodes and not the graph interface. - if (top->getParent() == node.getParent()) - { - shadergen.emitFunctionCall(*top, context, stage); - } - if (base->getParent() == node.getParent()) - { - shadergen.emitFunctionCall(*base, context, stage); - } - - // Get the result variables. - const string& topResult = topInput->getConnection()->getVariable(); - const string& baseResult = baseInput->getConnection()->getVariable(); - - // Emit the layer closure call. - shadergen.emitLineBegin(stage); - shadergen.emitOutput(output, true, false, context, stage); - shadergen.emitString(" = layer(" + topResult + ", " + baseResult + ")", stage); - shadergen.emitLineEnd(stage); + shadergen.emitFunctionCall(*base, context, stage); } + // Get the result variables. + const string& topResult = topInput->getConnection()->getVariable(); + const string& baseResult = baseInput->getConnection()->getVariable(); + + // Emit the layer closure call. + shadergen.emitLineBegin(stage); + shadergen.emitOutput(output, true, false, context, stage); + shadergen.emitString(" = layer(" + topResult + ", " + baseResult + ")", stage); + shadergen.emitLineEnd(stage); + #endif // MATERIALX_OSL_LEGACY_CLOSURES } diff --git a/source/MaterialXGenOsl/OslSyntax.cpp b/source/MaterialXGenOsl/OslSyntax.cpp index d421c5e3d9..68888c6440 100644 --- a/source/MaterialXGenOsl/OslSyntax.cpp +++ b/source/MaterialXGenOsl/OslSyntax.cpp @@ -451,10 +451,10 @@ OslSyntax::OslSyntax() Type::BSDF, std::make_shared( "BSDF", - "BSDF(null_closure, color(1.0), 0.0, 0.0)", - "{ 0, color(1.0), 0.0, 0.0 }", + "BSDF(null_closure, color(1.0))", + "{ 0, color(1.0) }", "closure color", - "struct BSDF { closure color response; color throughput; float thickness; float ior; };")); + "struct BSDF { closure color response; color throughput; };")); #else diff --git a/source/MaterialXGenShader/Nodes/ClosureLayerNode.cpp b/source/MaterialXGenShader/Nodes/ClosureLayerNode.cpp index a2554365c1..32127de997 100644 --- a/source/MaterialXGenShader/Nodes/ClosureLayerNode.cpp +++ b/source/MaterialXGenShader/Nodes/ClosureLayerNode.cpp @@ -12,8 +12,6 @@ MATERIALX_NAMESPACE_BEGIN const string ClosureLayerNode::TOP = "top"; const string ClosureLayerNode::BASE = "base"; -const string ClosureLayerNode::THICKNESS = "thickness"; -const string ClosureLayerNode::IOR = "ior"; ShaderNodeImplPtr ClosureLayerNode::create() { @@ -44,67 +42,41 @@ void ClosureLayerNode::emitFunctionCall(const ShaderNode& _node, GenContext& con ShaderNode* top = topInput->getConnection()->getNode(); ShaderNode* base = baseInput->getConnection()->getNode(); - if (top->hasClassification(ShaderNode::Classification::THINFILM)) - { - // This is a layer node with thin-film as top layer. - // Call only the base BSDF but with thin-film parameters set. - - // Make sure the connection to base is a sibling node and not the graph interface. - if (base->getParent() != node.getParent()) - { - throw ExceptionShaderGenError("Thin-film can only be applied to a sibling node, not through a graph interface"); - } + // Evaluate top and base nodes and combine their result + // according to throughput. + // + // TODO: In the BSDF over BSDF case should we emit code + // to check the top throughput amount before calling + // the base BSDF? - // Set the extra parameters for thin-film. - ClosureContext::ClosureParams params; - params[THICKNESS] = top->getInput(THICKNESS); - params[IOR] = top->getInput(IOR); - ScopedSetClosureParams setParams(¶ms, base, cct); + // Make sure the connections are sibling nodes and not the graph interface. + if (top->getParent() == node.getParent()) + { + // If this layer node has closure parameters set, + // we pass this on to the top component only. + ScopedSetClosureParams setParams(&node, top, cct); + shadergen.emitFunctionCall(*top, context, stage); + } + if (base->getParent() == node.getParent()) + { + shadergen.emitFunctionCall(*base, context, stage); + } - // Store the base result in the layer result variable. - ScopedSetVariableName setVariable(output->getVariable(), base->getOutput()); + // Get the result variables. + const string& topResult = topInput->getConnection()->getVariable(); + const string& baseResult = baseInput->getConnection()->getVariable(); - // Emit the function call. - shadergen.emitFunctionCall(*base, context, stage); + // Calculate the layering result. + emitOutputVariables(node, context, stage); + if (base->getOutput()->getType() == Type::VDF) + { + shadergen.emitLine(output->getVariable() + ".response = " + topResult + ".response * " + baseResult + ".throughput", stage); + shadergen.emitLine(output->getVariable() + ".throughput = " + topResult + ".throughput * " + baseResult + ".throughput", stage); } else { - // Evaluate top and base nodes and combine their result - // according to throughput. - // - // TODO: In the BSDF over BSDF case should we emit code - // to check the top throughput amount before calling - // the base BSDF? - - // Make sure the connections are sibling nodes and not the graph interface. - if (top->getParent() == node.getParent()) - { - // If this layer node has closure parameters set, - // we pass this on to the top component only. - ScopedSetClosureParams setParams(&node, top, cct); - shadergen.emitFunctionCall(*top, context, stage); - } - if (base->getParent() == node.getParent()) - { - shadergen.emitFunctionCall(*base, context, stage); - } - - // Get the result variables. - const string& topResult = topInput->getConnection()->getVariable(); - const string& baseResult = baseInput->getConnection()->getVariable(); - - // Calculate the layering result. - emitOutputVariables(node, context, stage); - if (base->getOutput()->getType() == Type::VDF) - { - shadergen.emitLine(output->getVariable() + ".response = " + topResult + ".response * " + baseResult + ".throughput", stage); - shadergen.emitLine(output->getVariable() + ".throughput = " + topResult + ".throughput * " + baseResult + ".throughput", stage); - } - else - { - shadergen.emitLine(output->getVariable() + ".response = " + topResult + ".response + " + baseResult + ".response * " + topResult + ".throughput", stage); - shadergen.emitLine(output->getVariable() + ".throughput = " + topResult + ".throughput * " + baseResult + ".throughput", stage); - } + shadergen.emitLine(output->getVariable() + ".response = " + topResult + ".response + " + baseResult + ".response * " + topResult + ".throughput", stage); + shadergen.emitLine(output->getVariable() + ".throughput = " + topResult + ".throughput * " + baseResult + ".throughput", stage); } } }