forked from blender/blender
MaterialX: add support for nodes #11
@ -165,6 +165,7 @@ if(WITH_MATERIALX)
|
|||||||
materialx/material.h
|
materialx/material.h
|
||||||
materialx/nodes/node_item.h
|
materialx/nodes/node_item.h
|
||||||
materialx/nodes/node_parser.h
|
materialx/nodes/node_parser.h
|
||||||
|
materialx/nodes/output_material.h
|
||||||
)
|
)
|
||||||
list(APPEND LIB
|
list(APPEND LIB
|
||||||
MaterialXCore
|
MaterialXCore
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||||
|
|
||||||
#include "material.h"
|
#include "material.h"
|
||||||
#include "nodes/node_parser.h"
|
#include "nodes/output_material.h"
|
||||||
|
|
||||||
#include <MaterialXFormat/XmlIo.h>
|
#include <MaterialXFormat/XmlIo.h>
|
||||||
|
|
||||||
@ -17,43 +17,27 @@ namespace blender::nodes::materialx {
|
|||||||
|
|
||||||
CLG_LOGREF_DECLARE_GLOBAL(LOG_MATERIALX_SHADER, "materialx.shader");
|
CLG_LOGREF_DECLARE_GLOBAL(LOG_MATERIALX_SHADER, "materialx.shader");
|
||||||
|
|
||||||
static void export_nodegraph(MaterialX::GraphElement *graph,
|
MaterialX::DocumentPtr export_to_materialx(Depsgraph *depsgraph,
|
||||||
Depsgraph *depsgraph,
|
Material *material,
|
||||||
Material *material)
|
const std::string &socket_name)
|
||||||
{
|
{
|
||||||
material->nodetree->ensure_topology_cache();
|
CLOG_INFO(LOG_MATERIALX_SHADER, 0, "Material: %s", material->id.name);
|
||||||
|
|
||||||
bNode *output_node = ntreeShaderOutputNode(material->nodetree, SHD_OUTPUT_ALL);
|
|
||||||
OutputMaterialNodeParser parser(graph, depsgraph, material, output_node);
|
|
||||||
parser.compute();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void create_standard_surface(MaterialX::GraphElement *graph, Material *material)
|
|
||||||
{
|
|
||||||
MaterialX::NodePtr standard_surface = graph->addNode(
|
|
||||||
"standard_surface", MaterialX::EMPTY_STRING, "surfaceshader");
|
|
||||||
|
|
||||||
standard_surface->addInput("base", "float")->setValue(1.0);
|
|
||||||
standard_surface->addInput("base_color", "color3")
|
|
||||||
->setValue(MaterialX::Color3(material->r, material->g, material->b));
|
|
||||||
|
|
||||||
MaterialX::NodePtr surfacematerial = graph->addNode(
|
|
||||||
"surfacematerial", MaterialX::EMPTY_STRING, "material");
|
|
||||||
surfacematerial->addInput(standard_surface->getType(), standard_surface->getType())
|
|
||||||
->setNodeName(standard_surface->getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
MaterialX::DocumentPtr export_to_materialx(Depsgraph *depsgraph, Material *material)
|
|
||||||
{
|
|
||||||
MaterialX::DocumentPtr doc = MaterialX::createDocument();
|
MaterialX::DocumentPtr doc = MaterialX::createDocument();
|
||||||
if (material->use_nodes) {
|
if (material->use_nodes) {
|
||||||
export_nodegraph(doc.get(), depsgraph, material);
|
material->nodetree->ensure_topology_cache();
|
||||||
|
bNode *output_node = ntreeShaderOutputNode(material->nodetree, SHD_OUTPUT_ALL);
|
||||||
|
OutputMaterialNodeParser(doc.get(), depsgraph, material, output_node).compute(socket_name);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
create_standard_surface(doc.get(), material);
|
OutputMaterialNodeParser(doc.get(), depsgraph, material, nullptr).compute_default();
|
||||||
}
|
}
|
||||||
std::string str = MaterialX::writeToXmlString(doc);
|
|
||||||
CLOG_INFO(LOG_MATERIALX_SHADER, 1, "Material: %s\n%s", material->id.name, str.c_str());
|
CLOG_INFO(LOG_MATERIALX_SHADER,
|
||||||
|
2,
|
||||||
|
"Material: %s\n%s",
|
||||||
|
material->id.name,
|
||||||
|
MaterialX::writeToXmlString(doc).c_str());
|
||||||
return doc;
|
return doc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,6 +15,8 @@ namespace blender::nodes::materialx {
|
|||||||
|
|
||||||
extern struct CLG_LogRef *LOG_MATERIALX_SHADER;
|
extern struct CLG_LogRef *LOG_MATERIALX_SHADER;
|
||||||
|
|
||||||
MaterialX::DocumentPtr export_to_materialx(Depsgraph *depsgraph, Material *material);
|
MaterialX::DocumentPtr export_to_materialx(Depsgraph *depsgraph,
|
||||||
|
Material *material,
|
||||||
|
const std::string &socket_name = "Surface");
|
||||||
|
|
||||||
} // namespace blender::nodes::materialx
|
} // namespace blender::nodes::materialx
|
||||||
|
@ -68,7 +68,7 @@ NodeItem BSDFPrincipledNodeParser::compute()
|
|||||||
NodeItem tangent = get_input_link("Tangent");
|
NodeItem tangent = get_input_link("Tangent");
|
||||||
|
|
||||||
/* Creating standard_surface */
|
/* Creating standard_surface */
|
||||||
NodeItem res = create_node("standard_surface", "surfaceshader", false);
|
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.to_color3());
|
||||||
res.set_input("diffuse_roughness", roughness);
|
res.set_input("diffuse_roughness", roughness);
|
||||||
@ -90,9 +90,11 @@ NodeItem BSDFPrincipledNodeParser::compute()
|
|||||||
res.set_input("specular_IOR", ior);
|
res.set_input("specular_IOR", ior);
|
||||||
if (anisotropic) {
|
if (anisotropic) {
|
||||||
res.set_input("specular_anisotropy", anisotropic);
|
res.set_input("specular_anisotropy", anisotropic);
|
||||||
|
if (anisotropic_rotation) {
|
||||||
res.set_input("specular_rotation", anisotropic_rotation);
|
res.set_input("specular_rotation", anisotropic_rotation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (transmission != zero) {
|
if (transmission != zero) {
|
||||||
res.set_input("transmission", transmission);
|
res.set_input("transmission", transmission);
|
||||||
|
@ -23,7 +23,7 @@ NodeItem HueSatValNodeParser::compute()
|
|||||||
combine.set_input("in2", saturation);
|
combine.set_input("in2", saturation);
|
||||||
combine.set_input("in3", val);
|
combine.set_input("in3", val);
|
||||||
|
|
||||||
NodeItem res = create_node("hsvadjust", "color3", false);
|
NodeItem res = create_node("hsvadjust", "color3");
|
||||||
res.set_input("in", color.to_color3());
|
res.set_input("in", color.to_color3());
|
||||||
res.set_input("amount", combine);
|
res.set_input("amount", combine);
|
||||||
return res;
|
return res;
|
||||||
|
@ -10,7 +10,7 @@ namespace blender::nodes::materialx {
|
|||||||
NodeItem MathNodeParser::compute()
|
NodeItem MathNodeParser::compute()
|
||||||
{
|
{
|
||||||
/* TODO: finish some math operations */
|
/* TODO: finish some math operations */
|
||||||
auto op = node->custom1;
|
auto op = node_->custom1;
|
||||||
NodeItem res = empty();
|
NodeItem res = empty();
|
||||||
|
|
||||||
/* Single operand operations */
|
/* Single operand operations */
|
||||||
@ -158,7 +158,7 @@ NodeItem MathNodeParser::compute()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool clamp_output = node->custom2 != 0;
|
bool clamp_output = node_->custom2 != 0;
|
||||||
if (clamp_output && res) {
|
if (clamp_output && res) {
|
||||||
res = res.clamp();
|
res = res.clamp();
|
||||||
}
|
}
|
||||||
|
@ -12,56 +12,59 @@ namespace blender::nodes::materialx {
|
|||||||
NodeParser::NodeParser(MaterialX::GraphElement *graph,
|
NodeParser::NodeParser(MaterialX::GraphElement *graph,
|
||||||
const Depsgraph *depsgraph,
|
const Depsgraph *depsgraph,
|
||||||
const Material *material,
|
const Material *material,
|
||||||
const bNode *node)
|
const bNode *node,
|
||||||
: graph(graph), depsgraph(depsgraph), material(material), node(node)
|
const bNodeSocket *socket_out)
|
||||||
|
: graph_(graph), depsgraph_(depsgraph), material_(material), node_(node), socket_out_(socket_out)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeItem NodeParser::create_node(const std::string &mx_category,
|
std::string NodeParser::node_name(const bNode *node, const bNodeSocket *socket_out)
|
||||||
const std::string &mx_type,
|
{
|
||||||
bool noname)
|
return MaterialX::createValidName(node->output_sockets().size() <= 1 ?
|
||||||
|
std::string(node->name) :
|
||||||
|
std::string(node->name) + "_" + socket_out->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeItem NodeParser::create_node(const std::string &mx_category, const std::string &mx_type)
|
||||||
{
|
{
|
||||||
NodeItem res = empty();
|
NodeItem res = empty();
|
||||||
res.node = graph->addNode(mx_category,
|
res.node = graph_->addNode(mx_category, MaterialX::EMPTY_STRING, mx_type);
|
||||||
noname ? MaterialX::EMPTY_STRING :
|
|
||||||
MaterialX::createValidName(node->name),
|
|
||||||
mx_type);
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeItem NodeParser::get_input_default(const std::string &name)
|
NodeItem NodeParser::get_input_default(const std::string &name)
|
||||||
{
|
{
|
||||||
return get_input_default(node->input_by_identifier(name));
|
return get_input_default(node_->input_by_identifier(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeItem NodeParser::get_input_default(int index)
|
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)
|
NodeItem NodeParser::get_input_link(const std::string &name)
|
||||||
{
|
{
|
||||||
return get_input_link(node->input_by_identifier(name));
|
return get_input_link(node_->input_by_identifier(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeItem NodeParser::get_input_link(int index)
|
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)
|
||||||
{
|
{
|
||||||
return get_input_value(node->input_by_identifier(name));
|
return get_input_value(node_->input_by_identifier(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeItem NodeParser::get_input_value(int index)
|
NodeItem NodeParser::get_input_value(int index)
|
||||||
{
|
{
|
||||||
return get_input_value(node->input_socket(index));
|
return get_input_value(node_->input_socket(index));
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeItem NodeParser::empty() const
|
NodeItem NodeParser::empty() const
|
||||||
{
|
{
|
||||||
return NodeItem(graph);
|
return NodeItem(graph_);
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeItem NodeParser::get_input_default(const bNodeSocket &socket)
|
NodeItem NodeParser::get_input_default(const bNodeSocket &socket)
|
||||||
@ -98,59 +101,49 @@ NodeItem NodeParser::get_input_link(const bNodeSocket &socket)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
const bNode *in_node = link->fromnode;
|
const bNode *from_node = link->fromnode;
|
||||||
|
|
||||||
/* Passing NODE_REROUTE nodes */
|
/* Passing NODE_REROUTE nodes */
|
||||||
while (in_node->type == NODE_REROUTE) {
|
while (from_node->type == NODE_REROUTE) {
|
||||||
link = in_node->input_socket(0).link;
|
link = from_node->input_socket(0).link;
|
||||||
if (!(link && link->is_used())) {
|
if (!(link && link->is_used())) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
in_node = link->fromnode;
|
from_node = link->fromnode;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Getting required NodeParser object */
|
/* Checking if node was already computed */
|
||||||
std::unique_ptr<NodeParser> parser;
|
res.node = graph_->getNode(node_name(from_node, link->fromsock));
|
||||||
switch (in_node->typeinfo->type) {
|
if (res.node) {
|
||||||
case SH_NODE_BSDF_PRINCIPLED:
|
|
||||||
parser = std::make_unique<BSDFPrincipledNodeParser>(graph, depsgraph, material, in_node);
|
|
||||||
break;
|
|
||||||
case SH_NODE_INVERT:
|
|
||||||
parser = std::make_unique<InvertNodeParser>(graph, depsgraph, material, in_node);
|
|
||||||
break;
|
|
||||||
case SH_NODE_HUE_SAT:
|
|
||||||
parser = std::make_unique<HueSatValNodeParser>(graph, depsgraph, material, in_node);
|
|
||||||
break;
|
|
||||||
case SH_NODE_MATH:
|
|
||||||
parser = std::make_unique<MathNodeParser>(graph, depsgraph, material, in_node);
|
|
||||||
break;
|
|
||||||
case SH_NODE_MIX_RGB_LEGACY:
|
|
||||||
parser = std::make_unique<MixRGBNodeParser>(graph, depsgraph, material, in_node);
|
|
||||||
break;
|
|
||||||
case SH_NODE_NORMAL_MAP:
|
|
||||||
parser = std::make_unique<NormalMapNodeParser>(graph, depsgraph, material, in_node);
|
|
||||||
break;
|
|
||||||
case SH_NODE_TEX_IMAGE:
|
|
||||||
parser = std::make_unique<TexImageNodeParser>(graph, depsgraph, material, in_node);
|
|
||||||
break;
|
|
||||||
case SH_NODE_TEX_ENVIRONMENT:
|
|
||||||
parser = std::make_unique<TexEnvironmentNodeParser>(graph, depsgraph, material, in_node);
|
|
||||||
break;
|
|
||||||
case SH_NODE_TEX_NOISE:
|
|
||||||
parser = std::make_unique<TexNoiseNodeParser>(graph, depsgraph, material, in_node);
|
|
||||||
break;
|
|
||||||
case SH_NODE_TEX_CHECKER:
|
|
||||||
parser = std::make_unique<TexCheckerNodeParser>(graph, depsgraph, material, in_node);
|
|
||||||
break;
|
|
||||||
case SH_NODE_VECTOR_MATH:
|
|
||||||
parser = std::make_unique<VectorMathNodeParser>(graph, depsgraph, material, in_node);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
CLOG_WARN(LOG_MATERIALX_SHADER, "Unsupported node: %s (%d)", in_node->name, in_node->type);
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = parser->compute();
|
/* Computing from_node with required NodeParser object */
|
||||||
|
#define CASE_NODE_TYPE(type, T) \
|
||||||
|
case type: \
|
||||||
|
res = T(graph_, depsgraph_, material_, from_node, link->fromsock).compute_full(); \
|
||||||
|
break;
|
||||||
|
|
||||||
|
switch (from_node->typeinfo->type) {
|
||||||
|
CASE_NODE_TYPE(SH_NODE_BSDF_PRINCIPLED, BSDFPrincipledNodeParser)
|
||||||
|
CASE_NODE_TYPE(SH_NODE_HUE_SAT, HueSatValNodeParser)
|
||||||
|
CASE_NODE_TYPE(SH_NODE_INVERT, InvertNodeParser)
|
||||||
|
CASE_NODE_TYPE(SH_NODE_MATH, MathNodeParser)
|
||||||
|
CASE_NODE_TYPE(SH_NODE_MIX_RGB_LEGACY, MixRGBNodeParser)
|
||||||
|
CASE_NODE_TYPE(SH_NODE_NORMAL_MAP, NormalMapNodeParser)
|
||||||
|
CASE_NODE_TYPE(SH_NODE_TEX_CHECKER, TexCheckerNodeParser)
|
||||||
|
CASE_NODE_TYPE(SH_NODE_TEX_ENVIRONMENT, TexEnvironmentNodeParser)
|
||||||
|
CASE_NODE_TYPE(SH_NODE_TEX_IMAGE, TexImageNodeParser)
|
||||||
|
CASE_NODE_TYPE(SH_NODE_TEX_NOISE, TexNoiseNodeParser)
|
||||||
|
CASE_NODE_TYPE(SH_NODE_VECTOR_MATH, VectorMathNodeParser)
|
||||||
|
|
||||||
|
default:
|
||||||
|
CLOG_WARN(LOG_MATERIALX_SHADER,
|
||||||
|
"Unsupported node: %s [%d]",
|
||||||
|
from_node->name,
|
||||||
|
from_node->typeinfo->type);
|
||||||
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -163,4 +156,14 @@ NodeItem NodeParser::get_input_value(const bNodeSocket &socket)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NodeItem NodeParser::compute_full()
|
||||||
|
{
|
||||||
|
CLOG_INFO(LOG_MATERIALX_SHADER, 1, "%s [%d]", node_->name, node_->typeinfo->type);
|
||||||
|
NodeItem res = compute();
|
||||||
|
if (res.node) {
|
||||||
|
res.node->setName(node_name(node_, socket_out_));
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace blender::nodes::materialx
|
} // namespace blender::nodes::materialx
|
||||||
|
@ -13,25 +13,26 @@
|
|||||||
namespace blender::nodes::materialx {
|
namespace blender::nodes::materialx {
|
||||||
|
|
||||||
class NodeParser {
|
class NodeParser {
|
||||||
public:
|
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_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
NodeParser(MaterialX::GraphElement *graph,
|
NodeParser(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);
|
||||||
virtual ~NodeParser() = default;
|
virtual ~NodeParser() = default;
|
||||||
|
|
||||||
virtual NodeItem compute() = 0;
|
virtual NodeItem compute() = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
NodeItem create_node(const std::string &mx_category,
|
static std::string node_name(const bNode *node, const bNodeSocket *socket_out);
|
||||||
const std::string &mx_type,
|
NodeItem create_node(const std::string &mx_category, const std::string &mx_type);
|
||||||
bool noname = true);
|
|
||||||
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);
|
NodeItem get_input_link(const std::string &name);
|
||||||
@ -45,6 +46,7 @@ class NodeParser {
|
|||||||
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);
|
||||||
|
NodeItem compute_full();
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class T> NodeItem NodeParser::value(const T &data) const
|
template<class T> NodeItem NodeParser::value(const T &data) const
|
||||||
@ -65,7 +67,6 @@ DECLARE_PARSER(InvertNodeParser)
|
|||||||
DECLARE_PARSER(MathNodeParser)
|
DECLARE_PARSER(MathNodeParser)
|
||||||
DECLARE_PARSER(MixRGBNodeParser)
|
DECLARE_PARSER(MixRGBNodeParser)
|
||||||
DECLARE_PARSER(NormalMapNodeParser)
|
DECLARE_PARSER(NormalMapNodeParser)
|
||||||
DECLARE_PARSER(OutputMaterialNodeParser)
|
|
||||||
DECLARE_PARSER(TexCheckerNodeParser)
|
DECLARE_PARSER(TexCheckerNodeParser)
|
||||||
DECLARE_PARSER(TexEnvironmentNodeParser)
|
DECLARE_PARSER(TexEnvironmentNodeParser)
|
||||||
DECLARE_PARSER(TexImageNodeParser)
|
DECLARE_PARSER(TexImageNodeParser)
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
*
|
*
|
||||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||||
|
|
||||||
|
#include "../material.h"
|
||||||
#include "node_parser.h"
|
#include "node_parser.h"
|
||||||
|
|
||||||
namespace blender::nodes::materialx {
|
namespace blender::nodes::materialx {
|
||||||
@ -9,11 +10,11 @@ namespace blender::nodes::materialx {
|
|||||||
NodeItem NormalMapNodeParser::compute()
|
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 strength = get_input_value("Strength");
|
NodeItem strength = get_input_value("Strength");
|
||||||
|
|
||||||
NodeItem res = create_node("normalmap", "vector3", false);
|
NodeItem res = create_node("normalmap", "vector3");
|
||||||
res.set_input("in", color.to_vector3());
|
res.set_input("in", color.to_vector3());
|
||||||
res.set_input("scale", strength);
|
res.set_input("scale", strength);
|
||||||
|
|
||||||
@ -29,8 +30,8 @@ NodeItem NormalMapNodeParser::compute()
|
|||||||
CLOG_WARN(LOG_MATERIALX_SHADER,
|
CLOG_WARN(LOG_MATERIALX_SHADER,
|
||||||
"Ignoring unsupported Space: %d %s (%d), %s will be used",
|
"Ignoring unsupported Space: %d %s (%d), %s will be used",
|
||||||
normal_map_node->space,
|
normal_map_node->space,
|
||||||
node->name,
|
node_->name,
|
||||||
node->type,
|
node_->type,
|
||||||
default_space);
|
default_space);
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
|
@ -2,19 +2,56 @@
|
|||||||
*
|
*
|
||||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||||
|
|
||||||
#include "node_parser.h"
|
#include "output_material.h"
|
||||||
|
|
||||||
namespace blender::nodes::materialx {
|
namespace blender::nodes::materialx {
|
||||||
|
OutputMaterialNodeParser::OutputMaterialNodeParser(MaterialX::GraphElement *graph,
|
||||||
|
const Depsgraph *depsgraph,
|
||||||
|
const Material *material,
|
||||||
|
const bNode *node)
|
||||||
|
: NodeParser(graph, depsgraph, material, node, nullptr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
NodeItem OutputMaterialNodeParser::compute()
|
NodeItem OutputMaterialNodeParser::compute()
|
||||||
{
|
{
|
||||||
NodeItem node = empty();
|
return empty();
|
||||||
NodeItem surface = get_input_link("Surface");
|
}
|
||||||
if (surface) {
|
|
||||||
node = create_node("surfacematerial", "material", false);
|
NodeItem OutputMaterialNodeParser::compute(const std::string &socket_name)
|
||||||
node.set_input("surfaceshader", surface);
|
{
|
||||||
|
NodeItem surface = empty();
|
||||||
|
if (node_) {
|
||||||
|
surface = get_input_link(socket_name);
|
||||||
}
|
}
|
||||||
return node;
|
else {
|
||||||
|
surface = create_node("standard_surface", "surfaceshader");
|
||||||
|
surface.set_input("base_color", value(MaterialX::Color3(1.0f, 0.0f, 1.0f)));
|
||||||
|
}
|
||||||
|
NodeItem res = create_node("surfacematerial", "material");
|
||||||
|
res.node->setName(node_name(node_, nullptr));
|
||||||
|
res.set_input("surfaceshader", surface);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeItem OutputMaterialNodeParser::compute_default()
|
||||||
|
{
|
||||||
|
NodeItem surface = create_node("standard_surface", "surfaceshader");
|
||||||
|
surface.set_input("base_color", value(MaterialX::Color3(material_->r, material_->g, material_->b)));
|
||||||
|
surface.set_input("diffuse_roughness", value(material_->roughness));
|
||||||
|
if (material_->metallic > 0.0f) {
|
||||||
|
surface.set_input("metalness", value(material_->metallic));
|
||||||
|
}
|
||||||
|
if (material_->spec) {
|
||||||
|
surface.set_input("specular", value(material_->spec));
|
||||||
|
surface.set_input("specular_color", value(material_->spec));
|
||||||
|
surface.set_input("specular_roughness", value(material_->roughness));
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeItem res = create_node("surfacematerial", "material");
|
||||||
|
res.node->setName("Material_Default");
|
||||||
|
res.set_input("surfaceshader", surface);
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace blender::nodes::materialx
|
} // namespace blender::nodes::materialx
|
||||||
|
@ -0,0 +1,22 @@
|
|||||||
|
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "node_parser.h"
|
||||||
|
|
||||||
|
namespace blender::nodes::materialx {
|
||||||
|
|
||||||
|
class OutputMaterialNodeParser : public NodeParser {
|
||||||
|
public:
|
||||||
|
OutputMaterialNodeParser(MaterialX::GraphElement *graph,
|
||||||
|
const Depsgraph *depsgraph,
|
||||||
|
const Material *material,
|
||||||
|
const bNode *node);
|
||||||
|
NodeItem compute() override;
|
||||||
|
NodeItem compute(const std::string &socket_name);
|
||||||
|
NodeItem compute_default();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace blender::nodes::materialx
|
@ -16,16 +16,11 @@ NodeItem TexCheckerNodeParser::compute()
|
|||||||
float v = scale.value->asA<float>();
|
float v = scale.value->asA<float>();
|
||||||
scale = value(MaterialX::Vector2(v, v));
|
scale = value(MaterialX::Vector2(v, v));
|
||||||
}
|
}
|
||||||
/* Modifier to follow Cycles result */
|
|
||||||
scale = scale * value(4.0f);
|
|
||||||
|
|
||||||
NodeItem texcoord = create_node("texcoord", "vector2");
|
NodeItem texcoord = create_node("texcoord", "vector2");
|
||||||
NodeItem place2d = create_node("place2d", "vector2");
|
NodeItem place2d = create_node("place2d", "vector2");
|
||||||
place2d.set_input("texcoord", texcoord * scale);
|
place2d.set_input("texcoord", texcoord * scale);
|
||||||
|
|
||||||
/* TODO: fix offset:
|
|
||||||
* place2d.set_input("offset", offset); */
|
|
||||||
|
|
||||||
NodeItem separate = create_node("separate2", "multioutput");
|
NodeItem separate = create_node("separate2", "multioutput");
|
||||||
separate.set_input("in", place2d);
|
separate.set_input("in", place2d);
|
||||||
separate.add_output("outx", "float");
|
separate.add_output("outx", "float");
|
||||||
@ -42,9 +37,9 @@ NodeItem TexCheckerNodeParser::compute()
|
|||||||
NodeItem ifequal =
|
NodeItem ifequal =
|
||||||
(modulo_x.floor() + modulo_y.floor()).if_else("==", value(1.0f), value(0.0f), value(1.0f));
|
(modulo_x.floor() + modulo_y.floor()).if_else("==", value(1.0f), value(0.0f), value(1.0f));
|
||||||
|
|
||||||
NodeItem res = create_node("mix", "color3", false);
|
NodeItem res = create_node("mix", "color3");
|
||||||
res.set_input("fg", color1.to_color3());
|
res.set_input("bg", color1.to_color3());
|
||||||
res.set_input("bg", color2.to_color3());
|
res.set_input("fg", color2.to_color3());
|
||||||
res.set_input("mix", ifequal);
|
res.set_input("mix", ifequal);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -12,10 +12,10 @@ namespace blender::nodes::materialx {
|
|||||||
|
|
||||||
NodeItem TexEnvironmentNodeParser::compute()
|
NodeItem TexEnvironmentNodeParser::compute()
|
||||||
{
|
{
|
||||||
Image *image = (Image *)node->id;
|
Image *image = (Image *)node_->id;
|
||||||
NodeTexEnvironment *tex = static_cast<NodeTexEnvironment *>(node->storage);
|
NodeTexEnvironment *tex = static_cast<NodeTexEnvironment *>(node_->storage);
|
||||||
Scene *scene = DEG_get_input_scene(depsgraph);
|
Scene *scene = DEG_get_input_scene(depsgraph_);
|
||||||
Main *bmain = DEG_get_bmain(depsgraph);
|
Main *bmain = DEG_get_bmain(depsgraph_);
|
||||||
std::string image_path;
|
std::string image_path;
|
||||||
/* TODO: What if Blender built without Hydra? Also io::hydra::cache_or_get_image_file contains
|
/* TODO: What if Blender built without Hydra? Also io::hydra::cache_or_get_image_file contains
|
||||||
* pretty general code, so could be moved from bf_usd project. */
|
* pretty general code, so could be moved from bf_usd project. */
|
||||||
@ -24,7 +24,7 @@ NodeItem TexEnvironmentNodeParser::compute()
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
NodeItem texcoord = create_node("texcoord", "vector2");
|
NodeItem texcoord = create_node("texcoord", "vector2");
|
||||||
NodeItem res = create_node("image", "color3", false);
|
NodeItem res = create_node("image", "color3");
|
||||||
res.set_input("file", image_path, "filename");
|
res.set_input("file", image_path, "filename");
|
||||||
res.set_input("texcoord", texcoord);
|
res.set_input("texcoord", texcoord);
|
||||||
return res;
|
return res;
|
||||||
|
@ -12,10 +12,10 @@ namespace blender::nodes::materialx {
|
|||||||
|
|
||||||
NodeItem TexImageNodeParser::compute()
|
NodeItem TexImageNodeParser::compute()
|
||||||
{
|
{
|
||||||
Image *image = (Image *)node->id;
|
Image *image = (Image *)node_->id;
|
||||||
NodeTexImage *tex = static_cast<NodeTexImage *>(node->storage);
|
NodeTexImage *tex = static_cast<NodeTexImage *>(node_->storage);
|
||||||
Scene *scene = DEG_get_input_scene(depsgraph);
|
Scene *scene = DEG_get_input_scene(depsgraph_);
|
||||||
Main *bmain = DEG_get_bmain(depsgraph);
|
Main *bmain = DEG_get_bmain(depsgraph_);
|
||||||
std::string image_path;
|
std::string image_path;
|
||||||
/* TODO: What if Blender built without Hydra? Also io::hydra::cache_or_get_image_file contains
|
/* TODO: What if Blender built without Hydra? Also io::hydra::cache_or_get_image_file contains
|
||||||
* pretty general code, so could be moved from bf_usd project. */
|
* pretty general code, so could be moved from bf_usd project. */
|
||||||
@ -24,7 +24,7 @@ NodeItem TexImageNodeParser::compute()
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
NodeItem texcoord = create_node("texcoord", "vector2");
|
NodeItem texcoord = create_node("texcoord", "vector2");
|
||||||
NodeItem res = create_node("image", "color3", false);
|
NodeItem res = create_node("image", "color3");
|
||||||
res.set_input("file", image_path, "filename");
|
res.set_input("file", image_path, "filename");
|
||||||
res.set_input("texcoord", texcoord);
|
res.set_input("texcoord", texcoord);
|
||||||
return res;
|
return res;
|
||||||
|
@ -18,7 +18,7 @@ NodeItem TexNoiseNodeParser::compute()
|
|||||||
|
|
||||||
NodeItem texcoord = create_node("position", "vector3");
|
NodeItem texcoord = create_node("position", "vector3");
|
||||||
|
|
||||||
NodeItem res = create_node("fractal3d", "color3", false);
|
NodeItem res = create_node("fractal3d", "color3");
|
||||||
res.set_input("position", texcoord * scale);
|
res.set_input("position", texcoord * scale);
|
||||||
res.set_input("octaves", detail);
|
res.set_input("octaves", detail);
|
||||||
res.set_input("lacunarity", lacunarity);
|
res.set_input("lacunarity", lacunarity);
|
||||||
|
@ -10,7 +10,7 @@ namespace blender::nodes::materialx {
|
|||||||
NodeItem VectorMathNodeParser::compute()
|
NodeItem VectorMathNodeParser::compute()
|
||||||
{
|
{
|
||||||
/* TODO: finish some math operations */
|
/* TODO: finish some math operations */
|
||||||
auto op = node->custom1;
|
auto op = node_->custom1;
|
||||||
NodeItem res = empty();
|
NodeItem res = empty();
|
||||||
|
|
||||||
/* Single operand operations */
|
/* Single operand operations */
|
||||||
|
Loading…
Reference in New Issue
Block a user