MaterialX: add support for Vector nodes #27

Merged
Bogdan Nagirniak merged 13 commits from Vasyl-Pidhirskyi/blender:BLEN-525 into matx-export-material 2023-09-22 10:03:45 +02:00
10 changed files with 267 additions and 1 deletions

View File

@ -53,6 +53,9 @@ NodeItem::Type NodeItem::type(const std::string &type_str)
if (type_str == "EDF") {
return Type::EDF;
}
if (type_str == "displacementshader") {
return Type::Displacementshader;
}
if (type_str == "surfaceshader") {
return Type::SurfaceShader;
}
@ -94,6 +97,8 @@ std::string NodeItem::type(Type type)
return "BSDF";
case Type::EDF:
return "EDF";
case Type::Displacementshader:
return "displacementshader";
case Type::SurfaceShader:
return "surfaceshader";
case Type::Material:
@ -612,6 +617,23 @@ NodeItem NodeItem::empty() const
return NodeItem(graph_);
}
NodeItem NodeItem::rotate3d(NodeItem rotation, bool invert)
{
NodeItem res = *this;
if (res.type() == Type::Vector3 && rotation.type() == Type::Vector3) {
for (int i = 0; i <= 2; i++) {
int j = invert ? 2 - i : i;
MaterialX::Vector3 axis_vector = MaterialX::Vector3();
axis_vector[j] = 1.0f;
res = create_node(
"rotate3d",
NodeItem::Type::Vector3,
{{"in", res}, {"amount", rotation.extract(j)}, {"axis", val(axis_vector)}});
}
}
return res;
}
NodeItem::Type NodeItem::type() const
{
if (value) {

View File

@ -39,6 +39,7 @@ class NodeItem {
* NOTE: There are only supported types */
BSDF,
EDF,
Displacementshader,
SurfaceShader,
Material,
};
@ -106,6 +107,7 @@ class NodeItem {
/* Useful functions */
NodeItem empty() const;
NodeItem rotate3d(NodeItem rotation, bool invert = false);
template<class T> NodeItem val(const T &data) const;
Type type() const;

View File

@ -71,6 +71,34 @@ static int gpu_shader_bump(GPUMaterial *mat,
return GPU_stack_link(mat, node, "node_bump", in, out, dheight, GPU_constant(&invert));
}
NODE_SHADER_MATERIALX_BEGIN
#ifdef WITH_MATERIALX
{
NodeItem height = get_input_link("Height", NodeItem::Type::Float);
NodeItem normal = get_input_link("Normal", NodeItem::Type::Vector3);
if (!height) {
if (!normal) {
return create_node(
"normal", NodeItem::Type::Vector3, {{"space", val(std::string("world"))}});
}
return normal;
}
NodeItem strength = get_input_value("Strength", NodeItem::Type::Float);
NodeItem distance = get_input_value("Distance", NodeItem::Type::Float);
NodeItem height_normal = create_node(
"heighttonormal", NodeItem::Type::Vector3, {{"in", height}, {"scale", strength}});
return create_node("normalmap",
NodeItem::Type::Vector3,
{{"in", height_normal},
{"scale", node_->custom1 ? distance * val(-1.0f) : distance},
{"normal", normal}});
}
#endif
NODE_SHADER_MATERIALX_END
} // namespace blender::nodes::node_shader_bump_cc
/* node type definition */
@ -84,6 +112,7 @@ void register_node_type_sh_bump()
ntype.declare = file_ns::node_declare;
ntype.draw_buttons = file_ns::node_shader_buts_bump;
ntype.gpu_fn = file_ns::gpu_shader_bump;
ntype.materialx_fn = file_ns::node_shader_materialx;
nodeRegisterType(&ntype);
}

View File

@ -37,6 +37,21 @@ static int gpu_shader_displacement(GPUMaterial *mat,
return GPU_stack_link(mat, node, "node_displacement_world", in, out);
}
NODE_SHADER_MATERIALX_BEGIN
#ifdef WITH_MATERIALX
{
/* NOTE: Normal input and Space feature don't have an implementation in MaterialX.*/
NodeItem midlevel = get_input_value("Midlevel", NodeItem::Type::Float);
NodeItem height = get_input_value("Height", NodeItem::Type::Float) - midlevel;
NodeItem scale = get_input_value("Scale", NodeItem::Type::Float);
return create_node("displacement",
NodeItem::Type::Displacementshader,
{{"displacement", height}, {"scale", scale}});
}
#endif
NODE_SHADER_MATERIALX_END
} // namespace blender::nodes::node_shader_displacement_cc
/* node type definition */
@ -50,6 +65,7 @@ void register_node_type_sh_displacement()
ntype.declare = file_ns::node_declare;
ntype.initfunc = file_ns::node_shader_init_displacement;
ntype.gpu_fn = file_ns::gpu_shader_displacement;
ntype.materialx_fn = file_ns::node_shader_materialx;
nodeRegisterType(&ntype);
}

View File

@ -74,6 +74,44 @@ static void node_shader_update_mapping(bNodeTree *ntree, bNode *node)
ntree, sock, ELEM(node->custom1, NODE_MAPPING_TYPE_POINT, NODE_MAPPING_TYPE_TEXTURE));
}
NODE_SHADER_MATERIALX_BEGIN
#ifdef WITH_MATERIALX
{
NodeItem res = empty();
NodeItem vector = get_input_link("Vector", NodeItem::Type::Vector3);
if (!vector) {
return res;
}
NodeItem scale = get_input_value("Scale", NodeItem::Type::Vector3);
NodeItem location = get_input_value("Location", NodeItem::Type::Vector3);
NodeItem rotation = (get_input_value("Rotation", NodeItem::Type::Vector3) *
val(float(180.0f / M_PI)));
switch (node_->custom1) {
case NODE_MAPPING_TYPE_POINT:
res = (vector * scale).rotate3d(rotation) + location;
break;
case NODE_MAPPING_TYPE_TEXTURE:
res = (vector - location).rotate3d(rotation, true) / scale;
break;
case NODE_MAPPING_TYPE_VECTOR:
res = (vector * scale).rotate3d(rotation * val(MaterialX::Vector3(1.0f, 1.0f, -1.0f)));
break;
case NODE_MAPPING_TYPE_NORMAL:
res = create_node(
"normalize", NodeItem::Type::Vector3, {{"in", (vector / scale).rotate3d(rotation)}});
break;
default:
BLI_assert_unreachable();
}
return res;
}
#endif
NODE_SHADER_MATERIALX_END
} // namespace blender::nodes::node_shader_mapping_cc
void register_node_type_sh_mapping()
@ -87,6 +125,7 @@ void register_node_type_sh_mapping()
ntype.draw_buttons = file_ns::node_shader_buts_mapping;
ntype.gpu_fn = file_ns::gpu_shader_mapping;
ntype.updatefunc = file_ns::node_shader_update_mapping;
ntype.materialx_fn = file_ns::node_shader_materialx;
nodeRegisterType(&ntype);
}

View File

@ -35,6 +35,20 @@ static int gpu_shader_normal(GPUMaterial *mat,
return GPU_stack_link(mat, node, "normal_new_shading", in, out, vec);
}
NODE_SHADER_MATERIALX_BEGIN
#ifdef WITH_MATERIALX
{
NodeItem res = get_output_default("Normal", NodeItem::Type::Vector3);
if (STREQ(socket_out_->name, "Dot")) {
return res.dotproduct(get_input_value("Normal", NodeItem::Type::Vector3));
}
return res;
}
#endif
NODE_SHADER_MATERIALX_END
} // namespace blender::nodes::node_shader_normal_cc
void register_node_type_sh_normal()
@ -46,6 +60,7 @@ void register_node_type_sh_normal()
sh_node_type_base(&ntype, SH_NODE_NORMAL, "Normal", NODE_CLASS_OP_VECTOR);
ntype.declare = file_ns::node_declare;
ntype.gpu_fn = file_ns::gpu_shader_normal;
ntype.materialx_fn = file_ns::node_shader_materialx;
nodeRegisterType(&ntype);
}

View File

@ -126,7 +126,7 @@ NODE_SHADER_MATERIALX_BEGIN
#ifdef WITH_MATERIALX
{
NodeShaderNormalMap *normal_map_node = static_cast<NodeShaderNormalMap *>(node_->storage);
NodeItem color = get_input_value("Color", NodeItem::Type::Color3);
NodeItem color = get_input_value("Color", NodeItem::Type::Vector3);
NodeItem strength = get_input_value("Strength", NodeItem::Type::Float);
std::string space;

View File

@ -41,6 +41,21 @@ static int gpu_shader_vector_displacement(GPUMaterial *mat,
}
}
NODE_SHADER_MATERIALX_BEGIN
#ifdef WITH_MATERIALX
{
/* NOTE: Midlevel input and Space feature don't have an implementation in MaterialX.*/
// NodeItem midlevel = get_input_value("midlevel", NodeItem::Type::Float);
NodeItem vector = get_input_link("Vector", NodeItem::Type::Vector3);
NodeItem scale = get_input_value("Scale", NodeItem::Type::Float);
return create_node("displacement",
NodeItem::Type::Displacementshader,
{{"displacement", vector}, {"scale", scale}});
}
#endif
NODE_SHADER_MATERIALX_END
} // namespace blender::nodes::node_shader_vector_displacement_cc
/* node type definition */
@ -55,6 +70,7 @@ void register_node_type_sh_vector_displacement()
ntype.declare = file_ns::node_declare;
ntype.initfunc = file_ns::node_shader_init_vector_displacement;
ntype.gpu_fn = file_ns::gpu_shader_vector_displacement;
ntype.materialx_fn = file_ns::node_shader_materialx;
nodeRegisterType(&ntype);
}

View File

@ -212,6 +212,69 @@ static void node_shader_update_vector_rotate(bNodeTree *ntree, bNode *node)
ntree, sock_angle, !ELEM(node->custom1, NODE_VECTOR_ROTATE_TYPE_EULER_XYZ));
}
NODE_SHADER_MATERIALX_BEGIN
#ifdef WITH_MATERIALX
{
NodeItem vector = get_input_link("Vector", NodeItem::Type::Vector3);
if (!vector) {
return empty();
}
NodeItem angle = empty();
NodeItem axis = empty();
NodeItem center = get_input_value("Center", NodeItem::Type::Vector3) *
val(MaterialX::Vector3(1.0f, 1.0f, -1.0f));
NodeItem res = vector - center;
int mode = node_->custom1;
bool invert = node_->custom1;
if (mode == NODE_VECTOR_ROTATE_TYPE_EULER_XYZ) {
angle = get_input_value("Rotation", NodeItem::Type::Vector3);
angle = angle * val(MaterialX::Vector3(1.0f, 1.0f, -1.0f));
}
else {
angle = get_input_value("Angle", NodeItem::Type::Float);
}
angle = angle * val(float(180.0f / M_PI));
angle = invert ? angle * val(-1.0f) : angle;
switch (mode) {
case NODE_VECTOR_ROTATE_TYPE_EULER_XYZ: {
return res.rotate3d(angle, invert) + center;
}
case NODE_VECTOR_ROTATE_TYPE_AXIS: {
axis = get_input_value("Axis", NodeItem::Type::Vector3) *
val(MaterialX::Vector3(1.0f, 1.0f, -1.0f));
break;
}
case NODE_VECTOR_ROTATE_TYPE_AXIS_X: {
axis = val(MaterialX::Vector3(1.0f, 0.0f, 0.0f));
break;
}
case NODE_VECTOR_ROTATE_TYPE_AXIS_Y: {
axis = val(MaterialX::Vector3(0.0f, 1.0f, 0.0f));
break;
}
case NODE_VECTOR_ROTATE_TYPE_AXIS_Z: {
axis = val(MaterialX::Vector3(0.0f, 0.0f, -1.0f));
break;
}
default: {
BLI_assert_unreachable();
return vector;
}
}
return create_node("rotate3d",
NodeItem::Type::Vector3,
{{"in", res}, {"amount", angle}, {"axis", axis}}) +
center;
}
#endif
NODE_SHADER_MATERIALX_END
} // namespace blender::nodes::node_shader_vector_rotate_cc
void register_node_type_sh_vector_rotate()
@ -226,6 +289,7 @@ void register_node_type_sh_vector_rotate()
ntype.gpu_fn = file_ns::gpu_shader_vector_rotate;
ntype.updatefunc = file_ns::node_shader_update_vector_rotate;
ntype.build_multi_function = file_ns::sh_node_vector_rotate_build_multi_function;
ntype.materialx_fn = file_ns::node_shader_materialx;
nodeRegisterType(&ntype);
}

View File

@ -137,6 +137,68 @@ static int gpu_shader_vect_transform(GPUMaterial *mat,
return true;
}
NODE_SHADER_MATERIALX_BEGIN
#ifdef WITH_MATERIALX
{
NodeItem res = empty();
NodeShaderVectTransform *nodeprop = (NodeShaderVectTransform *)node_->storage;
std::string fromspace;
std::string tospace;
std::string category;
NodeItem vector = get_input_value("Vector", NodeItem::Type::Vector3);
switch (nodeprop->convert_from) {
Vasyl-Pidhirskyi marked this conversation as resolved
Review

Here and other places:

default:
	BLI_assert_unreachable();
Here and other places: ``` default: BLI_assert_unreachable(); ```
case SHD_VECT_TRANSFORM_SPACE_WORLD:
fromspace = "world";
break;
case SHD_VECT_TRANSFORM_SPACE_OBJECT:
fromspace = "object";
break;
default:
/* NOTE: SHD_VECT_TRANSFORM_SPACE_CAMERA don't have an implementation in MaterialX.*/
BLI_assert_unreachable();
return vector;
}
switch (nodeprop->convert_to) {
case SHD_VECT_TRANSFORM_SPACE_WORLD:
tospace = "world";
break;
case SHD_VECT_TRANSFORM_SPACE_OBJECT:
tospace = "object";
break;
default:
/* NOTE: SHD_VECT_TRANSFORM_SPACE_CAMERA don't have an implementation in MaterialX.*/
BLI_assert_unreachable();
return vector;
}
if (fromspace == tospace) {
return vector;
}
switch (nodeprop->type) {
case SHD_VECT_TRANSFORM_TYPE_POINT:
category = "transformpoint";
break;
case SHD_VECT_TRANSFORM_TYPE_NORMAL:
category = "transformnormal";
break;
case SHD_VECT_TRANSFORM_TYPE_VECTOR:
category = "transformvector";
break;
default:
BLI_assert_unreachable();
return vector;
}
return create_node(category,
NodeItem::Type::Vector3,
{{"in", vector}, {"fromspace", val(fromspace)}, {"tospace", val(tospace)}});
}
#endif
NODE_SHADER_MATERIALX_END
} // namespace blender::nodes::node_shader_vector_transform_cc
void register_node_type_sh_vect_transform()
@ -152,6 +214,7 @@ void register_node_type_sh_vect_transform()
node_type_storage(
&ntype, "NodeShaderVectTransform", node_free_standard_storage, node_copy_standard_storage);
ntype.gpu_fn = file_ns::gpu_shader_vect_transform;
ntype.materialx_fn = file_ns::node_shader_materialx;
nodeRegisterType(&ntype);
}