Move the MaterialX export code into the existing shader node files #18

Merged
Bogdan Nagirniak merged 14 commits from BogdanNagirniak/blender:matx-move-code into matx-export-material 2023-09-12 13:55:27 +02:00
11 changed files with 58 additions and 118 deletions
Showing only changes of commit b431e57174 - Show all commits

View File

@ -9,11 +9,11 @@ namespace blender::nodes::materialx {
NodeItem AddShaderNodeParser::compute() NodeItem AddShaderNodeParser::compute()
{ {
NodeItem res = empty(); NodeItem res = empty();
switch (shader_type_) { switch (to_type_) {
case NodeItem::Type::BSDF: case NodeItem::Type::BSDF:
case NodeItem::Type::EDF: { case NodeItem::Type::EDF: {
NodeItem shader1 = get_input_shader(0, shader_type_); NodeItem shader1 = get_input_shader(0, to_type_);
NodeItem shader2 = get_input_shader(1, shader_type_); NodeItem shader2 = get_input_shader(1, to_type_);
if (shader1 && !shader2) { if (shader1 && !shader2) {
res = shader1; res = shader1;
@ -27,9 +27,9 @@ NodeItem AddShaderNodeParser::compute()
break; break;
} }
case NodeItem::Type::SurfaceShader: { case NodeItem::Type::SurfaceShader: {
res = get_input_shader(0, shader_type_); res = get_input_shader(0, to_type_);
if (!res) { if (!res) {
res = get_input_shader(1, shader_type_); res = get_input_shader(1, to_type_);
} }
break; break;
} }

View File

@ -8,7 +8,7 @@ namespace blender::nodes::materialx {
NodeItem BSDFDiffuseNodeParser::compute() NodeItem BSDFDiffuseNodeParser::compute()
{ {
if (shader_type_ != NodeItem::Type::BSDF) { if (to_type_ != NodeItem::Type::BSDF) {
return empty(); return empty();
} }

View File

@ -8,7 +8,7 @@ namespace blender::nodes::materialx {
NodeItem BSDFPrincipledNodeParser::compute() NodeItem BSDFPrincipledNodeParser::compute()
{ {
if (shader_type_ != NodeItem::Type::SurfaceShader) { if (to_type_ != NodeItem::Type::SurfaceShader) {
/* TODO: implement for BSDF and EDF */ /* TODO: implement for BSDF and EDF */
return empty(); return empty();
} }

View File

@ -8,7 +8,7 @@ namespace blender::nodes::materialx {
NodeItem EmissionNodeParser::compute() NodeItem EmissionNodeParser::compute()
{ {
if (shader_type_ != NodeItem::Type::EDF) { if (to_type_ != NodeItem::Type::EDF) {
return empty(); return empty();
} }

View File

@ -9,12 +9,12 @@ namespace blender::nodes::materialx {
NodeItem MixShaderNodeParser::compute() NodeItem MixShaderNodeParser::compute()
{ {
NodeItem res = empty(); NodeItem res = empty();
switch (shader_type_) { switch (to_type_) {
case NodeItem::Type::BSDF: case NodeItem::Type::BSDF:
case NodeItem::Type::EDF: { case NodeItem::Type::EDF: {
NodeItem fac = get_input_value(0, NodeItem::Type::Float); NodeItem fac = get_input_value(0, NodeItem::Type::Float);
NodeItem shader1 = get_input_shader(1, shader_type_); NodeItem shader1 = get_input_shader(1, to_type_);
NodeItem shader2 = get_input_shader(2, shader_type_); NodeItem shader2 = get_input_shader(2, to_type_);
if (shader1 && !shader2) { if (shader1 && !shader2) {
res = shader1 * (val(1.0f) - fac); res = shader1 * (val(1.0f) - fac);
@ -23,7 +23,7 @@ NodeItem MixShaderNodeParser::compute()
res = shader2 * fac; res = shader2 * fac;
} }
else if (shader1 && shader2) { else if (shader1 && shader2) {
res = create_node("mix", shader_type_); res = create_node("mix", to_type_);
res.set_input("fg", shader1); res.set_input("fg", shader1);
res.set_input("bg", shader2); res.set_input("bg", shader2);
res.set_input("mix", fac); res.set_input("mix", fac);

View File

@ -50,6 +50,7 @@ class NodeItem {
static Type type(const std::string &type_str); static Type type(const std::string &type_str);
static std::string type(Type type); static std::string type(Type type);
static bool is_arithmetic(Type type);
/* Operators */ /* Operators */
operator bool() const; operator bool() const;
@ -109,7 +110,6 @@ class NodeItem {
void add_output(const std::string &in_name, Type out_type); void add_output(const std::string &in_name, Type out_type);
private: private:
static bool is_arithmetic(Type type);
static Type cast_types(NodeItem &item1, NodeItem &item2); static Type cast_types(NodeItem &item1, NodeItem &item2);
bool is_arithmetic() const; bool is_arithmetic() const;

View File

@ -16,28 +16,40 @@ 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,
NodeItem::Type shader_type) NodeItem::Type to_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_type_(shader_type) to_type_(to_type)
{ {
} }
NodeItem NodeParser::compute_full() NodeItem NodeParser::compute_full()
{ {
NodeItem res = empty();
/* Checking if node was already computed */
res.node = graph_->getNode(node_name());
if (res.node) {
return res;
}
CLOG_INFO(LOG_MATERIALX_SHADER, CLOG_INFO(LOG_MATERIALX_SHADER,
1, 1,
"%s [%d] %s", "%s [%d] - %s",
node_->name, node_->name,
node_->typeinfo->type, node_->typeinfo->type,
NodeItem::type(shader_type_).c_str()); NodeItem::type(to_type_).c_str());
NodeItem res = compute();
res = compute();
if (res.node) { if (res.node) {
res.node->setName(node_name()); res.node->setName(node_name());
} }
if (NodeItem::is_arithmetic(to_type_)) {
res = res.convert(to_type_);
}
return res; return res;
} }
@ -47,8 +59,8 @@ std::string NodeParser::node_name()
if (node_->output_sockets().size() > 1) { if (node_->output_sockets().size() > 1) {
name += std::string("_") + socket_out_->name; name += std::string("_") + socket_out_->name;
} }
if (ELEM(shader_type_, NodeItem::Type::BSDF, NodeItem::Type::EDF)) { if (ELEM(to_type_, NodeItem::Type::BSDF, NodeItem::Type::EDF)) {
name += "_" + NodeItem::type(shader_type_); name += "_" + NodeItem::type(to_type_);
} }
return MaterialX::createValidName(name); return MaterialX::createValidName(name);
} }
@ -158,7 +170,7 @@ NodeItem NodeParser::get_input_link(const bNodeSocket &socket, NodeItem::Type to
#define CASE_NODE_TYPE(type, T) \ #define CASE_NODE_TYPE(type, T) \
case type: \ case type: \
parser = std::make_unique<T>( \ parser = std::make_unique<T>( \
graph_, depsgraph_, material_, from_node, link->fromsock, NodeItem::Type::Any); \ graph_, depsgraph_, material_, from_node, link->fromsock, to_type); \
break; break;
switch (from_node->typeinfo->type) { switch (from_node->typeinfo->type) {
@ -189,6 +201,20 @@ NodeItem NodeParser::get_input_link(const bNodeSocket &socket, NodeItem::Type to
CASE_NODE_TYPE(SH_NODE_VECTOR_MATH, VectorMathNodeParser) CASE_NODE_TYPE(SH_NODE_VECTOR_MATH, VectorMathNodeParser)
CASE_NODE_TYPE(SH_NODE_WAVELENGTH, WavelengthNodeParser) CASE_NODE_TYPE(SH_NODE_WAVELENGTH, WavelengthNodeParser)
CASE_NODE_TYPE(SH_NODE_ADD_SHADER, AddShaderNodeParser)
CASE_NODE_TYPE(SH_NODE_BSDF_DIFFUSE, BSDFDiffuseNodeParser)
// CASE_SHADER_NODE_TYPE(SH_NODE_BSDF_GLASS, BSDFGlassNodeParser)
// CASE_SHADER_NODE_TYPE(SH_NODE_BSDF_GLOSSY, BSDFGlossyNodeParser)
CASE_NODE_TYPE(SH_NODE_BSDF_PRINCIPLED, BSDFPrincipledNodeParser)
// CASE_SHADER_NODE_TYPE(SH_NODE_BSDF_REFRACTION, BSDFRefractionNodeParser)
// CASE_SHADER_NODE_TYPE(SH_NODE_BSDF_SHEEN, BSDFSheenNodeParser)
// CASE_SHADER_NODE_TYPE(SH_NODE_BSDF_TOON, BSDFToonNodeParser)
// CASE_SHADER_NODE_TYPE(SH_NODE_BSDF_TRANSLUCENT, BSDFTranslucentNodeParser)
// CASE_SHADER_NODE_TYPE(SH_NODE_BSDF_TRANSPARENT, BSDFTransparentNodeParser)
CASE_NODE_TYPE(SH_NODE_EMISSION, EmissionNodeParser)
CASE_NODE_TYPE(SH_NODE_MIX_SHADER, MixShaderNodeParser)
// CASE_SHADER_NODE_TYPE(SH_NODE_SUBSURFACE_SCATTERING, SubsurfaceScatteringNodeParser)
default: default:
CLOG_WARN(LOG_MATERIALX_SHADER, CLOG_WARN(LOG_MATERIALX_SHADER,
"Unsupported node: %s [%d]", "Unsupported node: %s [%d]",
@ -199,15 +225,9 @@ NodeItem NodeParser::get_input_link(const bNodeSocket &socket, NodeItem::Type to
return res; return res;
} }
/* Checking if node was already computed */
res.node = graph_->getNode(parser->node_name());
if (res.node) {
return res;
}
/* Computing */ /* Computing */
res = parser->compute_full(); res = parser->compute_full();
return res.convert(to_type); return res;
} }
NodeItem NodeParser::get_input_value(const bNodeSocket &socket, NodeItem::Type to_type) NodeItem NodeParser::get_input_value(const bNodeSocket &socket, NodeItem::Type to_type)
@ -221,77 +241,12 @@ NodeItem NodeParser::get_input_value(const bNodeSocket &socket, NodeItem::Type t
NodeItem NodeParser::get_input_shader(const std::string &name, NodeItem::Type shader_type) NodeItem NodeParser::get_input_shader(const std::string &name, NodeItem::Type shader_type)
{ {
return get_input_shader(node_->input_by_identifier(name), shader_type); return get_input_link(node_->input_by_identifier(name), shader_type);
} }
NodeItem NodeParser::get_input_shader(int index, NodeItem::Type shader_type) NodeItem NodeParser::get_input_shader(int index, NodeItem::Type shader_type)
{ {
return get_input_shader(node_->input_socket(index), shader_type); return get_input_link(node_->input_socket(index), shader_type);
}
NodeItem NodeParser::get_input_shader(const bNodeSocket &socket, NodeItem::Type shader_type)
{
NodeItem res = empty();
const bNodeLink *link = socket.link;
if (!(link && link->is_used())) {
return res;
}
const bNode *from_node = link->fromnode;
/* Passing NODE_REROUTE nodes */
while (from_node->type == NODE_REROUTE) {
link = from_node->input_socket(0).link;
if (!(link && link->is_used())) {
return res;
}
from_node = link->fromnode;
}
/* Creating required ShaderNodeParser object */
std::unique_ptr<NodeParser> parser;
#define CASE_SHADER_NODE_TYPE(type, T) \
case type: \
parser = std::make_unique<T>( \
graph_, depsgraph_, material_, from_node, link->fromsock, shader_type); \
break;
switch (from_node->typeinfo->type) {
CASE_SHADER_NODE_TYPE(SH_NODE_ADD_SHADER, AddShaderNodeParser)
CASE_SHADER_NODE_TYPE(SH_NODE_BSDF_DIFFUSE, BSDFDiffuseNodeParser)
// CASE_SHADER_NODE_TYPE(SH_NODE_BSDF_GLASS, BSDFGlassNodeParser)
// CASE_SHADER_NODE_TYPE(SH_NODE_BSDF_GLOSSY, BSDFGlossyNodeParser)
CASE_SHADER_NODE_TYPE(SH_NODE_BSDF_PRINCIPLED, BSDFPrincipledNodeParser)
// CASE_SHADER_NODE_TYPE(SH_NODE_BSDF_REFRACTION, BSDFRefractionNodeParser)
// CASE_SHADER_NODE_TYPE(SH_NODE_BSDF_SHEEN, BSDFSheenNodeParser)
// CASE_SHADER_NODE_TYPE(SH_NODE_BSDF_TOON, BSDFToonNodeParser)
// CASE_SHADER_NODE_TYPE(SH_NODE_BSDF_TRANSLUCENT, BSDFTranslucentNodeParser)
// CASE_SHADER_NODE_TYPE(SH_NODE_BSDF_TRANSPARENT, BSDFTransparentNodeParser)
CASE_SHADER_NODE_TYPE(SH_NODE_EMISSION, EmissionNodeParser)
CASE_SHADER_NODE_TYPE(SH_NODE_MIX_SHADER, MixShaderNodeParser)
// CASE_SHADER_NODE_TYPE(SH_NODE_SUBSURFACE_SCATTERING, SubsurfaceScatteringNodeParser)
default:
CLOG_WARN(LOG_MATERIALX_SHADER,
"Unsupported node: %s [%d]",
from_node->name,
from_node->typeinfo->type);
}
if (!parser) {
return res;
}
/* Checking if node was already computed */
res.node = graph_->getNode(parser->node_name());
if (res.node) {
return res;
}
/* Computing */
res = parser->compute_full();
return res;
} }
} // namespace blender::nodes::materialx } // namespace blender::nodes::materialx

View File

@ -19,7 +19,7 @@ class NodeParser {
const Material *material_; const Material *material_;
const bNode *node_; const bNode *node_;
const bNodeSocket *socket_out_; const bNodeSocket *socket_out_;
NodeItem::Type shader_type_; NodeItem::Type to_type_;
public: public:
NodeParser(MaterialX::GraphElement *graph, NodeParser(MaterialX::GraphElement *graph,
@ -31,10 +31,10 @@ class NodeParser {
virtual ~NodeParser() = default; virtual ~NodeParser() = default;
virtual NodeItem compute() = 0; virtual NodeItem compute() = 0;
virtual NodeItem compute_full();
protected: protected:
virtual NodeItem compute_full(); std::string node_name();
virtual std::string node_name();
NodeItem create_node(const std::string &category, NodeItem::Type type); NodeItem create_node(const std::string &category, NodeItem::Type type);
NodeItem get_input_default(const std::string &name, NodeItem::Type to_type); NodeItem get_input_default(const std::string &name, NodeItem::Type to_type);
NodeItem get_input_default(int index, NodeItem::Type to_type); NodeItem get_input_default(int index, NodeItem::Type to_type);
@ -52,7 +52,6 @@ class NodeParser {
NodeItem get_input_default(const bNodeSocket &socket, NodeItem::Type to_type); NodeItem get_input_default(const bNodeSocket &socket, NodeItem::Type to_type);
NodeItem get_input_link(const bNodeSocket &socket, NodeItem::Type to_type); NodeItem get_input_link(const bNodeSocket &socket, NodeItem::Type to_type);
NodeItem get_input_value(const bNodeSocket &socket, NodeItem::Type to_type); NodeItem get_input_value(const bNodeSocket &socket, NodeItem::Type to_type);
NodeItem get_input_shader(const bNodeSocket &socket, NodeItem::Type shader_type);
}; };
template<class T> NodeItem NodeParser::val(const T &data) const template<class T> NodeItem NodeParser::val(const T &data) const
@ -67,13 +66,6 @@ template<class T> NodeItem NodeParser::val(const T &data) const
NodeItem compute() override; \ NodeItem compute() override; \
}; };
#define DECLARE_SHADER_NODE_PARSER(T) \
class T : public ShaderNodeParser { \
public: \
using ShaderNodeParser::ShaderNodeParser; \
NodeItem compute() override; \
};
DECLARE_NODE_PARSER(BlackbodyNodeParser) DECLARE_NODE_PARSER(BlackbodyNodeParser)
DECLARE_NODE_PARSER(BrightContrastNodeParser) DECLARE_NODE_PARSER(BrightContrastNodeParser)
DECLARE_NODE_PARSER(ClampNodeParser) DECLARE_NODE_PARSER(ClampNodeParser)
@ -129,7 +121,8 @@ void node_shader_materialx(void *data, struct bNode *node, struct bNodeSocket *o
{ {
materialx::NodeParserData *d = reinterpret_cast<materialx::NodeParserData *>(data); materialx::NodeParserData *d = reinterpret_cast<materialx::NodeParserData *>(data);
T parser(d->graph, d->depsgraph, d->material, node, out, d->shader_type); T parser(d->graph, d->depsgraph, d->material, node, out, d->shader_type);
d->result = parser.compute();
d->result = parser.compute_full();
} }
#define NODE_SHADER_MATERIALX_BEGIN \ #define NODE_SHADER_MATERIALX_BEGIN \

View File

@ -62,9 +62,4 @@ NodeItem OutputMaterialNodeParser::compute_default()
return res; return res;
} }
std::string OutputMaterialNodeParser::node_name()
{
return NodeParser::node_name();
}
} // namespace blender::nodes::materialx } // namespace blender::nodes::materialx

View File

@ -18,9 +18,6 @@ class OutputMaterialNodeParser : public NodeParser {
using NodeParser::compute_full; using NodeParser::compute_full;
NodeItem compute_default(); NodeItem compute_default();
protected:
std::string node_name() override;
}; };
} // namespace blender::nodes::materialx } // namespace blender::nodes::materialx

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::Type::Any); NodeItem x = get_input_value(0, NodeItem::Type::Vector3);
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::Type::Any); NodeItem y = get_input_value(1, NodeItem::Type::Vector3);
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::Type::Any); NodeItem z = get_input_value(2, NodeItem::Type::Vector3);
switch (op) { switch (op) {
case NODE_VECTOR_MATH_MULTIPLY_ADD: case NODE_VECTOR_MATH_MULTIPLY_ADD:
res = x * y + z; res = x * y + z;