Export material to MaterialX for Hydra render #111765

Manually merged
Brecht Van Lommel merged 48 commits from DagerD/blender:matx-export-material into main 2023-09-26 18:56:40 +02:00
9 changed files with 141 additions and 2 deletions
Showing only changes of commit 956df4e4db - Show all commits

View File

@ -148,6 +148,7 @@ if(WITH_MATERIALX)
list(APPEND SRC
materialx/material.cc
materialx/nodes/add_shader.cc
materialx/nodes/blackbody.cc
materialx/nodes/brightness.cc
materialx/nodes/bsdf_diffuse.cc
materialx/nodes/bsdf_glass.cc
@ -158,9 +159,11 @@ if(WITH_MATERIALX)
materialx/nodes/bsdf_toon.cc
materialx/nodes/bsdf_translucent.cc
materialx/nodes/bsdf_transparent.cc
materialx/nodes/clamp.cc
materialx/nodes/emission.cc
materialx/nodes/huesatval.cc
materialx/nodes/invert.cc
materialx/nodes/map_range.cc
materialx/nodes/math.cc
materialx/nodes/mix_rgb.cc
materialx/nodes/mix_shader.cc
@ -168,15 +171,16 @@ if(WITH_MATERIALX)
materialx/nodes/node_parser.cc
materialx/nodes/normal_map.cc
materialx/nodes/output_material.cc
materialx/nodes/rgb_to_bw.cc
materialx/nodes/sepcomb_color.cc
materialx/nodes/sepcomb_xyz.cc
materialx/nodes/subsurface_scattering.cc
materialx/nodes/tex_checker.cc
BogdanNagirniak marked this conversation as resolved Outdated

Can the code for all these node types move into the corresponding source/blender/nodes/shader/nodes/node_shader_*.cc file? We are trying to make node implementations self contained instead of spread across multiple files.

Otherwise it's likely developers will forget to update the materialx code when making changes.

A new callback would be added to bNodeType, similar to gpu_fn, that would convert the node to materialx.

Can the code for all these node types move into the corresponding `source/blender/nodes/shader/nodes/node_shader_*.cc` file? We are trying to make node implementations self contained instead of spread across multiple files. Otherwise it's likely developers will forget to update the materialx code when making changes. A new callback would be added to `bNodeType`, similar to `gpu_fn`, that would convert the node to materialx.
materialx/nodes/tex_environment.cc
materialx/nodes/tex_image.cc
materialx/nodes/tex_noise.cc
materialx/nodes/tex_noise.cc
materialx/nodes/vector_math.cc
materialx/material.h
materialx/nodes/node_item.h
materialx/nodes/node_parser.h

View File

@ -0,0 +1,22 @@
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "node_parser.h"
namespace blender::nodes::materialx {
NodeItem BlackbodyNodeParser::compute()
{
/* This node doesn't have an implementation in MaterialX 1.38.6.
* It's added in MaterialX 1.38.8. Uncomment this code after switching to 1.38.8.
*
* NodeItem temperature = get_input_value("Temperature", NodeItem::Type::Float);
* NodeItem res = create_node("blackbody", NodeItem::Type::Color3);
* res.set_input("temperature", temperature);
* return res; */
return empty();
}
} // namespace blender::nodes::materialx

View File

@ -0,0 +1,27 @@
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "node_parser.h"
namespace blender::nodes::materialx {
NodeItem ClampNodeParser::compute()
{
auto type = node_->custom1;
NodeItem value = get_input_value("Value", NodeItem::Type::Float);
NodeItem min = get_input_value("Min", NodeItem::Type::Float);
NodeItem max = get_input_value("Max", NodeItem::Type::Float);
NodeItem res = empty();
if (type == NODE_CLAMP_RANGE) {
res = min.if_else(
NodeItem::CompareOp::Less, max, value.clamp(min, max), value.clamp(max, min));
}
else {
res = value.clamp(min, max);
}
return res;
}
} // namespace blender::nodes::materialx

View File

@ -0,0 +1,51 @@
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "node_parser.h"
namespace blender::nodes::materialx {
NodeItem MapRangeNodeParser::compute()
{
/* Interpolation isn't supported by MaterialX. */
const NodeMapRange *map_range = static_cast<NodeMapRange *>(node_->storage);
NodeItem::Type type;
NodeItem value = empty();
NodeItem from_min = empty();
NodeItem from_max = empty();
NodeItem to_min = empty();
NodeItem to_max = empty();
switch (map_range->data_type) {
case CD_PROP_FLOAT:
type = NodeItem::Type::Float;
value = get_input_value("Value", type);
from_min = get_input_value(1, type);
from_max = get_input_value(2, type);
to_min = get_input_value(3, type);
to_max = get_input_value(4, type);
break;
case CD_PROP_FLOAT3:
type = NodeItem::Type::Vector3;
value = get_input_value("Vector", type);
from_min = get_input_value(7, type);
from_max = get_input_value(8, type);
to_min = get_input_value(9, type);
to_max = get_input_value(10, type);
break;
default:
BLI_assert_unreachable();
}
NodeItem res = create_node("range", type);
res.set_input("in", value);
res.set_input("inlow", from_min);
res.set_input("inhigh", from_max);
res.set_input("outlow", to_min);
res.set_input("outhigh", to_max);
res.set_input("doclamp", val(bool(map_range->clamp)));
return res;
}
} // namespace blender::nodes::materialx

View File

@ -20,6 +20,9 @@ NodeItem::Type NodeItem::type(const std::string &type_str)
if (type_str == "filename") {
return Type::Filename;
}
if (type_str == "boolean") {
return Type::Boolean;
}
if (type_str == "integer") {
return Type::Integer;
}
@ -64,6 +67,8 @@ std::string NodeItem::type(Type type)
return "string";
case Type::Filename:
return "filename";
case Type::Boolean:
return "boolean";
case Type::Integer:
return "integer";
case Type::Float:
@ -633,6 +638,9 @@ void NodeItem::set_input(const std::string &in_name, const NodeItem &item)
case Type::String:
set_input(in_name, item.value->asA<std::string>(), item_type);
break;
case Type::Boolean:
set_input(in_name, item.value->asA<bool>(), item_type);
break;
case Type::Integer:
set_input(in_name, item.value->asA<int>(), item_type);
break;

View File

@ -17,6 +17,7 @@ class NodeItem {
/* Value types */
String,
Filename,
Boolean,
Integer,
/* Block of arithmetic types. Ordered by type cast */
Float,

View File

@ -136,14 +136,18 @@ NodeItem NodeParser::get_input_link(const bNodeSocket &socket, NodeItem::Type to
break;
switch (from_node->typeinfo->type) {
CASE_NODE_TYPE(SH_NODE_BLACKBODY, BlackbodyNodeParser)
BogdanNagirniak marked this conversation as resolved Outdated

If there is a node type callback, this switch statement will not be needed anymore.

If there is a node type callback, this switch statement will not be needed anymore.
CASE_NODE_TYPE(SH_NODE_BRIGHTCONTRAST, BrightContrastNodeParser)
CASE_NODE_TYPE(SH_NODE_CLAMP, ClampNodeParser)
CASE_NODE_TYPE(SH_NODE_COMBINE_COLOR, CombineColorNodeParser)
CASE_NODE_TYPE(SH_NODE_COMBXYZ, CombineXYZNodeParser)
CASE_NODE_TYPE(SH_NODE_HUE_SAT, HueSatValNodeParser)
CASE_NODE_TYPE(SH_NODE_INVERT, InvertNodeParser)
CASE_NODE_TYPE(SH_NODE_MAP_RANGE, MapRangeNodeParser)
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_RGBTOBW, RGBToBWNodeParser)
CASE_NODE_TYPE(SH_NODE_SEPARATE_COLOR, SeparateColorNodeParser)
CASE_NODE_TYPE(SH_NODE_SEPXYZ, SeparateXYZNodeParser)
CASE_NODE_TYPE(SH_NODE_TEX_CHECKER, TexCheckerNodeParser)

View File

@ -90,14 +90,18 @@ template<class T> NodeItem NodeParser::val(const T &data) const
NodeItem compute() override; \
};
DECLARE_NODE_PARSER(BlackbodyNodeParser)
DECLARE_NODE_PARSER(BrightContrastNodeParser)
DECLARE_NODE_PARSER(ClampNodeParser)
DECLARE_NODE_PARSER(CombineColorNodeParser)
DECLARE_NODE_PARSER(CombineXYZNodeParser)
DECLARE_NODE_PARSER(HueSatValNodeParser)
DECLARE_NODE_PARSER(InvertNodeParser)
DECLARE_NODE_PARSER(MapRangeNodeParser)
DECLARE_NODE_PARSER(MathNodeParser)
DECLARE_NODE_PARSER(MixRGBNodeParser)
DECLARE_NODE_PARSER(NormalMapNodeParser)
DECLARE_NODE_PARSER(RGBToBWNodeParser)
DECLARE_NODE_PARSER(SeparateColorNodeParser)
DECLARE_NODE_PARSER(SeparateXYZNodeParser)
DECLARE_NODE_PARSER(TexCheckerNodeParser)

View File

@ -0,0 +1,18 @@
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "node_parser.h"
namespace blender::nodes::materialx {
NodeItem RGBToBWNodeParser::compute()
{
NodeItem color = get_input_value("Color", NodeItem::Type::Color4);
NodeItem res = create_node("luminance", NodeItem::Type::Color4);
res.set_input("in", color);
return res;
}
} // namespace blender::nodes::materialx