MaterialX: make caching image in MaterialX independent from bf_usd project #31

Merged
Bogdan Nagirniak merged 4 commits from matx-cache-texture_2 into matx-export-material 2023-09-22 18:12:52 +02:00
9 changed files with 89 additions and 43 deletions

View File

@ -36,6 +36,7 @@
#include "intern/usd_exporter_context.h" #include "intern/usd_exporter_context.h"
#include "intern/usd_writer_material.h" #include "intern/usd_writer_material.h"
#ifdef WITH_MATERIALX #ifdef WITH_MATERIALX
# include "shader/materialx/node_parser.h"
# include "shader/materialx/material.h" # include "shader/materialx/material.h"
#endif #endif
namespace blender::io::hydra { namespace blender::io::hydra {
@ -79,7 +80,7 @@ void MaterialData::init()
#ifdef WITH_MATERIALX #ifdef WITH_MATERIALX
if (scene_delegate_->use_materialx) { if (scene_delegate_->use_materialx) {
MaterialX::DocumentPtr doc = blender::nodes::materialx::export_to_materialx( MaterialX::DocumentPtr doc = blender::nodes::materialx::export_to_materialx(
scene_delegate_->depsgraph, (Material *)id); scene_delegate_->depsgraph, (Material *)id, cache_or_get_image_file);
pxr::UsdMtlxRead(doc, stage); pxr::UsdMtlxRead(doc, stage);
/* Logging stage: creating lambda stage_str() for not to call stage->ExportToString() /* Logging stage: creating lambda stage_str() for not to call stage->ExportToString()

View File

@ -22,13 +22,6 @@ set(INC
${CMAKE_BINARY_DIR}/source/blender/makesrna ${CMAKE_BINARY_DIR}/source/blender/makesrna
) )
if(WITH_HYDRA)
list(APPEND INC
../../io/usd
)
add_definitions(-DWITH_HYDRA)
endif()
set(INC_SYS set(INC_SYS
) )

View File

@ -32,8 +32,14 @@ NodeItem GroupNodeParser::compute()
#endif #endif
NodeItem out = NodeItem out =
GroupOutputNodeParser( GroupOutputNodeParser(graph,
graph, depsgraph_, material_, node_out, socket_out_, NodeItem::Type::Any, this) depsgraph_,
material_,
node_out,
socket_out_,
NodeItem::Type::Any,
this,
export_image_fn_)
.compute_full(); .compute_full();
#ifdef USE_MATERIALX_NODEGRAPH #ifdef USE_MATERIALX_NODEGRAPH

View File

@ -54,7 +54,9 @@ class DefaultMaterialNodeParser : public NodeParser {
} }
}; };
MaterialX::DocumentPtr export_to_materialx(Depsgraph *depsgraph, Material *material) MaterialX::DocumentPtr export_to_materialx(Depsgraph *depsgraph,
Material *material,
ExportImageFunction export_image_fn)
{ {
CLOG_INFO(LOG_MATERIALX_SHADER, 0, "Material: %s", material->id.name); CLOG_INFO(LOG_MATERIALX_SHADER, 0, "Material: %s", material->id.name);
@ -63,19 +65,36 @@ MaterialX::DocumentPtr export_to_materialx(Depsgraph *depsgraph, Material *mater
material->nodetree->ensure_topology_cache(); material->nodetree->ensure_topology_cache();
bNode *output_node = ntreeShaderOutputNode(material->nodetree, SHD_OUTPUT_ALL); bNode *output_node = ntreeShaderOutputNode(material->nodetree, SHD_OUTPUT_ALL);
if (output_node) { if (output_node) {
NodeParserData data = { NodeParserData data = {doc.get(),
doc.get(), depsgraph, material, NodeItem::Type::Material, nullptr, NodeItem(doc.get())}; depsgraph,
material,
NodeItem::Type::Material,
nullptr,
NodeItem(doc.get()),
export_image_fn};
output_node->typeinfo->materialx_fn(&data, output_node, nullptr); output_node->typeinfo->materialx_fn(&data, output_node, nullptr);
} }
else { else {
DefaultMaterialNodeParser( DefaultMaterialNodeParser(doc.get(),
doc.get(), depsgraph, material, nullptr, nullptr, NodeItem::Type::Material, nullptr) depsgraph,
material,
nullptr,
nullptr,
NodeItem::Type::Material,
nullptr,
export_image_fn)
.compute_error(); .compute_error();
} }
} }
else { else {
DefaultMaterialNodeParser( DefaultMaterialNodeParser(doc.get(),
doc.get(), depsgraph, material, nullptr, nullptr, NodeItem::Type::Material, nullptr) depsgraph,
material,
nullptr,
nullptr,
NodeItem::Type::Material,
nullptr,
export_image_fn)
.compute(); .compute();
} }

View File

@ -9,8 +9,12 @@
struct Depsgraph; struct Depsgraph;
struct Material; struct Material;
class ExportImageFunction;
namespace blender::nodes::materialx { namespace blender::nodes::materialx {
MaterialX::DocumentPtr export_to_materialx(Depsgraph *depsgraph, Material *material); MaterialX::DocumentPtr export_to_materialx(Depsgraph *depsgraph,
Material *material,
ExportImageFunction export_image_fn);
} // namespace blender::nodes::materialx } // namespace blender::nodes::materialx

View File

@ -20,14 +20,16 @@ NodeParser::NodeParser(MaterialX::GraphElement *graph,
const bNode *node, const bNode *node,
const bNodeSocket *socket_out, const bNodeSocket *socket_out,
NodeItem::Type to_type, NodeItem::Type to_type,
GroupNodeParser *group_parser) GroupNodeParser *group_parser,
ExportImageFunction export_image_fn)
: graph_(graph), : graph_(graph),
depsgraph_(depsgraph), depsgraph_(depsgraph),
material_(material), material_(material),
node_(node), node_(node),
socket_out_(socket_out), socket_out_(socket_out),
to_type_(to_type), to_type_(to_type),
group_parser_(group_parser) group_parser_(group_parser),
export_image_fn_(export_image_fn)
{ {
} }
@ -207,13 +209,25 @@ NodeItem NodeParser::get_input_link(const bNodeSocket &socket, NodeItem::Type to
} }
if (from_node->is_group()) { if (from_node->is_group()) {
return GroupNodeParser( return GroupNodeParser(graph_,
graph_, depsgraph_, material_, from_node, link->fromsock, to_type, group_parser_) depsgraph_,
material_,
from_node,
link->fromsock,
to_type,
group_parser_,
export_image_fn_)
.compute_full(); .compute_full();
} }
if (from_node->is_group_input()) { if (from_node->is_group_input()) {
return GroupInputNodeParser( return GroupInputNodeParser(graph_,
graph_, depsgraph_, material_, from_node, link->fromsock, to_type, group_parser_) depsgraph_,
material_,
from_node,
link->fromsock,
to_type,
group_parser_,
export_image_fn_)
.compute_full(); .compute_full();
} }
@ -225,7 +239,8 @@ NodeItem NodeParser::get_input_link(const bNodeSocket &socket, NodeItem::Type to
return empty(); return empty();
} }
NodeParserData data = {graph_, depsgraph_, material_, to_type, group_parser_, empty()}; NodeParserData data = {
graph_, depsgraph_, material_, to_type, group_parser_, empty(), export_image_fn_};
from_node->typeinfo->materialx_fn(&data, const_cast<bNode *>(from_node), link->fromsock); from_node->typeinfo->materialx_fn(&data, const_cast<bNode *>(from_node), link->fromsock);
return data.result; return data.result;
} }

View File

@ -18,6 +18,8 @@ extern struct CLG_LogRef *LOG_MATERIALX_SHADER;
class GroupNodeParser; class GroupNodeParser;
using ExportImageFunction = std::function<std::string(Main *,Scene *, Image *, ImageUser *)>;
class NodeParser { class NodeParser {
protected: protected:
MaterialX::GraphElement *graph_; MaterialX::GraphElement *graph_;
@ -27,6 +29,7 @@ class NodeParser {
const bNodeSocket *socket_out_; const bNodeSocket *socket_out_;
NodeItem::Type to_type_; NodeItem::Type to_type_;
GroupNodeParser *group_parser_; GroupNodeParser *group_parser_;
ExportImageFunction export_image_fn_;
public: public:
NodeParser(MaterialX::GraphElement *graph, NodeParser(MaterialX::GraphElement *graph,
@ -35,7 +38,8 @@ class NodeParser {
const bNode *node, const bNode *node,
const bNodeSocket *socket_out, const bNodeSocket *socket_out,
NodeItem::Type to_type, NodeItem::Type to_type,
GroupNodeParser *group_parser); GroupNodeParser *group_parser,
ExportImageFunction export_image_fn);
virtual ~NodeParser() = default; virtual ~NodeParser() = default;
virtual NodeItem compute() = 0; virtual NodeItem compute() = 0;
@ -82,6 +86,7 @@ struct NodeParserData {
NodeItem::Type to_type; NodeItem::Type to_type;
GroupNodeParser *group_parser; GroupNodeParser *group_parser;
NodeItem result; NodeItem result;
ExportImageFunction export_image_fn;
}; };
#define NODE_SHADER_MATERIALX_BEGIN \ #define NODE_SHADER_MATERIALX_BEGIN \
@ -102,7 +107,14 @@ struct NodeParserData {
{ \ { \
materialx::NodeParserData *d = reinterpret_cast<materialx::NodeParserData *>(data); \ materialx::NodeParserData *d = reinterpret_cast<materialx::NodeParserData *>(data); \
d->result = MaterialXNodeParser( \ d->result = MaterialXNodeParser( \
d->graph, d->depsgraph, d->material, node, out, d->to_type, d->group_parser) \ d->graph, \
d->depsgraph, \
d->material, \
node, \
out, \
d->to_type, \
d->group_parser, \
d->export_image_fn) \
.compute_full(); \ .compute_full(); \
} }

View File

@ -11,8 +11,6 @@
#include "IMB_colormanagement.h" #include "IMB_colormanagement.h"
#include "hydra/image.h"
#include "DEG_depsgraph_query.h" #include "DEG_depsgraph_query.h"
namespace blender::nodes::node_shader_tex_environment_cc { namespace blender::nodes::node_shader_tex_environment_cc {
@ -142,13 +140,13 @@ NODE_SHADER_MATERIALX_BEGIN
} }
NodeTexEnvironment *tex_env = static_cast<NodeTexEnvironment *>(node_->storage); NodeTexEnvironment *tex_env = static_cast<NodeTexEnvironment *>(node_->storage);
Scene *scene = DEG_get_input_scene(depsgraph_);
Main *bmain = DEG_get_bmain(depsgraph_);
/* TODO: What if Blender built without Hydra? Also io::hydra::cache_or_get_image_file contains std::string image_path = image->id.name;
* pretty general code, so could be moved from bf_usd project. */ if (export_image_fn_) {
std::string image_path = io::hydra::cache_or_get_image_file( Scene *scene = DEG_get_input_scene(depsgraph_);
bmain, scene, image, &tex_env->iuser); Main *bmain = DEG_get_bmain(depsgraph_);
image_path = export_image_fn_(bmain, scene, image, &tex_env->iuser);
}
NodeItem vector = get_input_link("Vector", NodeItem::Type::Vector2); NodeItem vector = get_input_link("Vector", NodeItem::Type::Vector2);
if (!vector) { if (!vector) {

View File

@ -11,8 +11,6 @@
#include "IMB_colormanagement.h" #include "IMB_colormanagement.h"
#include "hydra/image.h"
#include "DEG_depsgraph_query.h" #include "DEG_depsgraph_query.h"
namespace blender::nodes::node_shader_tex_image_cc { namespace blender::nodes::node_shader_tex_image_cc {
@ -191,13 +189,13 @@ NODE_SHADER_MATERIALX_BEGIN
Image *image = (Image *)node_->id; Image *image = (Image *)node_->id;
if (image) { if (image) {
NodeTexImage *tex_image = static_cast<NodeTexImage *>(node_->storage); NodeTexImage *tex_image = static_cast<NodeTexImage *>(node_->storage);
Scene *scene = DEG_get_input_scene(depsgraph_);
Main *bmain = DEG_get_bmain(depsgraph_);
/* TODO: What if Blender built without Hydra? Also io::hydra::cache_or_get_image_file std::string image_path = image->id.name;
* contains pretty general code, so could be moved from bf_usd project. */ if (export_image_fn_) {
std::string image_path = io::hydra::cache_or_get_image_file( Scene *scene = DEG_get_input_scene(depsgraph_);
bmain, scene, image, &tex_image->iuser); Main *bmain = DEG_get_bmain(depsgraph_);
image_path = export_image_fn_(bmain, scene, image, &tex_image->iuser);
}
NodeItem vector = get_input_link("Vector", NodeItem::Type::Vector2); NodeItem vector = get_input_link("Vector", NodeItem::Type::Vector2);
if (!vector) { if (!vector) {