MaterialX: add support for nodes #11

Merged
Bogdan Nagirniak merged 17 commits from matx-add-other-nodes into matx-export-material 2023-09-06 10:37:26 +02:00
12 changed files with 634 additions and 568 deletions
Showing only changes of commit a5a6345f39 - Show all commits

View File

@ -49,7 +49,7 @@ NodeItem BSDFPrincipledNodeParser::compute()
/* Creating standard_surface */ /* Creating standard_surface */
NodeItem res = create_node("standard_surface", "surfaceshader"); NodeItem res = create_node("standard_surface", "surfaceshader");
res.set_input("base", 1.0, "float"); res.set_input("base", 1.0, "float");
res.set_input("base_color", base_color.to_color3()); res.set_input("base_color", base_color, NodeItem::Type::Color3);
res.set_input("diffuse_roughness", roughness); res.set_input("diffuse_roughness", roughness);
if (normal) { if (normal) {
res.set_input("normal", normal); res.set_input("normal", normal);
@ -60,27 +60,27 @@ NodeItem BSDFPrincipledNodeParser::compute()
res.set_input("metalness", metallic); res.set_input("metalness", metallic);
res.set_input("specular", specular); res.set_input("specular", specular);
res.set_input("specular_color", base_color.to_color3()); res.set_input("specular_color", base_color, NodeItem::Type::Color3);
res.set_input("specular_roughness", roughness); res.set_input("specular_roughness", roughness);
res.set_input("specular_IOR", ior); res.set_input("specular_IOR", ior);
res.set_input("specular_anisotropy", anisotropic); res.set_input("specular_anisotropy", anisotropic);
res.set_input("specular_rotation", anisotropic_rotation); res.set_input("specular_rotation", anisotropic_rotation);
res.set_input("transmission", transmission); res.set_input("transmission", transmission);
res.set_input("transmission_color", base_color.to_color3()); res.set_input("transmission_color", base_color, NodeItem::Type::Color3);
res.set_input("transmission_extra_roughness", roughness); res.set_input("transmission_extra_roughness", roughness);
res.set_input("subsurface", subsurface); res.set_input("subsurface", subsurface);
res.set_input("subsurface_color", subsurface_color.to_color3()); res.set_input("subsurface_color", subsurface_color, NodeItem::Type::Color3);
res.set_input("subsurface_radius", subsurface_radius); res.set_input("subsurface_radius", subsurface_radius, NodeItem::Type::Color3);
res.set_input("subsurface_anisotropy", anisotropic); res.set_input("subsurface_anisotropy", anisotropic);
res.set_input("sheen", sheen); res.set_input("sheen", sheen);
res.set_input("sheen_color", base_color.to_color3()); res.set_input("sheen_color", base_color, NodeItem::Type::Color3);
res.set_input("sheen_roughness", roughness); res.set_input("sheen_roughness", roughness);
res.set_input("coat", clearcoat); res.set_input("coat", clearcoat);
res.set_input("coat_color", base_color.to_color3()); res.set_input("coat_color", base_color, NodeItem::Type::Color3);
res.set_input("coat_roughness", clearcoat_roughness); res.set_input("coat_roughness", clearcoat_roughness);
res.set_input("coat_IOR", ior); res.set_input("coat_IOR", ior);
res.set_input("coat_anisotropy", anisotropic); res.set_input("coat_anisotropy", anisotropic);
@ -90,7 +90,7 @@ NodeItem BSDFPrincipledNodeParser::compute()
} }
res.set_input("emission", emission_strength); res.set_input("emission", emission_strength);
res.set_input("emission_color", emission.to_color3()); res.set_input("emission_color", emission, NodeItem::Type::Color3);
return res; return res;
} }

View File

@ -24,7 +24,7 @@ NodeItem HueSatValNodeParser::compute()
combine.set_input("in3", val); combine.set_input("in3", val);
NodeItem res = create_node("hsvadjust", "color3"); NodeItem res = create_node("hsvadjust", "color3");
res.set_input("in", color.to_color3()); res.set_input("in", color, NodeItem::Type::Color3);
res.set_input("amount", combine); res.set_input("amount", combine);
return res; return res;
} }

View File

@ -2,8 +2,8 @@
* *
* SPDX-License-Identifier: GPL-2.0-or-later */ * SPDX-License-Identifier: GPL-2.0-or-later */
#include "node_parser.h"
#include "../material.h" #include "../material.h"
#include "node_parser.h"
namespace blender::nodes::materialx { namespace blender::nodes::materialx {
@ -109,10 +109,10 @@ NodeItem MathNodeParser::compute()
res = x.max(y); res = x.max(y);
break; break;
case NODE_MATH_LESS_THAN: case NODE_MATH_LESS_THAN:
res = x.if_else("<", y, value(1.0f), value(0.0f)); res = x.if_else(NodeItem::CompareOp::Less, y, value(1.0f), value(0.0f));
break; break;
case NODE_MATH_GREATER_THAN: case NODE_MATH_GREATER_THAN:
res = x.if_else(">", y, value(1.0f), value(0.0f)); res = x.if_else(NodeItem::CompareOp::Greater, y, value(1.0f), value(0.0f));
break; break;
case NODE_MATH_MODULO: case NODE_MATH_MODULO:
res = x % y; res = x % y;
@ -138,7 +138,7 @@ NodeItem MathNodeParser::compute()
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op); CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);
break; break;
case NODE_MATH_COMPARE: case NODE_MATH_COMPARE:
res = z.if_else("<", (x - y).abs(), value(1.0f), value(0.0f)); res = z.if_else(NodeItem::CompareOp::Less, (x - y).abs(), value(1.0f), value(0.0f));
break; break;
case NODE_MATH_MULTIPLY_ADD: case NODE_MATH_MULTIPLY_ADD:
res = x * y + z; res = x * y + z;

File diff suppressed because it is too large Load Diff

View File

@ -9,6 +9,21 @@
namespace blender::nodes::materialx { namespace blender::nodes::materialx {
class NodeItem { class NodeItem {
public:
enum class Type {
Empty = 0,
Other, /* For MaterialX types like: surfaceshader, bsdf, edf, ...*/
String,
Integer,
Float,
Vector2,
Vector3,
Vector4,
Color3,
Color4
};
enum class CompareOp { Less = 0, LessEq, Eq, GreaterEq, Greater, NotEq };
public: public:
MaterialX::ValuePtr value; MaterialX::ValuePtr value;
MaterialX::NodePtr node; MaterialX::NodePtr node;
@ -20,20 +35,7 @@ class NodeItem {
NodeItem(MaterialX::GraphElement *graph); NodeItem(MaterialX::GraphElement *graph);
~NodeItem() = default; ~NodeItem() = default;
NodeItem empty() const; /* Operators */
template<class T> NodeItem val(const T &data) const;
template<class T>
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,
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,
const std::string &output_name = "");
void add_output(const std::string &name, const std::string &mx_type);
operator bool() const; operator bool() const;
NodeItem operator+(const NodeItem &other) const; NodeItem operator+(const NodeItem &other) const;
NodeItem operator-(const NodeItem &other) const; NodeItem operator-(const NodeItem &other) const;
@ -45,16 +47,13 @@ class NodeItem {
bool operator==(const NodeItem &other) const; bool operator==(const NodeItem &other) const;
bool operator!=(const NodeItem &other) const; bool operator!=(const NodeItem &other) const;
/* Math functions */
NodeItem abs() const; NodeItem abs() const;
NodeItem floor() const; NodeItem floor() const;
NodeItem ceil() const; NodeItem ceil() const;
NodeItem min(const NodeItem &other) const; NodeItem min(const NodeItem &other) const;
NodeItem max(const NodeItem &other) const; NodeItem max(const NodeItem &other) const;
NodeItem dotproduct(const NodeItem &other) const; NodeItem dotproduct(const NodeItem &other) const;
NodeItem if_else(const std::string &condition,
const NodeItem &other,
const NodeItem &if_val,
const NodeItem &else_val) const;
NodeItem blend(const NodeItem &a, const NodeItem &b) const; NodeItem blend(const NodeItem &a, const NodeItem &b) const;
NodeItem clamp(const NodeItem &min_val, const NodeItem &max_val) const; NodeItem clamp(const NodeItem &min_val, const NodeItem &max_val) const;
NodeItem clamp(float min_val = 0.0f, float max_val = 1.0f) const; NodeItem clamp(float min_val = 0.0f, float max_val = 1.0f) const;
@ -72,25 +71,42 @@ class NodeItem {
NodeItem sqrt() const; NodeItem sqrt() const;
NodeItem sign() const; NodeItem sign() const;
NodeItem exp() const; NodeItem exp() const;
NodeItem separate(const int index) const; NodeItem convert(Type to_type) const;
NodeItem if_else(CompareOp op,
const NodeItem &other,
const NodeItem &if_val,
const NodeItem &else_val) const;
NodeItem extract(const int index) const;
NodeItem separate_color(const int index) const; NodeItem separate_color(const int index) const;
NodeItem to_color3() const; /* Useful functions */
NodeItem to_vector3() const; NodeItem empty() const;
bool is_numeric() const; template<class T> NodeItem val(const T &data) const;
std::string type() const; Type type() const;
/* Functions to set input and output */
template<class T>
void set_input(const std::string &in_name, const T &value, const std::string &in_type);
void set_input(const std::string &in_name,
const NodeItem &item,
const std::string &out_name = "");
void set_input(const std::string &in_name,
const NodeItem &item,
Type in_type,
const std::string &out_name = "");
void add_output(const std::string &in_name, Type out_type);
private: private:
NodeItem arithmetic(const std::string &mx_category, std::function<float(float)> func) const; static Type type(const std::string &type_str);
static std::string type(Type type);
static bool is_arithmetic(Type type);
static Type adjust_types(NodeItem &item1, NodeItem &item2);
bool is_arithmetic() const;
NodeItem arithmetic(const std::string &category, std::function<float(float)> func) const;
NodeItem arithmetic(const NodeItem &other, NodeItem arithmetic(const NodeItem &other,
const std::string &mx_category, const std::string &category,
std::function<float(float, float)> func) const; std::function<float(float, float)> 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(NodeItem &val1, NodeItem &val2, std::string &mx_type);
}; };
template<class T> NodeItem NodeItem::val(const T &data) const template<class T> NodeItem NodeItem::val(const T &data) const
@ -101,9 +117,9 @@ template<class T> NodeItem NodeItem::val(const T &data) const
} }
template<class T> template<class T>
void NodeItem::set_input(const std::string &name, const T &value, const std::string &mx_type) void NodeItem::set_input(const std::string &in_name, const T &value, const std::string &in_type)
{ {
node->setInputValue(name, value, mx_type); node->setInputValue(in_name, value, in_type);
} }
} // namespace blender::nodes::materialx } // namespace blender::nodes::materialx

View File

@ -14,7 +14,11 @@ 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)
: graph_(graph), depsgraph_(depsgraph), material_(material), node_(node), socket_out_(socket_out) : graph_(graph),
depsgraph_(depsgraph),
material_(material),
node_(node),
socket_out_(socket_out)
{ {
} }
@ -74,17 +78,20 @@ NodeItem NodeParser::get_input_default(const bNodeSocket &socket)
case SOCK_FLOAT: { case SOCK_FLOAT: {
float v = socket.default_value_typed<bNodeSocketValueFloat>()->value; float v = socket.default_value_typed<bNodeSocketValueFloat>()->value;
res.value = MaterialX::Value::createValue<float>(v); res.value = MaterialX::Value::createValue<float>(v);
} break; break;
}
case SOCK_VECTOR: { case SOCK_VECTOR: {
const float *v = socket.default_value_typed<bNodeSocketValueVector>()->value; const float *v = socket.default_value_typed<bNodeSocketValueVector>()->value;
res.value = MaterialX::Value::createValue<MaterialX::Vector3>( res.value = MaterialX::Value::createValue<MaterialX::Vector3>(
MaterialX::Vector3(v[0], v[1], v[2])); MaterialX::Vector3(v[0], v[1], v[2]));
} break; break;
}
case SOCK_RGBA: { case SOCK_RGBA: {
const float *v = socket.default_value_typed<bNodeSocketValueRGBA>()->value; const float *v = socket.default_value_typed<bNodeSocketValueRGBA>()->value;
res.value = MaterialX::Value::createValue<MaterialX::Color4>( res.value = MaterialX::Value::createValue<MaterialX::Color4>(
MaterialX::Color4(v[0], v[1], v[2], v[3])); MaterialX::Color4(v[0], v[1], v[2], v[3]));
} break; break;
}
default: { default: {
CLOG_WARN(LOG_MATERIALX_SHADER, "Unsupported socket type: %d", socket.type); CLOG_WARN(LOG_MATERIALX_SHADER, "Unsupported socket type: %d", socket.type);
} }

View File

@ -15,7 +15,7 @@ NodeItem NormalMapNodeParser::compute()
NodeItem strength = get_input_value("Strength"); NodeItem strength = get_input_value("Strength");
NodeItem res = create_node("normalmap", "vector3"); NodeItem res = create_node("normalmap", "vector3");
res.set_input("in", color.to_vector3()); res.set_input("in", color, NodeItem::Type::Color3);
res.set_input("scale", strength); res.set_input("scale", strength);
switch (normal_map_node->space) { switch (normal_map_node->space) {

View File

@ -37,7 +37,8 @@ NodeItem OutputMaterialNodeParser::compute(const std::string &socket_name)
NodeItem OutputMaterialNodeParser::compute_default() NodeItem OutputMaterialNodeParser::compute_default()
{ {
NodeItem surface = create_node("standard_surface", "surfaceshader"); NodeItem surface = create_node("standard_surface", "surfaceshader");
surface.set_input("base_color", value(MaterialX::Color3(material_->r, material_->g, material_->b))); surface.set_input("base_color",
value(MaterialX::Color3(material_->r, material_->g, material_->b)));
surface.set_input("diffuse_roughness", value(material_->roughness)); surface.set_input("diffuse_roughness", value(material_->roughness));
if (material_->metallic > 0.0f) { if (material_->metallic > 0.0f) {
surface.set_input("metalness", value(material_->metallic)); surface.set_input("metalness", value(material_->metallic));

View File

@ -25,7 +25,7 @@ NodeItem SeparateColorNodeParser::compute()
channel_1 = "Hue"; channel_1 = "Hue";
channel_2 = "Saturation"; channel_2 = "Saturation";
convert = create_node("rgbtohsv", "color3"); convert = create_node("rgbtohsv", "color3");
convert.set_input("in", color.to_color3()); convert.set_input("in", color, NodeItem::Type::Color3);
break; break;
default: default:
BLI_assert_unreachable(); BLI_assert_unreachable();
@ -36,12 +36,13 @@ NodeItem SeparateColorNodeParser::compute()
2; 2;
NodeItem res = convert ? convert : color; NodeItem res = convert ? convert : color;
return res.separate(index); return res.extract(index);
} }
NodeItem CombineColorNodeParser::compute() NodeItem CombineColorNodeParser::compute()
{ {
/* TODO: implement. */ /* TODO: implement. */
return empty();
} }
} // namespace blender::nodes::materialx } // namespace blender::nodes::materialx

View File

@ -10,7 +10,7 @@ NodeItem SeparateXYZNodeParser::compute()
{ {
NodeItem vector = get_input_value("Vector"); NodeItem vector = get_input_value("Vector");
int index = STREQ(socket_out_->name, "X") ? 0 : STREQ(socket_out_->name, "Y") ? 1 : 2; int index = STREQ(socket_out_->name, "X") ? 0 : STREQ(socket_out_->name, "Y") ? 1 : 2;
return vector.separate(index); return vector.extract(index);
} }
NodeItem CombineXYZNodeParser::compute() NodeItem CombineXYZNodeParser::compute()

View File

@ -8,23 +8,20 @@ namespace blender::nodes::materialx {
NodeItem TexCheckerNodeParser::compute() NodeItem TexCheckerNodeParser::compute()
{ {
NodeItem scale = get_input_value("Scale"); NodeItem vector = get_input_link("Vector");
NodeItem color1 = get_input_value("Color1"); NodeItem color1 = get_input_value("Color1");
NodeItem color2 = get_input_value("Color2"); NodeItem color2 = get_input_value("Color2");
NodeItem scale = get_input_value("Scale");
if (scale.value && scale.type() == "float") { if (!vector) {
float v = scale.value->asA<float>(); vector = create_node("texcoord", "vector2");
scale = value(MaterialX::Vector2(v, v));
} }
vector = vector * scale;
NodeItem texcoord = create_node("texcoord", "vector2");
NodeItem place2d = create_node("place2d", "vector2");
place2d.set_input("texcoord", texcoord * scale);
NodeItem separate = create_node("separate2", "multioutput"); NodeItem separate = create_node("separate2", "multioutput");
separate.set_input("in", place2d); separate.set_input("in", vector, NodeItem::Type::Vector2);
separate.add_output("outx", "float"); separate.add_output("outx", NodeItem::Type::Float);
separate.add_output("outy", "float"); separate.add_output("outy", NodeItem::Type::Float);
NodeItem modulo_x = create_node("modulo", "float"); NodeItem modulo_x = create_node("modulo", "float");
modulo_x.set_input("in1", separate, "outx"); modulo_x.set_input("in1", separate, "outx");
@ -34,12 +31,12 @@ NodeItem TexCheckerNodeParser::compute()
modulo_y.set_input("in1", separate, "outy"); modulo_y.set_input("in1", separate, "outy");
modulo_y.set_input("in2", value(2.0f)); modulo_y.set_input("in2", value(2.0f));
NodeItem ifequal = NodeItem ifequal = (modulo_x.floor() + modulo_y.floor())
(modulo_x.floor() + modulo_y.floor()).if_else("==", value(1.0f), value(0.0f), value(1.0f)); .if_else(NodeItem::CompareOp::Eq, value(1.0f), value(0.0f), value(1.0f));
NodeItem res = create_node("mix", "color3"); NodeItem res = create_node("mix", "color3");
res.set_input("bg", color1.to_color3()); res.set_input("bg", color1, NodeItem::Type::Color3);
res.set_input("fg", color2.to_color3()); res.set_input("fg", color2, NodeItem::Type::Color3);
res.set_input("mix", ifequal); res.set_input("mix", ifequal);
return res; return res;
} }

View File

@ -12,14 +12,15 @@ NodeItem TexNoiseNodeParser::compute()
NodeItem detail = get_input_value("Detail"); NodeItem detail = get_input_value("Detail");
NodeItem lacunarity = get_input_value("Lacunarity"); NodeItem lacunarity = get_input_value("Lacunarity");
if (detail.value && detail.type() == "float") { if (detail.value && detail.type() == NodeItem::Type::Float) {
detail = value(int(detail.value->asA<float>())); detail = value(int(detail.value->asA<float>()));
} }
NodeItem texcoord = create_node("position", "vector3"); NodeItem position = create_node("position", "vector3");
position = position * scale;
NodeItem res = create_node("fractal3d", "color3"); NodeItem res = create_node("fractal3d", "color3");
res.set_input("position", texcoord * scale); res.set_input("position", position, NodeItem::Type::Vector3);
res.set_input("octaves", detail); res.set_input("octaves", detail);
res.set_input("lacunarity", lacunarity); res.set_input("lacunarity", lacunarity);
return res; return res;