diff --git a/source/blender/io/usd/hydra/material.cc b/source/blender/io/usd/hydra/material.cc index afc5048efb2..095ab4f1bbc 100644 --- a/source/blender/io/usd/hydra/material.cc +++ b/source/blender/io/usd/hydra/material.cc @@ -83,7 +83,7 @@ void MaterialData::init() scene_delegate_->depsgraph, (Material *)id, cache_or_get_image_file); pxr::UsdMtlxRead(doc, stage); - /* Logging stage: creating lambda stage_str() for not to call stage->ExportToString() + /* Logging stage: creating lambda stage_str() to not call stage->ExportToString() * if log won't be printed. */ auto stage_str = [&stage]() { std::string str; diff --git a/source/blender/nodes/shader/materialx/node_item.cc b/source/blender/nodes/shader/materialx/node_item.cc index 58dbf289aac..bcb7bdf52f9 100644 --- a/source/blender/nodes/shader/materialx/node_item.cc +++ b/source/blender/nodes/shader/materialx/node_item.cc @@ -182,6 +182,38 @@ NodeItem NodeItem::operator^(const NodeItem &other) const return arithmetic(other, "power", [](float a, float b) { return std::powf(a, b); }); } +NodeItem NodeItem::operator[](int index) const +{ + BLI_assert(is_arithmetic(type())); + + if (value) { + float v = 0.0f; + switch (type()) { + case Type::Float: + v = value->asA(); + break; + case Type::Vector2: + v = value->asA()[index]; + case Type::Vector3: + v = value->asA()[index]; + break; + case Type::Vector4: + v = value->asA()[index]; + break; + case Type::Color3: + v = value->asA()[index]; + break; + case Type::Color4: + v = value->asA()[index]; + break; + default: + BLI_assert_unreachable(); + } + return val(v); + } + return create_node("extract", Type::Float, {{"in", *this}, {"index", val(index)}}); +} + bool NodeItem::operator==(const NodeItem &other) const { if (!*this) { @@ -226,6 +258,22 @@ NodeItem NodeItem::ceil() const return arithmetic("ceil", [](float a) { return std::ceilf(a); }); } +NodeItem NodeItem::length() const +{ + if (value) { + return dotproduct(*this).sqrt(); + } + return create_node("magnitude", Type::Float, {{"in", to_vector()}}); +} + +NodeItem NodeItem::normalize() const +{ + if (value) { + return *this / length(); + } + return create_node("normalize", Type::Vector3, {{"in", to_vector()}}); +} + NodeItem NodeItem::min(const NodeItem &other) const { return arithmetic(other, "min", [](float a, float b) { return std::min(a, b); }); @@ -238,56 +286,86 @@ NodeItem NodeItem::max(const NodeItem &other) const NodeItem NodeItem::dotproduct(const NodeItem &other) const { - NodeItem d = arithmetic( - other, "dotproduct", [](float a, float b) { return a * b; }, Type::Float); - if (d.value) { + if (value && other.value) { + NodeItem d = *this * other; float f = 0.0f; switch (d.type()) { case Type::Float: { - f = value->asA(); + f = d.value->asA(); break; } case Type::Vector2: { - auto v = value->asA(); + auto v = d.value->asA(); f = v[0] + v[1]; break; } case Type::Vector3: { - auto v = value->asA(); + auto v = d.value->asA(); f = v[0] + v[1] + v[2]; break; } case Type::Vector4: { - auto v = value->asA(); + auto v = d.value->asA(); f = v[0] + v[1] + v[2] + v[3]; break; } case Type::Color3: { - auto v = value->asA(); + auto v = d.value->asA(); f = v[0] + v[1] + v[2]; break; } case Type::Color4: { - auto v = value->asA(); + auto v = d.value->asA(); f = v[0] + v[1] + v[2] + v[3]; break; } default: BLI_assert_unreachable(); } - d.value = MaterialX::Value::createValue(f); + return val(f); } - return d; + + NodeItem item1 = to_vector(); + NodeItem item2 = other.to_vector(); + cast_types(item1, item2); + return create_node("dotproduct", Type::Float, {{"in1", item1}, {"in2", item2}}); } -NodeItem NodeItem::blend(const NodeItem &a, const NodeItem &b) const +NodeItem NodeItem::mix(const NodeItem &val1, const NodeItem &val2) const { - return (val(1.0f) - *this) * a + *this * b; + if ((value && val1.value && val2.value) || type() != Type::Float) { + return (val(1.0f) - *this) * val1 + *this * val2; + } + + Type type1 = val1.type(); + if (ELEM(type1, Type::BSDF, Type::EDF)) { + BLI_assert(val2.type() == type1); + + /* Special case: mix BSDF/EDF shaders */ + return create_node("mix", type1, {{"bg", val1}, {"fg", val2}, {"mix", *this}}); + }; + + NodeItem item1 = val1; + NodeItem item2 = val2; + Type to_type = cast_types(item1, item2); + return create_node("mix", to_type, {{"bg", item1}, {"fg", item2}, {"mix", *this}}); } NodeItem NodeItem::clamp(const NodeItem &min_val, const NodeItem &max_val) const { - return min(max_val).max(min_val); + if (value && min_val.value && max_val.value) { + return min(max_val).max(min_val); + } + + if (min_val.type() == Type::Float && max_val.type() == Type::Float) { + return create_node("clamp", type(), {{"in", *this}, {"low", min_val}, {"high", max_val}}); + } + + Type type = this->type(); + return create_node( + "clamp", + type, + {{"in", *this}, {"low", min_val.convert(type)}, {"high", max_val.convert(type)}}); } NodeItem NodeItem::clamp(float min_val, float max_val) const @@ -295,64 +373,95 @@ NodeItem NodeItem::clamp(float min_val, float max_val) const return clamp(val(min_val), val(max_val)); } +NodeItem NodeItem::rotate(const NodeItem &angle, const NodeItem &axis) +{ + BLI_assert(type() == Type::Vector3); + BLI_assert(angle.type() == Type::Float); + BLI_assert(axis.type() == Type::Vector3); + + return create_node( + "rotate3d", NodeItem::Type::Vector3, {{"in", *this}, {"amount", angle}, {"axis", axis}}); +} + +NodeItem NodeItem::rotate(const NodeItem &angle_xyz, bool invert) +{ + NodeItem x = angle_xyz[0]; + NodeItem y = angle_xyz[1]; + NodeItem z = angle_xyz[2]; + if (invert) { + return rotate(z, val(MaterialX::Vector3(0.0f, 0.0f, 1.0f))) + .rotate(y, val(MaterialX::Vector3(0.0f, 1.0f, 0.0f))) + .rotate(x, val(MaterialX::Vector3(1.0f, 0.0f, 0.0f))); + } + return rotate(x, val(MaterialX::Vector3(1.0f, 0.0f, 0.0f))) + .rotate(y, val(MaterialX::Vector3(0.0f, 1.0f, 0.0f))) + .rotate(z, val(MaterialX::Vector3(0.0f, 0.0f, 1.0f))); +} + NodeItem NodeItem::sin() const { - return arithmetic("sin", [](float a) { return std::sinf(a); }); + return to_vector().arithmetic("sin", [](float a) { return std::sinf(a); }); } NodeItem NodeItem::cos() const { - return arithmetic("cos", [](float a) { return std::cosf(a); }); + return to_vector().arithmetic("cos", [](float a) { return std::cosf(a); }); } NodeItem NodeItem::tan() const { - return arithmetic("tan", [](float a) { return std::tanf(a); }); + return to_vector().arithmetic("tan", [](float a) { return std::tanf(a); }); } NodeItem NodeItem::asin() const { - return arithmetic("asin", [](float a) { return std::asinf(a); }); + return to_vector().arithmetic("asin", [](float a) { return std::asinf(a); }); } NodeItem NodeItem::acos() const { - return arithmetic("acos", [](float a) { return std::acosf(a); }); + return to_vector().arithmetic("acos", [](float a) { return std::acosf(a); }); } NodeItem NodeItem::atan() const { - return arithmetic("atan", [](float a) { return std::atanf(a); }); + return to_vector().arithmetic("atan", [](float a) { return std::atanf(a); }); } NodeItem NodeItem::atan2(const NodeItem &other) const { - return arithmetic(other, "atan2", [](float a, float b) { return std::atan2f(a, b); }); + return to_vector().arithmetic( + other, "atan2", [](float a, float b) { return std::atan2f(a, b); }); } NodeItem NodeItem::sinh() const { - return (exp() - (-*this).exp()) / val(2.0f); + NodeItem v = to_vector(); + return (v.exp() - (-v).exp()) / val(2.0f); } NodeItem NodeItem::cosh() const { - return (exp() - (-*this).exp()) / val(2.0f); + NodeItem v = to_vector(); + return (v.exp() + (-v).exp()) / val(2.0f); } NodeItem NodeItem::tanh() const { - return sinh() / cosh(); + NodeItem v = to_vector(); + NodeItem a = v.exp(); + NodeItem b = (-v).exp(); + return (a - b) / (a + b); } NodeItem NodeItem::ln() const { - return arithmetic("ln", [](float a) { return std::logf(a); }); + return to_vector().arithmetic("ln", [](float a) { return std::logf(a); }); } NodeItem NodeItem::sqrt() const { - return arithmetic("sqrt", [](float a) { return std::sqrtf(a); }); + return to_vector().arithmetic("sqrt", [](float a) { return std::sqrtf(a); }); } NodeItem NodeItem::sign() const @@ -362,7 +471,7 @@ NodeItem NodeItem::sign() const NodeItem NodeItem::exp() const { - return arithmetic("exp", [](float a) { return std::expf(a); }); + return to_vector().arithmetic("exp", [](float a) { return std::expf(a); }); } NodeItem NodeItem::convert(Type to_type) const @@ -380,7 +489,7 @@ NodeItem NodeItem::convert(Type to_type) const } if (to_type == Type::Float) { - return extract(0); + return (*this)[0]; } /* Converting types which requires > 1 iteration */ @@ -548,6 +657,27 @@ NodeItem NodeItem::convert(Type to_type) const return res; } +NodeItem NodeItem::to_vector() const +{ + switch (type()) { + case Type::Float: + case Type::Vector2: + case Type::Vector3: + case Type::Vector4: + return *this; + + case Type::Color3: + return convert(Type::Vector3); + + case Type::Color4: + return convert(Type::Vector4); + + default: + BLI_assert_unreachable(); + } + return empty(); +} + NodeItem NodeItem::if_else(CompareOp op, const NodeItem &other, const NodeItem &if_val, @@ -606,35 +736,11 @@ NodeItem NodeItem::if_else(CompareOp op, return res; } -NodeItem NodeItem::extract(const int index) const -{ - /* TODO: Add check if (value) { ... } */ - NodeItem res = create_node("extract", Type::Float, {{"in", *this}, {"index", val(index)}}); - return res; -} - NodeItem NodeItem::empty() const { return NodeItem(graph_); } -NodeItem NodeItem::rotate3d(NodeItem rotation, bool invert) -{ - NodeItem res = *this; - if (res.type() == Type::Vector3 && rotation.type() == Type::Vector3) { - for (int i = 0; i <= 2; i++) { - int j = invert ? 2 - i : i; - MaterialX::Vector3 axis_vector = MaterialX::Vector3(); - axis_vector[j] = 1.0f; - res = create_node( - "rotate3d", - NodeItem::Type::Vector3, - {{"in", res}, {"amount", rotation.extract(j)}, {"axis", val(axis_vector)}}); - } - } - return res; -} - NodeItem::Type NodeItem::type() const { if (value) { @@ -794,9 +900,7 @@ NodeItem NodeItem::arithmetic(const std::string &category, std::functiontype(); - if (!is_arithmetic(type)) { - return res; - } + BLI_assert(is_arithmetic(type)); if (value) { switch (type) { @@ -838,15 +942,7 @@ NodeItem NodeItem::arithmetic(const std::string &category, std::function>; @@ -21,22 +23,22 @@ class NodeItem { Any = 0, Empty, Multioutput, + /* Value types */ String, Filename, Boolean, Integer, - /* Block of arithmetic types. Ordered by type cast */ + + /* Arithmetic types. NOTE: Ordered by type cast */ Float, Vector2, Vector3, Color3, Vector4, Color4, - /* End of arithmetic types */ - /* Shader types - * NOTE: There are only supported types */ + /* Shader types. NOTE: There are only supported types */ BSDF, EDF, Displacementshader, @@ -74,6 +76,7 @@ class NodeItem { NodeItem operator/(const NodeItem &other) const; NodeItem operator%(const NodeItem &other) const; NodeItem operator^(const NodeItem &other) const; + NodeItem operator[](int index) const; bool operator==(const NodeItem &other) const; bool operator!=(const NodeItem &other) const; @@ -81,12 +84,16 @@ class NodeItem { NodeItem abs() const; NodeItem floor() const; NodeItem ceil() const; + NodeItem length() const; + NodeItem normalize() const; NodeItem min(const NodeItem &other) const; NodeItem max(const NodeItem &other) const; NodeItem dotproduct(const NodeItem &other) const; - NodeItem blend(const NodeItem &a, const NodeItem &b) const; + NodeItem mix(const NodeItem &val1, const NodeItem &val2) const; NodeItem clamp(const NodeItem &min_val, const NodeItem &max_val) const; NodeItem clamp(float min_val = 0.0f, float max_val = 1.0f) const; + NodeItem rotate(const NodeItem &angle, const NodeItem &axis); /* angle in degrees */ + NodeItem rotate(const NodeItem &angle_xyz, bool invert = false); /* angle in degrees */ NodeItem sin() const; NodeItem cos() const; NodeItem tan() const; @@ -102,15 +109,14 @@ class NodeItem { NodeItem sign() const; NodeItem exp() const; NodeItem convert(Type to_type) const; + NodeItem to_vector() const; NodeItem if_else(CompareOp op, const NodeItem &other, const NodeItem &if_val, const NodeItem &else_val) const; - NodeItem extract(const int index) const; /* Useful functions */ NodeItem empty() const; - NodeItem rotate3d(NodeItem rotation, bool invert = false); template NodeItem val(const T &data) const; Type type() const; diff --git a/source/blender/nodes/shader/materialx/node_parser.cc b/source/blender/nodes/shader/materialx/node_parser.cc index e22681cbe63..2f14a971ecb 100644 --- a/source/blender/nodes/shader/materialx/node_parser.cc +++ b/source/blender/nodes/shader/materialx/node_parser.cc @@ -148,13 +148,18 @@ NodeItem NodeParser::empty() const return NodeItem(graph_); } -NodeItem NodeParser::texcoord_node() +NodeItem NodeParser::texcoord_node(NodeItem::Type type) { + BLI_assert(ELEM(type, NodeItem::Type::Vector2, NodeItem::Type::Vector3)); + std::string name = TEXCOORD_NODE_NAME; + if (type == NodeItem::Type::Vector3) { + name += "_vector3"; + } NodeItem res = empty(); - res.node = graph_->getNode(TEXCOORD_NODE_NAME); + res.node = graph_->getNode(name); if (!res.node) { - res = create_node("texcoord", NodeItem::Type::Vector2); - res.node->setName(TEXCOORD_NODE_NAME); + res = create_node("texcoord", type); + res.node->setName(name); } return res; } diff --git a/source/blender/nodes/shader/materialx/node_parser.h b/source/blender/nodes/shader/materialx/node_parser.h index 4bc332442c6..6a93ad38f0f 100644 --- a/source/blender/nodes/shader/materialx/node_parser.h +++ b/source/blender/nodes/shader/materialx/node_parser.h @@ -20,6 +20,10 @@ class GroupNodeParser; using ExportImageFunction = std::function; +/** + * This is base abstraction class for parsing Blender nodes into MaterialX nodes. + * NodeParser::compute() should be overrided in child classes. + */ class NodeParser { protected: MaterialX::GraphElement *graph_; @@ -63,7 +67,7 @@ class NodeParser { NodeItem get_input_value(int index, NodeItem::Type to_type); NodeItem empty() const; template NodeItem val(const T &data) const; - NodeItem texcoord_node(); + NodeItem texcoord_node(NodeItem::Type type = NodeItem::Type::Vector2); private: NodeItem get_default(const bNodeSocket &socket, NodeItem::Type to_type); @@ -76,8 +80,21 @@ template NodeItem NodeParser::val(const T &data) const return empty().val(data); } -/* +/** * Defines for including MaterialX node parsing code into node_shader_.cc + * + * Example: + * \code{.c} + * NODE_SHADER_MATERIALX_BEGIN + * #ifdef WITH_MATERIALX + * { + * NodeItem color = get_input_value("Color", NodeItem::Type::Color4); + * NodeItem gamma = get_input_value("Gamma", NodeItem::Type::Float); + * return color ^ gamma; + * } + * #endif + * NODE_SHADER_MATERIALX_END + * \endcode */ struct NodeParserData { MaterialX::GraphElement *graph; diff --git a/source/blender/nodes/shader/nodes/node_shader_add_shader.cc b/source/blender/nodes/shader/nodes/node_shader_add_shader.cc index 7f5ba0162d7..6e0e0a81a51 100644 --- a/source/blender/nodes/shader/nodes/node_shader_add_shader.cc +++ b/source/blender/nodes/shader/nodes/node_shader_add_shader.cc @@ -25,36 +25,23 @@ static int node_shader_gpu_add_shader(GPUMaterial *mat, NODE_SHADER_MATERIALX_BEGIN #ifdef WITH_MATERIALX { - NodeItem res = empty(); - switch (to_type_) { - case NodeItem::Type::BSDF: - case NodeItem::Type::EDF: { - NodeItem shader1 = get_input_link(0, to_type_); - NodeItem shader2 = get_input_link(1, to_type_); - - if (shader1 && !shader2) { - res = shader1; - } - else if (!shader1 && shader2) { - res = shader2; - } - else if (shader1 && shader2) { - res = shader1 + shader2; - } - break; - } - case NodeItem::Type::SurfaceShader: { - /* SurfaceShaders can't be added, returning the first one connected */ - res = get_input_link(0, to_type_); - if (!res) { - res = get_input_link(1, to_type_); - } - break; - } - default: - BLI_assert_unreachable(); + if (!ELEM(to_type_, NodeItem::Type::BSDF, NodeItem::Type::EDF)) { + return empty(); } - return res; + + NodeItem shader1 = get_input_link(0, to_type_); + NodeItem shader2 = get_input_link(1, to_type_); + if (!shader1 && !shader2) { + return empty(); + } + + if (shader1 && !shader2) { + return shader1; + } + if (!shader1 && shader2) { + return shader2; + } + return shader1 + shader2; } #endif NODE_SHADER_MATERIALX_END diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.cc b/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.cc index ada2bb7be86..6a8b16ef14b 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.cc +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.cc @@ -289,9 +289,11 @@ static void node_shader_update_principled(bNodeTree *ntree, bNode *node) NODE_SHADER_MATERIALX_BEGIN #ifdef WITH_MATERIALX { + using InputsType = std::map; + /* NOTE: commented inputs aren't used for node creation. */ - auto bsdf_inputs = [&]() { - return std::map{ + auto bsdf_inputs = [&]() -> InputsType { + return { {"base_color", get_input_value("Base Color", NodeItem::Type::Color3)}, {"subsurface", get_input_value("Subsurface", NodeItem::Type::Float)}, {"subsurface_scale", get_input_value("Subsurface Scale", NodeItem::Type::Float)}, @@ -320,255 +322,225 @@ NODE_SHADER_MATERIALX_BEGIN }; }; - auto edf_inputs = [&]() { - return std::map{ + auto edf_inputs = [&]() -> InputsType { + return { {"emission", get_input_value("Emission Strength", NodeItem::Type::Float)}, - {"emission_color", get_input_value("Emission", NodeItem::Type::Color3)}}; + {"emission_color", get_input_value("Emission", NodeItem::Type::Color3)}, + }; }; NodeItem res = empty(); - if (to_type_ == NodeItem::Type::BSDF) { - auto in = bsdf_inputs(); - NodeItem roughness = in["roughness"]; - NodeItem anisotropy = in["anisotropic"]; - NodeItem rotation = in["anisotropic_rotation"]; - NodeItem base_color = in["base_color"]; - NodeItem specular = in["specular"]; - NodeItem coat = in["coat"]; - NodeItem ior = in["ior"]; - NodeItem normal = in["normal"]; - NodeItem tangent = in["tangent"]; - NodeItem coat_normal = in["coat_normal"]; + switch (to_type_) { + case NodeItem::Type::BSDF: { + auto in = bsdf_inputs(); - NodeItem n_main_tangent = empty(); - if (tangent && normal) { - NodeItem n_tangent_rotate = create_node( - "rotate3d", - NodeItem::Type::Vector3, - {{"in", tangent}, {"amount", rotation * val(360.0f)}, {"axis", normal}}); + NodeItem roughness = in["roughness"]; + NodeItem anisotropy = in["anisotropic"]; + NodeItem rotation = in["anisotropic_rotation"] * val(360.0f); + NodeItem base_color = in["base_color"]; + NodeItem specular = in["specular"]; + NodeItem coat = in["coat"]; + NodeItem ior = in["ior"]; + NodeItem normal = in["normal"]; + NodeItem tangent = in["tangent"]; + NodeItem coat_normal = in["coat_normal"]; - NodeItem n_tangent_rotate_normalize = create_node( - "normalize", NodeItem::Type::Vector3, {{"in", n_tangent_rotate}}); + NodeItem n_main_tangent = empty(); + if (tangent && normal) { + NodeItem n_tangent_rotate_normalize = tangent.rotate(rotation, normal).normalize(); + n_main_tangent = anisotropy.if_else( + NodeItem::CompareOp::Greater, val(0.0f), n_tangent_rotate_normalize, tangent); + } - n_main_tangent = anisotropy.if_else( - NodeItem::CompareOp::Greater, val(0.0f), n_tangent_rotate_normalize, tangent); - } + NodeItem n_coat_roughness_vector = create_node( + "roughness_anisotropy", + NodeItem::Type::Vector2, + {{"roughness", in["coat_roughness"]}, {"anisotropy", anisotropy}}); - NodeItem n_coat_roughness_vector = create_node( - "roughness_anisotropy", - NodeItem::Type::Vector2, - {{"roughness", in["coat_roughness"]}, {"anisotropy", anisotropy}}); + NodeItem n_coat_bsdf = create_node("dielectric_bsdf", + NodeItem::Type::BSDF, + {{"weight", coat}, + {"tint", in["coat_tint"]}, + {"ior", in["coat_ior"]}, + {"scatter_mode", val(std::string("R"))}, + {"roughness", n_coat_roughness_vector}, + {"normal", coat_normal}}); - NodeItem n_coat_bsdf = create_node("dielectric_bsdf", - NodeItem::Type::BSDF, - {{"weight", coat}, - {"tint", in["coat_tint"]}, - {"ior", in["coat_ior"]}, - {"scatter_mode", val(std::string("R"))}, - {"roughness", n_coat_roughness_vector}, - {"normal", coat_normal}}); + if (tangent && coat_normal) { + NodeItem n_coat_tangent_rotate_normalize = + tangent.rotate(rotation, coat_normal).normalize(); + NodeItem n_coat_tangent = anisotropy.if_else( + NodeItem::CompareOp::Greater, val(0.0f), n_coat_tangent_rotate_normalize, tangent); - if (tangent && coat_normal) { - NodeItem n_coat_tangent_rotate = create_node( - "rotate3d", - NodeItem::Type::Vector3, - {{"in", tangent}, {"amount", rotation * val(360.0f)}, {"axis", coat_normal}}); + n_coat_bsdf.set_input("tangent", n_coat_tangent); + } - NodeItem n_coat_tangent_rotate_normalize = create_node( - "normalize", NodeItem::Type::Vector3, {{"in", n_coat_tangent_rotate}}); + NodeItem n_thin_film_bsdf = create_node( + "thin_film_bsdf", NodeItem::Type::BSDF, {{"thickness", val(0.0f)}, {"ior", val(1.5f)}}); - NodeItem n_coat_tangent = anisotropy.if_else( - NodeItem::CompareOp::Greater, val(0.0f), n_coat_tangent_rotate_normalize, tangent); + NodeItem n_artistic_ior = create_node( + "artistic_ior", + NodeItem::Type::Multioutput, + {{"reflectivity", base_color * val(1.0f)}, {"edge_color", base_color * specular}}); - n_coat_bsdf.set_input("tangent", n_coat_tangent); - } + NodeItem n_ior_out = n_artistic_ior.add_output("ior", NodeItem::Type::Color3); + NodeItem n_extinction_out = n_artistic_ior.add_output("extinction", NodeItem::Type::Color3); - NodeItem n_thin_film_bsdf = create_node( - "thin_film_bsdf", NodeItem::Type::BSDF, {{"thickness", val(0.0f)}, {"ior", val(1.5f)}}); + NodeItem n_coat_affect_roughness_multiply2 = coat * val(0.0f) * in["coat_roughness"]; + NodeItem n_coat_affected_roughness = n_coat_affect_roughness_multiply2.mix(roughness, + val(1.0f)); - NodeItem n_artistic_ior = create_node( - "artistic_ior", - NodeItem::Type::Multioutput, - {{"reflectivity", base_color * val(1.0f)}, {"edge_color", base_color * specular}}); + NodeItem n_main_roughness = create_node( + "roughness_anisotropy", + NodeItem::Type::Vector2, + {{"roughness", n_coat_affected_roughness}, {"anisotropy", anisotropy}}); - NodeItem n_ior_out = n_artistic_ior.add_output("ior", NodeItem::Type::Color3); - NodeItem n_extinction_out = n_artistic_ior.add_output("extinction", NodeItem::Type::Color3); - - NodeItem n_coat_affect_roughness_multiply2 = coat * val(0.0f) * in["coat_roughness"]; - NodeItem n_coat_affected_roughness = create_node( - "mix", - NodeItem::Type::Float, - {{"fg", val(1.0f)}, {"bg", roughness}, {"mix", n_coat_affect_roughness_multiply2}}); - - NodeItem n_main_roughness = create_node( - "roughness_anisotropy", - NodeItem::Type::Vector2, - {{"roughness", n_coat_affected_roughness}, {"anisotropy", anisotropy}}); - - NodeItem n_metal_bsdf = create_node("conductor_bsdf", - NodeItem::Type::BSDF, - {{"ior", n_ior_out}, - {"extinction", n_extinction_out}, - {"roughness", n_main_roughness}, - {"normal", normal}, - {"tangent", n_main_tangent}}); - - NodeItem n_specular_bsdf = create_node("dielectric_bsdf", - NodeItem::Type::BSDF, - {{"weight", specular}, - {"tint", in["specular_tint"]}, - {"ior", ior}, - {"scatter_mode", val(std::string("R"))}, - {"roughness", n_main_roughness}, - {"normal", normal}, - {"tangent", n_main_tangent}}); - - NodeItem n_coat_affected_transmission_roughness = create_node( - "mix", - NodeItem::Type::Float, - {{"fg", val(1.0f)}, - {"bg", (roughness + roughness).clamp(0.0f, 1.0f)}, - {"mix", n_coat_affect_roughness_multiply2}}); - - NodeItem n_transmission_roughness = create_node( - "roughness_anisotropy", - NodeItem::Type::Vector2, - {{"roughness", n_coat_affected_transmission_roughness}, {"anisotropy", anisotropy}}); - - NodeItem n_transmission_bsdf = create_node("dielectric_bsdf", - NodeItem::Type::BSDF, - {{"tint", base_color}, - {"ior", ior}, - {"roughness", n_transmission_roughness}, - {"normal", normal}, - {"tangent", n_main_tangent}}); - - NodeItem n_coat_gamma = coat.clamp(0.0f, 1.0f) * val(0.0f) + val(1.0f); - NodeItem n_coat_affected_subsurface_color = base_color.max(val(0.0f)) ^ n_coat_gamma; - NodeItem n_translucent_bsdf = create_node( - "translucent_bsdf", - NodeItem::Type::BSDF, - {{"color", n_coat_affected_subsurface_color}, {"normal", normal}}); - - NodeItem n_subsurface_bsdf = create_node( - "subsurface_bsdf", - NodeItem::Type::BSDF, - {{"color", n_coat_affected_subsurface_color}, - {"radius", in["subsurface_radius"] * in["subsurface_scale"]}, - {"anisotropy", in["subsurface_anisotropy"]}, - {"normal", normal}}); - - NodeItem n_selected_subsurface_bsdf = create_node( - "mix", - NodeItem::Type::BSDF, - {{"fg", n_translucent_bsdf}, {"bg", n_subsurface_bsdf}, {"mix", val(0.0f)}}); - - NodeItem n_sheen_bsdf = create_node("sheen_bsdf", - NodeItem::Type::BSDF, - {{"weight", in["sheen"]}, - {"color", in["sheen_tint"]}, - {"roughness", in["sheen_roughness"]}, - {"normal", normal}}); - - NodeItem n_diffuse_bsdf = create_node("oren_nayar_diffuse_bsdf", + NodeItem n_metal_bsdf = create_node("conductor_bsdf", NodeItem::Type::BSDF, - {{"color", base_color.max(val(0.0f)) ^ n_coat_gamma}, - {"roughness", roughness}, - {"weight", val(1.0f)}, + {{"ior", n_ior_out}, + {"extinction", n_extinction_out}, + {"roughness", n_main_roughness}, + {"normal", normal}, + {"tangent", n_main_tangent}}); + + NodeItem n_specular_bsdf = create_node("dielectric_bsdf", + NodeItem::Type::BSDF, + {{"weight", specular}, + {"tint", in["specular_tint"]}, + {"ior", ior}, + {"scatter_mode", val(std::string("R"))}, + {"roughness", n_main_roughness}, + {"normal", normal}, + {"tangent", n_main_tangent}}); + + NodeItem n_coat_affected_transmission_roughness = n_coat_affect_roughness_multiply2.mix( + (roughness + roughness).clamp(), val(1.0f)); + + NodeItem n_transmission_roughness = create_node( + "roughness_anisotropy", + NodeItem::Type::Vector2, + {{"roughness", n_coat_affected_transmission_roughness}, {"anisotropy", anisotropy}}); + + NodeItem n_transmission_bsdf = create_node("dielectric_bsdf", + NodeItem::Type::BSDF, + {{"tint", base_color}, + {"ior", ior}, + {"roughness", n_transmission_roughness}, + {"normal", normal}, + {"tangent", n_main_tangent}}); + + NodeItem n_coat_gamma = coat.clamp(0.0f, 1.0f) * val(0.0f) + val(1.0f); + NodeItem n_coat_affected_subsurface_color = base_color.max(val(0.0f)) ^ n_coat_gamma; + NodeItem n_translucent_bsdf = create_node( + "translucent_bsdf", + NodeItem::Type::BSDF, + {{"color", n_coat_affected_subsurface_color}, {"normal", normal}}); + + NodeItem n_subsurface_bsdf = create_node( + "subsurface_bsdf", + NodeItem::Type::BSDF, + {{"color", n_coat_affected_subsurface_color}, + {"radius", in["subsurface_radius"] * in["subsurface_scale"]}, + {"anisotropy", in["subsurface_anisotropy"]}, + {"normal", normal}}); + + NodeItem n_sheen_bsdf = create_node("sheen_bsdf", + NodeItem::Type::BSDF, + {{"weight", in["sheen"]}, + {"color", in["sheen_tint"]}, + {"roughness", in["sheen_roughness"]}, {"normal", normal}}); - NodeItem n_subsurface_mix = create_node( - "mix", - NodeItem::Type::BSDF, - {{"fg", n_selected_subsurface_bsdf}, {"bg", n_diffuse_bsdf}, {"mix", in["subsurface"]}}); + NodeItem n_diffuse_bsdf = create_node("oren_nayar_diffuse_bsdf", + NodeItem::Type::BSDF, + {{"color", base_color.max(val(0.0f)) ^ n_coat_gamma}, + {"roughness", roughness}, + {"weight", val(1.0f)}, + {"normal", normal}}); - NodeItem n_sheen_layer = create_node( - "layer", NodeItem::Type::BSDF, {{"top", n_sheen_bsdf}, {"base", n_subsurface_mix}}); + NodeItem n_subsurface_mix = in["subsurface"].mix(n_diffuse_bsdf, n_subsurface_bsdf); - NodeItem n_transmission_mix = create_node( - "mix", - NodeItem::Type::BSDF, - {{"fg", n_transmission_bsdf}, {"bg", n_sheen_layer}, {"mix", in["transmission"]}}); + NodeItem n_sheen_layer = create_node( + "layer", NodeItem::Type::BSDF, {{"top", n_sheen_bsdf}, {"base", n_subsurface_mix}}); - NodeItem n_specular_layer = create_node( - "layer", NodeItem::Type::BSDF, {{"top", n_specular_bsdf}, {"base", n_transmission_mix}}); + NodeItem n_transmission_mix = in["transmission"].mix(n_sheen_layer, n_transmission_bsdf); - NodeItem n_metalness_mix = create_node( - "mix", - NodeItem::Type::BSDF, - {{"fg", n_metal_bsdf}, {"bg", n_specular_layer}, {"mix", in["metallic"]}}); + NodeItem n_specular_layer = create_node( + "layer", NodeItem::Type::BSDF, {{"top", n_specular_bsdf}, {"base", n_transmission_mix}}); - NodeItem n_thin_film_layer = create_node( - "layer", NodeItem::Type::BSDF, {{"top", n_thin_film_bsdf}, {"base", n_metalness_mix}}); + NodeItem n_metalness_mix = in["metallic"].mix(n_specular_layer, n_metal_bsdf); - NodeItem n_opacity_luminance = create_node( - "luminance", NodeItem::Type::Color3, {{"in", val(MaterialX::Color3(1.0f, 1.0f, 1.0f))}}); + NodeItem n_thin_film_layer = create_node( + "layer", NodeItem::Type::BSDF, {{"top", n_thin_film_bsdf}, {"base", n_metalness_mix}}); - NodeItem n_coat_attenuation = create_node("mix", - NodeItem::Type::Color3, - {{"fg", in["coat_tint"]}, - {"bg", val(MaterialX::Color3(1.0f, 1.0f, 1.0f))}, - {"mix", coat}}); + NodeItem n_opacity_luminance = create_node( + "luminance", NodeItem::Type::Color3, {{"in", val(MaterialX::Color3(1.0f, 1.0f, 1.0f))}}); - res = create_node("layer", - NodeItem::Type::BSDF, - {{"top", n_coat_bsdf}, {"base", n_thin_film_layer * n_coat_attenuation}}); + NodeItem n_coat_attenuation = coat.mix(val(MaterialX::Color3(1.0f, 1.0f, 1.0f)), + in["coat_tint"]); + + res = create_node("layer", + NodeItem::Type::BSDF, + {{"top", n_coat_bsdf}, {"base", n_thin_film_layer * n_coat_attenuation}}); + break; + } + + case NodeItem::Type::EDF: { + auto in = edf_inputs(); + res = create_node( + "uniform_edf", NodeItem::Type::EDF, {{"color", in["emission_color"] * in["emission"]}}); + break; + } + + case NodeItem::Type::SurfaceShader: { + auto in = bsdf_inputs(); + auto e_in = edf_inputs(); + in.insert(e_in.begin(), e_in.end()); + + NodeItem roughness = in["roughness"]; + NodeItem base_color = in["base_color"]; + NodeItem anisotropic = in["anisotropic"]; + NodeItem rotation = in["anisotropic_rotation"]; + + res = create_node("standard_surface", + NodeItem::Type::SurfaceShader, + {{"base", val(1.0f)}, + {"base_color", base_color}, + {"diffuse_roughness", roughness}, + {"metalness", in["metallic"]}, + {"specular", in["specular"]}, + {"specular_color", in["specular_tint"]}, + {"specular_roughness", roughness}, + {"specular_IOR", in["ior"]}, + {"specular_anisotropy", anisotropic}, + {"specular_rotation", rotation}, + {"transmission", in["transmission"]}, + {"transmission_color", base_color}, + {"transmission_extra_roughness", roughness}, + {"subsurface", in["subsurface"]}, + {"subsurface_color", base_color}, + {"subsurface_radius", in["subsurface_radius"] * in["subsurface_scale"]}, + {"subsurface_anisotropy", in["subsurface_anisotropy"]}, + {"sheen", in["sheen"]}, + {"sheen_color", in["sheen_tint"]}, + {"sheen_roughness", in["sheen_roughness"]}, + {"coat", in["coat"]}, + {"coat_color", in["coat_tint"]}, + {"coat_roughness", in["coat_roughness"]}, + {"coat_IOR", in["coat_ior"]}, + {"coat_anisotropy", anisotropic}, + {"coat_rotation", rotation}, + {"coat_normal", in["coat_normal"]}, + {"emission", in["emission"]}, + {"emission_color", in["emission_color"]}, + {"normal", in["normal"]}, + {"tangent", in["tangent"]}}); + break; + } + default: + BLI_assert_unreachable(); } - else if (to_type_ == NodeItem::Type::EDF) { - auto in = edf_inputs(); - - res = create_node( - "uniform_edf", NodeItem::Type::EDF, {{"color", in["emission_color"] * in["emission"]}}); - } - else if (to_type_ == NodeItem::Type::SurfaceShader) { - auto in = bsdf_inputs(); - auto e_in = edf_inputs(); - in.insert(e_in.begin(), e_in.end()); - - NodeItem roughness = in["roughness"]; - NodeItem base_color = in["base_color"]; - NodeItem anisotropic = in["anisotropic"]; - NodeItem rotation = in["anisotropic_rotation"]; - - res = create_node("standard_surface", - NodeItem::Type::SurfaceShader, - {{"base", val(1.0f)}, - {"base_color", base_color}, - {"diffuse_roughness", roughness}, - {"metalness", in["metallic"]}, - {"specular", in["specular"]}, - {"specular_color", in["specular_tint"]}, - {"specular_roughness", roughness}, - {"specular_IOR", in["ior"]}, - {"specular_anisotropy", anisotropic}, - {"specular_rotation", rotation}, - {"transmission", in["transmission"]}, - {"transmission_color", base_color}, - {"transmission_extra_roughness", roughness}, - {"subsurface", in["subsurface"]}, - {"subsurface_color", base_color}, - {"subsurface_radius", in["subsurface_radius"] * in["subsurface_scale"]}, - {"subsurface_anisotropy", in["subsurface_anisotropy"]}, - {"sheen", in["sheen"]}, - {"sheen_color", in["sheen_tint"]}, - {"sheen_roughness", in["sheen_roughness"]}, - {"coat", in["coat"]}, - {"coat_color", in["coat_tint"]}, - {"coat_roughness", in["coat_roughness"]}, - {"coat_IOR", in["coat_ior"]}, - {"coat_anisotropy", anisotropic}, - {"coat_rotation", rotation}, - {"coat_normal", in["coat_normal"]}, - {"emission", in["emission"]}, - {"emission_color", in["emission_color"]}, - {"normal", in["normal"]}, - {"tangent", in["tangent"]}}); - } - else { - BLI_assert_unreachable(); - } - return res; } #endif diff --git a/source/blender/nodes/shader/nodes/node_shader_gamma.cc b/source/blender/nodes/shader/nodes/node_shader_gamma.cc index 13964192252..96dd74475ab 100644 --- a/source/blender/nodes/shader/nodes/node_shader_gamma.cc +++ b/source/blender/nodes/shader/nodes/node_shader_gamma.cc @@ -22,6 +22,7 @@ static int node_shader_gpu_gamma(GPUMaterial *mat, { return GPU_stack_link(mat, node, "node_gamma", in, out); } + NODE_SHADER_MATERIALX_BEGIN #ifdef WITH_MATERIALX { diff --git a/source/blender/nodes/shader/nodes/node_shader_invert.cc b/source/blender/nodes/shader/nodes/node_shader_invert.cc index 332d3b4e055..8246662d3ec 100644 --- a/source/blender/nodes/shader/nodes/node_shader_invert.cc +++ b/source/blender/nodes/shader/nodes/node_shader_invert.cc @@ -31,7 +31,7 @@ NODE_SHADER_MATERIALX_BEGIN { NodeItem fac = get_input_value("Fac", NodeItem::Type::Float); NodeItem color = get_input_value("Color", NodeItem::Type::Color3); - return fac.blend(color, val(1.0f) - color); + return fac.mix(color, val(1.0f) - color); } #endif NODE_SHADER_MATERIALX_END diff --git a/source/blender/nodes/shader/nodes/node_shader_mapping.cc b/source/blender/nodes/shader/nodes/node_shader_mapping.cc index b1fff267626..9937c02cd17 100644 --- a/source/blender/nodes/shader/nodes/node_shader_mapping.cc +++ b/source/blender/nodes/shader/nodes/node_shader_mapping.cc @@ -77,37 +77,31 @@ static void node_shader_update_mapping(bNodeTree *ntree, bNode *node) NODE_SHADER_MATERIALX_BEGIN #ifdef WITH_MATERIALX { - NodeItem res = empty(); - NodeItem vector = get_input_link("Vector", NodeItem::Type::Vector3); - - if (!vector) { - return res; - } - + NodeItem vector = get_input_value("Vector", NodeItem::Type::Vector3); NodeItem scale = get_input_value("Scale", NodeItem::Type::Vector3); - NodeItem location = get_input_value("Location", NodeItem::Type::Vector3); - NodeItem rotation = (get_input_value("Rotation", NodeItem::Type::Vector3) * - val(float(180.0f / M_PI))); + NodeItem rotation = get_input_value("Rotation", NodeItem::Type::Vector3) * + val(float(180.0f / M_PI)); - switch (node_->custom1) { - case NODE_MAPPING_TYPE_POINT: - res = (vector * scale).rotate3d(rotation) + location; - break; - case NODE_MAPPING_TYPE_TEXTURE: - res = (vector - location).rotate3d(rotation, true) / scale; - break; - case NODE_MAPPING_TYPE_VECTOR: - res = (vector * scale).rotate3d(rotation * val(MaterialX::Vector3(1.0f, 1.0f, -1.0f))); - break; - case NODE_MAPPING_TYPE_NORMAL: - res = create_node( - "normalize", NodeItem::Type::Vector3, {{"in", (vector / scale).rotate3d(rotation)}}); - break; + int type = node_->custom1; + switch (type) { + case NODE_MAPPING_TYPE_POINT: { + NodeItem location = get_input_value("Location", NodeItem::Type::Vector3); + return (vector * scale).rotate(rotation) + location; + } + case NODE_MAPPING_TYPE_TEXTURE: { + NodeItem location = get_input_value("Location", NodeItem::Type::Vector3); + return (vector - location).rotate(rotation, true) / scale; + } + case NODE_MAPPING_TYPE_VECTOR: { + return (vector * scale).rotate(rotation * val(MaterialX::Vector3(1.0f, 1.0f, -1.0f))); + } + case NODE_MAPPING_TYPE_NORMAL: { + return (vector / scale).rotate(rotation).normalize(); + } default: BLI_assert_unreachable(); } - - return res; + return empty(); } #endif NODE_SHADER_MATERIALX_END diff --git a/source/blender/nodes/shader/nodes/node_shader_mix.cc b/source/blender/nodes/shader/nodes/node_shader_mix.cc index 54ed933a6f2..54a8affb561 100644 --- a/source/blender/nodes/shader/nodes/node_shader_mix.cc +++ b/source/blender/nodes/shader/nodes/node_shader_mix.cc @@ -543,6 +543,58 @@ static void sh_node_mix_build_multi_function(NodeMultiFunctionBuilder &builder) } } +NODE_SHADER_MATERIALX_BEGIN +#ifdef WITH_MATERIALX +{ + const NodeShaderMix *data = (NodeShaderMix *)node_->storage; + + NodeItem factor = empty(); + NodeItem value1 = empty(); + NodeItem value2 = empty(); + switch (data->data_type) { + case SOCK_FLOAT: + factor = get_input_value(0, NodeItem::Type::Float); + value1 = get_input_value(2, NodeItem::Type::Float); + value2 = get_input_value(3, NodeItem::Type::Float); + break; + + case SOCK_VECTOR: + if (data->factor_mode == NODE_MIX_MODE_UNIFORM) { + factor = get_input_value(0, NodeItem::Type::Float); + } + else { + factor = get_input_value(1, NodeItem::Type::Vector3); + } + value1 = get_input_value(4, NodeItem::Type::Vector3); + value2 = get_input_value(5, NodeItem::Type::Vector3); + break; + + case SOCK_RGBA: + factor = get_input_value(0, NodeItem::Type::Float); + value1 = get_input_value(6, NodeItem::Type::Color4); + value2 = get_input_value(7, NodeItem::Type::Color4); + break; + + default: + BLI_assert_unreachable(); + } + + if (data->clamp_factor) { + factor = factor.clamp(); + } + NodeItem res = factor.mix(value1, value2); + if (data->data_type == SOCK_RGBA) { + /* TODO: Apply data->blend_type */ + + if (data->clamp_result) { + res = res.clamp(); + } + } + return res; +} +#endif +NODE_SHADER_MATERIALX_END + } // namespace blender::nodes::node_sh_mix_cc void register_node_type_sh_mix() @@ -562,5 +614,7 @@ void register_node_type_sh_mix() ntype.draw_buttons = file_ns::sh_node_mix_layout; ntype.labelfunc = file_ns::sh_node_mix_label; ntype.gather_link_search_ops = file_ns::node_mix_gather_link_searches; + ntype.materialx_fn = file_ns::node_shader_materialx; + nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_mix_rgb.cc b/source/blender/nodes/shader/nodes/node_shader_mix_rgb.cc index 23ab08377e1..457ec46a091 100644 --- a/source/blender/nodes/shader/nodes/node_shader_mix_rgb.cc +++ b/source/blender/nodes/shader/nodes/node_shader_mix_rgb.cc @@ -150,15 +150,6 @@ static void sh_node_mix_rgb_build_multi_function(NodeMultiFunctionBuilder &build builder.construct_and_set_matching_fn(clamp, mix_type); } -NODE_SHADER_MATERIALX_BEGIN -#ifdef WITH_MATERIALX -{ - /* TODO: Implement */ - return empty(); -} -#endif -NODE_SHADER_MATERIALX_END - } // namespace blender::nodes::node_shader_mix_rgb_cc void register_node_type_sh_mix_rgb() @@ -173,6 +164,5 @@ void register_node_type_sh_mix_rgb() ntype.gpu_fn = file_ns::gpu_shader_mix_rgb; ntype.build_multi_function = file_ns::sh_node_mix_rgb_build_multi_function; ntype.gather_link_search_ops = nullptr; - ntype.materialx_fn = file_ns::node_shader_materialx; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_mix_shader.cc b/source/blender/nodes/shader/nodes/node_shader_mix_shader.cc index 08a671f5cab..249d4f85c7a 100644 --- a/source/blender/nodes/shader/nodes/node_shader_mix_shader.cc +++ b/source/blender/nodes/shader/nodes/node_shader_mix_shader.cc @@ -26,37 +26,25 @@ static int node_shader_gpu_mix_shader(GPUMaterial *mat, NODE_SHADER_MATERIALX_BEGIN #ifdef WITH_MATERIALX { - NodeItem res = empty(); - switch (to_type_) { - case NodeItem::Type::BSDF: - case NodeItem::Type::EDF: { - NodeItem fac = get_input_value(0, NodeItem::Type::Float); - NodeItem shader1 = get_input_link(1, to_type_); - NodeItem shader2 = get_input_link(2, to_type_); - - if (shader1 && !shader2) { - res = shader1 * (val(1.0f) - fac); - } - else if (!shader1 && shader2) { - res = shader2 * fac; - } - else if (shader1 && shader2) { - res = create_node("mix", to_type_, {{"fg", shader2}, {"bg", shader1}, {"mix", fac}}); - } - break; - } - case NodeItem::Type::SurfaceShader: { - /* SurfaceShaders can't be mixed, returning the first one connected */ - res = get_input_link(1, NodeItem::Type::SurfaceShader); - if (!res) { - res = get_input_link(2, NodeItem::Type::SurfaceShader); - } - break; - } - default: - BLI_assert_unreachable(); + if (!ELEM(to_type_, NodeItem::Type::BSDF, NodeItem::Type::EDF)) { + return empty(); } - return res; + + NodeItem shader1 = get_input_link(1, to_type_); + NodeItem shader2 = get_input_link(2, to_type_); + if (!shader1 && !shader2) { + return empty(); + } + + NodeItem fac = get_input_value(0, NodeItem::Type::Float); + + if (shader1 && !shader2) { + return shader1 * (val(1.0f) - fac); + } + if (!shader1 && shader2) { + return shader2 * fac; + } + return fac.mix(shader1, shader2); } #endif NODE_SHADER_MATERIALX_END diff --git a/source/blender/nodes/shader/nodes/node_shader_output_material.cc b/source/blender/nodes/shader/nodes/node_shader_output_material.cc index f9aa8cf13e6..b405c40e8af 100644 --- a/source/blender/nodes/shader/nodes/node_shader_output_material.cc +++ b/source/blender/nodes/shader/nodes/node_shader_output_material.cc @@ -46,20 +46,19 @@ static int node_shader_gpu_output_material(GPUMaterial *mat, NODE_SHADER_MATERIALX_BEGIN #ifdef WITH_MATERIALX { - NodeItem bsdf = get_input_link("Surface", NodeItem::Type::BSDF); - NodeItem edf = get_input_link("Surface", NodeItem::Type::EDF); - NodeItem surface = empty(); - if (bsdf || edf) { - surface = create_node("surface", NodeItem::Type::SurfaceShader); - if (bsdf) { - surface.set_input("bsdf", bsdf); + NodeItem surface = get_input_link("Surface", NodeItem::Type::SurfaceShader); + if (!surface) { + NodeItem bsdf = get_input_link("Surface", NodeItem::Type::BSDF); + NodeItem edf = get_input_link("Surface", NodeItem::Type::EDF); + if (bsdf || edf) { + surface = create_node("surface", NodeItem::Type::SurfaceShader); + if (bsdf) { + surface.set_input("bsdf", bsdf); + } + if (edf) { + surface.set_input("edf", edf); + } } - if (edf) { - surface.set_input("edf", edf); - } - } - else { - surface = get_input_link("Surface", NodeItem::Type::SurfaceShader); } return create_node("surfacematerial", NodeItem::Type::Material, {{"surfaceshader", surface}}); } diff --git a/source/blender/nodes/shader/nodes/node_shader_sepcomb_color.cc b/source/blender/nodes/shader/nodes/node_shader_sepcomb_color.cc index eaf7f5f4d93..32c1e0def8d 100644 --- a/source/blender/nodes/shader/nodes/node_shader_sepcomb_color.cc +++ b/source/blender/nodes/shader/nodes/node_shader_sepcomb_color.cc @@ -89,7 +89,7 @@ NODE_SHADER_MATERIALX_BEGIN } int index = STREQ(socket_out_->name, "Red") ? 0 : STREQ(socket_out_->name, "Green") ? 1 : 2; - return convert.extract(index); + return convert[index]; } #endif NODE_SHADER_MATERIALX_END diff --git a/source/blender/nodes/shader/nodes/node_shader_sepcomb_xyz.cc b/source/blender/nodes/shader/nodes/node_shader_sepcomb_xyz.cc index 4cf874e903e..b387a28d35b 100644 --- a/source/blender/nodes/shader/nodes/node_shader_sepcomb_xyz.cc +++ b/source/blender/nodes/shader/nodes/node_shader_sepcomb_xyz.cc @@ -95,7 +95,7 @@ NODE_SHADER_MATERIALX_BEGIN { NodeItem vector = get_input_value("Vector", NodeItem::Type::Vector3); int index = STREQ(socket_out_->name, "X") ? 0 : STREQ(socket_out_->name, "Y") ? 1 : 2; - return vector.extract(index); + return vector[index]; } #endif NODE_SHADER_MATERIALX_END diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_checker.cc b/source/blender/nodes/shader/nodes/node_shader_tex_checker.cc index 40dd136fafc..4fe06cd5094 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_checker.cc +++ b/source/blender/nodes/shader/nodes/node_shader_tex_checker.cc @@ -118,7 +118,7 @@ NODE_SHADER_MATERIALX_BEGIN NodeItem scale = get_input_value("Scale", NodeItem::Type::Float); vector = (vector * scale) % val(2.0f); - return (vector.extract(0).floor() + vector.extract(1).floor()) + return (vector[0].floor() + vector[1].floor()) .if_else(NodeItem::CompareOp::Eq, val(1.0f), value1, value2); } #endif diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_gradient.cc b/source/blender/nodes/shader/nodes/node_shader_tex_gradient.cc index 989a1e527ec..7dd9ad194bb 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_gradient.cc +++ b/source/blender/nodes/shader/nodes/node_shader_tex_gradient.cc @@ -160,21 +160,21 @@ NODE_SHADER_MATERIALX_BEGIN switch (gradient_type) { case SHD_BLEND_LINEAR: - res = vector.extract(0); + res = vector[0]; break; case SHD_BLEND_QUADRATIC: - res = vector.extract(0); + res = vector[0]; res = res * res; break; case SHD_BLEND_EASING: - res = vector.extract(0).clamp(val(0.0f), val(1.0f)); + res = vector[0].clamp(); res = res * res * (val(3.0f) - val(2.0f) * res); break; case SHD_BLEND_DIAGONAL: - res = (vector.extract(0) + vector.extract(1)) * val(0.5f); + res = (vector[0] + vector[1]) * val(0.5f); break; case SHD_BLEND_RADIAL: - res = vector.extract(1).atan2(vector.extract(0)) / (val(float(M_PI * 2.0f))) + val(0.5f); + res = vector[1].atan2(vector[0]) / (val(float(M_PI * 2.0f))) + val(0.5f); break; case SHD_BLEND_QUADRATIC_SPHERE: res = (val(1.0f) - vector.dotproduct(vector).sqrt()).max(val(0.0f)); diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_image.cc b/source/blender/nodes/shader/nodes/node_shader_tex_image.cc index 19f24f6c9cb..c81dbd6cf6b 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_image.cc +++ b/source/blender/nodes/shader/nodes/node_shader_tex_image.cc @@ -248,7 +248,7 @@ NODE_SHADER_MATERIALX_BEGIN } if (STREQ(socket_out_->name, "Alpha")) { - res = res.extract(3); + res = res[3]; } return res; } diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_wave.cc b/source/blender/nodes/shader/nodes/node_shader_tex_wave.cc index 63b0de98e44..73b0a97e65a 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_wave.cc +++ b/source/blender/nodes/shader/nodes/node_shader_tex_wave.cc @@ -223,59 +223,59 @@ NODE_SHADER_MATERIALX_BEGIN #ifdef WITH_MATERIALX { NodeTexWave *tex = (NodeTexWave *)node_->storage; - const int wave_type = tex->wave_type; - const int bands_direction = tex->bands_direction; - const int rings_direction = tex->rings_direction; - const int wave_profile = tex->wave_profile; NodeItem scale = get_input_value("Scale", NodeItem::Type::Float); - NodeItem distortion = get_input_value("Distortion", NodeItem::Type::Float) / - val(10.0f); // noise adjusment to get result as Cycles - NodeItem detail = get_input_value("Detail", NodeItem::Type::Float); - NodeItem detail_scale = get_input_value("Detail Scale", NodeItem::Type::Float) * - val(10.0f); // noise adjusment to get result as Cycles + NodeItem distortion = get_input_value("Distortion", NodeItem::Type::Float); + NodeItem detail = get_input_default("Detail", NodeItem::Type::Float); + NodeItem detail_scale = get_input_value("Detail Scale", NodeItem::Type::Float); NodeItem detail_rough = get_input_value("Detail Roughness", NodeItem::Type::Float); NodeItem phase_offset = get_input_value("Phase Offset", NodeItem::Type::Float); NodeItem vector = get_input_link("Vector", NodeItem::Type::Vector3); if (!vector) { - vector = texcoord_node(); + vector = texcoord_node(NodeItem::Type::Vector3); } - NodeItem p = vector * scale; - p = (p + val(0.000001f)) * val(0.999999f); - NodeItem n = val(0.0f); - NodeItem value = val(0.0f); + /* adjusment to get result as Cycles */ + distortion = distortion * val(10.0f); + detail_scale = detail_scale * val(10.0f); - switch (wave_type) { + NodeItem pos = vector * scale; + NodeItem fractal = create_node("fractal3d", + NodeItem::Type::Float, + {{"position", pos}, + {"octaves", val(int(detail.value->asA()))}, + {"lacunarity", val(2.0f)}}); + NodeItem value = val(0.0f); + switch (tex->wave_type) { case SHD_WAVE_BANDS: - switch (bands_direction) { + switch (tex->bands_direction) { case SHD_WAVE_BANDS_DIRECTION_X: - n = p.extract(0) * val(20.0f); + value = pos[0] * val(20.0f); break; case SHD_WAVE_BANDS_DIRECTION_Y: - n = p.extract(1) * val(20.0f); + value = pos[1] * val(20.0f); break; case SHD_WAVE_BANDS_DIRECTION_Z: - n = p.extract(2) * val(20.0f); + value = pos[2] * val(20.0f); break; case SHD_WAVE_BANDS_DIRECTION_DIAGONAL: - n = (p.extract(0) + p.extract(1) + p.extract(2)) * val(10.0f); + value = (pos[0] + pos[1] + pos[2]) * val(10.0f); break; default: BLI_assert_unreachable(); } break; case SHD_WAVE_RINGS: - NodeItem rp = p; - switch (rings_direction) { + NodeItem rpos = pos; + switch (tex->rings_direction) { case SHD_WAVE_RINGS_DIRECTION_X: - rp = rp * val(MaterialX::Vector3(0.0f, 1.0f, 1.0f)); + rpos = pos * val(MaterialX::Vector3(0.0f, 1.0f, 1.0f)); break; case SHD_WAVE_RINGS_DIRECTION_Y: - rp = rp * val(MaterialX::Vector3(1.0f, 0.0f, 1.0f)); + rpos = pos * val(MaterialX::Vector3(1.0f, 0.0f, 1.0f)); break; case SHD_WAVE_RINGS_DIRECTION_Z: - rp = rp * val(MaterialX::Vector3(1.0f, 1.0f, 0.0f)); + rpos = pos * val(MaterialX::Vector3(1.0f, 1.0f, 0.0f)); break; case SHD_WAVE_RINGS_DIRECTION_SPHERICAL: /* Ignore. */ @@ -283,33 +283,28 @@ NODE_SHADER_MATERIALX_BEGIN default: BLI_assert_unreachable(); } - n = rp.dotproduct(rp).sqrt() * val(20.0f); + value = rpos.length() * val(20.0f); break; } - n = n + phase_offset; - n = n + distortion * detail_scale * - create_node("fractal3d", - NodeItem::Type::Float, - {{"position", p}, - {"octaves", val(int(detail.value->asA()))}, - {"lacunarity", val(2.0f)}}); + value = value + phase_offset + distortion * detail_scale * fractal; - switch (wave_profile) { + NodeItem res = empty(); + switch (tex->wave_profile) { case SHD_WAVE_PROFILE_SIN: - value = val(0.5f) + val(0.5f) * (n - val(float(M_PI_2))).sin(); + res = val(0.5f) + val(0.5f) * (value - val(float(M_PI_2))).sin(); break; case SHD_WAVE_PROFILE_SAW: - n = n / val(float(M_PI * 2.0f)); - value = n - n.floor(); + value = value / val(float(M_PI * 2.0f)); + res = value - value.floor(); break; case SHD_WAVE_PROFILE_TRI: - n = n / val(float(M_PI * 2.0f)); - value = (n - (n + val(0.5f)).floor()).abs() * val(2.0f); + value = value / val(float(M_PI * 2.0f)); + res = (value - (value + val(0.5f)).floor()).abs() * val(2.0f); break; default: BLI_assert_unreachable(); } - return value; + return res; } #endif NODE_SHADER_MATERIALX_END diff --git a/source/blender/nodes/shader/nodes/node_shader_vector_rotate.cc b/source/blender/nodes/shader/nodes/node_shader_vector_rotate.cc index 5d71a97def4..c93cac85b81 100644 --- a/source/blender/nodes/shader/nodes/node_shader_vector_rotate.cc +++ b/source/blender/nodes/shader/nodes/node_shader_vector_rotate.cc @@ -215,62 +215,42 @@ static void node_shader_update_vector_rotate(bNodeTree *ntree, bNode *node) NODE_SHADER_MATERIALX_BEGIN #ifdef WITH_MATERIALX { - NodeItem vector = get_input_link("Vector", NodeItem::Type::Vector3); + int mode = node_->custom1; + bool invert = node_->custom2; - if (!vector) { - return empty(); - } - - NodeItem angle = empty(); - NodeItem axis = empty(); + NodeItem vector = get_input_value("Vector", NodeItem::Type::Vector3); NodeItem center = get_input_value("Center", NodeItem::Type::Vector3) * val(MaterialX::Vector3(1.0f, 1.0f, -1.0f)); - NodeItem res = vector - center; - int mode = node_->custom1; - bool invert = node_->custom1; + vector = vector - center; if (mode == NODE_VECTOR_ROTATE_TYPE_EULER_XYZ) { - angle = get_input_value("Rotation", NodeItem::Type::Vector3); - angle = angle * val(MaterialX::Vector3(1.0f, 1.0f, -1.0f)); - } - else { - angle = get_input_value("Angle", NodeItem::Type::Float); + NodeItem rotation = get_input_value("Rotation", NodeItem::Type::Vector3) * + val(MaterialX::Vector3(1.0f, 1.0f, -1.0f) * 180.0f / M_PI); + + return vector.rotate(invert ? -rotation : rotation, invert) + center; } - angle = angle * val(float(180.0f / M_PI)); - angle = invert ? angle * val(-1.0f) : angle; - + NodeItem angle = get_input_value("Angle", NodeItem::Type::Float) * val(float(180.0f / M_PI)); + NodeItem axis = empty(); switch (mode) { - case NODE_VECTOR_ROTATE_TYPE_EULER_XYZ: { - return res.rotate3d(angle, invert) + center; - } - case NODE_VECTOR_ROTATE_TYPE_AXIS: { + case NODE_VECTOR_ROTATE_TYPE_AXIS: axis = get_input_value("Axis", NodeItem::Type::Vector3) * val(MaterialX::Vector3(1.0f, 1.0f, -1.0f)); break; - } - case NODE_VECTOR_ROTATE_TYPE_AXIS_X: { + case NODE_VECTOR_ROTATE_TYPE_AXIS_X: axis = val(MaterialX::Vector3(1.0f, 0.0f, 0.0f)); break; - } - case NODE_VECTOR_ROTATE_TYPE_AXIS_Y: { + case NODE_VECTOR_ROTATE_TYPE_AXIS_Y: axis = val(MaterialX::Vector3(0.0f, 1.0f, 0.0f)); break; - } - case NODE_VECTOR_ROTATE_TYPE_AXIS_Z: { + case NODE_VECTOR_ROTATE_TYPE_AXIS_Z: axis = val(MaterialX::Vector3(0.0f, 0.0f, -1.0f)); break; - } - default: { + default: BLI_assert_unreachable(); - return vector; - } } - return create_node("rotate3d", - NodeItem::Type::Vector3, - {{"in", res}, {"amount", angle}, {"axis", axis}}) + - center; + return vector.rotate(invert ? -angle : angle, axis) + center; } #endif NODE_SHADER_MATERIALX_END