diff options
Diffstat (limited to 'source/blender/nodes/shader/nodes')
29 files changed, 534 insertions, 157 deletions
diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c index 89b7164693f..b9f4106c79a 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c @@ -169,17 +169,16 @@ static int node_shader_gpu_bsdf_principled(GPUMaterial *mat, static void node_shader_update_principled(bNodeTree *ntree, bNode *node) { - bNodeSocket *sock; - int distribution = node->custom1; - int sss_method = node->custom2; + const int distribution = node->custom1; + const int sss_method = node->custom2; - for (sock = node->inputs.first; sock; sock = sock->next) { + for (bNodeSocket *sock = node->inputs.first; sock; sock = sock->next) { if (STREQ(sock->name, "Transmission Roughness")) { nodeSetSocketAvailability(ntree, sock, distribution == SHD_GLOSSY_GGX); } if (STR_ELEM(sock->name, "Subsurface IOR", "Subsurface Anisotropy")) { - nodeSetSocketAvailability(ntree, sock, sss_method == SHD_SUBSURFACE_BURLEY); + nodeSetSocketAvailability(ntree, sock, sss_method != SHD_SUBSURFACE_BURLEY); } } } diff --git a/source/blender/nodes/shader/nodes/node_shader_clamp.cc b/source/blender/nodes/shader/nodes/node_shader_clamp.cc index 57a992a4275..6c3457151e5 100644 --- a/source/blender/nodes/shader/nodes/node_shader_clamp.cc +++ b/source/blender/nodes/shader/nodes/node_shader_clamp.cc @@ -75,7 +75,7 @@ static void sh_node_clamp_build_multi_function(blender::nodes::NodeMultiFunction } } -void register_node_type_sh_clamp(void) +void register_node_type_sh_clamp() { static bNodeType ntype; diff --git a/source/blender/nodes/shader/nodes/node_shader_common.c b/source/blender/nodes/shader/nodes/node_shader_common.c index a1dac05434e..190e0cfad4c 100644 --- a/source/blender/nodes/shader/nodes/node_shader_common.c +++ b/source/blender/nodes/shader/nodes/node_shader_common.c @@ -232,7 +232,7 @@ void register_node_type_sh_group(void) /* NOTE: cannot use #sh_node_type_base for node group, because it would map the node type * to the shared #NODE_GROUP integer type id. */ - node_type_base_custom(&ntype, "ShaderNodeGroup", "Group", NODE_CLASS_GROUP, NODE_CONST_OUTPUT); + node_type_base_custom(&ntype, "ShaderNodeGroup", "Group", NODE_CLASS_GROUP, 0); ntype.type = NODE_GROUP; ntype.poll = sh_node_poll_default; ntype.poll_instance = node_group_poll_instance; @@ -243,7 +243,7 @@ void register_node_type_sh_group(void) node_type_socket_templates(&ntype, NULL, NULL); node_type_size(&ntype, 140, 60, 400); - node_type_label(&ntype, node_group_label); + ntype.labelfunc = node_group_label; node_type_group_update(&ntype, node_group_update); node_type_exec(&ntype, group_initexec, group_freeexec, group_execute); node_type_gpu(&ntype, gpu_group_execute); diff --git a/source/blender/nodes/shader/nodes/node_shader_curves.cc b/source/blender/nodes/shader/nodes/node_shader_curves.cc index 7ce5150bf85..09bbf3d851c 100644 --- a/source/blender/nodes/shader/nodes/node_shader_curves.cc +++ b/source/blender/nodes/shader/nodes/node_shader_curves.cc @@ -152,7 +152,7 @@ static void sh_node_curve_vec_build_multi_function( builder.construct_and_set_matching_fn<CurveVecFunction>(*cumap); } -void register_node_type_sh_curve_vec(void) +void register_node_type_sh_curve_vec() { static bNodeType ntype; @@ -329,7 +329,7 @@ static void sh_node_curve_rgb_build_multi_function( builder.construct_and_set_matching_fn<CurveRGBFunction>(*cumap); } -void register_node_type_sh_curve_rgb(void) +void register_node_type_sh_curve_rgb() { static bNodeType ntype; @@ -473,7 +473,7 @@ static void sh_node_curve_float_build_multi_function( builder.construct_and_set_matching_fn<CurveFloatFunction>(*cumap); } -void register_node_type_sh_curve_float(void) +void register_node_type_sh_curve_float() { static bNodeType ntype; diff --git a/source/blender/nodes/shader/nodes/node_shader_map_range.cc b/source/blender/nodes/shader/nodes/node_shader_map_range.cc index e55963eb500..615ae276eb4 100644 --- a/source/blender/nodes/shader/nodes/node_shader_map_range.cc +++ b/source/blender/nodes/shader/nodes/node_shader_map_range.cc @@ -21,10 +21,14 @@ * \ingroup shdnodes */ +#include <algorithm> + #include "node_shader_util.h" #include "BLI_math_base_safe.h" +NODE_STORAGE_FUNCS(NodeMapRange) + namespace blender::nodes { static void sh_node_map_range_declare(NodeDeclarationBuilder &b) @@ -36,34 +40,80 @@ static void sh_node_map_range_declare(NodeDeclarationBuilder &b) b.add_input<decl::Float>(N_("To Min")).min(-10000.0f).max(10000.0f); b.add_input<decl::Float>(N_("To Max")).min(-10000.0f).max(10000.0f).default_value(1.0f); b.add_input<decl::Float>(N_("Steps")).min(-10000.0f).max(10000.0f).default_value(4.0f); + b.add_input<decl::Vector>(N_("Vector")).min(0.0f).max(1.0f).hide_value(); + b.add_input<decl::Vector>(N_("From Min"), "From_Min_FLOAT3"); + b.add_input<decl::Vector>(N_("From Max"), "From_Max_FLOAT3").default_value(float3(1.0f)); + b.add_input<decl::Vector>(N_("To Min"), "To_Min_FLOAT3"); + b.add_input<decl::Vector>(N_("To Max"), "To_Max_FLOAT3").default_value(float3(1.0f)); + b.add_input<decl::Vector>(N_("Steps"), "Steps_FLOAT3").default_value(float3(4.0f)); b.add_output<decl::Float>(N_("Result")); + b.add_output<decl::Vector>(N_("Vector")); }; } // namespace blender::nodes static void node_shader_update_map_range(bNodeTree *ntree, bNode *node) { - bNodeSocket *sockSteps = nodeFindSocket(node, SOCK_IN, "Steps"); - nodeSetSocketAvailability(ntree, sockSteps, node->custom2 == NODE_MAP_RANGE_STEPPED); + const NodeMapRange &storage = node_storage(*node); + const CustomDataType data_type = static_cast<CustomDataType>(storage.data_type); + const int type = (data_type == CD_PROP_FLOAT) ? SOCK_FLOAT : SOCK_VECTOR; + + LISTBASE_FOREACH (bNodeSocket *, socket, &node->inputs) { + nodeSetSocketAvailability(ntree, socket, socket->type == type); + } + + LISTBASE_FOREACH (bNodeSocket *, socket, &node->outputs) { + nodeSetSocketAvailability(ntree, socket, socket->type == type); + } + + if (storage.interpolation_type != NODE_MAP_RANGE_STEPPED) { + if (type == SOCK_FLOAT) { + bNodeSocket *sockSteps = (bNodeSocket *)BLI_findlink(&node->inputs, 5); + nodeSetSocketAvailability(ntree, sockSteps, false); + } + else { + bNodeSocket *sockSteps = (bNodeSocket *)BLI_findlink(&node->inputs, 11); + nodeSetSocketAvailability(ntree, sockSteps, false); + } + } } static void node_shader_init_map_range(bNodeTree *UNUSED(ntree), bNode *node) { + NodeMapRange *data = (NodeMapRange *)MEM_callocN(sizeof(NodeMapRange), __func__); + data->clamp = 1; + data->data_type = CD_PROP_FLOAT; + data->interpolation_type = NODE_MAP_RANGE_LINEAR; node->custom1 = true; /* use_clamp */ node->custom2 = NODE_MAP_RANGE_LINEAR; /* interpolation */ + node->storage = data; } -static const char *gpu_shader_get_name(int mode) +static const char *gpu_shader_get_name(int mode, bool use_vector) { - switch (mode) { - case NODE_MAP_RANGE_LINEAR: - return "map_range_linear"; - case NODE_MAP_RANGE_STEPPED: - return "map_range_stepped"; - case NODE_MAP_RANGE_SMOOTHSTEP: - return "map_range_smoothstep"; - case NODE_MAP_RANGE_SMOOTHERSTEP: - return "map_range_smootherstep"; + if (use_vector) { + switch (mode) { + case NODE_MAP_RANGE_LINEAR: + return "vector_map_range_linear"; + case NODE_MAP_RANGE_STEPPED: + return "vector_map_range_stepped"; + case NODE_MAP_RANGE_SMOOTHSTEP: + return "vector_map_range_smoothstep"; + case NODE_MAP_RANGE_SMOOTHERSTEP: + return "vector_map_range_smootherstep"; + } + } + else { + switch (mode) { + case NODE_MAP_RANGE_LINEAR: + return "map_range_linear"; + case NODE_MAP_RANGE_STEPPED: + return "map_range_stepped"; + case NODE_MAP_RANGE_SMOOTHSTEP: + return "map_range_smoothstep"; + case NODE_MAP_RANGE_SMOOTHERSTEP: + return "map_range_smootherstep"; + } } return nullptr; @@ -75,22 +125,207 @@ static int gpu_shader_map_range(GPUMaterial *mat, GPUNodeStack *in, GPUNodeStack *out) { - const char *name = gpu_shader_get_name(node->custom2); - + const NodeMapRange &storage = node_storage(*node); + bool use_vector = (storage.data_type == CD_PROP_FLOAT3); + const char *name = gpu_shader_get_name(storage.interpolation_type, use_vector); + float clamp = storage.clamp ? 1.0f : 0.0f; int ret = 0; if (name != nullptr) { - ret = GPU_stack_link(mat, node, name, in, out); + ret = GPU_stack_link(mat, node, name, in, out, GPU_constant(&clamp)); } else { - ret = GPU_stack_link(mat, node, "map_range_linear", in, out); + ret = GPU_stack_link(mat, node, "map_range_linear", in, out, GPU_constant(&clamp)); } - if (ret && node->custom1 && - !ELEM(node->custom2, NODE_MAP_RANGE_SMOOTHSTEP, NODE_MAP_RANGE_SMOOTHERSTEP)) { + if (ret && storage.clamp && !use_vector && + !ELEM(storage.interpolation_type, NODE_MAP_RANGE_SMOOTHSTEP, NODE_MAP_RANGE_SMOOTHERSTEP)) { GPU_link(mat, "clamp_range", out[0].link, in[3].link, in[4].link, &out[0].link); } return ret; } +namespace blender::nodes { + +static inline float clamp_range(const float value, const float min, const float max) +{ + return (min > max) ? std::clamp(value, max, min) : std::clamp(value, min, max); +} + +static float3 clamp_range(const float3 value, const float3 min, const float3 max) +{ + return float3(clamp_range(value.x, min.x, max.x), + clamp_range(value.y, min.y, max.y), + clamp_range(value.z, min.z, max.z)); +} + +static void map_range_vector_signature(blender::fn::MFSignatureBuilder *signature, bool use_steps) +{ + signature->single_input<float3>("Vector"); + signature->single_input<float3>("From Min"); + signature->single_input<float3>("From Max"); + signature->single_input<float3>("To Min"); + signature->single_input<float3>("To Max"); + if (use_steps) { + signature->single_input<float3>("Steps"); + } + signature->single_output<float3>("Vector"); +} + +class MapRangeVectorFunction : public blender::fn::MultiFunction { + private: + bool clamp_; + + public: + MapRangeVectorFunction(bool clamp) : clamp_(clamp) + { + static blender::fn::MFSignature signature = create_signature(); + this->set_signature(&signature); + } + + static blender::fn::MFSignature create_signature() + { + blender::fn::MFSignatureBuilder signature{"Vector Map Range"}; + map_range_vector_signature(&signature, false); + return signature.build(); + } + + void call(blender::IndexMask mask, + blender::fn::MFParams params, + blender::fn::MFContext UNUSED(context)) const override + { + const blender::VArray<float3> &values = params.readonly_single_input<float3>(0, "Vector"); + const blender::VArray<float3> &from_min = params.readonly_single_input<float3>(1, "From Min"); + const blender::VArray<float3> &from_max = params.readonly_single_input<float3>(2, "From Max"); + const blender::VArray<float3> &to_min = params.readonly_single_input<float3>(3, "To Min"); + const blender::VArray<float3> &to_max = params.readonly_single_input<float3>(4, "To Max"); + blender::MutableSpan<float3> results = params.uninitialized_single_output<float3>(5, "Vector"); + + for (int64_t i : mask) { + float3 factor = float3::safe_divide(values[i] - from_min[i], from_max[i] - from_min[i]); + results[i] = factor * (to_max[i] - to_min[i]) + to_min[i]; + } + + if (clamp_) { + for (int64_t i : mask) { + results[i] = clamp_range(results[i], to_min[i], to_max[i]); + } + } + } +}; + +class MapRangeSteppedVectorFunction : public blender::fn::MultiFunction { + private: + bool clamp_; + + public: + MapRangeSteppedVectorFunction(bool clamp) : clamp_(clamp) + { + static blender::fn::MFSignature signature = create_signature(); + this->set_signature(&signature); + } + + static blender::fn::MFSignature create_signature() + { + blender::fn::MFSignatureBuilder signature{"Vector Map Range Stepped"}; + map_range_vector_signature(&signature, true); + return signature.build(); + } + + void call(blender::IndexMask mask, + blender::fn::MFParams params, + blender::fn::MFContext UNUSED(context)) const override + { + const blender::VArray<float3> &values = params.readonly_single_input<float3>(0, "Vector"); + const blender::VArray<float3> &from_min = params.readonly_single_input<float3>(1, "From Min"); + const blender::VArray<float3> &from_max = params.readonly_single_input<float3>(2, "From Max"); + const blender::VArray<float3> &to_min = params.readonly_single_input<float3>(3, "To Min"); + const blender::VArray<float3> &to_max = params.readonly_single_input<float3>(4, "To Max"); + const blender::VArray<float3> &steps = params.readonly_single_input<float3>(5, "Steps"); + blender::MutableSpan<float3> results = params.uninitialized_single_output<float3>(6, "Vector"); + + for (int64_t i : mask) { + float3 factor = float3::safe_divide(values[i] - from_min[i], from_max[i] - from_min[i]); + factor = float3::safe_divide(float3::floor(factor * (steps[i] + 1.0f)), steps[i]); + results[i] = factor * (to_max[i] - to_min[i]) + to_min[i]; + } + + if (clamp_) { + for (int64_t i : mask) { + results[i] = clamp_range(results[i], to_min[i], to_max[i]); + } + } + } +}; + +class MapRangeSmoothstepVectorFunction : public blender::fn::MultiFunction { + public: + MapRangeSmoothstepVectorFunction() + { + static blender::fn::MFSignature signature = create_signature(); + this->set_signature(&signature); + } + + static blender::fn::MFSignature create_signature() + { + blender::fn::MFSignatureBuilder signature{"Vector Map Range Smoothstep"}; + map_range_vector_signature(&signature, false); + return signature.build(); + } + + void call(blender::IndexMask mask, + blender::fn::MFParams params, + blender::fn::MFContext UNUSED(context)) const override + { + const blender::VArray<float3> &values = params.readonly_single_input<float3>(0, "Vector"); + const blender::VArray<float3> &from_min = params.readonly_single_input<float3>(1, "From Min"); + const blender::VArray<float3> &from_max = params.readonly_single_input<float3>(2, "From Max"); + const blender::VArray<float3> &to_min = params.readonly_single_input<float3>(3, "To Min"); + const blender::VArray<float3> &to_max = params.readonly_single_input<float3>(4, "To Max"); + blender::MutableSpan<float3> results = params.uninitialized_single_output<float3>(5, "Vector"); + + for (int64_t i : mask) { + float3 factor = float3::safe_divide(values[i] - from_min[i], from_max[i] - from_min[i]); + clamp_v3(factor, 0.0f, 1.0f); + factor = (float3(3.0f) - 2.0f * factor) * (factor * factor); + results[i] = factor * (to_max[i] - to_min[i]) + to_min[i]; + } + } +}; + +class MapRangeSmootherstepVectorFunction : public blender::fn::MultiFunction { + public: + MapRangeSmootherstepVectorFunction() + { + static blender::fn::MFSignature signature = create_signature(); + this->set_signature(&signature); + } + + static blender::fn::MFSignature create_signature() + { + blender::fn::MFSignatureBuilder signature{"Vector Map Range Smoothstep"}; + map_range_vector_signature(&signature, false); + return signature.build(); + } + + void call(blender::IndexMask mask, + blender::fn::MFParams params, + blender::fn::MFContext UNUSED(context)) const override + { + const blender::VArray<float3> &values = params.readonly_single_input<float3>(0, "Vector"); + const blender::VArray<float3> &from_min = params.readonly_single_input<float3>(1, "From Min"); + const blender::VArray<float3> &from_max = params.readonly_single_input<float3>(2, "From Max"); + const blender::VArray<float3> &to_min = params.readonly_single_input<float3>(3, "To Min"); + const blender::VArray<float3> &to_max = params.readonly_single_input<float3>(4, "To Max"); + blender::MutableSpan<float3> results = params.uninitialized_single_output<float3>(5, "Vector"); + + for (int64_t i : mask) { + float3 factor = float3::safe_divide(values[i] - from_min[i], from_max[i] - from_min[i]); + clamp_v3(factor, 0.0f, 1.0f); + factor = factor * factor * factor * (factor * (factor * 6.0f - 15.0f) + 10.0f); + results[i] = factor * (to_max[i] - to_min[i]) + to_min[i]; + } + } +}; + static void map_range_signature(blender::fn::MFSignatureBuilder *signature, bool use_steps) { signature->single_input<float>("Value"); @@ -140,8 +375,7 @@ class MapRangeFunction : public blender::fn::MultiFunction { if (clamp_) { for (int64_t i : mask) { - results[i] = (to_min[i] > to_max[i]) ? clamp_f(results[i], to_max[i], to_min[i]) : - clamp_f(results[i], to_min[i], to_max[i]); + results[i] = clamp_range(results[i], to_min[i], to_max[i]); } } } @@ -185,8 +419,7 @@ class MapRangeSteppedFunction : public blender::fn::MultiFunction { if (clamp_) { for (int64_t i : mask) { - results[i] = (to_min[i] > to_max[i]) ? clamp_f(results[i], to_max[i], to_min[i]) : - clamp_f(results[i], to_min[i], to_max[i]); + results[i] = clamp_range(results[i], to_min[i], to_max[i]); } } } @@ -265,58 +498,104 @@ class MapRangeSmootherstepFunction : public blender::fn::MultiFunction { static void sh_node_map_range_build_multi_function( blender::nodes::NodeMultiFunctionBuilder &builder) { - bNode &bnode = builder.node(); - bool clamp = bnode.custom1 != 0; - int interpolation_type = bnode.custom2; - - switch (interpolation_type) { - case NODE_MAP_RANGE_LINEAR: { - if (clamp) { - static MapRangeFunction fn_with_clamp{true}; - builder.set_matching_fn(fn_with_clamp); - } - else { - static MapRangeFunction fn_without_clamp{false}; - builder.set_matching_fn(fn_without_clamp); + const NodeMapRange &storage = node_storage(builder.node()); + bool clamp = storage.clamp != 0; + int interpolation_type = storage.interpolation_type; + + switch (storage.data_type) { + case CD_PROP_FLOAT3: + switch (interpolation_type) { + case NODE_MAP_RANGE_LINEAR: { + if (clamp) { + static MapRangeVectorFunction fn_with_clamp{true}; + builder.set_matching_fn(fn_with_clamp); + } + else { + static MapRangeVectorFunction fn_without_clamp{false}; + builder.set_matching_fn(fn_without_clamp); + } + break; + } + case NODE_MAP_RANGE_STEPPED: { + if (clamp) { + static MapRangeSteppedVectorFunction fn_stepped_with_clamp{true}; + builder.set_matching_fn(fn_stepped_with_clamp); + } + else { + static MapRangeSteppedVectorFunction fn_stepped_without_clamp{false}; + builder.set_matching_fn(fn_stepped_without_clamp); + } + break; + } + case NODE_MAP_RANGE_SMOOTHSTEP: { + static MapRangeSmoothstepVectorFunction smoothstep; + builder.set_matching_fn(smoothstep); + break; + } + case NODE_MAP_RANGE_SMOOTHERSTEP: { + static MapRangeSmootherstepVectorFunction smootherstep; + builder.set_matching_fn(smootherstep); + break; + } + default: + break; } break; - } - case NODE_MAP_RANGE_STEPPED: { - if (clamp) { - static MapRangeSteppedFunction fn_stepped_with_clamp{true}; - builder.set_matching_fn(fn_stepped_with_clamp); - } - else { - static MapRangeSteppedFunction fn_stepped_without_clamp{false}; - builder.set_matching_fn(fn_stepped_without_clamp); + case CD_PROP_FLOAT: + switch (interpolation_type) { + case NODE_MAP_RANGE_LINEAR: { + if (clamp) { + static MapRangeFunction fn_with_clamp{true}; + builder.set_matching_fn(fn_with_clamp); + } + else { + static MapRangeFunction fn_without_clamp{false}; + builder.set_matching_fn(fn_without_clamp); + } + break; + } + case NODE_MAP_RANGE_STEPPED: { + if (clamp) { + static MapRangeSteppedFunction fn_stepped_with_clamp{true}; + builder.set_matching_fn(fn_stepped_with_clamp); + } + else { + static MapRangeSteppedFunction fn_stepped_without_clamp{false}; + builder.set_matching_fn(fn_stepped_without_clamp); + } + break; + } + case NODE_MAP_RANGE_SMOOTHSTEP: { + static MapRangeSmoothstepFunction smoothstep; + builder.set_matching_fn(smoothstep); + break; + } + case NODE_MAP_RANGE_SMOOTHERSTEP: { + static MapRangeSmootherstepFunction smootherstep; + builder.set_matching_fn(smootherstep); + break; + } + default: + break; } break; - } - case NODE_MAP_RANGE_SMOOTHSTEP: { - static MapRangeSmoothstepFunction smoothstep; - builder.set_matching_fn(smoothstep); - break; - } - case NODE_MAP_RANGE_SMOOTHERSTEP: { - static MapRangeSmootherstepFunction smootherstep; - builder.set_matching_fn(smootherstep); - break; - } - default: - break; } } -void register_node_type_sh_map_range(void) +} // namespace blender::nodes + +void register_node_type_sh_map_range() { static bNodeType ntype; sh_fn_node_type_base(&ntype, SH_NODE_MAP_RANGE, "Map Range", NODE_CLASS_CONVERTER, 0); ntype.declare = blender::nodes::sh_node_map_range_declare; node_type_init(&ntype, node_shader_init_map_range); + node_type_storage( + &ntype, "NodeMapRange", node_free_standard_storage, node_copy_standard_storage); node_type_update(&ntype, node_shader_update_map_range); node_type_gpu(&ntype, gpu_shader_map_range); - ntype.build_multi_function = sh_node_map_range_build_multi_function; + ntype.build_multi_function = blender::nodes::sh_node_map_range_build_multi_function; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_math.cc b/source/blender/nodes/shader/nodes/node_shader_math.cc index 284a5f1189f..da237be273f 100644 --- a/source/blender/nodes/shader/nodes/node_shader_math.cc +++ b/source/blender/nodes/shader/nodes/node_shader_math.cc @@ -24,6 +24,7 @@ #include "node_shader_util.h" #include "NOD_math_functions.hh" +#include "NOD_socket_search_link.hh" /* **************** SCALAR MATH ******************** */ @@ -44,6 +45,18 @@ static void sh_node_math_declare(NodeDeclarationBuilder &b) b.add_output<decl::Float>(N_("Value")); }; +static void sh_node_math_gather_link_searches(GatherLinkSearchOpParams ¶ms) +{ + /* For now, do something very basic (only exposing "Add", and a single "Value" socket). */ + if (params.node_tree().typeinfo->validate_link( + static_cast<eNodeSocketDatatype>(params.other_socket().type), SOCK_FLOAT)) { + params.add_item(IFACE_("Value"), [](LinkSearchOpParams ¶ms) { + bNode &node = params.add_node("ShaderNodeMath"); + params.update_and_connect_available_socket(node, "Value"); + }); + } +} + } // namespace blender::nodes static const char *gpu_shader_get_name(int mode) @@ -88,7 +101,8 @@ static const blender::fn::MultiFunction *get_base_multi_function(bNode &node) blender::nodes::try_dispatch_float_math_fl_to_fl( mode, [&](auto function, const blender::nodes::FloatMathOperationInfo &info) { - static blender::fn::CustomMF_SI_SO<float, float> fn{info.title_case_name, function}; + static blender::fn::CustomMF_SI_SO<float, float> fn{info.title_case_name.c_str(), + function}; base_fn = &fn; }); if (base_fn != nullptr) { @@ -97,7 +111,7 @@ static const blender::fn::MultiFunction *get_base_multi_function(bNode &node) blender::nodes::try_dispatch_float_math_fl_fl_to_fl( mode, [&](auto function, const blender::nodes::FloatMathOperationInfo &info) { - static blender::fn::CustomMF_SI_SI_SO<float, float, float> fn{info.title_case_name, + static blender::fn::CustomMF_SI_SI_SO<float, float, float> fn{info.title_case_name.c_str(), function}; base_fn = &fn; }); @@ -108,7 +122,7 @@ static const blender::fn::MultiFunction *get_base_multi_function(bNode &node) blender::nodes::try_dispatch_float_math_fl_fl_fl_to_fl( mode, [&](auto function, const blender::nodes::FloatMathOperationInfo &info) { static blender::fn::CustomMF_SI_SI_SI_SO<float, float, float, float> fn{ - info.title_case_name, function}; + info.title_case_name.c_str(), function}; base_fn = &fn; }); if (base_fn != nullptr) { @@ -160,16 +174,17 @@ static void sh_node_math_build_multi_function(blender::nodes::NodeMultiFunctionB } } -void register_node_type_sh_math(void) +void register_node_type_sh_math() { static bNodeType ntype; sh_fn_node_type_base(&ntype, SH_NODE_MATH, "Math", NODE_CLASS_CONVERTER, 0); ntype.declare = blender::nodes::sh_node_math_declare; - node_type_label(&ntype, node_math_label); + ntype.labelfunc = node_math_label; node_type_gpu(&ntype, gpu_shader_math); node_type_update(&ntype, node_math_update); ntype.build_multi_function = sh_node_math_build_multi_function; + ntype.gather_link_search_ops = blender::nodes::sh_node_math_gather_link_searches; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_mixRgb.cc b/source/blender/nodes/shader/nodes/node_shader_mix_rgb.cc index 06fafff578e..b89e0527eed 100644 --- a/source/blender/nodes/shader/nodes/node_shader_mixRgb.cc +++ b/source/blender/nodes/shader/nodes/node_shader_mix_rgb.cc @@ -183,13 +183,13 @@ static void sh_node_mix_rgb_build_multi_function(blender::nodes::NodeMultiFuncti builder.construct_and_set_matching_fn<MixRGBFunction>(clamp, mix_type); } -void register_node_type_sh_mix_rgb(void) +void register_node_type_sh_mix_rgb() { static bNodeType ntype; sh_fn_node_type_base(&ntype, SH_NODE_MIX_RGB, "Mix", NODE_CLASS_OP_COLOR, 0); ntype.declare = blender::nodes::sh_node_mix_rgb_declare; - node_type_label(&ntype, node_blend_label); + ntype.labelfunc = node_blend_label; node_type_exec(&ntype, nullptr, nullptr, node_shader_exec_mix_rgb); node_type_gpu(&ntype, gpu_shader_mix_rgb); ntype.build_multi_function = sh_node_mix_rgb_build_multi_function; diff --git a/source/blender/nodes/shader/nodes/node_shader_valToRgb.cc b/source/blender/nodes/shader/nodes/node_shader_rgb_to_bw.cc index e4f1b2c76f0..e3808985c0e 100644 --- a/source/blender/nodes/shader/nodes/node_shader_valToRgb.cc +++ b/source/blender/nodes/shader/nodes/node_shader_rgb_to_bw.cc @@ -172,7 +172,7 @@ static void sh_node_valtorgb_build_multi_function( builder.construct_and_set_matching_fn<ColorBandFunction>(*color_band); } -void register_node_type_sh_valtorgb(void) +void register_node_type_sh_valtorgb() { static bNodeType ntype; @@ -222,7 +222,7 @@ static int gpu_shader_rgbtobw(GPUMaterial *mat, return GPU_stack_link(mat, node, "rgbtobw", in, out); } -void register_node_type_sh_rgbtobw(void) +void register_node_type_sh_rgbtobw() { static bNodeType ntype; diff --git a/source/blender/nodes/shader/nodes/node_shader_sepcombHSV.c b/source/blender/nodes/shader/nodes/node_shader_sepcomb_hsv.c index dfecb830b35..dfecb830b35 100644 --- a/source/blender/nodes/shader/nodes/node_shader_sepcombHSV.c +++ b/source/blender/nodes/shader/nodes/node_shader_sepcomb_hsv.c diff --git a/source/blender/nodes/shader/nodes/node_shader_sepcombRGB.cc b/source/blender/nodes/shader/nodes/node_shader_sepcomb_rgb.cc index 08a9e01786e..4984a530d8b 100644 --- a/source/blender/nodes/shader/nodes/node_shader_sepcombRGB.cc +++ b/source/blender/nodes/shader/nodes/node_shader_sepcomb_rgb.cc @@ -103,7 +103,7 @@ static void sh_node_seprgb_build_multi_function(blender::nodes::NodeMultiFunctio builder.set_matching_fn(fn); } -void register_node_type_sh_seprgb(void) +void register_node_type_sh_seprgb() { static bNodeType ntype; @@ -163,7 +163,7 @@ static void sh_node_combrgb_build_multi_function(blender::nodes::NodeMultiFuncti builder.set_matching_fn(fn); } -void register_node_type_sh_combrgb(void) +void register_node_type_sh_combrgb() { static bNodeType ntype; diff --git a/source/blender/nodes/shader/nodes/node_shader_sepcombXYZ.cc b/source/blender/nodes/shader/nodes/node_shader_sepcomb_xyz.cc index 1bbfa629462..a414630829e 100644 --- a/source/blender/nodes/shader/nodes/node_shader_sepcombXYZ.cc +++ b/source/blender/nodes/shader/nodes/node_shader_sepcomb_xyz.cc @@ -88,7 +88,7 @@ static void sh_node_sepxyz_build_multi_function(blender::nodes::NodeMultiFunctio builder.set_matching_fn(separate_fn); } -void register_node_type_sh_sepxyz(void) +void register_node_type_sh_sepxyz() { static bNodeType ntype; @@ -129,7 +129,7 @@ static void sh_node_combxyz_build_multi_function(blender::nodes::NodeMultiFuncti builder.set_matching_fn(fn); } -void register_node_type_sh_combxyz(void) +void register_node_type_sh_combxyz() { static bNodeType ntype; diff --git a/source/blender/nodes/shader/nodes/node_shader_shaderToRgb.c b/source/blender/nodes/shader/nodes/node_shader_shader_to_rgb.c index 25c30aa4081..25c30aa4081 100644 --- a/source/blender/nodes/shader/nodes/node_shader_shaderToRgb.c +++ b/source/blender/nodes/shader/nodes/node_shader_shader_to_rgb.c diff --git a/source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.c b/source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.c index e917858e0f2..85a4a6aa425 100644 --- a/source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.c +++ b/source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.c @@ -67,6 +67,17 @@ static int node_shader_gpu_subsurface_scattering(GPUMaterial *mat, mat, node, "node_subsurface_scattering", in, out, GPU_constant(&node->sss_id)); } +static void node_shader_update_subsurface_scattering(bNodeTree *ntree, bNode *node) +{ + const int sss_method = node->custom1; + + for (bNodeSocket *sock = node->inputs.first; sock; sock = sock->next) { + if (STR_ELEM(sock->name, "IOR", "Anisotropy")) { + nodeSetSocketAvailability(ntree, sock, sss_method != SHD_SUBSURFACE_BURLEY); + } + } +} + /* node type definition */ void register_node_type_sh_subsurface_scattering(void) { @@ -80,6 +91,7 @@ void register_node_type_sh_subsurface_scattering(void) node_type_init(&ntype, node_shader_init_subsurface_scattering); node_type_storage(&ntype, "", NULL, NULL); node_type_gpu(&ntype, node_shader_gpu_subsurface_scattering); + node_type_update(&ntype, node_shader_update_subsurface_scattering); nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_brick.cc b/source/blender/nodes/shader/nodes/node_shader_tex_brick.cc index b840bd75e42..7925c96db3d 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_brick.cc +++ b/source/blender/nodes/shader/nodes/node_shader_tex_brick.cc @@ -268,7 +268,7 @@ static void sh_node_brick_build_multi_function(blender::nodes::NodeMultiFunction } // namespace blender::nodes -void register_node_type_sh_tex_brick(void) +void register_node_type_sh_tex_brick() { static bNodeType ntype; diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_checker.cc b/source/blender/nodes/shader/nodes/node_shader_tex_checker.cc index 7c1223a6a32..6d2d199aec8 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_checker.cc +++ b/source/blender/nodes/shader/nodes/node_shader_tex_checker.cc @@ -123,7 +123,7 @@ static void sh_node_tex_checker_build_multi_function( } // namespace blender::nodes -void register_node_type_sh_tex_checker(void) +void register_node_type_sh_tex_checker() { static bNodeType ntype; diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c index 26a1db1f3a6..ff08961b3e9 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c @@ -143,7 +143,7 @@ void register_node_type_sh_tex_environment(void) node_type_storage( &ntype, "NodeTexEnvironment", node_free_standard_storage, node_copy_standard_storage); node_type_gpu(&ntype, node_shader_gpu_tex_environment); - node_type_label(&ntype, node_image_label); + ntype.labelfunc = node_image_label; node_type_size_preset(&ntype, NODE_SIZE_LARGE); nodeRegisterType(&ntype); diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_gradient.cc b/source/blender/nodes/shader/nodes/node_shader_tex_gradient.cc index 33832c42b3c..48199968547 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_gradient.cc +++ b/source/blender/nodes/shader/nodes/node_shader_tex_gradient.cc @@ -160,7 +160,7 @@ static void sh_node_gradient_tex_build_multi_function( } // namespace blender::nodes -void register_node_type_sh_tex_gradient(void) +void register_node_type_sh_tex_gradient() { static bNodeType ntype; diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_image.cc b/source/blender/nodes/shader/nodes/node_shader_tex_image.cc index f20fc85cbe0..d139707c6d7 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_image.cc +++ b/source/blender/nodes/shader/nodes/node_shader_tex_image.cc @@ -174,7 +174,7 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, } /* node type definition */ -void register_node_type_sh_tex_image(void) +void register_node_type_sh_tex_image() { static bNodeType ntype; @@ -184,7 +184,7 @@ void register_node_type_sh_tex_image(void) node_type_storage( &ntype, "NodeTexImage", node_free_standard_storage, node_copy_standard_storage); node_type_gpu(&ntype, node_shader_gpu_tex_image); - node_type_label(&ntype, node_image_label); + ntype.labelfunc = node_image_label; node_type_size_preset(&ntype, NODE_SIZE_LARGE); nodeRegisterType(&ntype); diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_magic.cc b/source/blender/nodes/shader/nodes/node_shader_tex_magic.cc index 62e68d53d03..9bd5c335cee 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_magic.cc +++ b/source/blender/nodes/shader/nodes/node_shader_tex_magic.cc @@ -181,7 +181,7 @@ static void sh_node_magic_tex_build_multi_function( } // namespace blender::nodes -void register_node_type_sh_tex_magic(void) +void register_node_type_sh_tex_magic() { static bNodeType ntype; diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.cc b/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.cc index e426d9cc49c..97ac199bc03 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.cc +++ b/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.cc @@ -21,13 +21,18 @@ #include "BLI_noise.hh" +NODE_STORAGE_FUNCS(NodeTexMusgrave) + namespace blender::nodes { static void sh_node_tex_musgrave_declare(NodeDeclarationBuilder &b) { b.is_function_node(); b.add_input<decl::Vector>(N_("Vector")).hide_value().implicit_field(); - b.add_input<decl::Float>(N_("W")).min(-1000.0f).max(1000.0f); + b.add_input<decl::Float>(N_("W")).min(-1000.0f).max(1000.0f).make_available([](bNode &node) { + /* Default to 1 instead of 4, because it is much faster. */ + node_storage(node).dimensions = 1; + }); b.add_input<decl::Float>(N_("Scale")).min(-1000.0f).max(1000.0f).default_value(5.0f); b.add_input<decl::Float>(N_("Detail")).min(0.0f).max(15.0f).default_value(2.0f); b.add_input<decl::Float>(N_("Dimension")).min(0.0f).max(1000.0f).default_value(2.0f); @@ -106,23 +111,23 @@ static int node_shader_gpu_tex_musgrave(GPUMaterial *mat, static void node_shader_update_tex_musgrave(bNodeTree *ntree, bNode *node) { - NodeTexMusgrave *tex = (NodeTexMusgrave *)node->storage; + const NodeTexMusgrave &storage = node_storage(*node); bNodeSocket *inVectorSock = nodeFindSocket(node, SOCK_IN, "Vector"); bNodeSocket *inWSock = nodeFindSocket(node, SOCK_IN, "W"); bNodeSocket *inOffsetSock = nodeFindSocket(node, SOCK_IN, "Offset"); bNodeSocket *inGainSock = nodeFindSocket(node, SOCK_IN, "Gain"); - nodeSetSocketAvailability(ntree, inVectorSock, tex->dimensions != 1); - nodeSetSocketAvailability(ntree, inWSock, tex->dimensions == 1 || tex->dimensions == 4); + nodeSetSocketAvailability(ntree, inVectorSock, storage.dimensions != 1); + nodeSetSocketAvailability(ntree, inWSock, storage.dimensions == 1 || storage.dimensions == 4); nodeSetSocketAvailability(ntree, inOffsetSock, - tex->musgrave_type != SHD_MUSGRAVE_MULTIFRACTAL && - tex->musgrave_type != SHD_MUSGRAVE_FBM); + storage.musgrave_type != SHD_MUSGRAVE_MULTIFRACTAL && + storage.musgrave_type != SHD_MUSGRAVE_FBM); nodeSetSocketAvailability(ntree, inGainSock, - tex->musgrave_type == SHD_MUSGRAVE_HYBRID_MULTIFRACTAL || - tex->musgrave_type == SHD_MUSGRAVE_RIDGED_MULTIFRACTAL); + storage.musgrave_type == SHD_MUSGRAVE_HYBRID_MULTIFRACTAL || + storage.musgrave_type == SHD_MUSGRAVE_RIDGED_MULTIFRACTAL); bNodeSocket *outFacSock = nodeFindSocket(node, SOCK_OUT, "Fac"); node_sock_label(outFacSock, "Height"); @@ -531,7 +536,7 @@ static void sh_node_musgrave_build_multi_function( } // namespace blender::nodes -void register_node_type_sh_tex_musgrave(void) +void register_node_type_sh_tex_musgrave() { static bNodeType ntype; diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_noise.cc b/source/blender/nodes/shader/nodes/node_shader_tex_noise.cc index 7dd2695ecf7..d7f21853a01 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_noise.cc +++ b/source/blender/nodes/shader/nodes/node_shader_tex_noise.cc @@ -21,13 +21,18 @@ #include "BLI_noise.hh" +NODE_STORAGE_FUNCS(NodeTexNoise) + namespace blender::nodes { static void sh_node_tex_noise_declare(NodeDeclarationBuilder &b) { b.is_function_node(); b.add_input<decl::Vector>(N_("Vector")).implicit_field(); - b.add_input<decl::Float>(N_("W")).min(-1000.0f).max(1000.0f); + b.add_input<decl::Float>(N_("W")).min(-1000.0f).max(1000.0f).make_available([](bNode &node) { + /* Default to 1 instead of 4, because it is much faster. */ + node_storage(node).dimensions = 1; + }); b.add_input<decl::Float>(N_("Scale")).min(-1000.0f).max(1000.0f).default_value(5.0f); b.add_input<decl::Float>(N_("Detail")).min(0.0f).max(15.0f).default_value(2.0f); b.add_input<decl::Float>(N_("Roughness")) @@ -71,8 +76,8 @@ static int node_shader_gpu_tex_noise(GPUMaterial *mat, node_shader_gpu_default_tex_coord(mat, node, &in[0].link); node_shader_gpu_tex_mapping(mat, node, in, out); - NodeTexNoise *tex = (NodeTexNoise *)node->storage; - const char *name = gpu_shader_get_name(tex->dimensions); + const NodeTexNoise &storage = node_storage(*node); + const char *name = gpu_shader_get_name(storage.dimensions); return GPU_stack_link(mat, node, name, in, out); } @@ -81,9 +86,9 @@ static void node_shader_update_tex_noise(bNodeTree *ntree, bNode *node) bNodeSocket *sockVector = nodeFindSocket(node, SOCK_IN, "Vector"); bNodeSocket *sockW = nodeFindSocket(node, SOCK_IN, "W"); - NodeTexNoise *tex = (NodeTexNoise *)node->storage; - nodeSetSocketAvailability(ntree, sockVector, tex->dimensions != 1); - nodeSetSocketAvailability(ntree, sockW, tex->dimensions == 1 || tex->dimensions == 4); + const NodeTexNoise &storage = node_storage(*node); + nodeSetSocketAvailability(ntree, sockVector, storage.dimensions != 1); + nodeSetSocketAvailability(ntree, sockW, storage.dimensions == 1 || storage.dimensions == 4); } namespace blender::nodes { @@ -229,19 +234,26 @@ class NoiseFunction : public fn::MultiFunction { } } } + + ExecutionHints get_execution_hints() const override + { + ExecutionHints hints; + hints.allocates_array = false; + hints.min_grain_size = 100; + return hints; + } }; static void sh_node_noise_build_multi_function(blender::nodes::NodeMultiFunctionBuilder &builder) { - bNode &node = builder.node(); - NodeTexNoise *tex = (NodeTexNoise *)node.storage; - builder.construct_and_set_matching_fn<NoiseFunction>(tex->dimensions); + const NodeTexNoise &storage = node_storage(builder.node()); + builder.construct_and_set_matching_fn<NoiseFunction>(storage.dimensions); } } // namespace blender::nodes /* node type definition */ -void register_node_type_sh_tex_noise(void) +void register_node_type_sh_tex_noise() { static bNodeType ntype; diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.cc b/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.cc index 1bc3741d27c..8a1170de304 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.cc +++ b/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.cc @@ -21,20 +21,30 @@ #include "BLI_noise.hh" +NODE_STORAGE_FUNCS(NodeTexVoronoi) + namespace blender::nodes { static void sh_node_tex_voronoi_declare(NodeDeclarationBuilder &b) { b.is_function_node(); b.add_input<decl::Vector>(N_("Vector")).hide_value().implicit_field(); - b.add_input<decl::Float>(N_("W")).min(-1000.0f).max(1000.0f); + b.add_input<decl::Float>(N_("W")).min(-1000.0f).max(1000.0f).make_available([](bNode &node) { + /* Default to 1 instead of 4, because it is much faster. */ + node_storage(node).dimensions = 1; + }); b.add_input<decl::Float>(N_("Scale")).min(-1000.0f).max(1000.0f).default_value(5.0f); b.add_input<decl::Float>(N_("Smoothness")) .min(0.0f) .max(1.0f) .default_value(1.0f) - .subtype(PROP_FACTOR); - b.add_input<decl::Float>(N_("Exponent")).min(0.0f).max(32.0f).default_value(0.5f); + .subtype(PROP_FACTOR) + .make_available([](bNode &node) { node_storage(node).feature = SHD_VORONOI_SMOOTH_F1; }); + b.add_input<decl::Float>(N_("Exponent")) + .min(0.0f) + .max(32.0f) + .default_value(0.5f) + .make_available([](bNode &node) { node_storage(node).distance = SHD_VORONOI_MINKOWSKI; }); b.add_input<decl::Float>(N_("Randomness")) .min(0.0f) .max(1.0f) @@ -43,8 +53,13 @@ static void sh_node_tex_voronoi_declare(NodeDeclarationBuilder &b) b.add_output<decl::Float>(N_("Distance")).no_muted_links(); b.add_output<decl::Color>(N_("Color")).no_muted_links(); b.add_output<decl::Vector>(N_("Position")).no_muted_links(); - b.add_output<decl::Float>(N_("W")).no_muted_links(); - b.add_output<decl::Float>(N_("Radius")).no_muted_links(); + b.add_output<decl::Float>(N_("W")).no_muted_links().make_available([](bNode &node) { + /* Default to 1 instead of 4, because it is much faster. */ + node_storage(node).dimensions = 1; + }); + b.add_output<decl::Float>(N_("Radius")).no_muted_links().make_available([](bNode &node) { + node_storage(node).feature = SHD_VORONOI_N_SPHERE_RADIUS; + }); }; } // namespace blender::nodes @@ -136,37 +151,40 @@ static void node_shader_update_tex_voronoi(bNodeTree *ntree, bNode *node) bNodeSocket *outWSock = nodeFindSocket(node, SOCK_OUT, "W"); bNodeSocket *outRadiusSock = nodeFindSocket(node, SOCK_OUT, "Radius"); - NodeTexVoronoi *tex = (NodeTexVoronoi *)node->storage; + const NodeTexVoronoi &storage = node_storage(*node); - nodeSetSocketAvailability(ntree, inWSock, tex->dimensions == 1 || tex->dimensions == 4); - nodeSetSocketAvailability(ntree, inVectorSock, tex->dimensions != 1); + nodeSetSocketAvailability(ntree, inWSock, storage.dimensions == 1 || storage.dimensions == 4); + nodeSetSocketAvailability(ntree, inVectorSock, storage.dimensions != 1); nodeSetSocketAvailability( ntree, inExponentSock, - tex->distance == SHD_VORONOI_MINKOWSKI && tex->dimensions != 1 && - !ELEM(tex->feature, SHD_VORONOI_DISTANCE_TO_EDGE, SHD_VORONOI_N_SPHERE_RADIUS)); - nodeSetSocketAvailability(ntree, inSmoothnessSock, tex->feature == SHD_VORONOI_SMOOTH_F1); + storage.distance == SHD_VORONOI_MINKOWSKI && storage.dimensions != 1 && + !ELEM(storage.feature, SHD_VORONOI_DISTANCE_TO_EDGE, SHD_VORONOI_N_SPHERE_RADIUS)); + nodeSetSocketAvailability(ntree, inSmoothnessSock, storage.feature == SHD_VORONOI_SMOOTH_F1); - nodeSetSocketAvailability(ntree, outDistanceSock, tex->feature != SHD_VORONOI_N_SPHERE_RADIUS); + nodeSetSocketAvailability( + ntree, outDistanceSock, storage.feature != SHD_VORONOI_N_SPHERE_RADIUS); nodeSetSocketAvailability(ntree, outColorSock, - tex->feature != SHD_VORONOI_DISTANCE_TO_EDGE && - tex->feature != SHD_VORONOI_N_SPHERE_RADIUS); + storage.feature != SHD_VORONOI_DISTANCE_TO_EDGE && + storage.feature != SHD_VORONOI_N_SPHERE_RADIUS); nodeSetSocketAvailability(ntree, outPositionSock, - tex->feature != SHD_VORONOI_DISTANCE_TO_EDGE && - tex->feature != SHD_VORONOI_N_SPHERE_RADIUS && - tex->dimensions != 1); + storage.feature != SHD_VORONOI_DISTANCE_TO_EDGE && + storage.feature != SHD_VORONOI_N_SPHERE_RADIUS && + storage.dimensions != 1); nodeSetSocketAvailability(ntree, outWSock, - tex->feature != SHD_VORONOI_DISTANCE_TO_EDGE && - tex->feature != SHD_VORONOI_N_SPHERE_RADIUS && - (ELEM(tex->dimensions, 1, 4))); - nodeSetSocketAvailability(ntree, outRadiusSock, tex->feature == SHD_VORONOI_N_SPHERE_RADIUS); + storage.feature != SHD_VORONOI_DISTANCE_TO_EDGE && + storage.feature != SHD_VORONOI_N_SPHERE_RADIUS && + (ELEM(storage.dimensions, 1, 4))); + nodeSetSocketAvailability(ntree, outRadiusSock, storage.feature == SHD_VORONOI_N_SPHERE_RADIUS); } namespace blender::nodes { +static MultiFunction::ExecutionHints voronoi_execution_hints{50, false}; + class VoronoiMinowskiFunction : public fn::MultiFunction { private: int dimensions_; @@ -592,6 +610,11 @@ class VoronoiMinowskiFunction : public fn::MultiFunction { } } } + + ExecutionHints get_execution_hints() const override + { + return voronoi_execution_hints; + } }; class VoronoiMetricFunction : public fn::MultiFunction { @@ -1106,6 +1129,11 @@ class VoronoiMetricFunction : public fn::MultiFunction { } } } + + ExecutionHints get_execution_hints() const override + { + return voronoi_execution_hints; + } }; class VoronoiEdgeFunction : public fn::MultiFunction { @@ -1282,31 +1310,39 @@ class VoronoiEdgeFunction : public fn::MultiFunction { break; } } - }; + } + + ExecutionHints get_execution_hints() const override + { + return voronoi_execution_hints; + } }; static void sh_node_voronoi_build_multi_function(blender::nodes::NodeMultiFunctionBuilder &builder) { - bNode &node = builder.node(); - NodeTexVoronoi *tex = (NodeTexVoronoi *)node.storage; - bool minowski = (tex->distance == SHD_VORONOI_MINKOWSKI && tex->dimensions != 1 && - !ELEM(tex->feature, SHD_VORONOI_DISTANCE_TO_EDGE, SHD_VORONOI_N_SPHERE_RADIUS)); - bool dist_radius = ELEM(tex->feature, SHD_VORONOI_DISTANCE_TO_EDGE, SHD_VORONOI_N_SPHERE_RADIUS); + const NodeTexVoronoi &storage = node_storage(builder.node()); + bool minowski = + (storage.distance == SHD_VORONOI_MINKOWSKI && storage.dimensions != 1 && + !ELEM(storage.feature, SHD_VORONOI_DISTANCE_TO_EDGE, SHD_VORONOI_N_SPHERE_RADIUS)); + bool dist_radius = ELEM( + storage.feature, SHD_VORONOI_DISTANCE_TO_EDGE, SHD_VORONOI_N_SPHERE_RADIUS); if (dist_radius) { - builder.construct_and_set_matching_fn<VoronoiEdgeFunction>(tex->dimensions, tex->feature); + builder.construct_and_set_matching_fn<VoronoiEdgeFunction>(storage.dimensions, + storage.feature); } else if (minowski) { - builder.construct_and_set_matching_fn<VoronoiMinowskiFunction>(tex->dimensions, tex->feature); + builder.construct_and_set_matching_fn<VoronoiMinowskiFunction>(storage.dimensions, + storage.feature); } else { builder.construct_and_set_matching_fn<VoronoiMetricFunction>( - tex->dimensions, tex->feature, tex->distance); + storage.dimensions, storage.feature, storage.distance); } } } // namespace blender::nodes -void register_node_type_sh_tex_voronoi(void) +void register_node_type_sh_tex_voronoi() { static bNodeType ntype; diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_wave.cc b/source/blender/nodes/shader/nodes/node_shader_tex_wave.cc index fe534c605e9..d3e25b533e5 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_wave.cc +++ b/source/blender/nodes/shader/nodes/node_shader_tex_wave.cc @@ -218,7 +218,7 @@ static void sh_node_wave_tex_build_multi_function( } // namespace blender::nodes -void register_node_type_sh_tex_wave(void) +void register_node_type_sh_tex_wave() { static bNodeType ntype; diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_white_noise.cc b/source/blender/nodes/shader/nodes/node_shader_tex_white_noise.cc index 7b4ff7fec5c..0e72cee38e7 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_white_noise.cc +++ b/source/blender/nodes/shader/nodes/node_shader_tex_white_noise.cc @@ -27,7 +27,10 @@ static void sh_node_tex_white_noise_declare(NodeDeclarationBuilder &b) { b.is_function_node(); b.add_input<decl::Vector>(N_("Vector")).min(-10000.0f).max(10000.0f).implicit_field(); - b.add_input<decl::Float>(N_("W")).min(-10000.0f).max(10000.0f); + b.add_input<decl::Float>(N_("W")).min(-10000.0f).max(10000.0f).make_available([](bNode &node) { + /* Default to 1 instead of 4, because it is faster. */ + node.custom1 = 1; + }); b.add_output<decl::Float>(N_("Value")); b.add_output<decl::Color>(N_("Color")); }; @@ -191,7 +194,7 @@ static void sh_node_noise_build_multi_function(blender::nodes::NodeMultiFunction } // namespace blender::nodes -void register_node_type_sh_tex_white_noise(void) +void register_node_type_sh_tex_white_noise() { static bNodeType ntype; diff --git a/source/blender/nodes/shader/nodes/node_shader_uvAlongStroke.c b/source/blender/nodes/shader/nodes/node_shader_uv_along_stroke.c index 05c3248af65..05c3248af65 100644 --- a/source/blender/nodes/shader/nodes/node_shader_uvAlongStroke.c +++ b/source/blender/nodes/shader/nodes/node_shader_uv_along_stroke.c diff --git a/source/blender/nodes/shader/nodes/node_shader_value.cc b/source/blender/nodes/shader/nodes/node_shader_value.cc index b0f152d8526..f0eb3ea9bee 100644 --- a/source/blender/nodes/shader/nodes/node_shader_value.cc +++ b/source/blender/nodes/shader/nodes/node_shader_value.cc @@ -49,7 +49,7 @@ static void sh_node_value_build_multi_function(blender::nodes::NodeMultiFunction builder.construct_and_set_matching_fn<blender::fn::CustomMF_Constant<float>>(value->value); } -void register_node_type_sh_value(void) +void register_node_type_sh_value() { static bNodeType ntype; diff --git a/source/blender/nodes/shader/nodes/node_shader_vector_math.cc b/source/blender/nodes/shader/nodes/node_shader_vector_math.cc index fad93962708..5f5969de78c 100644 --- a/source/blender/nodes/shader/nodes/node_shader_vector_math.cc +++ b/source/blender/nodes/shader/nodes/node_shader_vector_math.cc @@ -24,6 +24,7 @@ #include "node_shader_util.h" #include "NOD_math_functions.hh" +#include "NOD_socket_search_link.hh" namespace blender::nodes { @@ -38,6 +39,18 @@ static void sh_node_vector_math_declare(NodeDeclarationBuilder &b) b.add_output<decl::Float>(N_("Value")); }; +static void sh_node_vector_math_gather_link_searches(GatherLinkSearchOpParams ¶ms) +{ + /* For now, do something very basic (only exposing "Add", and a single "Vector" socket). */ + if (params.node_tree().typeinfo->validate_link( + static_cast<eNodeSocketDatatype>(params.other_socket().type), SOCK_VECTOR)) { + params.add_item(IFACE_("Vector"), [](LinkSearchOpParams ¶ms) { + bNode &node = params.add_node("ShaderNodeVectorMath"); + params.update_and_connect_available_socket(node, "Vector"); + }); + } +} + } // namespace blender::nodes static const char *gpu_shader_get_name(int mode) @@ -201,8 +214,8 @@ static const blender::fn::MultiFunction *get_multi_function(bNode &node) blender::nodes::try_dispatch_float_math_fl3_fl3_to_fl3( operation, [&](auto function, const blender::nodes::FloatMathOperationInfo &info) { - static blender::fn::CustomMF_SI_SI_SO<float3, float3, float3> fn{info.title_case_name, - function}; + static blender::fn::CustomMF_SI_SI_SO<float3, float3, float3> fn{ + info.title_case_name.c_str(), function}; multi_fn = &fn; }); if (multi_fn != nullptr) { @@ -212,7 +225,7 @@ static const blender::fn::MultiFunction *get_multi_function(bNode &node) blender::nodes::try_dispatch_float_math_fl3_fl3_fl3_to_fl3( operation, [&](auto function, const blender::nodes::FloatMathOperationInfo &info) { static blender::fn::CustomMF_SI_SI_SI_SO<float3, float3, float3, float3> fn{ - info.title_case_name, function}; + info.title_case_name.c_str(), function}; multi_fn = &fn; }); if (multi_fn != nullptr) { @@ -222,7 +235,7 @@ static const blender::fn::MultiFunction *get_multi_function(bNode &node) blender::nodes::try_dispatch_float_math_fl3_fl3_fl_to_fl3( operation, [&](auto function, const blender::nodes::FloatMathOperationInfo &info) { static blender::fn::CustomMF_SI_SI_SI_SO<float3, float3, float, float3> fn{ - info.title_case_name, function}; + info.title_case_name.c_str(), function}; multi_fn = &fn; }); if (multi_fn != nullptr) { @@ -231,8 +244,8 @@ static const blender::fn::MultiFunction *get_multi_function(bNode &node) blender::nodes::try_dispatch_float_math_fl3_fl3_to_fl( operation, [&](auto function, const blender::nodes::FloatMathOperationInfo &info) { - static blender::fn::CustomMF_SI_SI_SO<float3, float3, float> fn{info.title_case_name, - function}; + static blender::fn::CustomMF_SI_SI_SO<float3, float3, float> fn{ + info.title_case_name.c_str(), function}; multi_fn = &fn; }); if (multi_fn != nullptr) { @@ -241,8 +254,8 @@ static const blender::fn::MultiFunction *get_multi_function(bNode &node) blender::nodes::try_dispatch_float_math_fl3_fl_to_fl3( operation, [&](auto function, const blender::nodes::FloatMathOperationInfo &info) { - static blender::fn::CustomMF_SI_SI_SO<float3, float, float3> fn{info.title_case_name, - function}; + static blender::fn::CustomMF_SI_SI_SO<float3, float, float3> fn{ + info.title_case_name.c_str(), function}; multi_fn = &fn; }); if (multi_fn != nullptr) { @@ -251,7 +264,8 @@ static const blender::fn::MultiFunction *get_multi_function(bNode &node) blender::nodes::try_dispatch_float_math_fl3_to_fl3( operation, [&](auto function, const blender::nodes::FloatMathOperationInfo &info) { - static blender::fn::CustomMF_SI_SO<float3, float3> fn{info.title_case_name, function}; + static blender::fn::CustomMF_SI_SO<float3, float3> fn{info.title_case_name.c_str(), + function}; multi_fn = &fn; }); if (multi_fn != nullptr) { @@ -260,7 +274,8 @@ static const blender::fn::MultiFunction *get_multi_function(bNode &node) blender::nodes::try_dispatch_float_math_fl3_to_fl( operation, [&](auto function, const blender::nodes::FloatMathOperationInfo &info) { - static blender::fn::CustomMF_SI_SO<float3, float> fn{info.title_case_name, function}; + static blender::fn::CustomMF_SI_SO<float3, float> fn{info.title_case_name.c_str(), + function}; multi_fn = &fn; }); if (multi_fn != nullptr) { @@ -277,16 +292,17 @@ static void sh_node_vector_math_build_multi_function( builder.set_matching_fn(fn); } -void register_node_type_sh_vect_math(void) +void register_node_type_sh_vect_math() { static bNodeType ntype; sh_fn_node_type_base(&ntype, SH_NODE_VECTOR_MATH, "Vector Math", NODE_CLASS_OP_VECTOR, 0); ntype.declare = blender::nodes::sh_node_vector_math_declare; - node_type_label(&ntype, node_vector_math_label); + ntype.labelfunc = node_vector_math_label; node_type_gpu(&ntype, gpu_shader_vector_math); node_type_update(&ntype, node_shader_update_vector_math); ntype.build_multi_function = sh_node_vector_math_build_multi_function; + ntype.gather_link_search_ops = blender::nodes::sh_node_vector_math_gather_link_searches; 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 3c1f1ed8d39..a3cb82f3245 100644 --- a/source/blender/nodes/shader/nodes/node_shader_vector_rotate.cc +++ b/source/blender/nodes/shader/nodes/node_shader_vector_rotate.cc @@ -205,7 +205,7 @@ static void node_shader_update_vector_rotate(bNodeTree *ntree, bNode *node) ntree, sock_angle, !ELEM(node->custom1, NODE_VECTOR_ROTATE_TYPE_EULER_XYZ)); } -void register_node_type_sh_vector_rotate(void) +void register_node_type_sh_vector_rotate() { static bNodeType ntype; diff --git a/source/blender/nodes/shader/nodes/node_shader_vectTransform.c b/source/blender/nodes/shader/nodes/node_shader_vector_transform.c index 7b08178f874..7b08178f874 100644 --- a/source/blender/nodes/shader/nodes/node_shader_vectTransform.c +++ b/source/blender/nodes/shader/nodes/node_shader_vector_transform.c |