Implement export of Shader BSDF nodes #13

Merged
Bogdan Nagirniak merged 13 commits from BogdanNagirniak/blender:matx-shader-bsdf-nodes into matx-export-material 2023-09-07 11:22:44 +02:00
7 changed files with 69 additions and 36 deletions
Showing only changes of commit c18534dbe4 - Show all commits

View File

@ -25,13 +25,11 @@ MaterialX::DocumentPtr export_to_materialx(Depsgraph *depsgraph, Material *mater
if (material->use_nodes) { if (material->use_nodes) {
material->nodetree->ensure_topology_cache(); material->nodetree->ensure_topology_cache();
bNode *output_node = ntreeShaderOutputNode(material->nodetree, SHD_OUTPUT_ALL); bNode *output_node = ntreeShaderOutputNode(material->nodetree, SHD_OUTPUT_ALL);
OutputMaterialNodeParser( OutputMaterialNodeParser(doc.get(), depsgraph, material, output_node, NodeItem::Type::Material)
doc.get(), depsgraph, material, output_node, NodeParser::ShaderType::SurfaceMaterial)
.compute(); .compute();
} }
else { else {
OutputMaterialNodeParser( OutputMaterialNodeParser(doc.get(), depsgraph, material, nullptr, NodeItem::Type::Material)
doc.get(), depsgraph, material, nullptr, NodeParser::ShaderType::SurfaceMaterial)
.compute_default(); .compute_default();
} }

View File

@ -71,7 +71,7 @@ bool NodeItem::operator==(const NodeItem &other) const
NodeItem item1 = *this; NodeItem item1 = *this;
NodeItem item2 = other; NodeItem item2 = other;
Type to_type = adjust_types(item1, item2); Type to_type = adjust_types(item1, item2);
if (to_type == Type::Empty) { if (to_type == Type::None) {
return false; return false;
} }
return item1.value->getValueString() == item2.value->getValueString(); return item1.value->getValueString() == item2.value->getValueString();
@ -449,7 +449,7 @@ NodeItem NodeItem::if_else(CompareOp op,
auto item1 = if_val; auto item1 = if_val;
auto item2 = else_val; auto item2 = else_val;
Type to_type = adjust_types(item1, item2); Type to_type = adjust_types(item1, item2);
if (to_type == Type::Empty) { if (to_type == Type::None) {
return res; return res;
} }
@ -499,7 +499,7 @@ NodeItem::Type NodeItem::type() const
if (node) { if (node) {
return type(node->getType()); return type(node->getType());
} }
return Type::Empty; return Type::None;
} }
void NodeItem::set_input(const std::string &name, void NodeItem::set_input(const std::string &name,
@ -567,6 +567,9 @@ NodeItem::Type NodeItem::type(const std::string &type_str)
if (type_str == "string") { if (type_str == "string") {
return Type::String; return Type::String;
} }
if (type_str == "filename") {
return Type::Filename;
}
if (type_str == "integer") { if (type_str == "integer") {
return Type::Integer; return Type::Integer;
} }
@ -588,7 +591,20 @@ NodeItem::Type NodeItem::type(const std::string &type_str)
if (type_str == "color4") { if (type_str == "color4") {
return Type::Color4; return Type::Color4;
} }
return Type::Other; if (type_str == "BSDF") {
return Type::BSDF;
}
if (type_str == "EDF") {
return Type::EDF;
}
if (type_str == "surfaceshader") {
return Type::SurfaceShader;
}
if (type_str == "material") {
return Type::Material;
}
BLI_assert_unreachable();
return Type::None;
} }
std::string NodeItem::type(Type type) std::string NodeItem::type(Type type)
@ -596,6 +612,8 @@ std::string NodeItem::type(Type type)
switch (type) { switch (type) {
case Type::String: case Type::String:
return "string"; return "string";
case Type::Filename:
return "filename";
case Type::Integer: case Type::Integer:
return "integer"; return "integer";
case Type::Float: case Type::Float:
@ -610,15 +628,23 @@ std::string NodeItem::type(Type type)
return "color3"; return "color3";
case Type::Color4: case Type::Color4:
return "color4"; return "color4";
case Type::BSDF:
return "BSDF";
case Type::EDF:
return "EDF";
case Type::SurfaceShader:
return "surfaceshader";
case Type::Material:
return "material";
default: default:
break; BLI_assert_unreachable();
} }
return ""; return "";
} }
bool NodeItem::is_arithmetic(Type type) bool NodeItem::is_arithmetic(Type type)
{ {
return type >= Type::Float; return type >= Type::Float && type <= Type::Color4;
} }
NodeItem::Type NodeItem::adjust_types(NodeItem &item1, NodeItem &item2) NodeItem::Type NodeItem::adjust_types(NodeItem &item1, NodeItem &item2)
@ -629,7 +655,7 @@ NodeItem::Type NodeItem::adjust_types(NodeItem &item1, NodeItem &item2)
return t1; return t1;
} }
if (!is_arithmetic(t1) || !is_arithmetic(t2)) { if (!is_arithmetic(t1) || !is_arithmetic(t2)) {
return Type::Empty; return Type::None;
} }
if (t1 < t2) { if (t1 < t2) {
item1 = item1.convert(t2); item1 = item1.convert(t2);
@ -710,7 +736,7 @@ NodeItem NodeItem::arithmetic(const NodeItem &other,
NodeItem item1 = *this; NodeItem item1 = *this;
NodeItem item2 = other; NodeItem item2 = other;
Type to_type = adjust_types(item1, item2); Type to_type = adjust_types(item1, item2);
if (to_type == Type::Empty) { if (to_type == Type::None) {
return res; return res;
} }

View File

@ -11,16 +11,26 @@ namespace blender::nodes::materialx {
class NodeItem { class NodeItem {
public: public:
enum class Type { enum class Type {
Empty = 0, None = 0,
Other, /* For MaterialX types like: surfaceshader, bsdf, edf, ...*/
/* Value types */
String, String,
Filename,
Integer, Integer,
Float, Float,
Vector2, Vector2,
Vector3, Vector3,
Vector4, Vector4,
Color3, Color3,
Color4 Color4,
/* Shader types
* Note: There are only supported types */
BSDF,
EDF,
SurfaceShader,
Material,
}; };
enum class CompareOp { Less = 0, LessEq, Eq, GreaterEq, Greater, NotEq }; enum class CompareOp { Less = 0, LessEq, Eq, GreaterEq, Greater, NotEq };

View File

@ -14,13 +14,13 @@ NodeParser::NodeParser(MaterialX::GraphElement *graph,
const Material *material, const Material *material,
const bNode *node, const bNode *node,
const bNodeSocket *socket_out, const bNodeSocket *socket_out,
ShaderType shader) NodeItem::Type shader_type)
: graph_(graph), : graph_(graph),
depsgraph_(depsgraph), depsgraph_(depsgraph),
material_(material), material_(material),
node_(node), node_(node),
socket_out_(socket_out), socket_out_(socket_out),
shader_(shader) shader_type_(shader_type)
{ {
} }
@ -48,14 +48,14 @@ NodeItem NodeParser::get_input_default(int index)
return get_input_default(node_->input_socket(index)); return get_input_default(node_->input_socket(index));
} }
NodeItem NodeParser::get_input_link(const std::string &name, ShaderType shader) NodeItem NodeParser::get_input_link(const std::string &name, NodeItem::Type shader_type)
{ {
return get_input_link(node_->input_by_identifier(name), shader); return get_input_link(node_->input_by_identifier(name), shader_type);
} }
NodeItem NodeParser::get_input_link(int index, ShaderType shader) NodeItem NodeParser::get_input_link(int index, NodeItem::Type shader_type)
{ {
return get_input_link(node_->input_socket(index), shader); return get_input_link(node_->input_socket(index), shader_type);
} }
NodeItem NodeParser::get_input_value(const std::string &name) NodeItem NodeParser::get_input_value(const std::string &name)
@ -101,7 +101,7 @@ NodeItem NodeParser::get_input_default(const bNodeSocket &socket)
return res; return res;
} }
NodeItem NodeParser::get_input_link(const bNodeSocket &socket, ShaderType channel) NodeItem NodeParser::get_input_link(const bNodeSocket &socket, NodeItem::Type shader_type)
{ {
NodeItem res = empty(); NodeItem res = empty();
@ -130,7 +130,8 @@ NodeItem NodeParser::get_input_link(const bNodeSocket &socket, ShaderType channe
/* Computing from_node with required NodeParser object */ /* Computing from_node with required NodeParser object */
#define CASE_NODE_TYPE(type, T) \ #define CASE_NODE_TYPE(type, T) \
case type: \ case type: \
res = T(graph_, depsgraph_, material_, from_node, link->fromsock, channel).compute_full(); \ res = \
T(graph_, depsgraph_, material_, from_node, link->fromsock, shader_type).compute_full(); \
break; break;
switch (from_node->typeinfo->type) { switch (from_node->typeinfo->type) {
@ -163,7 +164,7 @@ NodeItem NodeParser::get_input_link(const bNodeSocket &socket, ShaderType channe
NodeItem NodeParser::get_input_value(const bNodeSocket &socket) NodeItem NodeParser::get_input_value(const bNodeSocket &socket)
{ {
NodeItem res = get_input_link(socket, ShaderType::Value); NodeItem res = get_input_link(socket, NodeItem::Type::None);
if (!res) { if (!res) {
res = get_input_default(socket); res = get_input_default(socket);
} }

View File

@ -13,16 +13,13 @@
namespace blender::nodes::materialx { namespace blender::nodes::materialx {
class NodeParser { class NodeParser {
public:
enum class ShaderType { Value = 0, BSDF, EDF, VDF, SurfaceShader, SurfaceMaterial };
protected: protected:
MaterialX::GraphElement *graph_; MaterialX::GraphElement *graph_;
const Depsgraph *depsgraph_; const Depsgraph *depsgraph_;
const Material *material_; const Material *material_;
const bNode *node_; const bNode *node_;
const bNodeSocket *socket_out_; const bNodeSocket *socket_out_;
ShaderType shader_; NodeItem::Type shader_type_;
public: public:
NodeParser(MaterialX::GraphElement *graph, NodeParser(MaterialX::GraphElement *graph,
@ -30,7 +27,7 @@ class NodeParser {
const Material *material, const Material *material,
const bNode *node, const bNode *node,
const bNodeSocket *socket_out, const bNodeSocket *socket_out,
ShaderType shader); NodeItem::Type shader_type);
virtual ~NodeParser() = default; virtual ~NodeParser() = default;
virtual NodeItem compute() = 0; virtual NodeItem compute() = 0;
@ -40,8 +37,9 @@ class NodeParser {
NodeItem create_node(const std::string &mx_category, const std::string &mx_type); NodeItem create_node(const std::string &mx_category, const std::string &mx_type);
NodeItem get_input_default(const std::string &name); NodeItem get_input_default(const std::string &name);
NodeItem get_input_default(int index); NodeItem get_input_default(int index);
NodeItem get_input_link(const std::string &name, ShaderType shader = ShaderType::Value); NodeItem get_input_link(const std::string &name,
NodeItem get_input_link(int index, ShaderType shader = ShaderType::Value); NodeItem::Type shader_type = NodeItem::Type::None);
NodeItem get_input_link(int index, NodeItem::Type shader_type = NodeItem::Type::None);
NodeItem get_input_value(const std::string &name); NodeItem get_input_value(const std::string &name);
NodeItem get_input_value(int index); NodeItem get_input_value(int index);
NodeItem empty() const; NodeItem empty() const;
@ -49,7 +47,7 @@ class NodeParser {
private: private:
NodeItem get_input_default(const bNodeSocket &socket); NodeItem get_input_default(const bNodeSocket &socket);
NodeItem get_input_link(const bNodeSocket &socket, ShaderType shader); NodeItem get_input_link(const bNodeSocket &socket, NodeItem::Type shader_type);
NodeItem get_input_value(const bNodeSocket &socket); NodeItem get_input_value(const bNodeSocket &socket);
NodeItem compute_full(); NodeItem compute_full();
}; };

View File

@ -9,8 +9,8 @@ OutputMaterialNodeParser::OutputMaterialNodeParser(MaterialX::GraphElement *grap
const Depsgraph *depsgraph, const Depsgraph *depsgraph,
const Material *material, const Material *material,
const bNode *node, const bNode *node,
ShaderType shader) NodeItem::Type shader_type)
: NodeParser(graph, depsgraph, material, node, nullptr, shader) : NodeParser(graph, depsgraph, material, node, nullptr, shader_type)
{ {
} }
@ -18,7 +18,7 @@ NodeItem OutputMaterialNodeParser::compute()
{ {
NodeItem surface = empty(); NodeItem surface = empty();
if (node_) { if (node_) {
surface = get_input_link("Surface", ShaderType::SurfaceShader); surface = get_input_link("Surface", NodeItem::Type::SurfaceShader);
} }
else { else {
surface = create_node("standard_surface", "surfaceshader"); surface = create_node("standard_surface", "surfaceshader");

View File

@ -14,7 +14,7 @@ class OutputMaterialNodeParser : public NodeParser {
const Depsgraph *depsgraph, const Depsgraph *depsgraph,
const Material *material, const Material *material,
const bNode *node, const bNode *node,
ShaderType shader); NodeItem::Type shader_type);
NodeItem compute() override; NodeItem compute() override;
NodeItem compute_default(); NodeItem compute_default();
}; };