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) {
material->nodetree->ensure_topology_cache();
bNode *output_node = ntreeShaderOutputNode(material->nodetree, SHD_OUTPUT_ALL);
OutputMaterialNodeParser(
doc.get(), depsgraph, material, output_node, NodeParser::ShaderType::SurfaceMaterial)
OutputMaterialNodeParser(doc.get(), depsgraph, material, output_node, NodeItem::Type::Material)
.compute();
}
else {
OutputMaterialNodeParser(
doc.get(), depsgraph, material, nullptr, NodeParser::ShaderType::SurfaceMaterial)
OutputMaterialNodeParser(doc.get(), depsgraph, material, nullptr, NodeItem::Type::Material)
.compute_default();
}

View File

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

View File

@ -11,16 +11,26 @@ namespace blender::nodes::materialx {
class NodeItem {
public:
enum class Type {
Empty = 0,
Other, /* For MaterialX types like: surfaceshader, bsdf, edf, ...*/
None = 0,
/* Value types */
String,
Filename,
Integer,
Float,
Vector2,
Vector3,
Vector4,
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 };

View File

@ -14,13 +14,13 @@ NodeParser::NodeParser(MaterialX::GraphElement *graph,
const Material *material,
const bNode *node,
const bNodeSocket *socket_out,
ShaderType shader)
NodeItem::Type shader_type)
: graph_(graph),
depsgraph_(depsgraph),
material_(material),
node_(node),
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));
}
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)
@ -101,7 +101,7 @@ NodeItem NodeParser::get_input_default(const bNodeSocket &socket)
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();
@ -130,7 +130,8 @@ NodeItem NodeParser::get_input_link(const bNodeSocket &socket, ShaderType channe
/* Computing from_node with required NodeParser object */
#define CASE_NODE_TYPE(type, T) \
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;
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 res = get_input_link(socket, ShaderType::Value);
NodeItem res = get_input_link(socket, NodeItem::Type::None);
if (!res) {
res = get_input_default(socket);
}

View File

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

View File

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

View File

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