forked from blender/blender
Support group nodes #22
@ -81,6 +81,16 @@ void MaterialData::init()
|
||||
MaterialX::DocumentPtr doc = blender::nodes::materialx::export_to_materialx(
|
||||
scene_delegate_->depsgraph, (Material *)id);
|
||||
pxr::UsdMtlxRead(doc, stage);
|
||||
|
||||
/* Logging stage: creating lambda stage_str() for not to call stage->ExportToString()
|
||||
* if log won't be printed. */
|
||||
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()) {
|
||||
|
@ -150,10 +150,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
|
||||
|
151
source/blender/nodes/shader/materialx/group_nodes.cc
Normal file
151
source/blender/nodes/shader/materialx/group_nodes.cc
Normal file
@ -0,0 +1,151 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "group_nodes.h"
|
||||
#include "node_parser.h"
|
||||
|
||||
#include "BLI_vector.hh"
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
MaterialX::GraphElement *graph = graph_;
|
||||
#ifdef USE_MATERIALX_NODEGRAPH
|
||||
std::string name = MaterialX::createValidName(ngroup->id.name);
|
||||
MaterialX::NodeGraphPtr group_graph = graph_->getChildOfType<MaterialX::NodeGraph>(name);
|
||||
if (!group_graph) {
|
||||
CLOG_INFO(LOG_MATERIALX_SHADER, 1, "<nodegraph name=%s>", name.c_str());
|
||||
group_graph = graph_->addChild<MaterialX::NodeGraph>(name);
|
||||
}
|
||||
graph = group_graph.get();
|
||||
#endif
|
||||
|
||||
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 GroupNodeParser::compute_full()
|
||||
{
|
||||
NodeItem res = compute();
|
||||
if (NodeItem::is_arithmetic(to_type_)) {
|
||||
res = res.convert(to_type_);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
NodeItem GroupOutputNodeParser::compute()
|
||||
{
|
||||
#ifdef USE_MATERIALX_NODEGRAPH
|
||||
Vector<NodeItem> values;
|
||||
for (auto socket_in : node_->input_sockets()) {
|
||||
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<NodeItem> outputs;
|
||||
for (int i = 0; i < values.size(); ++i) {
|
||||
if (values[i]) {
|
||||
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 */
|
||||
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;
|
||||
#else
|
||||
return NodeParser::compute_full();
|
||||
#endif
|
||||
}
|
||||
|
||||
NodeItem GroupInputNodeParser::compute()
|
||||
{
|
||||
#ifdef USE_MATERIALX_NODEGRAPH
|
||||
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);
|
||||
value = constant;
|
||||
}
|
||||
return create_input("input" + std::to_string(socket_out_->index() + 1), value);
|
||||
#else
|
||||
return group_parser_->get_input_link(socket_out_->index(), to_type_);
|
||||
#endif
|
||||
}
|
||||
|
||||
NodeItem GroupInputNodeParser::compute_full()
|
||||
{
|
||||
#ifdef USE_MATERIALX_NODEGRAPH
|
||||
NodeItem res = empty();
|
||||
|
||||
/* Checking if output was already computed */
|
||||
res.input = graph_->getInput("input" + std::to_string(socket_out_->index() + 1));
|
||||
if (res.input) {
|
||||
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;
|
||||
#else
|
||||
return NodeParser::compute_full();
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace blender::nodes::materialx
|
41
source/blender/nodes/shader/materialx/group_nodes.h
Normal file
41
source/blender/nodes/shader/materialx/group_nodes.h
Normal file
@ -0,0 +1,41 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#pragma once
|
||||
|
||||
#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:
|
||||
using NodeParser::NodeParser;
|
||||
NodeItem compute() override;
|
||||
NodeItem compute_full() override;
|
||||
};
|
||||
|
||||
class GroupOutputNodeParser : public NodeParser {
|
||||
public:
|
||||
using NodeParser::NodeParser;
|
||||
NodeItem compute() override;
|
||||
NodeItem compute_full() override;
|
||||
};
|
||||
|
||||
class GroupInputNodeParser : public NodeParser {
|
||||
public:
|
||||
using NodeParser::NodeParser;
|
||||
NodeItem compute() override;
|
||||
NodeItem compute_full() override;
|
||||
};
|
||||
|
||||
} // namespace blender::nodes::materialx
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -66,7 +66,7 @@ std::string NodeItem::type(Type type)
|
||||
{
|
||||
switch (type) {
|
||||
case Type::Any:
|
||||
return "";
|
||||
return "any";
|
||||
case Type::Multioutput:
|
||||
return "multioutput";
|
||||
case Type::String:
|
||||
@ -103,9 +103,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 || input || output;
|
||||
}
|
||||
|
||||
NodeItem NodeItem::operator+(const NodeItem &other) const
|
||||
@ -604,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;
|
||||
@ -624,6 +629,9 @@ NodeItem::Type NodeItem::type() const
|
||||
if (node) {
|
||||
return type(node->getType());
|
||||
}
|
||||
if (output) {
|
||||
return type(output->getType());
|
||||
}
|
||||
return Type::Empty;
|
||||
}
|
||||
|
||||
@ -675,30 +683,59 @@ 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);
|
||||
}
|
||||
else {
|
||||
CLOG_WARN(LOG_MATERIALX_SHADER, "Empty item to input: %s", in_name.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void NodeItem::set_input_output(const std::string &in_name,
|
||||
const NodeItem &item,
|
||||
const std::string &out_name)
|
||||
NodeItem NodeItem::add_output(const std::string &out_name, Type out_type)
|
||||
{
|
||||
if (!item.node) {
|
||||
NodeItem res = empty();
|
||||
res.output = node->addOutput(out_name, type(out_type));
|
||||
return res;
|
||||
}
|
||||
|
||||
NodeItem NodeItem::create_input(const std::string &name, const NodeItem &item) const
|
||||
{
|
||||
NodeItem res = empty();
|
||||
res.input = graph_->addInput(name);
|
||||
|
||||
Type item_type = item.type();
|
||||
if (item.node) {
|
||||
res.input->setConnectedNode(item.node);
|
||||
}
|
||||
else {
|
||||
BLI_assert_unreachable();
|
||||
}
|
||||
node->setConnectedNode(in_name, item.node);
|
||||
node->setConnectedOutput(in_name, item.node->getOutput(out_name));
|
||||
res.input->setType(type(item_type));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void NodeItem::add_output(const std::string &name, Type out_type)
|
||||
NodeItem NodeItem::create_output(const std::string &name, const NodeItem &item) const
|
||||
{
|
||||
node->addOutput(name, type(out_type));
|
||||
}
|
||||
NodeItem res = empty();
|
||||
res.output = graph_->addOutput(name);
|
||||
|
||||
bool NodeItem::is_arithmetic(Type type)
|
||||
{
|
||||
return type >= Type::Float && type <= Type::Color4;
|
||||
Type item_type = item.type();
|
||||
if (item.node) {
|
||||
res.output->setConnectedNode(item.node);
|
||||
}
|
||||
else if (item.input) {
|
||||
res.output->setInterfaceName(item.input->getName());
|
||||
}
|
||||
else {
|
||||
BLI_assert_unreachable();
|
||||
}
|
||||
res.output->setType(type(item_type));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
NodeItem::Type NodeItem::cast_types(NodeItem &item1, NodeItem &item2)
|
||||
@ -776,10 +813,16 @@ NodeItem NodeItem::arithmetic(const std::string &category, std::function<float(f
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* TODO: Some of math functions (sin, cos, ...) doesn't work with Color types,
|
||||
* we have to convert to Vector */
|
||||
NodeItem v = *this;
|
||||
if (ELEM(type, Type::Color3, Type::Color4) &&
|
||||
ELEM(category, "sin", "cos", "tan", "asin", "acos", "atan2", "sqrt", "ln", "exp"))
|
||||
{
|
||||
/* These functions haven't implementation in MaterialX, converting to Vector types */
|
||||
type = type == Type::Color3 ? Type::Vector3 : Type::Vector4;
|
||||
v = v.convert(type);
|
||||
}
|
||||
res = create_node(category, type);
|
||||
res.set_input("in", *this);
|
||||
res.set_input("in", v);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
@ -43,6 +43,8 @@ class NodeItem {
|
||||
public:
|
||||
MaterialX::ValuePtr value;
|
||||
MaterialX::NodePtr node;
|
||||
MaterialX::InputPtr input;
|
||||
MaterialX::OutputPtr output;
|
||||
|
||||
private:
|
||||
MaterialX::GraphElement *graph_;
|
||||
@ -102,15 +104,16 @@ class NodeItem {
|
||||
NodeItem empty() const;
|
||||
template<class T> 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<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_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_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);
|
||||
|
@ -4,6 +4,8 @@
|
||||
|
||||
#include "node_parser.h"
|
||||
|
||||
#include "group_nodes.h"
|
||||
|
||||
#include "BKE_node_runtime.hh"
|
||||
|
||||
namespace blender::nodes::materialx {
|
||||
@ -17,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)
|
||||
{
|
||||
}
|
||||
|
||||
@ -52,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) {
|
||||
@ -61,7 +65,18 @@ std::string NodeParser::node_name()
|
||||
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<const bNodeTree *>(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)
|
||||
@ -69,6 +84,16 @@ NodeItem NodeParser::create_node(const std::string &category, NodeItem::Type typ
|
||||
return empty().create_node(category, type);
|
||||
}
|
||||
|
||||
NodeItem NodeParser::create_input(const std::string &name, const NodeItem &item)
|
||||
{
|
||||
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)
|
||||
{
|
||||
return get_default(node_->input_by_identifier(name), to_type);
|
||||
@ -129,6 +154,9 @@ NodeItem NodeParser::get_default(const bNodeSocket &socket, NodeItem::Type to_ty
|
||||
{
|
||||
NodeItem res = empty();
|
||||
switch (socket.type) {
|
||||
case SOCK_CUSTOM:
|
||||
/* Return empty */
|
||||
break;
|
||||
case SOCK_FLOAT: {
|
||||
float v = socket.default_value_typed<bNodeSocketValueFloat>()->value;
|
||||
res.value = MaterialX::Value::createValue<float>(v);
|
||||
@ -163,7 +191,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();
|
||||
@ -171,6 +199,17 @@ 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, group_parser_)
|
||||
.compute_full();
|
||||
}
|
||||
if (from_node->is_group_input()) {
|
||||
return GroupInputNodeParser(
|
||||
graph_, depsgraph_, material_, from_node, link->fromsock, to_type, group_parser_)
|
||||
.compute_full();
|
||||
}
|
||||
|
||||
if (!from_node->typeinfo->materialx_fn) {
|
||||
CLOG_WARN(LOG_MATERIALX_SHADER,
|
||||
"Unsupported node: %s [%d]",
|
||||
@ -179,7 +218,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<bNode *>(from_node), link->fromsock);
|
||||
return data.result;
|
||||
}
|
||||
|
@ -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,15 +34,18 @@ 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:
|
||||
std::string node_name();
|
||||
std::string node_name() const;
|
||||
NodeItem create_node(const std::string &category, NodeItem::Type type);
|
||||
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_output_default(const std::string &name, NodeItem::Type to_type);
|
||||
@ -71,6 +77,7 @@ struct NodeParserData {
|
||||
const Depsgraph *depsgraph;
|
||||
const Material *material;
|
||||
NodeItem::Type to_type;
|
||||
GroupNodeParser *group_parser;
|
||||
NodeItem result;
|
||||
};
|
||||
|
||||
@ -91,7 +98,8 @@ struct NodeParserData {
|
||||
void node_shader_materialx(void *data, struct bNode *node, struct bNodeSocket *out) \
|
||||
{ \
|
||||
materialx::NodeParserData *d = reinterpret_cast<materialx::NodeParserData *>(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(); \
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -261,7 +261,7 @@ NODE_SHADER_MATERIALX_BEGIN
|
||||
#ifdef WITH_MATERIALX
|
||||
{
|
||||
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);
|
||||
@ -269,9 +269,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("lacunarity", lacunarity);
|
||||
return res;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user