/* SPDX-License-Identifier: GPL-2.0-or-later * Copyright 2014 Blender Foundation. All rights reserved. */ /** \file * \ingroup shdnodes */ #include "node_shader_util.hh" namespace blender::nodes::node_shader_sepcomb_xyz_cc { static void sh_node_sepxyz_declare(NodeDeclarationBuilder &b) { b.is_function_node(); b.add_input(N_("Vector")).min(-10000.0f).max(10000.0f); b.add_output(N_("X")); b.add_output(N_("Y")); b.add_output(N_("Z")); } static int gpu_shader_sepxyz(GPUMaterial *mat, bNode *node, bNodeExecData * /*execdata*/, GPUNodeStack *in, GPUNodeStack *out) { return GPU_stack_link(mat, node, "separate_xyz", in, out); } class MF_SeparateXYZ : public fn::MultiFunction { public: MF_SeparateXYZ() { static fn::MFSignature signature = create_signature(); this->set_signature(&signature); } static fn::MFSignature create_signature() { fn::MFSignatureBuilder signature{"Separate XYZ"}; signature.single_input("XYZ"); signature.single_output("X"); signature.single_output("Y"); signature.single_output("Z"); return signature.build(); } void call(IndexMask mask, fn::MFParams params, fn::MFContext /*context*/) const override { const VArray &vectors = params.readonly_single_input(0, "XYZ"); MutableSpan xs = params.uninitialized_single_output_if_required(1, "X"); MutableSpan ys = params.uninitialized_single_output_if_required(2, "Y"); MutableSpan zs = params.uninitialized_single_output_if_required(3, "Z"); std::array, 3> outputs = {xs, ys, zs}; Vector used_outputs; if (!xs.is_empty()) { used_outputs.append(0); } if (!ys.is_empty()) { used_outputs.append(1); } if (!zs.is_empty()) { used_outputs.append(2); } devirtualize_varray(vectors, [&](auto vectors) { mask.to_best_mask_type([&](auto mask) { const int used_outputs_num = used_outputs.size(); const int *used_outputs_data = used_outputs.data(); for (const int64_t i : mask) { const float3 &vector = vectors[i]; for (const int out_i : IndexRange(used_outputs_num)) { const int coordinate = used_outputs_data[out_i]; outputs[coordinate][i] = vector[coordinate]; } } }); }); } }; static void sh_node_sepxyz_build_multi_function(NodeMultiFunctionBuilder &builder) { static MF_SeparateXYZ separate_fn; builder.set_matching_fn(separate_fn); } } // namespace blender::nodes::node_shader_sepcomb_xyz_cc void register_node_type_sh_sepxyz() { namespace file_ns = blender::nodes::node_shader_sepcomb_xyz_cc; static bNodeType ntype; sh_fn_node_type_base(&ntype, SH_NODE_SEPXYZ, "Separate XYZ", NODE_CLASS_CONVERTER); ntype.declare = file_ns::sh_node_sepxyz_declare; ntype.gpu_fn = file_ns::gpu_shader_sepxyz; ntype.build_multi_function = file_ns::sh_node_sepxyz_build_multi_function; nodeRegisterType(&ntype); } namespace blender::nodes::node_shader_sepcomb_xyz_cc { static void sh_node_combxyz_declare(NodeDeclarationBuilder &b) { b.is_function_node(); b.add_input(N_("X")).min(-10000.0f).max(10000.0f); b.add_input(N_("Y")).min(-10000.0f).max(10000.0f); b.add_input(N_("Z")).min(-10000.0f).max(10000.0f); b.add_output(N_("Vector")); } static int gpu_shader_combxyz(GPUMaterial *mat, bNode *node, bNodeExecData * /*execdata*/, GPUNodeStack *in, GPUNodeStack *out) { return GPU_stack_link(mat, node, "combine_xyz", in, out); } static void sh_node_combxyz_build_multi_function(NodeMultiFunctionBuilder &builder) { static fn::CustomMF_SI_SI_SI_SO fn{ "Combine Vector", [](float x, float y, float z) { return float3(x, y, z); }, fn::CustomMF_presets::AllSpanOrSingle()}; builder.set_matching_fn(fn); } } // namespace blender::nodes::node_shader_sepcomb_xyz_cc void register_node_type_sh_combxyz() { namespace file_ns = blender::nodes::node_shader_sepcomb_xyz_cc; static bNodeType ntype; sh_fn_node_type_base(&ntype, SH_NODE_COMBXYZ, "Combine XYZ", NODE_CLASS_CONVERTER); ntype.declare = file_ns::sh_node_combxyz_declare; ntype.gpu_fn = file_ns::gpu_shader_combxyz; ntype.build_multi_function = file_ns::sh_node_combxyz_build_multi_function; nodeRegisterType(&ntype); }