Support group nodes #22

Merged
Bogdan Nagirniak merged 18 commits from BogdanNagirniak/blender:matx-group-nodes into matx-export-material 2023-09-18 12:49:19 +02:00
8 changed files with 118 additions and 10 deletions
Showing only changes of commit 998e86536e - Show all commits

View File

@ -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

View File

@ -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<const bNodeTree *>(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<MaterialX::NodeGraph>(name);
if (!group_graph) {
group_graph = graph_->addChild<MaterialX::NodeGraph>(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

View File

@ -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

View File

@ -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));
}

View File

@ -104,6 +104,7 @@ class NodeItem {
/* Functions to set input and output */
template<class T> 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);

View File

@ -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]",

View File

@ -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);

View File

@ -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<float>())));
}
res.set_input("octaves", val(int(detail.value->asA<float>())));
res.set_input("lacunarity", lacunarity);
return res;
}