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
15 changed files with 71 additions and 83 deletions
Showing only changes of commit d697d4c727 - Show all commits

View File

@ -8,9 +8,9 @@ namespace blender::nodes::materialx {
NodeItem BrightContrastNodeParser::compute() NodeItem BrightContrastNodeParser::compute()
{ {
NodeItem color = get_input_value("Color"); NodeItem color = get_input_value("Color", NodeItem::Type::Color3);
NodeItem bright = get_input_value("Bright"); NodeItem bright = get_input_value("Bright", NodeItem::Type::Float);
NodeItem contrast = get_input_value("Contrast"); NodeItem contrast = get_input_value("Contrast", NodeItem::Type::Float);
/* This formula was given from OSL shader code in Cycles. */ /* This formula was given from OSL shader code in Cycles. */
return (bright + color * (contrast + value(1.0f)) - contrast * value(0.5f)).max(value(0.0f)); return (bright + color * (contrast + value(1.0f)) - contrast * value(0.5f)).max(value(0.0f));

View File

@ -18,38 +18,36 @@ NodeItem BSDFPrincipledNodeParser::compute_edf()
NodeItem BSDFPrincipledNodeParser::compute_surface() NodeItem BSDFPrincipledNodeParser::compute_surface()
{ {
/* Getting required inputs NodeItem base_color = get_input_value("Base Color", NodeItem::Type::Color3);
* Note: if some inputs are not needed they won't be taken */
NodeItem base_color = get_input_value("Base Color");
NodeItem subsurface = get_input_value("Subsurface"); NodeItem subsurface = get_input_value("Subsurface", NodeItem::Type::Float);
NodeItem subsurface_radius = get_input_value("Subsurface Radius"); NodeItem subsurface_radius = get_input_value("Subsurface Radius", NodeItem::Type::Color3);
NodeItem subsurface_color = get_input_value("Subsurface Color"); NodeItem subsurface_color = get_input_value("Subsurface Color", NodeItem::Type::Color3);
NodeItem metallic = get_input_value("Metallic"); NodeItem metallic = get_input_value("Metallic", NodeItem::Type::Float);
NodeItem specular = get_input_value("Specular"); NodeItem specular = get_input_value("Specular", NodeItem::Type::Float);
// NodeItem specular_tint = get_input_value("Specular Tint"); // NodeItem specular_tint = get_input_value("Specular Tint");
NodeItem roughness = get_input_value("Roughness"); NodeItem roughness = get_input_value("Roughness", NodeItem::Type::Float);
/* TODO: use Specular Tint input */ /* TODO: use Specular Tint input */
NodeItem anisotropic = get_input_value("Anisotropic"); NodeItem anisotropic = get_input_value("Anisotropic", NodeItem::Type::Float);
NodeItem anisotropic_rotation = get_input_value("Anisotropic Rotation"); NodeItem anisotropic_rotation = get_input_value("Anisotropic Rotation", NodeItem::Type::Float);
// anisotropic_rotation = 0.5 - (anisotropic_rotation % 1.0) // anisotropic_rotation = 0.5 - (anisotropic_rotation % 1.0)
NodeItem sheen = get_input_value("Sheen"); NodeItem sheen = get_input_value("Sheen", NodeItem::Type::Float);
// sheen_tint = get_input_value("Sheen Tint"); // sheen_tint = get_input_value("Sheen Tint");
NodeItem clearcoat = get_input_value("Clearcoat"); NodeItem clearcoat = get_input_value("Clearcoat", NodeItem::Type::Float);
NodeItem clearcoat_roughness = get_input_value("Clearcoat Roughness"); NodeItem clearcoat_roughness = get_input_value("Clearcoat Roughness", NodeItem::Type::Float);
NodeItem ior = get_input_value("IOR"); NodeItem ior = get_input_value("IOR", NodeItem::Type::Float);
NodeItem transmission = get_input_value("Transmission"); NodeItem transmission = get_input_value("Transmission", NodeItem::Type::Float);
NodeItem emission = get_input_value("Emission"); NodeItem emission = get_input_value("Emission", NodeItem::Type::Color3);
NodeItem emission_strength = get_input_value("Emission Strength"); NodeItem emission_strength = get_input_value("Emission Strength", NodeItem::Type::Float);
NodeItem alpha = get_input_value("Alpha"); NodeItem alpha = get_input_value("Alpha", NodeItem::Type::Float);
// transparency = 1.0 - alpha // transparency = 1.0 - alpha
NodeItem normal = get_input_link("Normal"); NodeItem normal = get_input_link("Normal");
@ -59,7 +57,7 @@ NodeItem BSDFPrincipledNodeParser::compute_surface()
/* 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, NodeItem::Type::Color3); res.set_input("base_color", base_color);
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);
@ -70,27 +68,27 @@ NodeItem BSDFPrincipledNodeParser::compute_surface()
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, NodeItem::Type::Color3); res.set_input("specular_color", base_color);
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, NodeItem::Type::Color3); res.set_input("transmission_color", base_color);
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, NodeItem::Type::Color3); res.set_input("subsurface_color", subsurface_color);
res.set_input("subsurface_radius", subsurface_radius, NodeItem::Type::Color3); res.set_input("subsurface_radius", subsurface_radius);
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, NodeItem::Type::Color3); res.set_input("sheen_color", base_color);
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, NodeItem::Type::Color3); res.set_input("coat_color", base_color);
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);
@ -100,7 +98,7 @@ NodeItem BSDFPrincipledNodeParser::compute_surface()
} }
res.set_input("emission", emission_strength); res.set_input("emission", emission_strength);
res.set_input("emission_color", emission, NodeItem::Type::Color3); res.set_input("emission_color", emission);
return res; return res;
} }

View File

@ -10,11 +10,11 @@ NodeItem HueSatValNodeParser::compute()
{ {
/* TODO: implement fac, see do_hue_sat_fac in /* TODO: implement fac, see do_hue_sat_fac in
* source\blender\nodes\texture\nodes\node_texture_hueSatVal.cc */ * source\blender\nodes\texture\nodes\node_texture_hueSatVal.cc */
NodeItem hue = get_input_value("Hue"); NodeItem hue = get_input_value("Hue", NodeItem::Type::Float);
NodeItem saturation = get_input_value("Saturation"); NodeItem saturation = get_input_value("Saturation", NodeItem::Type::Float);
NodeItem val = get_input_value("Value"); NodeItem val = get_input_value("Value", NodeItem::Type::Float);
NodeItem fac = get_input_value("Fac"); NodeItem fac = get_input_value("Fac", NodeItem::Type::Float);
NodeItem color = get_input_value("Color"); NodeItem color = get_input_value("Color", NodeItem::Type::Color3);
/* Modifier to follow Cycles result */ /* Modifier to follow Cycles result */
hue = hue - value(0.5f); hue = hue - value(0.5f);
@ -25,7 +25,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, NodeItem::Type::Color3); res.set_input("in", color);
res.set_input("amount", combine); res.set_input("amount", combine);
return res; return res;
} }

View File

@ -8,8 +8,8 @@ namespace blender::nodes::materialx {
NodeItem InvertNodeParser::compute() NodeItem InvertNodeParser::compute()
{ {
NodeItem fac = get_input_value("Fac"); NodeItem fac = get_input_value("Fac", NodeItem::Type::Float);
NodeItem color = get_input_value("Color"); NodeItem color = get_input_value("Color", NodeItem::Type::Color3);
return fac.blend(color, fac.val(1.0f) - color); return fac.blend(color, fac.val(1.0f) - color);
} }

View File

@ -14,7 +14,7 @@ NodeItem MathNodeParser::compute()
NodeItem res = empty(); NodeItem res = empty();
/* Single operand operations */ /* Single operand operations */
NodeItem x = get_input_value(0); NodeItem x = get_input_value(0, NodeItem::Type::Empty);
switch (op) { switch (op) {
case NODE_MATH_SINE: case NODE_MATH_SINE:
res = x.sin(); res = x.sin();
@ -82,7 +82,7 @@ NodeItem MathNodeParser::compute()
default: { default: {
/* 2-operand operations */ /* 2-operand operations */
NodeItem y = get_input_value(1); NodeItem y = get_input_value(1, NodeItem::Type::Empty);
switch (op) { switch (op) {
case NODE_MATH_ADD: case NODE_MATH_ADD:
res = x + y; res = x + y;
@ -132,7 +132,7 @@ NodeItem MathNodeParser::compute()
default: { default: {
/* 3-operand operations */ /* 3-operand operations */
NodeItem z = get_input_value(2); NodeItem z = get_input_value(2, NodeItem::Type::Empty);
switch (op) { switch (op) {
case NODE_MATH_WRAP: case NODE_MATH_WRAP:
CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op); CLOG_WARN(LOG_MATERIALX_SHADER, "Unimplemented math operation %d", op);

View File

@ -629,14 +629,6 @@ void NodeItem::set_input(const std::string &name,
} }
} }
void NodeItem::set_input(const std::string &name,
const NodeItem &item,
Type in_type,
const std::string &output_name)
{
set_input(name, item.convert(in_type), output_name);
}
void NodeItem::add_output(const std::string &name, Type out_type) void NodeItem::add_output(const std::string &name, Type out_type)
{ {
node->addOutput(name, type(out_type)); node->addOutput(name, type(out_type));

View File

@ -102,10 +102,6 @@ class NodeItem {
void set_input(const std::string &in_name, void set_input(const std::string &in_name,
const NodeItem &item, const NodeItem &item,
const std::string &out_name = ""); 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); void add_output(const std::string &in_name, Type out_type);
private: private:

View File

@ -66,14 +66,14 @@ NodeItem NodeParser::get_input_link(int index)
return get_input_link(node_->input_socket(index)); return get_input_link(node_->input_socket(index));
} }
NodeItem NodeParser::get_input_value(const std::string &name) NodeItem NodeParser::get_input_value(const std::string &name, const NodeItem::Type type)
{ {
return get_input_value(node_->input_by_identifier(name)); return get_input_value(node_->input_by_identifier(name), type);
} }
NodeItem NodeParser::get_input_value(int index) NodeItem NodeParser::get_input_value(int index, const NodeItem::Type type)
{ {
return get_input_value(node_->input_socket(index)); return get_input_value(node_->input_socket(index), type);
} }
NodeItem NodeParser::empty() const NodeItem NodeParser::empty() const
@ -170,13 +170,13 @@ NodeItem NodeParser::get_input_link(const bNodeSocket &socket)
return res; return res;
} }
NodeItem NodeParser::get_input_value(const bNodeSocket &socket) NodeItem NodeParser::get_input_value(const bNodeSocket &socket, const NodeItem::Type type)
{ {
NodeItem res = get_input_link(socket); NodeItem res = get_input_link(socket);
if (!res) { if (!res) {
res = get_input_default(socket); res = get_input_default(socket);
} }
return res; return type == NodeItem::Type::Empty ? res : res.convert(type);
} }
ShaderNodeParser::ShaderNodeParser(MaterialX::GraphElement *graph, ShaderNodeParser::ShaderNodeParser(MaterialX::GraphElement *graph,

View File

@ -38,15 +38,17 @@ class NodeParser {
NodeItem get_input_default(int index); NodeItem get_input_default(int index);
NodeItem get_input_link(const std::string &name); NodeItem get_input_link(const std::string &name);
NodeItem get_input_link(int index); NodeItem get_input_link(int index);
NodeItem get_input_value(const std::string &name); NodeItem get_input_value(const std::string &name,
NodeItem get_input_value(int index); const NodeItem::Type type);
NodeItem get_input_value(int index, const NodeItem::Type type);
NodeItem empty() const; NodeItem empty() const;
template<class T> NodeItem value(const T &data) const; template<class T> NodeItem value(const T &data) const;
private: private:
NodeItem get_input_default(const bNodeSocket &socket); NodeItem get_input_default(const bNodeSocket &socket);
NodeItem get_input_link(const bNodeSocket &socket); NodeItem get_input_link(const bNodeSocket &socket);
NodeItem get_input_value(const bNodeSocket &socket); NodeItem get_input_value(const bNodeSocket &socket,
const NodeItem::Type type);
}; };
class ShaderNodeParser : public NodeParser { class ShaderNodeParser : public NodeParser {

View File

@ -11,11 +11,11 @@ NodeItem NormalMapNodeParser::compute()
{ {
std::string default_space = "object"; std::string default_space = "object";
NodeShaderNormalMap *normal_map_node = static_cast<NodeShaderNormalMap *>(node_->storage); NodeShaderNormalMap *normal_map_node = static_cast<NodeShaderNormalMap *>(node_->storage);
NodeItem color = get_input_value("Color"); NodeItem color = get_input_value("Color", NodeItem::Type::Color3);
NodeItem strength = get_input_value("Strength"); NodeItem strength = get_input_value("Strength", NodeItem::Type::Float);
NodeItem res = create_node("normalmap", "vector3"); NodeItem res = create_node("normalmap", "vector3");
res.set_input("in", color, NodeItem::Type::Color3); res.set_input("in", color);
res.set_input("scale", strength); res.set_input("scale", strength);
switch (normal_map_node->space) { switch (normal_map_node->space) {

View File

@ -10,7 +10,7 @@ namespace blender::nodes::materialx {
NodeItem SeparateColorNodeParser::compute() NodeItem SeparateColorNodeParser::compute()
{ {
int mode = static_cast<NodeCombSepColor *>(node_->storage)->mode; int mode = static_cast<NodeCombSepColor *>(node_->storage)->mode;
NodeItem color = get_input_value("Color"); NodeItem color = get_input_value("Color", NodeItem::Type::Color3);
NodeItem convert = empty(); NodeItem convert = empty();
@ -39,9 +39,9 @@ NodeItem SeparateColorNodeParser::compute()
NodeItem CombineColorNodeParser::compute() NodeItem CombineColorNodeParser::compute()
{ {
int mode = static_cast<NodeCombSepColor *>(node_->storage)->mode; int mode = static_cast<NodeCombSepColor *>(node_->storage)->mode;
NodeItem red = get_input_value("Red"); NodeItem red = get_input_value("Red", NodeItem::Type::Float);
NodeItem green = get_input_value("Green"); NodeItem green = get_input_value("Green", NodeItem::Type::Float);
NodeItem blue = get_input_value("Blue"); NodeItem blue = get_input_value("Blue", NodeItem::Type::Float);
NodeItem convert = empty(); NodeItem convert = empty();
NodeItem combine = create_node("combine3", "color3"); NodeItem combine = create_node("combine3", "color3");

View File

@ -8,16 +8,16 @@ namespace blender::nodes::materialx {
NodeItem SeparateXYZNodeParser::compute() NodeItem SeparateXYZNodeParser::compute()
{ {
NodeItem vector = get_input_value("Vector"); NodeItem vector = get_input_value("Vector", NodeItem::Type::Vector3);
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.extract(index); return vector.extract(index);
} }
NodeItem CombineXYZNodeParser::compute() NodeItem CombineXYZNodeParser::compute()
{ {
NodeItem x = get_input_value("X"); NodeItem x = get_input_value("X", NodeItem::Type::Float);
NodeItem y = get_input_value("Y"); NodeItem y = get_input_value("Y", NodeItem::Type::Float);
NodeItem z = get_input_value("Z"); NodeItem z = get_input_value("Z", NodeItem::Type::Float);
NodeItem res = create_node("combine3", "vector3"); NodeItem res = create_node("combine3", "vector3");
res.set_input("in1", x); res.set_input("in1", x);
res.set_input("in2", y); res.set_input("in2", y);

View File

@ -9,9 +9,9 @@ namespace blender::nodes::materialx {
NodeItem TexCheckerNodeParser::compute() NodeItem TexCheckerNodeParser::compute()
{ {
NodeItem vector = get_input_link("Vector"); NodeItem vector = get_input_link("Vector");
NodeItem color1 = get_input_value("Color1"); NodeItem color1 = get_input_value("Color1", NodeItem::Type::Color3);
NodeItem color2 = get_input_value("Color2"); NodeItem color2 = get_input_value("Color2", NodeItem::Type::Color3);
NodeItem scale = get_input_value("Scale"); NodeItem scale = get_input_value("Scale", NodeItem::Type::Float);
if (!vector) { if (!vector) {
vector = create_node("texcoord", "vector2"); vector = create_node("texcoord", "vector2");

View File

@ -8,9 +8,9 @@ namespace blender::nodes::materialx {
NodeItem TexNoiseNodeParser::compute() NodeItem TexNoiseNodeParser::compute()
{ {
NodeItem scale = get_input_value("Scale"); NodeItem scale = get_input_value("Scale", NodeItem::Type::Float);
NodeItem detail = get_input_value("Detail"); NodeItem detail = get_input_value("Detail", NodeItem::Type::Float);
NodeItem lacunarity = get_input_value("Lacunarity"); NodeItem lacunarity = get_input_value("Lacunarity", NodeItem::Type::Float);
if (detail.value && detail.type() == NodeItem::Type::Float) { if (detail.value && detail.type() == NodeItem::Type::Float) {
detail = value(int(detail.value->asA<float>())); detail = value(int(detail.value->asA<float>()));
@ -20,7 +20,7 @@ NodeItem TexNoiseNodeParser::compute()
position = position * scale; position = position * scale;
NodeItem res = create_node("fractal3d", "color3"); NodeItem res = create_node("fractal3d", "color3");
res.set_input("position", position, NodeItem::Type::Vector3); res.set_input("position", position);
res.set_input("octaves", detail); res.set_input("octaves", detail);
res.set_input("lacunarity", lacunarity); res.set_input("lacunarity", lacunarity);
return res; return res;

View File

@ -14,7 +14,7 @@ NodeItem VectorMathNodeParser::compute()
NodeItem res = empty(); NodeItem res = empty();
/* Single operand operations */ /* Single operand operations */
NodeItem x = get_input_value(0); NodeItem x = get_input_value(0, NodeItem::Type::Empty);
switch (op) { switch (op) {
case NODE_VECTOR_MATH_SINE: case NODE_VECTOR_MATH_SINE:
res = x.sin(); res = x.sin();
@ -46,7 +46,7 @@ NodeItem VectorMathNodeParser::compute()
default: { default: {
/* 2-operand operations */ /* 2-operand operations */
NodeItem y = get_input_value(1); NodeItem y = get_input_value(1, NodeItem::Type::Empty);
switch (op) { switch (op) {
case NODE_VECTOR_MATH_ADD: case NODE_VECTOR_MATH_ADD:
res = x + y; res = x + y;
@ -93,7 +93,7 @@ NodeItem VectorMathNodeParser::compute()
default: { default: {
/* 3-operand operations */ /* 3-operand operations */
NodeItem z = get_input_value(2); NodeItem z = get_input_value(2, NodeItem::Type::Empty);
switch (op) { switch (op) {
case NODE_VECTOR_MATH_MULTIPLY_ADD: case NODE_VECTOR_MATH_MULTIPLY_ADD:
res = x * y + z; res = x * y + z;