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_writer_material.h"
#ifdef WITH_MATERIALX
# include "shader/materialx/node_parser.h"
# include "shader/materialx/material.h"
#endif
namespace blender::io::hydra {
@ -79,7 +80,7 @@ void MaterialData::init()
#ifdef WITH_MATERIALX
if (scene_delegate_->use_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);
/* 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
)
if(WITH_HYDRA)
list(APPEND INC
../../io/usd
)
add_definitions(-DWITH_HYDRA)
endif()
set(INC_SYS
)

View File

@ -32,8 +32,14 @@ NodeItem GroupNodeParser::compute()
#endif
NodeItem out =
GroupOutputNodeParser(
graph, depsgraph_, material_, node_out, socket_out_, NodeItem::Type::Any, this)
GroupOutputNodeParser(graph,
depsgraph_,
material_,
node_out,
socket_out_,
NodeItem::Type::Any,
this,
export_image_fn_)
.compute_full();
#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);
@ -63,19 +65,36 @@ MaterialX::DocumentPtr export_to_materialx(Depsgraph *depsgraph, Material *mater
material->nodetree->ensure_topology_cache();
bNode *output_node = ntreeShaderOutputNode(material->nodetree, SHD_OUTPUT_ALL);
if (output_node) {
NodeParserData data = {
doc.get(), depsgraph, material, NodeItem::Type::Material, nullptr, NodeItem(doc.get())};
NodeParserData data = {doc.get(),
depsgraph,
material,
NodeItem::Type::Material,
nullptr,
NodeItem(doc.get()),
export_image_fn};
output_node->typeinfo->materialx_fn(&data, output_node, nullptr);
}
else {
DefaultMaterialNodeParser(
doc.get(), depsgraph, material, nullptr, nullptr, NodeItem::Type::Material, nullptr)
DefaultMaterialNodeParser(doc.get(),
depsgraph,
material,
nullptr,
nullptr,
NodeItem::Type::Material,
nullptr,
export_image_fn)
.compute_error();
}
}
else {
DefaultMaterialNodeParser(
doc.get(), depsgraph, material, nullptr, nullptr, NodeItem::Type::Material, nullptr)
DefaultMaterialNodeParser(doc.get(),
depsgraph,
material,
nullptr,
nullptr,
NodeItem::Type::Material,
nullptr,
export_image_fn)
.compute();
}

View File

@ -9,8 +9,12 @@
struct Depsgraph;
struct Material;
class ExportImageFunction;
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

View File

@ -20,14 +20,16 @@ NodeParser::NodeParser(MaterialX::GraphElement *graph,
const bNode *node,
const bNodeSocket *socket_out,
NodeItem::Type to_type,
GroupNodeParser *group_parser)
GroupNodeParser *group_parser,
ExportImageFunction export_image_fn)
: graph_(graph),
depsgraph_(depsgraph),
material_(material),
node_(node),
socket_out_(socket_out),
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()) {
return GroupNodeParser(
graph_, depsgraph_, material_, from_node, link->fromsock, to_type, group_parser_)
return GroupNodeParser(graph_,
depsgraph_,
material_,
from_node,
link->fromsock,
to_type,
group_parser_,
export_image_fn_)
.compute_full();
}
if (from_node->is_group_input()) {
return GroupInputNodeParser(
graph_, depsgraph_, material_, from_node, link->fromsock, to_type, group_parser_)
return GroupInputNodeParser(graph_,
depsgraph_,
material_,
from_node,
link->fromsock,
to_type,
group_parser_,
export_image_fn_)
.compute_full();
}
@ -225,7 +239,8 @@ NodeItem NodeParser::get_input_link(const bNodeSocket &socket, NodeItem::Type to
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);
return data.result;
}

View File

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

View File

@ -11,8 +11,6 @@
#include "IMB_colormanagement.h"
#include "hydra/image.h"
#include "DEG_depsgraph_query.h"
namespace blender::nodes::node_shader_tex_environment_cc {
@ -142,13 +140,13 @@ NODE_SHADER_MATERIALX_BEGIN
}
NodeTexEnvironment *tex_env = static_cast<NodeTexEnvironment *>(node_->storage);
std::string image_path = image->id.name;
if (export_image_fn_) {
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
* pretty general code, so could be moved from bf_usd project. */
std::string image_path = io::hydra::cache_or_get_image_file(
bmain, scene, image, &tex_env->iuser);
image_path = export_image_fn_(bmain, scene, image, &tex_env->iuser);
}
NodeItem vector = get_input_link("Vector", NodeItem::Type::Vector2);
if (!vector) {

View File

@ -11,8 +11,6 @@
#include "IMB_colormanagement.h"
#include "hydra/image.h"
#include "DEG_depsgraph_query.h"
namespace blender::nodes::node_shader_tex_image_cc {
@ -191,13 +189,13 @@ NODE_SHADER_MATERIALX_BEGIN
Image *image = (Image *)node_->id;
if (image) {
NodeTexImage *tex_image = static_cast<NodeTexImage *>(node_->storage);
std::string image_path = image->id.name;
if (export_image_fn_) {
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 pretty general code, so could be moved from bf_usd project. */
std::string image_path = io::hydra::cache_or_get_image_file(
bmain, scene, image, &tex_image->iuser);
image_path = export_image_fn_(bmain, scene, image, &tex_image->iuser);
}
NodeItem vector = get_input_link("Vector", NodeItem::Type::Vector2);
if (!vector) {