From 96f76cf3be09865bb9997aead1e2df086869c7a3 Mon Sep 17 00:00:00 2001 From: Bogdan Nagirniak Date: Mon, 28 Aug 2023 21:50:10 +0300 Subject: [PATCH 1/3] Created basic arithmetic for NodeItem --- .../shader/materialx/nodes/node_parser.cc | 172 ++++++++++++++++-- .../shader/materialx/nodes/node_parser.h | 20 +- 2 files changed, 178 insertions(+), 14 deletions(-) diff --git a/source/blender/nodes/shader/materialx/nodes/node_parser.cc b/source/blender/nodes/shader/materialx/nodes/node_parser.cc index 11da5c8158a7..2657730fd01e 100644 --- a/source/blender/nodes/shader/materialx/nodes/node_parser.cc +++ b/source/blender/nodes/shader/materialx/nodes/node_parser.cc @@ -25,20 +25,27 @@ void NodeItem::set_input(const std::string &name, const NodeItem &item) void NodeItem::set_input(const std::string &name, const MaterialX::ValuePtr value) { + std::string mx_type = value->getTypeString(); if (value->isA()) { - set_input(name, value->asA(), "float"); + set_input(name, value->asA(), mx_type); + } + else if (value->isA()) { + set_input(name, value->asA(), mx_type); } else if (value->isA()) { - set_input(name, value->asA(), "vector3"); + set_input(name, value->asA(), mx_type); } else if (value->isA()) { - set_input(name, value->asA(), "vector4"); + set_input(name, value->asA(), mx_type); } else if (value->isA()) { - set_input(name, value->asA(), "color3"); + set_input(name, value->asA(), mx_type); } else if (value->isA()) { - set_input(name, value->asA(), "color4"); + set_input(name, value->asA(), mx_type); + } + else if (value->isA()) { + set_input(name, value->asA(), mx_type); } else { BLI_assert_unreachable(); @@ -55,25 +62,164 @@ NodeItem::operator bool() const return value || node; } -NodeItem NodeItem::to_color3() +NodeItem NodeItem::operator+(const NodeItem &other) { + return arithmetic(other, "add", [](float a, float b) { return a + b; }); +} + +NodeItem NodeItem::operator-(const NodeItem &other) +{ + return arithmetic(other, "subtract", [](float a, float b) { return a - b; }); +} + +NodeItem NodeItem::operator*(const NodeItem &other) +{ + return arithmetic(other, "multiply", [](float a, float b) { return a * b; }); +} + +NodeItem NodeItem::operator/(const NodeItem &other) +{ + return arithmetic(other, "divide", [](float a, float b) { return b == 0.0f ? 0.0f : a / b; }); +} + +NodeItem NodeItem::to_color3() const +{ + NodeItem res(graph_); + if (value) { + MaterialX::Color3 c; + if (value->isA()) { + float v = value->asA(); + c = {v, v ,v}; + } + else if (value->isA()) { + auto v = value->asA(); + c = {v[0], v[1], v[2]}; + } + else if (value->isA()) { + auto v = value->asA(); + c = {v[0], v[1], v[2]}; + } + else if (value->isA()) { + auto v = value->asA(); + c = {v[0], v[1], v[2]}; + } + else if (value->isA()) { + auto v = value->asA(); + c = {v[0], v[1], v[2]}; + } + else { + /* Default color */ + c = {0.0f, 0.0f, 0.0f}; + } + res.value = MaterialX::Value::createValue(c); + } + else if (node) { + res.node = node; + } + return res; +} + +NodeItem NodeItem::arithmetic(const std::string &mx_category, std::function func) +{ + std::string t = value ? value->getTypeString() : node->getType(); NodeItem res(graph_); if (value) { if (value->isA()) { float v = value->asA(); - res.value = MaterialX::Value::createValue(MaterialX::Color3(v, v, v)); + res.value = MaterialX::Value::createValue(func(v)); } else if (value->isA()) { - res.value = value; + auto v = value->asA(); + res.value = MaterialX::Value::createValue( + {func(v[0]), func(v[1]), func(v[2])}); } else if (value->isA()) { - auto c = value->asA(); - res.value = MaterialX::Value::createValue( - MaterialX::Color3(c[0], c[1], c[2])); + auto v = value->asA(); + res.value = MaterialX::Value::createValue( + {func(v[0]), func(v[1]), func(v[2]), func(v[3])}); + } + else if (value->isA()) { + auto v = value->asA(); + res.value = MaterialX::Value::createValue({func(v[0]), func(v[1])}); + } + else if (value->isA()) { + auto v = value->asA(); + res.value = MaterialX::Value::createValue( + {func(v[0]), func(v[1]), func(v[2])}); + } + else if (value->isA()) { + auto v = value->asA(); + res.value = MaterialX::Value::createValue( + {func(v[0]), func(v[1]), func(v[2]), func(v[3])}); + } + else { + /* Nothing change */ + res.value = value; } } - else if (node) { - res.node = node; + else { + res.node = graph_->addNode(mx_category, MaterialX::EMPTY_STRING, t); + res.set_input("in", *this); + } + return res; +} + +NodeItem NodeItem::arithmetic(const NodeItem &other, + const std::string &mx_category, + std::function func) +{ + std::string t1 = value ? value->getTypeString() : node->getType(); + std::string t2 = other.value ? other.value->getTypeString() : other.node->getType(); + if (t1 != t2) { + return *this; + } + + NodeItem res(graph_); + if (value && other.value) { + if (value->isA()) { + float v1 = value->asA(); + float v2 = other.value->asA(); + res.value = MaterialX::Value::createValue(func(v1, v2)); + } + else if (value->isA()) { + auto v1 = value->asA(); + auto v2 = other.value->asA(); + res.value = MaterialX::Value::createValue( + {func(v1[0], v2[0]), func(v1[1], v2[1]), func(v1[2], v2[2])}); + } + else if (value->isA()) { + auto v1 = value->asA(); + auto v2 = other.value->asA(); + res.value = MaterialX::Value::createValue( + {func(v1[0], v2[0]), func(v1[1], v2[1]), func(v1[2], v2[2]), func(v1[3], v2[3])}); + } + else if (value->isA()) { + auto v1 = value->asA(); + auto v2 = other.value->asA(); + res.value = MaterialX::Value::createValue( + {func(v1[0], v2[0]), func(v1[1], v2[1])}); + } + else if (value->isA()) { + auto v1 = value->asA(); + auto v2 = other.value->asA(); + res.value = MaterialX::Value::createValue( + {func(v1[0], v2[0]), func(v1[1], v2[1]), func(v1[2], v2[2])}); + } + else if (value->isA()) { + auto v1 = value->asA(); + auto v2 = other.value->asA(); + res.value = MaterialX::Value::createValue( + {func(v1[0], v2[0]), func(v1[1], v2[1]), func(v1[2], v2[2]), func(v1[3], v2[3])}); + } + else { + /* default color */ + res.value = value; + } + } + else { + res.node = graph_->addNode(mx_category, MaterialX::EMPTY_STRING, t1); + res.set_input("in1", *this); + res.set_input("in2", other); } return res; } diff --git a/source/blender/nodes/shader/materialx/nodes/node_parser.h b/source/blender/nodes/shader/materialx/nodes/node_parser.h index 5a021e8bb33f..51a4af39c6e7 100644 --- a/source/blender/nodes/shader/materialx/nodes/node_parser.h +++ b/source/blender/nodes/shader/materialx/nodes/node_parser.h @@ -31,8 +31,19 @@ class NodeItem { void set_input(const std::string &name, const MaterialX::NodePtr node); operator bool() const; + template NodeItem &operator=(const T &value); + NodeItem operator+(const NodeItem &other); + NodeItem operator-(const NodeItem &other); + NodeItem operator*(const NodeItem &other); + NodeItem operator/(const NodeItem &other); - NodeItem to_color3(); + NodeItem to_color3() const; + + private: + NodeItem arithmetic(const std::string &mx_category, std::function func); + NodeItem arithmetic(const NodeItem &other, + const std::string &mx_category, + std::function func); }; template @@ -41,6 +52,13 @@ void NodeItem::set_input(const std::string &name, const T &value, const std::str node->setInputValue(name, value, mx_type); } +template NodeItem &NodeItem::operator=(const T &value) +{ + this->value = MaterialX::Value::createValue(value); + node = nullptr; + return *this; +} + class NodeParser { public: MaterialX::GraphElement *graph; -- 2.30.2 From 10569ba1110a6dc217865e725922b37305dca331 Mon Sep 17 00:00:00 2001 From: Bogdan Nagirniak Date: Mon, 28 Aug 2023 22:59:09 +0300 Subject: [PATCH 2/3] Added some math nodes: InvertNodeParser, MathNodeParser, MixRGBNodeParser. Improved parser declaration: added DECLARE_PARSER macros. --- source/blender/nodes/shader/CMakeLists.txt | 6 ++-- .../nodes/shader/materialx/material.cc | 2 +- .../shader/materialx/nodes/bsdf_principled.cc | 4 +-- .../nodes/{output_material.h => invert.cc} | 13 ++++--- .../materialx/nodes/{tex_image.h => math.cc} | 11 +++--- .../nodes/{bsdf_principled.h => mix_rgb.cc} | 11 +++--- .../shader/materialx/nodes/node_parser.cc | 34 +++++++++++++++++-- .../shader/materialx/nodes/node_parser.h | 19 +++++++++++ .../shader/materialx/nodes/output_material.cc | 2 +- .../nodes/shader/materialx/nodes/tex_image.cc | 1 - 10 files changed, 70 insertions(+), 33 deletions(-) rename source/blender/nodes/shader/materialx/nodes/{output_material.h => invert.cc} (55%) rename source/blender/nodes/shader/materialx/nodes/{tex_image.h => math.cc} (61%) rename source/blender/nodes/shader/materialx/nodes/{bsdf_principled.h => mix_rgb.cc} (60%) diff --git a/source/blender/nodes/shader/CMakeLists.txt b/source/blender/nodes/shader/CMakeLists.txt index 1888021af16c..064f203db349 100644 --- a/source/blender/nodes/shader/CMakeLists.txt +++ b/source/blender/nodes/shader/CMakeLists.txt @@ -149,15 +149,15 @@ if(WITH_MATERIALX) list(APPEND SRC materialx/material.cc materialx/nodes/bsdf_principled.cc + materialx/nodes/invert.cc + materialx/nodes/math.cc + materialx/nodes/mix_rgb.cc materialx/nodes/node_parser.cc materialx/nodes/output_material.cc materialx/nodes/tex_image.cc materialx/material.h - materialx/nodes/bsdf_principled.h materialx/nodes/node_parser.h - materialx/nodes/output_material.h - materialx/nodes/tex_image.h ) endif() diff --git a/source/blender/nodes/shader/materialx/material.cc b/source/blender/nodes/shader/materialx/material.cc index 8e3350199e85..5fec3563571f 100644 --- a/source/blender/nodes/shader/materialx/material.cc +++ b/source/blender/nodes/shader/materialx/material.cc @@ -3,7 +3,7 @@ * SPDX-License-Identifier: GPL-2.0-or-later */ #include "material.h" -#include "nodes/output_material.h" +#include "nodes/node_parser.h" #include #include diff --git a/source/blender/nodes/shader/materialx/nodes/bsdf_principled.cc b/source/blender/nodes/shader/materialx/nodes/bsdf_principled.cc index e00bbce4d598..5dee4cc40d61 100644 --- a/source/blender/nodes/shader/materialx/nodes/bsdf_principled.cc +++ b/source/blender/nodes/shader/materialx/nodes/bsdf_principled.cc @@ -2,9 +2,7 @@ * * SPDX-License-Identifier: GPL-2.0-or-later */ -#include "bsdf_principled.h" - -#include +#include "node_parser.h" namespace blender::nodes::materialx { diff --git a/source/blender/nodes/shader/materialx/nodes/output_material.h b/source/blender/nodes/shader/materialx/nodes/invert.cc similarity index 55% rename from source/blender/nodes/shader/materialx/nodes/output_material.h rename to source/blender/nodes/shader/materialx/nodes/invert.cc index 0701c0769e8a..c54f5f9b6972 100644 --- a/source/blender/nodes/shader/materialx/nodes/output_material.h +++ b/source/blender/nodes/shader/materialx/nodes/invert.cc @@ -2,16 +2,15 @@ * * SPDX-License-Identifier: GPL-2.0-or-later */ -#pragma once - #include "node_parser.h" namespace blender::nodes::materialx { -class OutputMaterialNodeParser : public NodeParser { - public: - using NodeParser::NodeParser; - NodeItem compute() override; -}; +NodeItem InvertNodeParser::compute() +{ + NodeItem fac = get_input_value("Fac"); + NodeItem color = get_input_value("Color"); + return fac.blend(color, fac.one() - color); +} } // namespace blender::nodes::materialx diff --git a/source/blender/nodes/shader/materialx/nodes/tex_image.h b/source/blender/nodes/shader/materialx/nodes/math.cc similarity index 61% rename from source/blender/nodes/shader/materialx/nodes/tex_image.h rename to source/blender/nodes/shader/materialx/nodes/math.cc index cc6f962ef88a..909d8ecb1e52 100644 --- a/source/blender/nodes/shader/materialx/nodes/tex_image.h +++ b/source/blender/nodes/shader/materialx/nodes/math.cc @@ -2,16 +2,13 @@ * * SPDX-License-Identifier: GPL-2.0-or-later */ -#pragma once - #include "node_parser.h" namespace blender::nodes::materialx { -class TexImageNodeParser : public NodeParser { - public: - using NodeParser::NodeParser; - NodeItem compute() override; -}; +NodeItem MathNodeParser::compute() +{ + return empty_value(); +} } // namespace blender::nodes::materialx diff --git a/source/blender/nodes/shader/materialx/nodes/bsdf_principled.h b/source/blender/nodes/shader/materialx/nodes/mix_rgb.cc similarity index 60% rename from source/blender/nodes/shader/materialx/nodes/bsdf_principled.h rename to source/blender/nodes/shader/materialx/nodes/mix_rgb.cc index b4cace6d8216..5b0c8a2085e2 100644 --- a/source/blender/nodes/shader/materialx/nodes/bsdf_principled.h +++ b/source/blender/nodes/shader/materialx/nodes/mix_rgb.cc @@ -2,16 +2,13 @@ * * SPDX-License-Identifier: GPL-2.0-or-later */ -#pragma once - #include "node_parser.h" namespace blender::nodes::materialx { -class BSDFPrincipledNodeParser : public NodeParser { - public: - using NodeParser::NodeParser; - NodeItem compute() override; -}; +NodeItem MixRGBNodeParser::compute() +{ + return empty_value(); +} } // namespace blender::nodes::materialx diff --git a/source/blender/nodes/shader/materialx/nodes/node_parser.cc b/source/blender/nodes/shader/materialx/nodes/node_parser.cc index 2657730fd01e..c7be1112b450 100644 --- a/source/blender/nodes/shader/materialx/nodes/node_parser.cc +++ b/source/blender/nodes/shader/materialx/nodes/node_parser.cc @@ -4,9 +4,6 @@ #include "node_parser.h" -#include "bsdf_principled.h" -#include "tex_image.h" - #include namespace blender::nodes::materialx { @@ -82,6 +79,21 @@ NodeItem NodeItem::operator/(const NodeItem &other) return arithmetic(other, "divide", [](float a, float b) { return b == 0.0f ? 0.0f : a / b; }); } +NodeItem NodeItem::min(const NodeItem &other) +{ + return arithmetic(other, "min", [](float a, float b) { return std::min(a, b); }); +} + +NodeItem NodeItem::max(const NodeItem &other) +{ + return arithmetic(other, "max", [](float a, float b) { return std::max(a, b); }); +} + +NodeItem NodeItem::blend(const NodeItem &a, const NodeItem &b) +{ + return *this * a + (one() - *this) * b; +} + NodeItem NodeItem::to_color3() const { NodeItem res(graph_); @@ -119,6 +131,13 @@ NodeItem NodeItem::to_color3() const return res; } +NodeItem NodeItem::one() const +{ + NodeItem res(graph_); + res = 1.0f; + return res; +} + NodeItem NodeItem::arithmetic(const std::string &mx_category, std::function func) { std::string t = value ? value->getTypeString() : node->getType(); @@ -297,6 +316,15 @@ NodeItem NodeParser::get_input_link(const std::string &name) case SH_NODE_BSDF_PRINCIPLED: parser = std::make_unique(graph, depsgraph, material, in_node); break; + case SH_NODE_INVERT: + parser = std::make_unique(graph, depsgraph, material, in_node); + break; + case SH_NODE_MATH: + parser = std::make_unique(graph, depsgraph, material, in_node); + break; + case SH_NODE_MIX_RGB_LEGACY: + parser = std::make_unique(graph, depsgraph, material, in_node); + break; case SH_NODE_TEX_IMAGE: parser = std::make_unique(graph, depsgraph, material, in_node); break; diff --git a/source/blender/nodes/shader/materialx/nodes/node_parser.h b/source/blender/nodes/shader/materialx/nodes/node_parser.h index 51a4af39c6e7..8a5e4c78172c 100644 --- a/source/blender/nodes/shader/materialx/nodes/node_parser.h +++ b/source/blender/nodes/shader/materialx/nodes/node_parser.h @@ -37,7 +37,12 @@ class NodeItem { NodeItem operator*(const NodeItem &other); NodeItem operator/(const NodeItem &other); + NodeItem min(const NodeItem &other); + NodeItem max(const NodeItem &other); + NodeItem blend(const NodeItem &a, const NodeItem &b); + NodeItem to_color3() const; + NodeItem one() const; private: NodeItem arithmetic(const std::string &mx_category, std::function func); @@ -85,4 +90,18 @@ class NodeParser { NodeItem empty_value(); }; +#define DECLARE_PARSER(T) \ +class T : public NodeParser { \ + public: \ + using NodeParser::NodeParser; \ + NodeItem compute() override; \ +}; + +DECLARE_PARSER(BSDFPrincipledNodeParser) +DECLARE_PARSER(InvertNodeParser) +DECLARE_PARSER(MathNodeParser) +DECLARE_PARSER(MixRGBNodeParser) +DECLARE_PARSER(OutputMaterialNodeParser) +DECLARE_PARSER(TexImageNodeParser) + } // namespace blender::nodes::materialx diff --git a/source/blender/nodes/shader/materialx/nodes/output_material.cc b/source/blender/nodes/shader/materialx/nodes/output_material.cc index 6b3a4584ec53..dd44f7692ba9 100644 --- a/source/blender/nodes/shader/materialx/nodes/output_material.cc +++ b/source/blender/nodes/shader/materialx/nodes/output_material.cc @@ -2,7 +2,7 @@ * * SPDX-License-Identifier: GPL-2.0-or-later */ -#include "output_material.h" +#include "node_parser.h" namespace blender::nodes::materialx { diff --git a/source/blender/nodes/shader/materialx/nodes/tex_image.cc b/source/blender/nodes/shader/materialx/nodes/tex_image.cc index 3d1a0423c9fa..6c0239459e06 100644 --- a/source/blender/nodes/shader/materialx/nodes/tex_image.cc +++ b/source/blender/nodes/shader/materialx/nodes/tex_image.cc @@ -2,7 +2,6 @@ * * SPDX-License-Identifier: GPL-2.0-or-later */ -#include "tex_image.h" #include "node_parser.h" #include "hydra/image.h" -- 2.30.2 From 9b53dd3fc05e1285d6d9b9db028ee7ba3c6666e5 Mon Sep 17 00:00:00 2001 From: Bogdan Nagirniak Date: Tue, 29 Aug 2023 02:01:01 +0300 Subject: [PATCH 3/3] Added float conversion to arithmetic. Fixed invert. --- .../nodes/shader/materialx/nodes/invert.cc | 2 +- .../nodes/shader/materialx/nodes/math.cc | 1 + .../nodes/shader/materialx/nodes/mix_rgb.cc | 1 + .../shader/materialx/nodes/node_parser.cc | 200 ++++++++++++------ .../shader/materialx/nodes/node_parser.h | 51 +++-- 5 files changed, 172 insertions(+), 83 deletions(-) diff --git a/source/blender/nodes/shader/materialx/nodes/invert.cc b/source/blender/nodes/shader/materialx/nodes/invert.cc index c54f5f9b6972..b6ca706330fe 100644 --- a/source/blender/nodes/shader/materialx/nodes/invert.cc +++ b/source/blender/nodes/shader/materialx/nodes/invert.cc @@ -10,7 +10,7 @@ NodeItem InvertNodeParser::compute() { NodeItem fac = get_input_value("Fac"); NodeItem color = get_input_value("Color"); - return fac.blend(color, fac.one() - color); + return fac.blend(color, fac.val(1.0f) - color); } } // namespace blender::nodes::materialx diff --git a/source/blender/nodes/shader/materialx/nodes/math.cc b/source/blender/nodes/shader/materialx/nodes/math.cc index 909d8ecb1e52..3cee80450a6a 100644 --- a/source/blender/nodes/shader/materialx/nodes/math.cc +++ b/source/blender/nodes/shader/materialx/nodes/math.cc @@ -8,6 +8,7 @@ namespace blender::nodes::materialx { NodeItem MathNodeParser::compute() { + /* TODO: implement */ return empty_value(); } diff --git a/source/blender/nodes/shader/materialx/nodes/mix_rgb.cc b/source/blender/nodes/shader/materialx/nodes/mix_rgb.cc index 5b0c8a2085e2..34cfad6891e5 100644 --- a/source/blender/nodes/shader/materialx/nodes/mix_rgb.cc +++ b/source/blender/nodes/shader/materialx/nodes/mix_rgb.cc @@ -8,6 +8,7 @@ namespace blender::nodes::materialx { NodeItem MixRGBNodeParser::compute() { + /* TODO: implement */ return empty_value(); } diff --git a/source/blender/nodes/shader/materialx/nodes/node_parser.cc b/source/blender/nodes/shader/materialx/nodes/node_parser.cc index c7be1112b450..3b65ec9bf3f6 100644 --- a/source/blender/nodes/shader/materialx/nodes/node_parser.cc +++ b/source/blender/nodes/shader/materialx/nodes/node_parser.cc @@ -10,6 +10,11 @@ namespace blender::nodes::materialx { NodeItem::NodeItem(MaterialX::GraphElement *graph) : graph_(graph) {} +NodeItem NodeItem::empty() const +{ + return NodeItem(graph_); +} + void NodeItem::set_input(const std::string &name, const NodeItem &item) { if (item.value) { @@ -59,121 +64,141 @@ NodeItem::operator bool() const return value || node; } -NodeItem NodeItem::operator+(const NodeItem &other) +NodeItem NodeItem::operator+(const NodeItem &other) const { return arithmetic(other, "add", [](float a, float b) { return a + b; }); } -NodeItem NodeItem::operator-(const NodeItem &other) +NodeItem NodeItem::operator-(const NodeItem &other) const { return arithmetic(other, "subtract", [](float a, float b) { return a - b; }); } -NodeItem NodeItem::operator*(const NodeItem &other) +NodeItem NodeItem::operator*(const NodeItem &other) const { return arithmetic(other, "multiply", [](float a, float b) { return a * b; }); } -NodeItem NodeItem::operator/(const NodeItem &other) +NodeItem NodeItem::operator/(const NodeItem &other) const { return arithmetic(other, "divide", [](float a, float b) { return b == 0.0f ? 0.0f : a / b; }); } -NodeItem NodeItem::min(const NodeItem &other) +bool NodeItem::operator==(const NodeItem &other) const +{ + if (node && node == other.node) { + return true; + } + /* TODO: implement */ + return false; +} + +NodeItem NodeItem::min(const NodeItem &other) const { return arithmetic(other, "min", [](float a, float b) { return std::min(a, b); }); } -NodeItem NodeItem::max(const NodeItem &other) +NodeItem NodeItem::max(const NodeItem &other) const { return arithmetic(other, "max", [](float a, float b) { return std::max(a, b); }); } -NodeItem NodeItem::blend(const NodeItem &a, const NodeItem &b) +NodeItem NodeItem::blend(const NodeItem &a, const NodeItem &b) const { - return *this * a + (one() - *this) * b; + return (val(1.0f) - *this) * a + *this * b; } NodeItem NodeItem::to_color3() const { - NodeItem res(graph_); + std::string t = type(); + NodeItem res = empty(); if (value) { MaterialX::Color3 c; - if (value->isA()) { + if (t == "float") { float v = value->asA(); - c = {v, v ,v}; + c = {v, v, v}; } - else if (value->isA()) { + else if (t == "color3") { auto v = value->asA(); c = {v[0], v[1], v[2]}; } - else if (value->isA()) { + else if (t == "color4") { auto v = value->asA(); c = {v[0], v[1], v[2]}; } - else if (value->isA()) { + else if (t == "vector3") { auto v = value->asA(); c = {v[0], v[1], v[2]}; } - else if (value->isA()) { + else if (t == "vector4") { auto v = value->asA(); c = {v[0], v[1], v[2]}; } else { - /* Default color */ - c = {0.0f, 0.0f, 0.0f}; + return res; } res.value = MaterialX::Value::createValue(c); } else if (node) { + if (t != "color3") { + return res; + } res.node = node; } return res; } -NodeItem NodeItem::one() const +bool NodeItem::is_numeric() const { - NodeItem res(graph_); - res = 1.0f; - return res; + std::string t = type(); + return ELEM(t, "float", "color3", "color4", "vector2", "vector3", "vector4"); } -NodeItem NodeItem::arithmetic(const std::string &mx_category, std::function func) +std::string NodeItem::type() const { + return value ? value->getTypeString() : node->getType(); +} + +NodeItem NodeItem::arithmetic(const std::string &mx_category, + std::function func) const +{ + if (!is_numeric()) { + return empty(); + } + std::string t = value ? value->getTypeString() : node->getType(); NodeItem res(graph_); if (value) { - if (value->isA()) { + if (t == "float") { float v = value->asA(); res.value = MaterialX::Value::createValue(func(v)); } - else if (value->isA()) { + else if (t == "color3") { auto v = value->asA(); res.value = MaterialX::Value::createValue( {func(v[0]), func(v[1]), func(v[2])}); } - else if (value->isA()) { + else if (t == "color4") { auto v = value->asA(); res.value = MaterialX::Value::createValue( {func(v[0]), func(v[1]), func(v[2]), func(v[3])}); } - else if (value->isA()) { + else if (t == "vector2") { auto v = value->asA(); res.value = MaterialX::Value::createValue({func(v[0]), func(v[1])}); } - else if (value->isA()) { + else if (t == "vector3") { auto v = value->asA(); res.value = MaterialX::Value::createValue( {func(v[0]), func(v[1]), func(v[2])}); } - else if (value->isA()) { + else if (t == "vector4") { auto v = value->asA(); res.value = MaterialX::Value::createValue( {func(v[0]), func(v[1]), func(v[2]), func(v[3])}); } else { - /* Nothing change */ - res.value = value; + BLI_assert_unreachable(); } } else { @@ -185,64 +210,121 @@ NodeItem NodeItem::arithmetic(const std::string &mx_category, std::function func) + std::function func) const { - std::string t1 = value ? value->getTypeString() : node->getType(); - std::string t2 = other.value ? other.value->getTypeString() : other.node->getType(); - if (t1 != t2) { - return *this; + NodeItem res = empty(); + if (!is_numeric() || !other.is_numeric()) { + return res; } - NodeItem res(graph_); + std::string t1 = type(); + std::string t2 = other.type(); + if (value && other.value) { - if (value->isA()) { - float v1 = value->asA(); - float v2 = other.value->asA(); + std::string t = t1; + auto val1 = value; + auto val2 = other.value; + if (t1 != t2) { + if (t1 == "float") { + val1 = float_to_type(val1->asA(), t2); + t = t2; + } + else if (t2 == "float") { + val2 = float_to_type(val2->asA(), t1); + } + else { + return res; + } + } + + if (t == "float") { + float v1 = val1->asA(); + float v2 = val2->asA(); res.value = MaterialX::Value::createValue(func(v1, v2)); } - else if (value->isA()) { - auto v1 = value->asA(); - auto v2 = other.value->asA(); + else if (t == "color3") { + auto v1 = val1->asA(); + auto v2 = val2->asA(); res.value = MaterialX::Value::createValue( {func(v1[0], v2[0]), func(v1[1], v2[1]), func(v1[2], v2[2])}); } - else if (value->isA()) { - auto v1 = value->asA(); - auto v2 = other.value->asA(); + else if (t == "color4") { + auto v1 = val1->asA(); + auto v2 = val2->asA(); res.value = MaterialX::Value::createValue( {func(v1[0], v2[0]), func(v1[1], v2[1]), func(v1[2], v2[2]), func(v1[3], v2[3])}); } - else if (value->isA()) { - auto v1 = value->asA(); - auto v2 = other.value->asA(); + else if (t == "vector2") { + auto v1 = val1->asA(); + auto v2 = val2->asA(); res.value = MaterialX::Value::createValue( {func(v1[0], v2[0]), func(v1[1], v2[1])}); } - else if (value->isA()) { - auto v1 = value->asA(); - auto v2 = other.value->asA(); + else if (t == "vector3") { + auto v1 = val1->asA(); + auto v2 = val2->asA(); res.value = MaterialX::Value::createValue( {func(v1[0], v2[0]), func(v1[1], v2[1]), func(v1[2], v2[2])}); } - else if (value->isA()) { - auto v1 = value->asA(); - auto v2 = other.value->asA(); + else if (t == "vector4") { + auto v1 = val1->asA(); + auto v2 = val2->asA(); res.value = MaterialX::Value::createValue( {func(v1[0], v2[0]), func(v1[1], v2[1]), func(v1[2], v2[2]), func(v1[3], v2[3])}); } else { - /* default color */ - res.value = value; + BLI_assert_unreachable(); } } else { - res.node = graph_->addNode(mx_category, MaterialX::EMPTY_STRING, t1); - res.set_input("in1", *this); - res.set_input("in2", other); + std::string t = t1; + auto val1 = *this; + auto val2 = other; + if (t1 != t2) { + if (val1.value && t1 == "float") { + val1.value = float_to_type(val1.value->asA(), t2); + t = t2; + } + else if (val2.value && t2 == "float") { + val2.value = float_to_type(val2.value->asA(), t1); + } + else { + return res; + } + } + + res.node = graph_->addNode(mx_category, MaterialX::EMPTY_STRING, t); + res.set_input("in1", val1); + res.set_input("in2", val2); } return res; } +MaterialX::ValuePtr NodeItem::float_to_type(float v, std::string t) const +{ + if (t == "float") { + return MaterialX::Value::createValue(v); + } + if (t == "color3") { + return MaterialX::Value::createValue({v, v, v}); + } + if (t == "color4") { + return MaterialX::Value::createValue({v, v, v, 1.0f}); + } + if (t == "vector2") { + return MaterialX::Value::createValue({v, v}); + } + if (t == "vector3") { + return MaterialX::Value::createValue({v, v, v}); + } + if (t == "vector4") { + return MaterialX::Value::createValue({v, v, v, 1.0f}); + } + + BLI_assert_unreachable(); + return nullptr; +} + NodeParser::NodeParser(MaterialX::GraphElement *graph, const Depsgraph *depsgraph, const Material *material, diff --git a/source/blender/nodes/shader/materialx/nodes/node_parser.h b/source/blender/nodes/shader/materialx/nodes/node_parser.h index 8a5e4c78172c..d2604ff265b2 100644 --- a/source/blender/nodes/shader/materialx/nodes/node_parser.h +++ b/source/blender/nodes/shader/materialx/nodes/node_parser.h @@ -24,6 +24,9 @@ class NodeItem { NodeItem(MaterialX::GraphElement *graph); ~NodeItem() = default; + NodeItem empty() const; + template NodeItem val(const T &data) const; + template void set_input(const std::string &name, const T &value, const std::string &mx_type); void set_input(const std::string &name, const NodeItem &item); @@ -31,39 +34,41 @@ class NodeItem { void set_input(const std::string &name, const MaterialX::NodePtr node); operator bool() const; - template NodeItem &operator=(const T &value); - NodeItem operator+(const NodeItem &other); - NodeItem operator-(const NodeItem &other); - NodeItem operator*(const NodeItem &other); - NodeItem operator/(const NodeItem &other); + NodeItem operator+(const NodeItem &other) const; + NodeItem operator-(const NodeItem &other) const; + NodeItem operator*(const NodeItem &other) const; + NodeItem operator/(const NodeItem &other) const; + bool operator==(const NodeItem &other) const; - NodeItem min(const NodeItem &other); - NodeItem max(const NodeItem &other); - NodeItem blend(const NodeItem &a, const NodeItem &b); + NodeItem min(const NodeItem &other) const; + NodeItem max(const NodeItem &other) const; + NodeItem blend(const NodeItem &a, const NodeItem &b) const; NodeItem to_color3() const; - NodeItem one() const; + bool is_numeric() const; + std::string type() const; private: - NodeItem arithmetic(const std::string &mx_category, std::function func); + NodeItem arithmetic(const std::string &mx_category, std::function func) const; NodeItem arithmetic(const NodeItem &other, const std::string &mx_category, - std::function func); + std::function func) const; + MaterialX::ValuePtr float_to_type(float v, std::string t) const; }; +template NodeItem NodeItem::val(const T &data) const +{ + NodeItem res(graph_); + res.value = MaterialX::Value::createValue(data); + return res; +} + template void NodeItem::set_input(const std::string &name, const T &value, const std::string &mx_type) { node->setInputValue(name, value, mx_type); } -template NodeItem &NodeItem::operator=(const T &value) -{ - this->value = MaterialX::Value::createValue(value); - node = nullptr; - return *this; -} - class NodeParser { public: MaterialX::GraphElement *graph; @@ -91,11 +96,11 @@ class NodeParser { }; #define DECLARE_PARSER(T) \ -class T : public NodeParser { \ - public: \ - using NodeParser::NodeParser; \ - NodeItem compute() override; \ -}; + class T : public NodeParser { \ + public: \ + using NodeParser::NodeParser; \ + NodeItem compute() override; \ + }; DECLARE_PARSER(BSDFPrincipledNodeParser) DECLARE_PARSER(InvertNodeParser) -- 2.30.2