From 998e86536ecc0846c1baa7a53fe1fb1a81597719 Mon Sep 17 00:00:00 2001 From: Bogdan Nagirniak Date: Thu, 14 Sep 2023 02:24:27 +0300 Subject: [PATCH 01/14] Initial changes for group nodes. --- source/blender/nodes/shader/CMakeLists.txt | 2 + .../nodes/shader/materialx/group_nodes.cc | 65 +++++++++++++++++++ .../nodes/shader/materialx/group_nodes.h | 33 ++++++++++ .../nodes/shader/materialx/node_item.cc | 8 ++- .../nodes/shader/materialx/node_item.h | 1 + .../nodes/shader/materialx/node_parser.cc | 11 +++- .../nodes/shader/materialx/node_parser.h | 2 +- .../shader/nodes/node_shader_tex_noise.cc | 6 +- 8 files changed, 118 insertions(+), 10 deletions(-) create mode 100644 source/blender/nodes/shader/materialx/group_nodes.cc create mode 100644 source/blender/nodes/shader/materialx/group_nodes.h diff --git a/source/blender/nodes/shader/CMakeLists.txt b/source/blender/nodes/shader/CMakeLists.txt index 98e9f7db99a..72cc3b30b92 100644 --- a/source/blender/nodes/shader/CMakeLists.txt +++ b/source/blender/nodes/shader/CMakeLists.txt @@ -149,10 +149,12 @@ if(WITH_MATERIALX) materialx/material.cc materialx/node_item.cc materialx/node_parser.cc + materialx/group_nodes.cc materialx/material.h materialx/node_item.h materialx/node_parser.h + materialx/group_nodes.h ) list(APPEND LIB MaterialXCore diff --git a/source/blender/nodes/shader/materialx/group_nodes.cc b/source/blender/nodes/shader/materialx/group_nodes.cc new file mode 100644 index 00000000000..0e4b049d378 --- /dev/null +++ b/source/blender/nodes/shader/materialx/group_nodes.cc @@ -0,0 +1,65 @@ +/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation + * + * SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "node_parser.h" +#include "group_nodes.h" + +namespace blender::nodes::materialx { + +NodeItem GroupNodeParser::compute() +{ + NodeItem res = empty(); + + const bNodeTree *ngroup = reinterpret_cast(node_->id); + ngroup->ensure_topology_cache(); + const bNode *node_out = ngroup->group_output_node(); + if (!node_out) { + return res; + } + + std::string name = MaterialX::createValidName(node_->name); /* or ngroup->name */ + MaterialX::NodeGraphPtr group_graph = graph_->getChildOfType(name); + if (!group_graph) { + group_graph = graph_->addChild(name); + } + + GroupOutputNodeParser parser( + group_graph.get(), depsgraph_, material_, node_out, socket_out_, NodeItem::Type::Any); + NodeItem out = parser.compute_full(); + res.node = group_graph; + if (parser.output) { + res = create_node("constant", out.type()); + res.set_input("value", parser.output); + } + return res; +} + +NodeItem GroupOutputNodeParser::compute() +{ + NodeItem res = get_input_link(socket_out_->index(), to_type_); + if (res) { + output = graph_->addOutput(MaterialX::EMPTY_STRING, NodeItem::type(res.type())); + output->setValue(1.0f); + } + return res; +} + +NodeItem GroupInputNodeParser::compute() +{ + return empty(); +} + +NodeItem GroupInputNodeParser::compute_full() +{ + CLOG_INFO(LOG_MATERIALX_SHADER, + 1, + "%s [%d] => %s", + node_->name, + node_->typeinfo->type, + NodeItem::type(to_type_).c_str()); + + return compute(); +} + +} // namespace blender::nodes::materialx diff --git a/source/blender/nodes/shader/materialx/group_nodes.h b/source/blender/nodes/shader/materialx/group_nodes.h new file mode 100644 index 00000000000..2aaf77f8123 --- /dev/null +++ b/source/blender/nodes/shader/materialx/group_nodes.h @@ -0,0 +1,33 @@ +/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation + * + * SPDX-License-Identifier: GPL-2.0-or-later */ + +#pragma once + +#include "node_parser.h" + +namespace blender::nodes::materialx { + +class GroupNodeParser : public NodeParser { + public: + using NodeParser::NodeParser; + NodeItem compute() override; +}; + +class GroupOutputNodeParser : public NodeParser { + public: + MaterialX::OutputPtr output; + + public: + using NodeParser::NodeParser; + NodeItem compute() override; +}; + +class GroupInputNodeParser : public NodeParser { + public: + using NodeParser::NodeParser; + NodeItem compute() override; + NodeItem compute_full() override; +}; + +} // namespace blender::nodes::materialx diff --git a/source/blender/nodes/shader/materialx/node_item.cc b/source/blender/nodes/shader/materialx/node_item.cc index af3d6af54f6..f9e04b8bd33 100644 --- a/source/blender/nodes/shader/materialx/node_item.cc +++ b/source/blender/nodes/shader/materialx/node_item.cc @@ -675,13 +675,15 @@ void NodeItem::set_input(const std::string &in_name, const NodeItem &item) } } +void NodeItem::set_input(const std::string &in_name, MaterialX::OutputPtr output) +{ + node->setConnectedOutput(in_name, output); +} + void NodeItem::set_input_output(const std::string &in_name, const NodeItem &item, const std::string &out_name) { - if (!item.node) { - BLI_assert_unreachable(); - } node->setConnectedNode(in_name, item.node); node->setConnectedOutput(in_name, item.node->getOutput(out_name)); } diff --git a/source/blender/nodes/shader/materialx/node_item.h b/source/blender/nodes/shader/materialx/node_item.h index f9e45822f66..84277d0016f 100644 --- a/source/blender/nodes/shader/materialx/node_item.h +++ b/source/blender/nodes/shader/materialx/node_item.h @@ -104,6 +104,7 @@ class NodeItem { /* Functions to set input and output */ template void set_input(const std::string &in_name, const T &value, Type in_type); void set_input(const std::string &in_name, const NodeItem &item); + void set_input(const std::string &in_name, MaterialX::OutputPtr output); void set_input_output(const std::string &in_name, const NodeItem &item, const std::string &out_name); diff --git a/source/blender/nodes/shader/materialx/node_parser.cc b/source/blender/nodes/shader/materialx/node_parser.cc index 357a27cacbb..3b90aea20d9 100644 --- a/source/blender/nodes/shader/materialx/node_parser.cc +++ b/source/blender/nodes/shader/materialx/node_parser.cc @@ -4,6 +4,8 @@ #include "node_parser.h" +#include "group_nodes.h" + #include "BKE_node_runtime.hh" namespace blender::nodes::materialx { @@ -54,7 +56,7 @@ NodeItem NodeParser::compute_full() return res; } -std::string NodeParser::node_name() +std::string NodeParser::node_name() const { std::string name = node_->name; if (node_->output_sockets().size() > 1) { @@ -155,7 +157,7 @@ NodeItem NodeParser::get_input_link(const bNodeSocket &socket, NodeItem::Type to const bNode *from_node = link->fromnode; /* Passing NODE_REROUTE nodes */ - while (from_node->type == NODE_REROUTE) { + while (from_node->is_reroute()) { link = from_node->input_socket(0).link; if (!(link && link->is_used())) { return empty(); @@ -163,6 +165,11 @@ NodeItem NodeParser::get_input_link(const bNodeSocket &socket, NodeItem::Type to from_node = link->fromnode; } + if (from_node->is_group()) { + return GroupNodeParser(graph_, depsgraph_, material_, from_node, link->fromsock, to_type) + .compute_full(); + } + if (!from_node->typeinfo->materialx_fn) { CLOG_WARN(LOG_MATERIALX_SHADER, "Unsupported node: %s [%d]", diff --git a/source/blender/nodes/shader/materialx/node_parser.h b/source/blender/nodes/shader/materialx/node_parser.h index c0e6d6952f0..d1e551ff237 100644 --- a/source/blender/nodes/shader/materialx/node_parser.h +++ b/source/blender/nodes/shader/materialx/node_parser.h @@ -38,7 +38,7 @@ class NodeParser { virtual NodeItem compute_full(); protected: - std::string node_name(); + std::string node_name() const; NodeItem create_node(const std::string &category, NodeItem::Type type); NodeItem get_input_default(const std::string &name, NodeItem::Type to_type); NodeItem get_input_default(int index, NodeItem::Type to_type); diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_noise.cc b/source/blender/nodes/shader/nodes/node_shader_tex_noise.cc index bc6ff5a5cff..e12569a9880 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_noise.cc +++ b/source/blender/nodes/shader/nodes/node_shader_tex_noise.cc @@ -260,7 +260,7 @@ static void sh_node_noise_build_multi_function(NodeMultiFunctionBuilder &builder NODE_SHADER_MATERIALX_BEGIN { NodeItem scale = get_input_value("Scale", NodeItem::Type::Float); - NodeItem detail = get_input_value("Detail", NodeItem::Type::Float); + NodeItem detail = get_input_default("Detail", NodeItem::Type::Float); NodeItem lacunarity = get_input_value("Lacunarity", NodeItem::Type::Float); NodeItem position = create_node("position", NodeItem::Type::Vector3); @@ -268,9 +268,7 @@ NODE_SHADER_MATERIALX_BEGIN NodeItem res = create_node("fractal3d", NodeItem::Type::Color3); res.set_input("position", position); - if (detail.value) { - res.set_input("octaves", val(int(detail.value->asA()))); - } + res.set_input("octaves", val(int(detail.value->asA()))); res.set_input("lacunarity", lacunarity); return res; } -- 2.30.2 From 1bd4ae1663a464ea8792479f37b2d79e3c4be158 Mon Sep 17 00:00:00 2001 From: Bogdan Nagirniak Date: Thu, 14 Sep 2023 05:57:26 +0300 Subject: [PATCH 02/14] Added NodeItem::output and corresponded functionality. Made group nodes to work with output --- .../nodes/shader/materialx/group_nodes.cc | 21 ++--- .../nodes/shader/materialx/group_nodes.h | 3 - .../nodes/shader/materialx/node_item.cc | 81 +++++++++++++++---- .../nodes/shader/materialx/node_item.h | 21 +++-- .../nodes/shader/materialx/node_parser.cc | 5 ++ .../nodes/shader/materialx/node_parser.h | 1 + 6 files changed, 94 insertions(+), 38 deletions(-) diff --git a/source/blender/nodes/shader/materialx/group_nodes.cc b/source/blender/nodes/shader/materialx/group_nodes.cc index 0e4b049d378..53061046eb8 100644 --- a/source/blender/nodes/shader/materialx/group_nodes.cc +++ b/source/blender/nodes/shader/materialx/group_nodes.cc @@ -24,24 +24,19 @@ NodeItem GroupNodeParser::compute() group_graph = graph_->addChild(name); } - GroupOutputNodeParser parser( - group_graph.get(), depsgraph_, material_, node_out, socket_out_, NodeItem::Type::Any); - NodeItem out = parser.compute_full(); - res.node = group_graph; - if (parser.output) { - res = create_node("constant", out.type()); - res.set_input("value", parser.output); - } + NodeItem out = + GroupOutputNodeParser( + group_graph.get(), depsgraph_, material_, node_out, socket_out_, NodeItem::Type::Any) + .compute_full(); + res.output = out.output; return res; } NodeItem GroupOutputNodeParser::compute() { - NodeItem res = get_input_link(socket_out_->index(), to_type_); - if (res) { - output = graph_->addOutput(MaterialX::EMPTY_STRING, NodeItem::type(res.type())); - output->setValue(1.0f); - } + NodeItem value = get_input_link(socket_out_->index(), to_type_); + NodeItem res = create_output(); + res.set_output(value); return res; } diff --git a/source/blender/nodes/shader/materialx/group_nodes.h b/source/blender/nodes/shader/materialx/group_nodes.h index 2aaf77f8123..afa073ce123 100644 --- a/source/blender/nodes/shader/materialx/group_nodes.h +++ b/source/blender/nodes/shader/materialx/group_nodes.h @@ -15,9 +15,6 @@ class GroupNodeParser : public NodeParser { }; class GroupOutputNodeParser : public NodeParser { - public: - MaterialX::OutputPtr output; - public: using NodeParser::NodeParser; NodeItem compute() override; diff --git a/source/blender/nodes/shader/materialx/node_item.cc b/source/blender/nodes/shader/materialx/node_item.cc index f9e04b8bd33..501de883f2e 100644 --- a/source/blender/nodes/shader/materialx/node_item.cc +++ b/source/blender/nodes/shader/materialx/node_item.cc @@ -98,9 +98,14 @@ std::string NodeItem::type(Type type) return ""; } +bool NodeItem::is_arithmetic(Type type) +{ + return type >= Type::Float && type <= Type::Color4; +} + NodeItem::operator bool() const { - return value || node; + return value || node || output; } NodeItem NodeItem::operator+(const NodeItem &other) const @@ -619,6 +624,9 @@ NodeItem::Type NodeItem::type() const if (node) { return type(node->getType()); } + if (output) { + return type(output->getType()); + } return Type::Empty; } @@ -670,32 +678,75 @@ void NodeItem::set_input(const std::string &in_name, const NodeItem &item) else if (item.node) { node->setConnectedNode(in_name, item.node); } + else if (item.output) { + node->setConnectedOutput(in_name, item.output); + } else { CLOG_WARN(LOG_MATERIALX_SHADER, "Empty item to input: %s", in_name.c_str()); } } -void NodeItem::set_input(const std::string &in_name, MaterialX::OutputPtr output) +NodeItem NodeItem::add_output(const std::string &out_name, Type out_type) { - node->setConnectedOutput(in_name, output); + NodeItem res = empty(); + res.output = node->addOutput(out_name, type(out_type)); + return res; } -void NodeItem::set_input_output(const std::string &in_name, - const NodeItem &item, - const std::string &out_name) +NodeItem NodeItem::create_output(const std::string &out_name) const { - node->setConnectedNode(in_name, item.node); - node->setConnectedOutput(in_name, item.node->getOutput(out_name)); + NodeItem res = empty(); + res.output = graph_->addOutput(out_name); + return res; } -void NodeItem::add_output(const std::string &name, Type out_type) +void NodeItem::set_output(const NodeItem &item) const { - node->addOutput(name, type(out_type)); -} - -bool NodeItem::is_arithmetic(Type type) -{ - return type >= Type::Float && type <= Type::Color4; + Type item_type = item.type(); + if (item.value) { + switch (item_type) { + case Type::String: + set_output(item.value->asA(), item_type); + break; + case Type::Boolean: + set_output(item.value->asA(), item_type); + break; + case Type::Integer: + set_output(item.value->asA(), item_type); + break; + case Type::Float: + set_output(item.value->asA(), item_type); + break; + case Type::Vector2: + set_output(item.value->asA(), item_type); + break; + case Type::Vector3: + set_output(item.value->asA(), item_type); + break; + case Type::Vector4: + set_output(item.value->asA(), item_type); + break; + case Type::Color3: + set_output(item.value->asA(), item_type); + break; + case Type::Color4: + set_output(item.value->asA(), item_type); + break; + default: + BLI_assert_unreachable(); + } + } + else if (item.node) { + output->setConnectedNode(item.node); + output->setType(type(item_type)); + } + else if (item.output) { + output->setConnectedOutput(item.output); + output->setType(type(item_type)); + } + else { + CLOG_WARN(LOG_MATERIALX_SHADER, "Empty item to output: %s", output->getName().c_str()); + } } NodeItem::Type NodeItem::cast_types(NodeItem &item1, NodeItem &item2) diff --git a/source/blender/nodes/shader/materialx/node_item.h b/source/blender/nodes/shader/materialx/node_item.h index 80b470f32dc..81766358d9b 100644 --- a/source/blender/nodes/shader/materialx/node_item.h +++ b/source/blender/nodes/shader/materialx/node_item.h @@ -43,6 +43,7 @@ class NodeItem { public: MaterialX::ValuePtr value; MaterialX::NodePtr node; + MaterialX::OutputPtr output; private: MaterialX::GraphElement *graph_; @@ -102,16 +103,17 @@ class NodeItem { NodeItem empty() const; template NodeItem val(const T &data) const; Type type() const; - NodeItem create_node(const std::string &category, NodeItem::Type type) const; - /* Functions to set input and output */ + /* Node functions */ + NodeItem create_node(const std::string &category, NodeItem::Type type) const; template void set_input(const std::string &in_name, const T &value, Type in_type); void set_input(const std::string &in_name, const NodeItem &item); - void set_input(const std::string &in_name, MaterialX::OutputPtr output); - void set_input_output(const std::string &in_name, - const NodeItem &item, - const std::string &out_name); - void add_output(const std::string &in_name, Type out_type); + NodeItem add_output(const std::string &out_name, Type out_type); + + /* Output functions */ + NodeItem create_output(const std::string &out_name) const; + template void set_output(const T &value, Type out_type) const; + void set_output(const NodeItem &item) const; private: static Type cast_types(NodeItem &item1, NodeItem &item2); @@ -136,4 +138,9 @@ void NodeItem::set_input(const std::string &in_name, const T &value, Type in_typ node->setInputValue(in_name, value, type(in_type)); } +template void NodeItem::set_output(const T &value, Type out_type) const +{ + output->setValue(value, type(out_type)); +} + } // namespace blender::nodes::materialx diff --git a/source/blender/nodes/shader/materialx/node_parser.cc b/source/blender/nodes/shader/materialx/node_parser.cc index 3b90aea20d9..65d3a6f5811 100644 --- a/source/blender/nodes/shader/materialx/node_parser.cc +++ b/source/blender/nodes/shader/materialx/node_parser.cc @@ -73,6 +73,11 @@ NodeItem NodeParser::create_node(const std::string &category, NodeItem::Type typ return empty().create_node(category, type); } +NodeItem NodeParser::create_output() +{ + return empty().create_output(""); +} + NodeItem NodeParser::get_input_default(const std::string &name, NodeItem::Type to_type) { return get_input_default(node_->input_by_identifier(name), to_type); diff --git a/source/blender/nodes/shader/materialx/node_parser.h b/source/blender/nodes/shader/materialx/node_parser.h index d1e551ff237..b42f018da7d 100644 --- a/source/blender/nodes/shader/materialx/node_parser.h +++ b/source/blender/nodes/shader/materialx/node_parser.h @@ -40,6 +40,7 @@ class NodeParser { protected: std::string node_name() const; NodeItem create_node(const std::string &category, NodeItem::Type type); + NodeItem create_output(); NodeItem get_input_default(const std::string &name, NodeItem::Type to_type); NodeItem get_input_default(int index, NodeItem::Type to_type); NodeItem get_input_link(const std::string &name, NodeItem::Type to_type); -- 2.30.2 From 9530f24d3d7adb31b5cf074575c7393f375d2ece Mon Sep 17 00:00:00 2001 From: Bogdan Nagirniak Date: Thu, 14 Sep 2023 12:41:48 +0300 Subject: [PATCH 03/14] Different fixes --- .../nodes/shader/materialx/group_nodes.cc | 28 +++++++++---------- .../nodes/shader/materialx/group_nodes.h | 4 ++- .../nodes/shader/materialx/node_parser.cc | 17 +++++++++-- .../nodes/shader/materialx/node_parser.h | 2 +- 4 files changed, 32 insertions(+), 19 deletions(-) diff --git a/source/blender/nodes/shader/materialx/group_nodes.cc b/source/blender/nodes/shader/materialx/group_nodes.cc index 53061046eb8..8d414fecdac 100644 --- a/source/blender/nodes/shader/materialx/group_nodes.cc +++ b/source/blender/nodes/shader/materialx/group_nodes.cc @@ -18,7 +18,7 @@ NodeItem GroupNodeParser::compute() return res; } - std::string name = MaterialX::createValidName(node_->name); /* or ngroup->name */ + std::string name = MaterialX::createValidName(ngroup->idname); MaterialX::NodeGraphPtr group_graph = graph_->getChildOfType(name); if (!group_graph) { group_graph = graph_->addChild(name); @@ -28,33 +28,33 @@ NodeItem GroupNodeParser::compute() GroupOutputNodeParser( group_graph.get(), depsgraph_, material_, node_out, socket_out_, NodeItem::Type::Any) .compute_full(); + + /* We have to be in NodeParser's graph_, therefore copying output */ res.output = out.output; return res; } NodeItem GroupOutputNodeParser::compute() { - NodeItem value = get_input_link(socket_out_->index(), to_type_); + NodeItem value = get_input_value(socket_out_->index(), to_type_); NodeItem res = create_output(); res.set_output(value); return res; } +std::string GroupOutputNodeParser::name_out() const +{ + std::string name = "output"; + if (node_->input_sockets().size() > 1) { + name += std::to_string(socket_out_->index() + 1); + } + return name; +} + NodeItem GroupInputNodeParser::compute() { + auto in = graph_->addInput(); return empty(); } -NodeItem GroupInputNodeParser::compute_full() -{ - CLOG_INFO(LOG_MATERIALX_SHADER, - 1, - "%s [%d] => %s", - node_->name, - node_->typeinfo->type, - NodeItem::type(to_type_).c_str()); - - return compute(); -} - } // namespace blender::nodes::materialx diff --git a/source/blender/nodes/shader/materialx/group_nodes.h b/source/blender/nodes/shader/materialx/group_nodes.h index afa073ce123..f3126294054 100644 --- a/source/blender/nodes/shader/materialx/group_nodes.h +++ b/source/blender/nodes/shader/materialx/group_nodes.h @@ -18,13 +18,15 @@ class GroupOutputNodeParser : public NodeParser { public: using NodeParser::NodeParser; NodeItem compute() override; + + protected: + std::string name_out() const override; }; class GroupInputNodeParser : public NodeParser { public: using NodeParser::NodeParser; NodeItem compute() override; - NodeItem compute_full() override; }; } // namespace blender::nodes::materialx diff --git a/source/blender/nodes/shader/materialx/node_parser.cc b/source/blender/nodes/shader/materialx/node_parser.cc index 65d3a6f5811..6c74dab81c5 100644 --- a/source/blender/nodes/shader/materialx/node_parser.cc +++ b/source/blender/nodes/shader/materialx/node_parser.cc @@ -34,10 +34,14 @@ NodeItem NodeParser::compute_full() NodeItem res = empty(); /* Checking if node was already computed */ - res.node = graph_->getNode(node_name()); + res.node = graph_->getNode(name_out()); if (res.node) { return res; } + res.output = graph_->getOutput(name_out()); + if (res.output) { + return res; + } CLOG_INFO(LOG_MATERIALX_SHADER, 1, @@ -48,7 +52,10 @@ NodeItem NodeParser::compute_full() res = compute(); if (res.node) { - res.node->setName(node_name()); + res.node->setName(name_out()); + } + else if (res.output) { + res.output->setName(name_out()); } if (NodeItem::is_arithmetic(to_type_)) { res = res.convert(to_type_); @@ -56,7 +63,7 @@ NodeItem NodeParser::compute_full() return res; } -std::string NodeParser::node_name() const +std::string NodeParser::name_out() const { std::string name = node_->name; if (node_->output_sockets().size() > 1) { @@ -174,6 +181,10 @@ NodeItem NodeParser::get_input_link(const bNodeSocket &socket, NodeItem::Type to return GroupNodeParser(graph_, depsgraph_, material_, from_node, link->fromsock, to_type) .compute_full(); } + if (from_node->is_group_input()) { + return GroupInputNodeParser(graph_, depsgraph_, material_, from_node, link->fromsock, to_type) + .compute_full(); + } if (!from_node->typeinfo->materialx_fn) { CLOG_WARN(LOG_MATERIALX_SHADER, diff --git a/source/blender/nodes/shader/materialx/node_parser.h b/source/blender/nodes/shader/materialx/node_parser.h index b42f018da7d..20aaf2511d7 100644 --- a/source/blender/nodes/shader/materialx/node_parser.h +++ b/source/blender/nodes/shader/materialx/node_parser.h @@ -38,7 +38,7 @@ class NodeParser { virtual NodeItem compute_full(); protected: - std::string node_name() const; + virtual std::string name_out() const; NodeItem create_node(const std::string &category, NodeItem::Type type); NodeItem create_output(); NodeItem get_input_default(const std::string &name, NodeItem::Type to_type); -- 2.30.2 From 6a6837672360ed45e4bc673858c6144b494a160f Mon Sep 17 00:00:00 2001 From: Bogdan Nagirniak Date: Thu, 14 Sep 2023 15:25:15 +0300 Subject: [PATCH 04/14] Fixes, preparing for GroupInputNodeParser --- .../nodes/shader/materialx/group_nodes.cc | 48 ++++++++++++++----- .../nodes/shader/materialx/group_nodes.h | 4 +- .../nodes/shader/materialx/material.cc | 6 +-- .../nodes/shader/materialx/node_item.cc | 6 +-- .../nodes/shader/materialx/node_item.h | 2 +- .../nodes/shader/materialx/node_parser.cc | 32 ++++++------- .../nodes/shader/materialx/node_parser.h | 12 +++-- 7 files changed, 69 insertions(+), 41 deletions(-) diff --git a/source/blender/nodes/shader/materialx/group_nodes.cc b/source/blender/nodes/shader/materialx/group_nodes.cc index 8d414fecdac..1d1d0439832 100644 --- a/source/blender/nodes/shader/materialx/group_nodes.cc +++ b/source/blender/nodes/shader/materialx/group_nodes.cc @@ -5,6 +5,8 @@ #include "node_parser.h" #include "group_nodes.h" +#include "BLI_vector.hh" + namespace blender::nodes::materialx { NodeItem GroupNodeParser::compute() @@ -18,15 +20,16 @@ NodeItem GroupNodeParser::compute() return res; } - std::string name = MaterialX::createValidName(ngroup->idname); + std::string name = MaterialX::createValidName(ngroup->id.name); MaterialX::NodeGraphPtr group_graph = graph_->getChildOfType(name); if (!group_graph) { + CLOG_INFO(LOG_MATERIALX_SHADER, 1, "", name.c_str()); group_graph = graph_->addChild(name); } NodeItem out = GroupOutputNodeParser( - group_graph.get(), depsgraph_, material_, node_out, socket_out_, NodeItem::Type::Any) + group_graph.get(), depsgraph_, material_, node_out, socket_out_, NodeItem::Type::Any, this) .compute_full(); /* We have to be in NodeParser's graph_, therefore copying output */ @@ -36,24 +39,45 @@ NodeItem GroupNodeParser::compute() NodeItem GroupOutputNodeParser::compute() { - NodeItem value = get_input_value(socket_out_->index(), to_type_); - NodeItem res = create_output(); - res.set_output(value); - return res; + Vector values; + for (auto socket_in : node_->input_sockets()) { + values.append(get_input_value(socket_in->index(), NodeItem::Type::Any)); + } + Vector outputs; + for (int i = 0; i < values.size(); ++i) { + if (values[i]) { + outputs.append(create_output()); + outputs[i].set_output(values[i]); + outputs[i].output->setName("output" + std::to_string(i + 1)); + } + } + return outputs[socket_out_->index()]; } -std::string GroupOutputNodeParser::name_out() const +NodeItem GroupOutputNodeParser::compute_full() { - std::string name = "output"; - if (node_->input_sockets().size() > 1) { - name += std::to_string(socket_out_->index() + 1); + NodeItem res = empty(); + + /* Checking if output was already computed */ + res.output = graph_->getOutput("output" + std::to_string(socket_out_->index() + 1)); + if (res.output) { + return res; } - return name; + + CLOG_INFO(LOG_MATERIALX_SHADER, + 1, + "%s [%d] => %s", + node_->name, + node_->typeinfo->type, + NodeItem::type(to_type_).c_str()); + + res = compute(); + return res; } NodeItem GroupInputNodeParser::compute() { - auto in = graph_->addInput(); + //auto in = graph_->addInput(); return empty(); } diff --git a/source/blender/nodes/shader/materialx/group_nodes.h b/source/blender/nodes/shader/materialx/group_nodes.h index f3126294054..b854725ca96 100644 --- a/source/blender/nodes/shader/materialx/group_nodes.h +++ b/source/blender/nodes/shader/materialx/group_nodes.h @@ -18,9 +18,7 @@ class GroupOutputNodeParser : public NodeParser { public: using NodeParser::NodeParser; NodeItem compute() override; - - protected: - std::string name_out() const override; + NodeItem compute_full() override; }; class GroupInputNodeParser : public NodeParser { diff --git a/source/blender/nodes/shader/materialx/material.cc b/source/blender/nodes/shader/materialx/material.cc index 540204a8d87..9e40a51489b 100644 --- a/source/blender/nodes/shader/materialx/material.cc +++ b/source/blender/nodes/shader/materialx/material.cc @@ -62,18 +62,18 @@ MaterialX::DocumentPtr export_to_materialx(Depsgraph *depsgraph, Material *mater bNode *output_node = ntreeShaderOutputNode(material->nodetree, SHD_OUTPUT_ALL); if (output_node) { NodeParserData data = { - doc.get(), depsgraph, material, NodeItem::Type::Material, NodeItem(doc.get())}; + doc.get(), depsgraph, material, NodeItem::Type::Material, nullptr, NodeItem(doc.get())}; output_node->typeinfo->materialx_fn(&data, output_node, nullptr); } else { DefaultMaterialNodeParser( - doc.get(), depsgraph, material, nullptr, nullptr, NodeItem::Type::Material) + doc.get(), depsgraph, material, nullptr, nullptr, NodeItem::Type::Material, nullptr) .compute_error(); } } else { DefaultMaterialNodeParser( - doc.get(), depsgraph, material, nullptr, nullptr, NodeItem::Type::Material) + doc.get(), depsgraph, material, nullptr, nullptr, NodeItem::Type::Material, nullptr) .compute(); } diff --git a/source/blender/nodes/shader/materialx/node_item.cc b/source/blender/nodes/shader/materialx/node_item.cc index 501de883f2e..a7a03968110 100644 --- a/source/blender/nodes/shader/materialx/node_item.cc +++ b/source/blender/nodes/shader/materialx/node_item.cc @@ -63,7 +63,7 @@ std::string NodeItem::type(Type type) { switch (type) { case Type::Any: - return ""; + return "any"; case Type::String: return "string"; case Type::Filename: @@ -693,10 +693,10 @@ NodeItem NodeItem::add_output(const std::string &out_name, Type out_type) return res; } -NodeItem NodeItem::create_output(const std::string &out_name) const +NodeItem NodeItem::create_output() const { NodeItem res = empty(); - res.output = graph_->addOutput(out_name); + res.output = graph_->addOutput(); return res; } diff --git a/source/blender/nodes/shader/materialx/node_item.h b/source/blender/nodes/shader/materialx/node_item.h index 81766358d9b..b1d5b8f712d 100644 --- a/source/blender/nodes/shader/materialx/node_item.h +++ b/source/blender/nodes/shader/materialx/node_item.h @@ -111,7 +111,7 @@ class NodeItem { NodeItem add_output(const std::string &out_name, Type out_type); /* Output functions */ - NodeItem create_output(const std::string &out_name) const; + NodeItem create_output() const; template void set_output(const T &value, Type out_type) const; void set_output(const NodeItem &item) const; diff --git a/source/blender/nodes/shader/materialx/node_parser.cc b/source/blender/nodes/shader/materialx/node_parser.cc index 6c74dab81c5..989f4cb87e2 100644 --- a/source/blender/nodes/shader/materialx/node_parser.cc +++ b/source/blender/nodes/shader/materialx/node_parser.cc @@ -19,13 +19,15 @@ NodeParser::NodeParser(MaterialX::GraphElement *graph, const Material *material, const bNode *node, const bNodeSocket *socket_out, - NodeItem::Type to_type) + NodeItem::Type to_type, + GroupNodeParser *group_parser) : graph_(graph), depsgraph_(depsgraph), material_(material), node_(node), socket_out_(socket_out), - to_type_(to_type) + to_type_(to_type), + group_parser_(group_parser) { } @@ -34,14 +36,10 @@ NodeItem NodeParser::compute_full() NodeItem res = empty(); /* Checking if node was already computed */ - res.node = graph_->getNode(name_out()); + res.node = graph_->getNode(node_name()); if (res.node) { return res; } - res.output = graph_->getOutput(name_out()); - if (res.output) { - return res; - } CLOG_INFO(LOG_MATERIALX_SHADER, 1, @@ -52,10 +50,7 @@ NodeItem NodeParser::compute_full() res = compute(); if (res.node) { - res.node->setName(name_out()); - } - else if (res.output) { - res.output->setName(name_out()); + res.node->setName(node_name()); } if (NodeItem::is_arithmetic(to_type_)) { res = res.convert(to_type_); @@ -63,7 +58,7 @@ NodeItem NodeParser::compute_full() return res; } -std::string NodeParser::name_out() const +std::string NodeParser::node_name() const { std::string name = node_->name; if (node_->output_sockets().size() > 1) { @@ -82,7 +77,7 @@ NodeItem NodeParser::create_node(const std::string &category, NodeItem::Type typ NodeItem NodeParser::create_output() { - return empty().create_output(""); + return empty().create_output(); } NodeItem NodeParser::get_input_default(const std::string &name, NodeItem::Type to_type) @@ -135,6 +130,9 @@ NodeItem NodeParser::get_input_default(const bNodeSocket &socket, NodeItem::Type { NodeItem res = empty(); switch (socket.type) { + case SOCK_CUSTOM: + /* Return empty */ + break; case SOCK_FLOAT: { float v = socket.default_value_typed()->value; res.value = MaterialX::Value::createValue(v); @@ -178,11 +176,13 @@ NodeItem NodeParser::get_input_link(const bNodeSocket &socket, NodeItem::Type to } if (from_node->is_group()) { - return GroupNodeParser(graph_, depsgraph_, material_, from_node, link->fromsock, to_type) + return GroupNodeParser( + graph_, depsgraph_, material_, from_node, link->fromsock, to_type, group_parser_) .compute_full(); } if (from_node->is_group_input()) { - return GroupInputNodeParser(graph_, depsgraph_, material_, from_node, link->fromsock, to_type) + return GroupInputNodeParser( + graph_, depsgraph_, material_, from_node, link->fromsock, to_type, group_parser_) .compute_full(); } @@ -194,7 +194,7 @@ NodeItem NodeParser::get_input_link(const bNodeSocket &socket, NodeItem::Type to return empty(); } - NodeParserData data = {graph_, depsgraph_, material_, to_type, empty()}; + NodeParserData data = {graph_, depsgraph_, material_, to_type, group_parser_, empty()}; from_node->typeinfo->materialx_fn(&data, const_cast(from_node), link->fromsock); return data.result; } diff --git a/source/blender/nodes/shader/materialx/node_parser.h b/source/blender/nodes/shader/materialx/node_parser.h index 20aaf2511d7..8e888827b35 100644 --- a/source/blender/nodes/shader/materialx/node_parser.h +++ b/source/blender/nodes/shader/materialx/node_parser.h @@ -16,6 +16,8 @@ namespace blender::nodes::materialx { extern struct CLG_LogRef *LOG_MATERIALX_SHADER; +class GroupNodeParser; + class NodeParser { protected: MaterialX::GraphElement *graph_; @@ -24,6 +26,7 @@ class NodeParser { const bNode *node_; const bNodeSocket *socket_out_; NodeItem::Type to_type_; + GroupNodeParser *group_parser_; public: NodeParser(MaterialX::GraphElement *graph, @@ -31,14 +34,15 @@ class NodeParser { const Material *material, const bNode *node, const bNodeSocket *socket_out, - NodeItem::Type to_type); + NodeItem::Type to_type, + GroupNodeParser *group_parser); virtual ~NodeParser() = default; virtual NodeItem compute() = 0; virtual NodeItem compute_full(); protected: - virtual std::string name_out() const; + std::string node_name() const; NodeItem create_node(const std::string &category, NodeItem::Type type); NodeItem create_output(); NodeItem get_input_default(const std::string &name, NodeItem::Type to_type); @@ -70,6 +74,7 @@ struct NodeParserData { const Depsgraph *depsgraph; const Material *material; NodeItem::Type to_type; + GroupNodeParser *group_parser; NodeItem result; }; @@ -90,7 +95,8 @@ struct NodeParserData { void node_shader_materialx(void *data, struct bNode *node, struct bNodeSocket *out) \ { \ materialx::NodeParserData *d = reinterpret_cast(data); \ - d->result = MaterialXNodeParser(d->graph, d->depsgraph, d->material, node, out, d->to_type) \ + d->result = MaterialXNodeParser( \ + d->graph, d->depsgraph, d->material, node, out, d->to_type, d->group_parser) \ .compute_full(); \ } -- 2.30.2 From 57b0e8abf225cd434b40ecd6158f2ad46b675b6e Mon Sep 17 00:00:00 2001 From: Bogdan Nagirniak Date: Thu, 14 Sep 2023 16:27:02 +0300 Subject: [PATCH 05/14] Implementing GroupInputNodeParser --- source/blender/nodes/shader/materialx/group_nodes.cc | 3 +-- source/blender/nodes/shader/materialx/group_nodes.h | 4 ++++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/source/blender/nodes/shader/materialx/group_nodes.cc b/source/blender/nodes/shader/materialx/group_nodes.cc index 1d1d0439832..21461be65b7 100644 --- a/source/blender/nodes/shader/materialx/group_nodes.cc +++ b/source/blender/nodes/shader/materialx/group_nodes.cc @@ -77,8 +77,7 @@ NodeItem GroupOutputNodeParser::compute_full() NodeItem GroupInputNodeParser::compute() { - //auto in = graph_->addInput(); - return empty(); + return group_parser_->get_input_default(socket_out_->index(), to_type_); } } // namespace blender::nodes::materialx diff --git a/source/blender/nodes/shader/materialx/group_nodes.h b/source/blender/nodes/shader/materialx/group_nodes.h index b854725ca96..d9465efdbfd 100644 --- a/source/blender/nodes/shader/materialx/group_nodes.h +++ b/source/blender/nodes/shader/materialx/group_nodes.h @@ -8,7 +8,11 @@ namespace blender::nodes::materialx { +class GroupInputNodeParser; + class GroupNodeParser : public NodeParser { + friend GroupInputNodeParser; + public: using NodeParser::NodeParser; NodeItem compute() override; -- 2.30.2 From db50b39e478eecbe0d454a1bbda630a69feff1c0 Mon Sep 17 00:00:00 2001 From: Bogdan Nagirniak Date: Thu, 14 Sep 2023 17:36:24 +0300 Subject: [PATCH 06/14] Add logging of material stage --- source/blender/io/usd/hydra/material.cc | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/source/blender/io/usd/hydra/material.cc b/source/blender/io/usd/hydra/material.cc index a992dbdbfa3..0d084273857 100644 --- a/source/blender/io/usd/hydra/material.cc +++ b/source/blender/io/usd/hydra/material.cc @@ -81,6 +81,15 @@ void MaterialData::init() MaterialX::DocumentPtr doc = blender::nodes::materialx::export_to_materialx( scene_delegate_->depsgraph, (Material *)id); pxr::UsdMtlxRead(doc, stage); + pxr::UsdMtlxReadNodeGraphs(doc, stage); + + auto stage_str = [&stage]() { + std::string str; + stage->ExportToString(&str); + return str; + }; + ID_LOGN(2, "Stage:\n%s", stage_str().c_str()); + if (pxr::UsdPrim materials = stage->GetPrimAtPath(pxr::SdfPath("/MaterialX/Materials"))) { pxr::UsdPrimSiblingRange children = materials.GetChildren(); if (!children.empty()) { -- 2.30.2 From 414217ae7342066b3945f094c0090fe386c7a4f8 Mon Sep 17 00:00:00 2001 From: Bogdan Nagirniak Date: Thu, 14 Sep 2023 19:03:10 +0300 Subject: [PATCH 07/14] Added NodeItem::input, code improvements --- .../nodes/shader/materialx/group_nodes.cc | 33 +++++++-- .../nodes/shader/materialx/group_nodes.h | 1 + .../nodes/shader/materialx/node_item.cc | 70 +++++++------------ .../nodes/shader/materialx/node_item.h | 11 +-- .../nodes/shader/materialx/node_parser.cc | 9 ++- .../nodes/shader/materialx/node_parser.h | 3 +- 6 files changed, 69 insertions(+), 58 deletions(-) diff --git a/source/blender/nodes/shader/materialx/group_nodes.cc b/source/blender/nodes/shader/materialx/group_nodes.cc index 21461be65b7..485872aa001 100644 --- a/source/blender/nodes/shader/materialx/group_nodes.cc +++ b/source/blender/nodes/shader/materialx/group_nodes.cc @@ -41,14 +41,18 @@ NodeItem GroupOutputNodeParser::compute() { Vector values; for (auto socket_in : node_->input_sockets()) { - values.append(get_input_value(socket_in->index(), NodeItem::Type::Any)); + NodeItem value = get_input_value(socket_in->index(), NodeItem::Type::Any); + if (value.value) { + NodeItem constant = create_node("constant", value.type()); + constant.set_input("value", value); + value = constant; + } + values.append(value); } Vector outputs; for (int i = 0; i < values.size(); ++i) { if (values[i]) { - outputs.append(create_output()); - outputs[i].set_output(values[i]); - outputs[i].output->setName("output" + std::to_string(i + 1)); + outputs.append(create_output("output" + std::to_string(i + 1), values[i])); } } return outputs[socket_out_->index()]; @@ -80,4 +84,25 @@ NodeItem GroupInputNodeParser::compute() return group_parser_->get_input_default(socket_out_->index(), to_type_); } +NodeItem GroupInputNodeParser::compute_full() +{ + NodeItem res = empty(); + + /* Checking if output was already computed */ + res.output = graph_->getOutput("output" + std::to_string(socket_out_->index() + 1)); + if (res.output) { + return res; + } + + CLOG_INFO(LOG_MATERIALX_SHADER, + 1, + "%s [%d] => %s", + node_->name, + node_->typeinfo->type, + NodeItem::type(to_type_).c_str()); + + res = compute(); + return res; +} + } // namespace blender::nodes::materialx diff --git a/source/blender/nodes/shader/materialx/group_nodes.h b/source/blender/nodes/shader/materialx/group_nodes.h index d9465efdbfd..390494f6f2c 100644 --- a/source/blender/nodes/shader/materialx/group_nodes.h +++ b/source/blender/nodes/shader/materialx/group_nodes.h @@ -29,6 +29,7 @@ class GroupInputNodeParser : public NodeParser { public: using NodeParser::NodeParser; NodeItem compute() override; + NodeItem compute_full() override; }; } // namespace blender::nodes::materialx diff --git a/source/blender/nodes/shader/materialx/node_item.cc b/source/blender/nodes/shader/materialx/node_item.cc index a7a03968110..74e16d4f5b0 100644 --- a/source/blender/nodes/shader/materialx/node_item.cc +++ b/source/blender/nodes/shader/materialx/node_item.cc @@ -678,6 +678,9 @@ void NodeItem::set_input(const std::string &in_name, const NodeItem &item) else if (item.node) { node->setConnectedNode(in_name, item.node); } + else if (item.input) { + node->setAttribute("interfacename", item.input->getName()); + } else if (item.output) { node->setConnectedOutput(in_name, item.output); } @@ -693,60 +696,41 @@ NodeItem NodeItem::add_output(const std::string &out_name, Type out_type) return res; } -NodeItem NodeItem::create_output() const +NodeItem NodeItem::create_input(const std::string &name, const NodeItem &item) const { NodeItem res = empty(); - res.output = graph_->addOutput(); + res.input = graph_->addInput(name); + + Type item_type = item.type(); + if (item.node) { + res.input->setConnectedNode(item.node); + } + else { + BLI_assert_unreachable(); + } + res.input->setType(type(item_type)); + return res; } -void NodeItem::set_output(const NodeItem &item) const +NodeItem NodeItem::create_output(const std::string &name, const NodeItem &item) const { + NodeItem res = empty(); + res.output = graph_->addOutput(name); + Type item_type = item.type(); - if (item.value) { - switch (item_type) { - case Type::String: - set_output(item.value->asA(), item_type); - break; - case Type::Boolean: - set_output(item.value->asA(), item_type); - break; - case Type::Integer: - set_output(item.value->asA(), item_type); - break; - case Type::Float: - set_output(item.value->asA(), item_type); - break; - case Type::Vector2: - set_output(item.value->asA(), item_type); - break; - case Type::Vector3: - set_output(item.value->asA(), item_type); - break; - case Type::Vector4: - set_output(item.value->asA(), item_type); - break; - case Type::Color3: - set_output(item.value->asA(), item_type); - break; - case Type::Color4: - set_output(item.value->asA(), item_type); - break; - default: - BLI_assert_unreachable(); - } + if (item.node) { + res.output->setConnectedNode(item.node); } - else if (item.node) { - output->setConnectedNode(item.node); - output->setType(type(item_type)); - } - else if (item.output) { - output->setConnectedOutput(item.output); - output->setType(type(item_type)); + else if (item.input) { + res.output->setInterfaceName(item.input->getName()); } else { - CLOG_WARN(LOG_MATERIALX_SHADER, "Empty item to output: %s", output->getName().c_str()); + BLI_assert_unreachable(); } + res.output->setType(type(item_type)); + + return res; } NodeItem::Type NodeItem::cast_types(NodeItem &item1, NodeItem &item2) diff --git a/source/blender/nodes/shader/materialx/node_item.h b/source/blender/nodes/shader/materialx/node_item.h index b1d5b8f712d..a516ddbd3e5 100644 --- a/source/blender/nodes/shader/materialx/node_item.h +++ b/source/blender/nodes/shader/materialx/node_item.h @@ -43,6 +43,7 @@ class NodeItem { public: MaterialX::ValuePtr value; MaterialX::NodePtr node; + MaterialX::InputPtr input; MaterialX::OutputPtr output; private: @@ -111,9 +112,8 @@ class NodeItem { NodeItem add_output(const std::string &out_name, Type out_type); /* Output functions */ - NodeItem create_output() const; - template void set_output(const T &value, Type out_type) const; - void set_output(const NodeItem &item) const; + NodeItem create_input(const std::string &name, const NodeItem &item) const; + NodeItem create_output(const std::string &name, const NodeItem &item) const; private: static Type cast_types(NodeItem &item1, NodeItem &item2); @@ -138,9 +138,4 @@ void NodeItem::set_input(const std::string &in_name, const T &value, Type in_typ node->setInputValue(in_name, value, type(in_type)); } -template void NodeItem::set_output(const T &value, Type out_type) const -{ - output->setValue(value, type(out_type)); -} - } // namespace blender::nodes::materialx diff --git a/source/blender/nodes/shader/materialx/node_parser.cc b/source/blender/nodes/shader/materialx/node_parser.cc index 989f4cb87e2..d7c05cf7121 100644 --- a/source/blender/nodes/shader/materialx/node_parser.cc +++ b/source/blender/nodes/shader/materialx/node_parser.cc @@ -75,9 +75,14 @@ NodeItem NodeParser::create_node(const std::string &category, NodeItem::Type typ return empty().create_node(category, type); } -NodeItem NodeParser::create_output() +NodeItem NodeParser::create_input(const std::string &name, const NodeItem &item) { - return empty().create_output(); + return empty().create_input(name, item); +} + +NodeItem NodeParser::create_output(const std::string &name, const NodeItem &item) +{ + return empty().create_output(name, item); } NodeItem NodeParser::get_input_default(const std::string &name, NodeItem::Type to_type) diff --git a/source/blender/nodes/shader/materialx/node_parser.h b/source/blender/nodes/shader/materialx/node_parser.h index 8e888827b35..761ec9fa041 100644 --- a/source/blender/nodes/shader/materialx/node_parser.h +++ b/source/blender/nodes/shader/materialx/node_parser.h @@ -44,7 +44,8 @@ class NodeParser { protected: std::string node_name() const; NodeItem create_node(const std::string &category, NodeItem::Type type); - NodeItem create_output(); + NodeItem create_input(const std::string &name, const NodeItem &item); + NodeItem create_output(const std::string &name, const NodeItem &item); NodeItem get_input_default(const std::string &name, NodeItem::Type to_type); NodeItem get_input_default(int index, NodeItem::Type to_type); NodeItem get_input_link(const std::string &name, NodeItem::Type to_type); -- 2.30.2 From 8f67ebb00720afdd4e472994053e10fad7c0ef2e Mon Sep 17 00:00:00 2001 From: Bogdan Nagirniak Date: Thu, 14 Sep 2023 19:13:14 +0300 Subject: [PATCH 08/14] Finished GroupInputNodeParser --- .../nodes/shader/materialx/group_nodes.cc | 28 +++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/source/blender/nodes/shader/materialx/group_nodes.cc b/source/blender/nodes/shader/materialx/group_nodes.cc index 485872aa001..63282863095 100644 --- a/source/blender/nodes/shader/materialx/group_nodes.cc +++ b/source/blender/nodes/shader/materialx/group_nodes.cc @@ -2,8 +2,8 @@ * * SPDX-License-Identifier: GPL-2.0-or-later */ -#include "node_parser.h" #include "group_nodes.h" +#include "node_parser.h" #include "BLI_vector.hh" @@ -27,10 +27,14 @@ NodeItem GroupNodeParser::compute() group_graph = graph_->addChild(name); } - NodeItem out = - GroupOutputNodeParser( - group_graph.get(), depsgraph_, material_, node_out, socket_out_, NodeItem::Type::Any, this) - .compute_full(); + NodeItem out = GroupOutputNodeParser(group_graph.get(), + depsgraph_, + material_, + node_out, + socket_out_, + NodeItem::Type::Any, + this) + .compute_full(); /* We have to be in NodeParser's graph_, therefore copying output */ res.output = out.output; @@ -55,6 +59,7 @@ NodeItem GroupOutputNodeParser::compute() outputs.append(create_output("output" + std::to_string(i + 1), values[i])); } } + return outputs[socket_out_->index()]; } @@ -81,7 +86,14 @@ NodeItem GroupOutputNodeParser::compute_full() NodeItem GroupInputNodeParser::compute() { - return group_parser_->get_input_default(socket_out_->index(), to_type_); + NodeItem value = group_parser_->get_input_value(socket_out_->index(), to_type_); + if (value.value) { + NodeItem constant = create_node("constant", value.type()); + constant.set_input("value", value); + value = constant; + } + + return create_input("input" + std::to_string(socket_out_->index() + 1), value); } NodeItem GroupInputNodeParser::compute_full() @@ -89,8 +101,8 @@ NodeItem GroupInputNodeParser::compute_full() NodeItem res = empty(); /* Checking if output was already computed */ - res.output = graph_->getOutput("output" + std::to_string(socket_out_->index() + 1)); - if (res.output) { + res.input = graph_->getInput("input" + std::to_string(socket_out_->index() + 1)); + if (res.input) { return res; } -- 2.30.2 From 61e0e054302b305f97053a4cf4c32a951d8fc3c7 Mon Sep 17 00:00:00 2001 From: Bogdan Nagirniak Date: Thu, 14 Sep 2023 19:54:02 +0300 Subject: [PATCH 09/14] Added #define USE_MATERIALX_NODEGRAPH. Implemented node group parsing without nodegraph creation. --- source/blender/io/usd/hydra/material.cc | 3 +- .../nodes/shader/materialx/group_nodes.cc | 38 ++++++++++++++----- .../nodes/shader/materialx/group_nodes.h | 5 +++ .../nodes/shader/materialx/node_parser.cc | 11 ++++++ 4 files changed, 46 insertions(+), 11 deletions(-) diff --git a/source/blender/io/usd/hydra/material.cc b/source/blender/io/usd/hydra/material.cc index 0d084273857..ae538ce817b 100644 --- a/source/blender/io/usd/hydra/material.cc +++ b/source/blender/io/usd/hydra/material.cc @@ -81,8 +81,9 @@ void MaterialData::init() MaterialX::DocumentPtr doc = blender::nodes::materialx::export_to_materialx( scene_delegate_->depsgraph, (Material *)id); pxr::UsdMtlxRead(doc, stage); - pxr::UsdMtlxReadNodeGraphs(doc, stage); + /* Logging stage: creating lambda stage_str() for not to call stage->ExportToString() + * if log doesn't execute. */ auto stage_str = [&stage]() { std::string str; stage->ExportToString(&str); diff --git a/source/blender/nodes/shader/materialx/group_nodes.cc b/source/blender/nodes/shader/materialx/group_nodes.cc index 63282863095..a9c25ba4587 100644 --- a/source/blender/nodes/shader/materialx/group_nodes.cc +++ b/source/blender/nodes/shader/materialx/group_nodes.cc @@ -20,29 +20,34 @@ NodeItem GroupNodeParser::compute() return res; } + MaterialX::GraphElement *graph = graph_; +#ifdef USE_MATERIALX_NODEGRAPH std::string name = MaterialX::createValidName(ngroup->id.name); MaterialX::NodeGraphPtr group_graph = graph_->getChildOfType(name); if (!group_graph) { CLOG_INFO(LOG_MATERIALX_SHADER, 1, "", name.c_str()); group_graph = graph_->addChild(name); } + graph = group_graph.get(); +#endif - NodeItem out = GroupOutputNodeParser(group_graph.get(), - depsgraph_, - material_, - node_out, - socket_out_, - NodeItem::Type::Any, - this) - .compute_full(); + NodeItem out = + GroupOutputNodeParser( + graph, depsgraph_, material_, node_out, socket_out_, NodeItem::Type::Any, this) + .compute_full(); +#ifdef USE_MATERIALX_NODEGRAPH /* We have to be in NodeParser's graph_, therefore copying output */ res.output = out.output; +#else + res = out; +#endif return res; } NodeItem GroupOutputNodeParser::compute() { +#ifdef USE_MATERIALX_NODEGRAPH Vector values; for (auto socket_in : node_->input_sockets()) { NodeItem value = get_input_value(socket_in->index(), NodeItem::Type::Any); @@ -59,12 +64,15 @@ NodeItem GroupOutputNodeParser::compute() outputs.append(create_output("output" + std::to_string(i + 1), values[i])); } } - return outputs[socket_out_->index()]; +#else + return get_input_value(socket_out_->index(), NodeItem::Type::Any); +#endif } NodeItem GroupOutputNodeParser::compute_full() { +#ifdef USE_MATERIALX_NODEGRAPH NodeItem res = empty(); /* Checking if output was already computed */ @@ -82,22 +90,29 @@ NodeItem GroupOutputNodeParser::compute_full() res = compute(); return res; +#else + return NodeParser::compute_full(); +#endif } NodeItem GroupInputNodeParser::compute() { +#ifdef USE_MATERIALX_NODEGRAPH NodeItem value = group_parser_->get_input_value(socket_out_->index(), to_type_); if (value.value) { NodeItem constant = create_node("constant", value.type()); constant.set_input("value", value); value = constant; } - return create_input("input" + std::to_string(socket_out_->index() + 1), value); +#else + return group_parser_->get_input_value(socket_out_->index(), to_type_); +#endif } NodeItem GroupInputNodeParser::compute_full() { +#ifdef USE_MATERIALX_NODEGRAPH NodeItem res = empty(); /* Checking if output was already computed */ @@ -115,6 +130,9 @@ NodeItem GroupInputNodeParser::compute_full() res = compute(); return res; +#else + return NodeParser::compute_full(); +#endif } } // namespace blender::nodes::materialx diff --git a/source/blender/nodes/shader/materialx/group_nodes.h b/source/blender/nodes/shader/materialx/group_nodes.h index 390494f6f2c..4034eb2393e 100644 --- a/source/blender/nodes/shader/materialx/group_nodes.h +++ b/source/blender/nodes/shader/materialx/group_nodes.h @@ -6,11 +6,16 @@ #include "node_parser.h" +/* TODO: pxr::UsdMtlxRead() doesn't perform nodegraphs. + * Uncomment USE_MATERIALX_NODEGRAPH after fixing it. */ +/* #define USE_MATERIALX_NODEGRAPH */ + namespace blender::nodes::materialx { class GroupInputNodeParser; class GroupNodeParser : public NodeParser { + friend NodeParser; friend GroupInputNodeParser; public: diff --git a/source/blender/nodes/shader/materialx/node_parser.cc b/source/blender/nodes/shader/materialx/node_parser.cc index d7c05cf7121..c9a4e785a5b 100644 --- a/source/blender/nodes/shader/materialx/node_parser.cc +++ b/source/blender/nodes/shader/materialx/node_parser.cc @@ -67,7 +67,18 @@ std::string NodeParser::node_name() const if (ELEM(to_type_, NodeItem::Type::BSDF, NodeItem::Type::EDF)) { name += "_" + NodeItem::type(to_type_); } +#ifdef USE_MATERIALX_NODEGRAPH return MaterialX::createValidName(name); +#else + std::string prefix; + GroupNodeParser *gr = group_parser_; + while (gr) { + const bNodeTree *ngroup = reinterpret_cast(gr->node_->id); + prefix = MaterialX::createValidName(ngroup->id.name) + "_" + prefix; + gr = gr->group_parser_; + } + return prefix + MaterialX::createValidName(name); +#endif } NodeItem NodeParser::create_node(const std::string &category, NodeItem::Type type) -- 2.30.2 From 23e05a2e7740ebf01c30439b38e7d840d1c25089 Mon Sep 17 00:00:00 2001 From: Bogdan Nagirniak Date: Fri, 15 Sep 2023 11:09:36 +0300 Subject: [PATCH 10/14] Fixes in group_nodes.cc and node_item.cc --- .../nodes/shader/materialx/group_nodes.cc | 19 +++++++++++++++++-- .../nodes/shader/materialx/group_nodes.h | 3 ++- .../nodes/shader/materialx/node_item.cc | 14 ++++++++++---- 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/source/blender/nodes/shader/materialx/group_nodes.cc b/source/blender/nodes/shader/materialx/group_nodes.cc index a9c25ba4587..e30b31139ce 100644 --- a/source/blender/nodes/shader/materialx/group_nodes.cc +++ b/source/blender/nodes/shader/materialx/group_nodes.cc @@ -45,6 +45,17 @@ NodeItem GroupNodeParser::compute() return res; } +NodeItem GroupNodeParser::compute_full() +{ + CLOG_INFO(LOG_MATERIALX_SHADER, + 1, + "%s [%d] => %s", + node_->name, + node_->typeinfo->type, + NodeItem::type(to_type_).c_str()); + return compute(); +} + NodeItem GroupOutputNodeParser::compute() { #ifdef USE_MATERIALX_NODEGRAPH @@ -98,7 +109,11 @@ NodeItem GroupOutputNodeParser::compute_full() NodeItem GroupInputNodeParser::compute() { #ifdef USE_MATERIALX_NODEGRAPH - NodeItem value = group_parser_->get_input_value(socket_out_->index(), to_type_); + NodeItem value = group_parser_->get_input_link(socket_out_->index(), to_type_); + if (!value) { + return empty(); + } + if (value.value) { NodeItem constant = create_node("constant", value.type()); constant.set_input("value", value); @@ -106,7 +121,7 @@ NodeItem GroupInputNodeParser::compute() } return create_input("input" + std::to_string(socket_out_->index() + 1), value); #else - return group_parser_->get_input_value(socket_out_->index(), to_type_); + return group_parser_->get_input_link(socket_out_->index(), to_type_); #endif } diff --git a/source/blender/nodes/shader/materialx/group_nodes.h b/source/blender/nodes/shader/materialx/group_nodes.h index 4034eb2393e..7e46a5c7f9e 100644 --- a/source/blender/nodes/shader/materialx/group_nodes.h +++ b/source/blender/nodes/shader/materialx/group_nodes.h @@ -8,7 +8,7 @@ /* TODO: pxr::UsdMtlxRead() doesn't perform nodegraphs. * Uncomment USE_MATERIALX_NODEGRAPH after fixing it. */ -/* #define USE_MATERIALX_NODEGRAPH */ +#define USE_MATERIALX_NODEGRAPH namespace blender::nodes::materialx { @@ -21,6 +21,7 @@ class GroupNodeParser : public NodeParser { public: using NodeParser::NodeParser; NodeItem compute() override; + NodeItem compute_full() override; }; class GroupOutputNodeParser : public NodeParser { diff --git a/source/blender/nodes/shader/materialx/node_item.cc b/source/blender/nodes/shader/materialx/node_item.cc index 74e16d4f5b0..86c75b12b2a 100644 --- a/source/blender/nodes/shader/materialx/node_item.cc +++ b/source/blender/nodes/shader/materialx/node_item.cc @@ -105,7 +105,7 @@ bool NodeItem::is_arithmetic(Type type) NodeItem::operator bool() const { - return value || node || output; + return value || node || input || output; } NodeItem NodeItem::operator+(const NodeItem &other) const @@ -808,10 +808,16 @@ NodeItem NodeItem::arithmetic(const std::string &category, std::function Date: Fri, 15 Sep 2023 11:52:12 +0300 Subject: [PATCH 11/14] Fixed GroupNodeParser::compute_full() --- source/blender/io/usd/hydra/material.cc | 2 +- source/blender/nodes/shader/materialx/group_nodes.cc | 12 +++++------- source/blender/nodes/shader/materialx/group_nodes.h | 2 +- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/source/blender/io/usd/hydra/material.cc b/source/blender/io/usd/hydra/material.cc index ae538ce817b..9fdf47965a8 100644 --- a/source/blender/io/usd/hydra/material.cc +++ b/source/blender/io/usd/hydra/material.cc @@ -83,7 +83,7 @@ void MaterialData::init() pxr::UsdMtlxRead(doc, stage); /* Logging stage: creating lambda stage_str() for not to call stage->ExportToString() - * if log doesn't execute. */ + * if log won't be printed. */ auto stage_str = [&stage]() { std::string str; stage->ExportToString(&str); diff --git a/source/blender/nodes/shader/materialx/group_nodes.cc b/source/blender/nodes/shader/materialx/group_nodes.cc index e30b31139ce..f2de9e68b4d 100644 --- a/source/blender/nodes/shader/materialx/group_nodes.cc +++ b/source/blender/nodes/shader/materialx/group_nodes.cc @@ -47,13 +47,11 @@ NodeItem GroupNodeParser::compute() NodeItem GroupNodeParser::compute_full() { - CLOG_INFO(LOG_MATERIALX_SHADER, - 1, - "%s [%d] => %s", - node_->name, - node_->typeinfo->type, - NodeItem::type(to_type_).c_str()); - return compute(); + NodeItem res = compute(); + if (NodeItem::is_arithmetic(to_type_)) { + res = res.convert(to_type_); + } + return res; } NodeItem GroupOutputNodeParser::compute() diff --git a/source/blender/nodes/shader/materialx/group_nodes.h b/source/blender/nodes/shader/materialx/group_nodes.h index 7e46a5c7f9e..a486a4af5fd 100644 --- a/source/blender/nodes/shader/materialx/group_nodes.h +++ b/source/blender/nodes/shader/materialx/group_nodes.h @@ -8,7 +8,7 @@ /* TODO: pxr::UsdMtlxRead() doesn't perform nodegraphs. * Uncomment USE_MATERIALX_NODEGRAPH after fixing it. */ -#define USE_MATERIALX_NODEGRAPH +//#define USE_MATERIALX_NODEGRAPH namespace blender::nodes::materialx { -- 2.30.2 From b6662ecbd3f5febd1cab6cce8252221497bf6b16 Mon Sep 17 00:00:00 2001 From: Bogdan Nagirniak Date: Fri, 15 Sep 2023 21:25:38 +0300 Subject: [PATCH 12/14] Fixes after merge --- .../blender/nodes/shader/nodes/node_shader_bsdf_glass.cc | 8 ++++---- .../blender/nodes/shader/nodes/node_shader_bsdf_glossy.cc | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_glass.cc b/source/blender/nodes/shader/nodes/node_shader_bsdf_glass.cc index 5469569339b..6d7f59c2e51 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_glass.cc +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_glass.cc @@ -64,17 +64,17 @@ NODE_SHADER_MATERIALX_BEGIN dielectric.set_input("scatter_mode", val(std::string("RT"))); NodeItem artistic_ior = create_node("artistic_ior", NodeItem::Type::Multioutput); - artistic_ior.add_output("ior", NodeItem::Type::Color3); - artistic_ior.add_output("extinction", NodeItem::Type::Color3); artistic_ior.set_input("reflectivity", color); artistic_ior.set_input("edge_color", color); + NodeItem ior_out = artistic_ior.add_output("ior", NodeItem::Type::Color3); + NodeItem extinction_out = artistic_ior.add_output("extinction", NodeItem::Type::Color3); NodeItem conductor = create_node("conductor_bsdf", NodeItem::Type::BSDF); if (normal) { conductor.set_input("normal", normal); } - conductor.set_input_output("ior", artistic_ior, "ior"); - conductor.set_input_output("extinction", artistic_ior, "extinction"); + conductor.set_input("ior", ior_out); + conductor.set_input("extinction", extinction_out); conductor.set_input("roughness", roughness); NodeItem res = create_node("mix", NodeItem::Type::BSDF); diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.cc b/source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.cc index 60956f9f0a2..b340b8e62a4 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.cc +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.cc @@ -70,10 +70,10 @@ NODE_SHADER_MATERIALX_BEGIN NodeItem tangent = get_input_link("Tangent", NodeItem::Type::Vector3); NodeItem artistic_ior = create_node("artistic_ior", NodeItem::Type::Multioutput); - artistic_ior.add_output("ior", NodeItem::Type::Color3); - artistic_ior.add_output("extinction", NodeItem::Type::Color3); artistic_ior.set_input("reflectivity", color); artistic_ior.set_input("edge_color", color); + NodeItem ior_out = artistic_ior.add_output("ior", NodeItem::Type::Color3); + NodeItem extinction_out = artistic_ior.add_output("extinction", NodeItem::Type::Color3); NodeItem res = create_node("conductor_bsdf", NodeItem::Type::BSDF); if (normal) { @@ -82,8 +82,8 @@ NODE_SHADER_MATERIALX_BEGIN if (tangent) { res.set_input("tangent", tangent); } - res.set_input_output("ior", artistic_ior, "ior"); - res.set_input_output("extinction", artistic_ior, "extinction"); + res.set_input("ior", ior_out); + res.set_input("extinction", extinction_out); res.set_input("roughness", roughness); return res; -- 2.30.2 From 17dfdbd6310031e6b058fc72cf142414351bb319 Mon Sep 17 00:00:00 2001 From: Bogdan Nagirniak Date: Fri, 15 Sep 2023 21:27:23 +0300 Subject: [PATCH 13/14] make format --- source/blender/nodes/shader/nodes/node_shader_bsdf_glass.cc | 2 +- .../blender/nodes/shader/nodes/node_shader_bsdf_refraction.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_glass.cc b/source/blender/nodes/shader/nodes/node_shader_bsdf_glass.cc index 6d7f59c2e51..d4467eb5765 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_glass.cc +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_glass.cc @@ -82,7 +82,7 @@ NODE_SHADER_MATERIALX_BEGIN res.set_input("bg", conductor); res.set_input("mix", val(0.5f)); - return res ; + return res; } #endif NODE_SHADER_MATERIALX_END diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_refraction.cc b/source/blender/nodes/shader/nodes/node_shader_bsdf_refraction.cc index c3427ec9138..dfaf30c5e98 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_refraction.cc +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_refraction.cc @@ -60,7 +60,7 @@ NODE_SHADER_MATERIALX_BEGIN res.set_input("roughness", roughness); res.set_input("ior", ior); res.set_input("scatter_mode", val(std::string("T"))); - + return res; } #endif -- 2.30.2 From 90b89b4d101357badc42c5f48bfc6312785a341f Mon Sep 17 00:00:00 2001 From: Bogdan Nagirniak Date: Mon, 18 Sep 2023 13:35:52 +0300 Subject: [PATCH 14/14] Review fixes --- source/blender/nodes/shader/materialx/node_item.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/blender/nodes/shader/materialx/node_item.cc b/source/blender/nodes/shader/materialx/node_item.cc index 17e40af94d4..f431a711ce3 100644 --- a/source/blender/nodes/shader/materialx/node_item.cc +++ b/source/blender/nodes/shader/materialx/node_item.cc @@ -609,8 +609,8 @@ NodeItem NodeItem::if_else(CompareOp op, NodeItem NodeItem::extract(const int index) const { - NodeItem res = empty(); - res = create_node("extract", Type::Float); + /* TODO: Add check if (value) { ... } */ + NodeItem res = create_node("extract", Type::Float); res.set_input("in", *this); res.set_input("index", val(index)); return res; @@ -817,7 +817,7 @@ NodeItem NodeItem::arithmetic(const std::string &category, std::function