diff --git a/source/blender/nodes/shader/materialx/node_item.cc b/source/blender/nodes/shader/materialx/node_item.cc index 8fa84213de7..fbf8bdc6c8c 100644 --- a/source/blender/nodes/shader/materialx/node_item.cc +++ b/source/blender/nodes/shader/materialx/node_item.cc @@ -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) { diff --git a/source/blender/nodes/shader/materialx/node_item.h b/source/blender/nodes/shader/materialx/node_item.h index 40be1153031..a2b160ec4df 100644 --- a/source/blender/nodes/shader/materialx/node_item.h +++ b/source/blender/nodes/shader/materialx/node_item.h @@ -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 NodeItem val(const T &data) const; Type type() const; diff --git a/source/blender/nodes/shader/nodes/node_shader_bump.cc b/source/blender/nodes/shader/nodes/node_shader_bump.cc index d8b008884ad..655ebc9513f 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bump.cc +++ b/source/blender/nodes/shader/nodes/node_shader_bump.cc @@ -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); } diff --git a/source/blender/nodes/shader/nodes/node_shader_displacement.cc b/source/blender/nodes/shader/nodes/node_shader_displacement.cc index cc0fed413ce..2083e7eed77 100644 --- a/source/blender/nodes/shader/nodes/node_shader_displacement.cc +++ b/source/blender/nodes/shader/nodes/node_shader_displacement.cc @@ -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); } diff --git a/source/blender/nodes/shader/nodes/node_shader_mapping.cc b/source/blender/nodes/shader/nodes/node_shader_mapping.cc index 742d32937b7..b1fff267626 100644 --- a/source/blender/nodes/shader/nodes/node_shader_mapping.cc +++ b/source/blender/nodes/shader/nodes/node_shader_mapping.cc @@ -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); } diff --git a/source/blender/nodes/shader/nodes/node_shader_normal.cc b/source/blender/nodes/shader/nodes/node_shader_normal.cc index 6af7f4316fa..ac1fc498c38 100644 --- a/source/blender/nodes/shader/nodes/node_shader_normal.cc +++ b/source/blender/nodes/shader/nodes/node_shader_normal.cc @@ -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); } diff --git a/source/blender/nodes/shader/nodes/node_shader_normal_map.cc b/source/blender/nodes/shader/nodes/node_shader_normal_map.cc index 86ec4a19885..0bd79164ffc 100644 --- a/source/blender/nodes/shader/nodes/node_shader_normal_map.cc +++ b/source/blender/nodes/shader/nodes/node_shader_normal_map.cc @@ -126,7 +126,7 @@ NODE_SHADER_MATERIALX_BEGIN #ifdef WITH_MATERIALX { NodeShaderNormalMap *normal_map_node = static_cast(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; diff --git a/source/blender/nodes/shader/nodes/node_shader_vector_displacement.cc b/source/blender/nodes/shader/nodes/node_shader_vector_displacement.cc index 07cf11433ae..8d0a87ad17d 100644 --- a/source/blender/nodes/shader/nodes/node_shader_vector_displacement.cc +++ b/source/blender/nodes/shader/nodes/node_shader_vector_displacement.cc @@ -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); } diff --git a/source/blender/nodes/shader/nodes/node_shader_vector_rotate.cc b/source/blender/nodes/shader/nodes/node_shader_vector_rotate.cc index 68a4314d701..5d71a97def4 100644 --- a/source/blender/nodes/shader/nodes/node_shader_vector_rotate.cc +++ b/source/blender/nodes/shader/nodes/node_shader_vector_rotate.cc @@ -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); } diff --git a/source/blender/nodes/shader/nodes/node_shader_vector_transform.cc b/source/blender/nodes/shader/nodes/node_shader_vector_transform.cc index d7385147788..a580f5ac52d 100644 --- a/source/blender/nodes/shader/nodes/node_shader_vector_transform.cc +++ b/source/blender/nodes/shader/nodes/node_shader_vector_transform.cc @@ -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) { + 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); }