diff --git a/source/blender/nodes/shader/CMakeLists.txt b/source/blender/nodes/shader/CMakeLists.txt index abbe0851ff55..991128fec7f7 100644 --- a/source/blender/nodes/shader/CMakeLists.txt +++ b/source/blender/nodes/shader/CMakeLists.txt @@ -156,6 +156,9 @@ if(WITH_MATERIALX) materialx/nodes/node_parser.cc materialx/nodes/output_material.cc materialx/nodes/tex_image.cc + materialx/nodes/tex_environment.cc + materialx/nodes/tex_noise.cc + materialx/nodes/tex_checker.cc materialx/material.h materialx/nodes/node_item.h diff --git a/source/blender/nodes/shader/materialx/nodes/bsdf_principled.cc b/source/blender/nodes/shader/materialx/nodes/bsdf_principled.cc index 3da7211f7ddf..a87a0782881b 100644 --- a/source/blender/nodes/shader/materialx/nodes/bsdf_principled.cc +++ b/source/blender/nodes/shader/materialx/nodes/bsdf_principled.cc @@ -68,7 +68,7 @@ NodeItem BSDFPrincipledNodeParser::compute() NodeItem tangent = get_input_link("Tangent"); /* Creating standard_surface */ - NodeItem res = create_node("standard_surface", "surfaceshader"); + NodeItem res = create_node("standard_surface", "surfaceshader", false); res.set_input("base", 1.0, "float"); res.set_input("base_color", base_color.to_color3()); res.set_input("diffuse_roughness", roughness); diff --git a/source/blender/nodes/shader/materialx/nodes/node_item.cc b/source/blender/nodes/shader/materialx/nodes/node_item.cc index 8a65fe155a2b..b5b85fb6eeac 100644 --- a/source/blender/nodes/shader/materialx/nodes/node_item.cc +++ b/source/blender/nodes/shader/materialx/nodes/node_item.cc @@ -16,13 +16,15 @@ NodeItem NodeItem::empty() const return NodeItem(graph_); } -void NodeItem::set_input(const std::string &name, const NodeItem &item) +void NodeItem::set_input(const std::string &name, + const NodeItem &item, + const std::string &output_name) { if (item.value) { set_input(name, item.value); } else if (item.node) { - set_input(name, item.node); + set_input(name, item.node, output_name); } } @@ -58,9 +60,19 @@ void NodeItem::set_input(const std::string &name, const MaterialX::ValuePtr valu } } -void NodeItem::set_input(const std::string &name, const MaterialX::NodePtr node) +void NodeItem::set_input(const std::string &name, + const MaterialX::NodePtr node, + const std::string &output_name) { this->node->setConnectedNode(name, node); + if (output_name != "") { + this->node->setConnectedOutput("in1", node->getOutput(output_name)); + } +} + +void NodeItem::add_output(const std::string &name, const std::string &mx_type) +{ + node->addOutput(name, mx_type); } NodeItem::operator bool() const @@ -550,7 +562,9 @@ MaterialX::ValuePtr NodeItem::float_to_type(float v, std::string mx_type) return nullptr; } -bool NodeItem::adjust_types(MaterialX::ValuePtr &val1, MaterialX::ValuePtr &val2, std::string &mx_type) +bool NodeItem::adjust_types(MaterialX::ValuePtr &val1, + MaterialX::ValuePtr &val2, + std::string &mx_type) { std::string t1 = val1->getTypeString(); std::string t2 = val2->getTypeString(); diff --git a/source/blender/nodes/shader/materialx/nodes/node_item.h b/source/blender/nodes/shader/materialx/nodes/node_item.h index 26d3f58b02f9..2f746cda36b7 100644 --- a/source/blender/nodes/shader/materialx/nodes/node_item.h +++ b/source/blender/nodes/shader/materialx/nodes/node_item.h @@ -25,9 +25,14 @@ class NodeItem { template void set_input(const std::string &name, const T &value, const std::string &mx_type); - void set_input(const std::string &name, const NodeItem &item); + void set_input(const std::string &name, + const NodeItem &item, + const std::string &output_name = ""); void set_input(const std::string &name, const MaterialX::ValuePtr value); - void set_input(const std::string &name, const MaterialX::NodePtr node); + void set_input(const std::string &name, + const MaterialX::NodePtr node, + const std::string &output_name = ""); + void add_output(const std::string &name, const std::string &mx_type); operator bool() const; NodeItem operator+(const NodeItem &other) const; @@ -79,7 +84,9 @@ class NodeItem { std::function func) const; static MaterialX::ValuePtr float_to_type(float v, std::string mx_type); /* Functions for adjusting values to make equal types */ - static bool adjust_types(MaterialX::ValuePtr &val1, MaterialX::ValuePtr &val2, std::string &mx_type); + static bool adjust_types(MaterialX::ValuePtr &val1, + MaterialX::ValuePtr &val2, + std::string &mx_type); static bool adjust_types(NodeItem &val1, NodeItem &val2, std::string &mx_type); }; diff --git a/source/blender/nodes/shader/materialx/nodes/node_parser.cc b/source/blender/nodes/shader/materialx/nodes/node_parser.cc index 61bda4d32628..edbdffd6f09d 100644 --- a/source/blender/nodes/shader/materialx/nodes/node_parser.cc +++ b/source/blender/nodes/shader/materialx/nodes/node_parser.cc @@ -18,12 +18,12 @@ NodeParser::NodeParser(MaterialX::GraphElement *graph, NodeItem NodeParser::create_node(const std::string &mx_category, const std::string &mx_type, - bool accessory) + bool noname) { NodeItem res = empty(); res.node = graph->addNode(mx_category, - accessory ? MaterialX::EMPTY_STRING : - MaterialX::createValidName(node->name), + noname ? MaterialX::EMPTY_STRING : + MaterialX::createValidName(node->name), mx_type); return res; } @@ -110,7 +110,7 @@ NodeItem NodeParser::get_input_link(const bNodeSocket &socket) /* Getting required NodeParser object */ std::unique_ptr parser; - switch (in_node->type) { + switch (in_node->typeinfo->type) { case SH_NODE_BSDF_PRINCIPLED: parser = std::make_unique(graph, depsgraph, material, in_node); break; @@ -126,6 +126,15 @@ NodeItem NodeParser::get_input_link(const bNodeSocket &socket) case SH_NODE_TEX_IMAGE: parser = std::make_unique(graph, depsgraph, material, in_node); break; + case SH_NODE_TEX_ENVIRONMENT: + parser = std::make_unique(graph, depsgraph, material, in_node); + break; + case SH_NODE_TEX_NOISE: + parser = std::make_unique(graph, depsgraph, material, in_node); + break; + case SH_NODE_TEX_CHECKER: + parser = std::make_unique(graph, depsgraph, material, in_node); + break; default: // TODO: warning log return res; diff --git a/source/blender/nodes/shader/materialx/nodes/node_parser.h b/source/blender/nodes/shader/materialx/nodes/node_parser.h index 4849e430bc35..86d1935e41fd 100644 --- a/source/blender/nodes/shader/materialx/nodes/node_parser.h +++ b/source/blender/nodes/shader/materialx/nodes/node_parser.h @@ -31,7 +31,7 @@ class NodeParser { protected: NodeItem create_node(const std::string &mx_category, const std::string &mx_type, - bool accessory = false); + bool noname = true); NodeItem get_input_default(const std::string &name); NodeItem get_input_default(int index); NodeItem get_input_link(const std::string &name); @@ -64,6 +64,9 @@ DECLARE_PARSER(InvertNodeParser) DECLARE_PARSER(MathNodeParser) DECLARE_PARSER(MixRGBNodeParser) DECLARE_PARSER(OutputMaterialNodeParser) +DECLARE_PARSER(TexCheckerNodeParser) +DECLARE_PARSER(TexEnvironmentNodeParser) DECLARE_PARSER(TexImageNodeParser) +DECLARE_PARSER(TexNoiseNodeParser) } // namespace blender::nodes::materialx diff --git a/source/blender/nodes/shader/materialx/nodes/output_material.cc b/source/blender/nodes/shader/materialx/nodes/output_material.cc index 94a106c40c03..81d00737027d 100644 --- a/source/blender/nodes/shader/materialx/nodes/output_material.cc +++ b/source/blender/nodes/shader/materialx/nodes/output_material.cc @@ -11,7 +11,7 @@ NodeItem OutputMaterialNodeParser::compute() NodeItem node = empty(); NodeItem surface = get_input_link("Surface"); if (surface) { - node = create_node("surfacematerial", "material"); + node = create_node("surfacematerial", "material", false); node.set_input("surfaceshader", surface); } return node; diff --git a/source/blender/nodes/shader/materialx/nodes/tex_checker.cc b/source/blender/nodes/shader/materialx/nodes/tex_checker.cc new file mode 100644 index 000000000000..f04f8ed2c457 --- /dev/null +++ b/source/blender/nodes/shader/materialx/nodes/tex_checker.cc @@ -0,0 +1,52 @@ +/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation + * + * SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "node_parser.h" + +namespace blender::nodes::materialx { + +NodeItem TexCheckerNodeParser::compute() +{ + NodeItem scale = get_input_value("Scale"); + NodeItem color1 = get_input_value("Color1"); + NodeItem color2 = get_input_value("Color2"); + + if (scale.value && scale.type() == "float") { + float v = scale.value->asA(); + scale = value(MaterialX::Vector2(v, v)); + } + /* Modifier to follow Cycles result */ + scale = scale * value(4.0f); + + NodeItem texcoord = create_node("texcoord", "vector2"); + NodeItem place2d = create_node("place2d", "vector2"); + place2d.set_input("texcoord", texcoord * scale); + + /* TODO: fix offset: + * place2d.set_input("offset", offset); */ + + NodeItem separate = create_node("separate2", "multioutput"); + separate.set_input("in", place2d); + separate.add_output("outx", "float"); + separate.add_output("outy", "float"); + + NodeItem modulo_x = create_node("modulo", "float"); + modulo_x.set_input("in1", separate, "outx"); + modulo_x.set_input("in2", value(2.0f)); + + NodeItem modulo_y = create_node("modulo", "float"); + modulo_y.set_input("in1", separate, "outy"); + modulo_y.set_input("in2", value(2.0f)); + + NodeItem ifequal = + (modulo_x.floor() + modulo_y.floor()).if_else("==", value(1.0f), value(0.0f), value(1.0f)); + + NodeItem res = create_node("mix", "color3", false); + res.set_input("fg", color1.to_color3()); + res.set_input("bg", color2.to_color3()); + res.set_input("mix", ifequal); + return res; +} + +} // namespace blender::nodes::materialx diff --git a/source/blender/nodes/shader/materialx/nodes/tex_environment.cc b/source/blender/nodes/shader/materialx/nodes/tex_environment.cc new file mode 100644 index 000000000000..a6048db0412c --- /dev/null +++ b/source/blender/nodes/shader/materialx/nodes/tex_environment.cc @@ -0,0 +1,33 @@ +/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation + * + * SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "node_parser.h" + +#include "hydra/image.h" + +#include "DEG_depsgraph_query.h" + +namespace blender::nodes::materialx { + +NodeItem TexEnvironmentNodeParser::compute() +{ + Image *image = (Image *)node->id; + NodeTexEnvironment *tex = static_cast(node->storage); + Scene *scene = DEG_get_input_scene(depsgraph); + Main *bmain = DEG_get_bmain(depsgraph); + std::string image_path; + /* TODO: What if Blender built without Hydra? Also io::hydra::cache_or_get_image_file contains + * pretty general code, so could be moved from bf_usd project. */ +#ifdef WITH_HYDRA + image_path = io::hydra::cache_or_get_image_file(bmain, scene, image, &tex->iuser); +#endif + + NodeItem texcoord = create_node("texcoord", "vector2"); + NodeItem res = create_node("image", "color3", false); + res.set_input("file", image_path, "filename"); + res.set_input("texcoord", texcoord); + return res; +} + +} // namespace blender::nodes::materialx diff --git a/source/blender/nodes/shader/materialx/nodes/tex_image.cc b/source/blender/nodes/shader/materialx/nodes/tex_image.cc index 6c0239459e06..9d0d3d033195 100644 --- a/source/blender/nodes/shader/materialx/nodes/tex_image.cc +++ b/source/blender/nodes/shader/materialx/nodes/tex_image.cc @@ -17,14 +17,14 @@ NodeItem TexImageNodeParser::compute() Scene *scene = DEG_get_input_scene(depsgraph); Main *bmain = DEG_get_bmain(depsgraph); std::string image_path; - /* TODO: What if Blender built without Hydra? Also io::hydra::cache_or_get_image_file contain + /* TODO: What if Blender built without Hydra? Also io::hydra::cache_or_get_image_file contains * pretty general code, so could be moved from bf_usd project. */ #ifdef WITH_HYDRA image_path = io::hydra::cache_or_get_image_file(bmain, scene, image, &tex->iuser); #endif - NodeItem texcoord = create_node("texcoord", "vector2", true); - NodeItem res = create_node("image", "color3"); + NodeItem texcoord = create_node("texcoord", "vector2"); + NodeItem res = create_node("image", "color3", false); res.set_input("file", image_path, "filename"); res.set_input("texcoord", texcoord); return res; diff --git a/source/blender/nodes/shader/materialx/nodes/tex_noise.cc b/source/blender/nodes/shader/materialx/nodes/tex_noise.cc new file mode 100644 index 000000000000..63268d1fd8c6 --- /dev/null +++ b/source/blender/nodes/shader/materialx/nodes/tex_noise.cc @@ -0,0 +1,28 @@ +/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation + * + * SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "node_parser.h" + +namespace blender::nodes::materialx { + +NodeItem TexNoiseNodeParser::compute() +{ + NodeItem scale = get_input_value("Scale"); + NodeItem detail = get_input_value("Detail"); + NodeItem lacunarity = get_input_value("Lacunarity"); + + if (detail.value && detail.type() == "float") { + detail = value(int(detail.value->asA())); + } + + NodeItem texcoord = create_node("position", "vector3"); + + NodeItem res = create_node("fractal3d", "color3", false); + res.set_input("position", texcoord * scale); + res.set_input("octaves", detail); + res.set_input("lacunarity", lacunarity); + return res; +} + +} // namespace blender::nodes::materialx