diff options
Diffstat (limited to 'source/blender/nodes/shader')
19 files changed, 1128 insertions, 291 deletions
diff --git a/source/blender/nodes/shader/node_shader_tree.c b/source/blender/nodes/shader/node_shader_tree.c index 179a92ec7bd..758f7edfe49 100644 --- a/source/blender/nodes/shader/node_shader_tree.c +++ b/source/blender/nodes/shader/node_shader_tree.c @@ -344,15 +344,23 @@ static void ntree_shader_unlink_hidden_value_sockets(bNode *group_node, bNodeSoc bool removed_link = false; for (node = group_ntree->nodes.first; node; node = node->next) { + const bool is_group = ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP) && (node->id != NULL); + LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) { - if ((sock->flag & SOCK_HIDE_VALUE) == 0) { + if (!is_group && (sock->flag & SOCK_HIDE_VALUE) == 0) { continue; } /* If socket is linked to a group input node and sockets id match. */ if (sock && sock->link && sock->link->fromnode->type == NODE_GROUP_INPUT) { if (STREQ(isock->identifier, sock->link->fromsock->identifier)) { - nodeRemLink(group_ntree, sock->link); - removed_link = true; + if (is_group) { + /* Recursively unlink sockets within the nested group. */ + ntree_shader_unlink_hidden_value_sockets(node, sock); + } + else { + nodeRemLink(group_ntree, sock->link); + removed_link = true; + } } } } diff --git a/source/blender/nodes/shader/node_shader_util.h b/source/blender/nodes/shader/node_shader_util.h index fbb9979cdfa..de192f51a5f 100644 --- a/source/blender/nodes/shader/node_shader_util.h +++ b/source/blender/nodes/shader/node_shader_util.h @@ -21,8 +21,7 @@ * \ingroup nodes */ -#ifndef __NODE_SHADER_UTIL_H__ -#define __NODE_SHADER_UTIL_H__ +#pragma once #include <float.h> #include <math.h> @@ -42,6 +41,7 @@ #include "BLI_blenlib.h" #include "BLI_math.h" +#include "BLI_math_base_safe.h" #include "BLI_rand.h" #include "BLI_threads.h" #include "BLI_utildefines.h" @@ -70,6 +70,13 @@ #include "GPU_uniformbuffer.h" #ifdef __cplusplus +# include "FN_multi_function_builder.hh" + +# include "NOD_node_tree_multi_function.hh" + +# include "BLI_color.hh" +# include "BLI_float3.hh" + extern "C" { #endif @@ -108,5 +115,3 @@ void ntreeExecGPUNodes(struct bNodeTreeExec *exec, #ifdef __cplusplus } #endif - -#endif diff --git a/source/blender/nodes/shader/nodes/node_shader_clamp.c b/source/blender/nodes/shader/nodes/node_shader_clamp.cc index 808f9686f0a..1077f616a62 100644 --- a/source/blender/nodes/shader/nodes/node_shader_clamp.c +++ b/source/blender/nodes/shader/nodes/node_shader_clamp.cc @@ -50,6 +50,30 @@ static int gpu_shader_clamp(GPUMaterial *mat, GPU_stack_link(mat, node, "clamp_range", in, out); } +static void sh_node_clamp_expand_in_mf_network(blender::nodes::NodeMFNetworkBuilder &builder) +{ + static blender::fn::CustomMF_SI_SI_SI_SO<float, float, float, float> minmax_fn{ + "Clamp (Min Max)", + [](float value, float min, float max) { return std::min(std::max(value, min), max); }}; + static blender::fn::CustomMF_SI_SI_SI_SO<float, float, float, float> range_fn{ + "Clamp (Range)", [](float value, float a, float b) { + if (a < b) { + return clamp_f(value, a, b); + } + else { + return clamp_f(value, b, a); + } + }}; + + int clamp_type = builder.bnode().custom1; + if (clamp_type == NODE_CLAMP_MINMAX) { + builder.set_matching_fn(minmax_fn); + } + else { + builder.set_matching_fn(range_fn); + } +} + void register_node_type_sh_clamp(void) { static bNodeType ntype; @@ -58,6 +82,7 @@ void register_node_type_sh_clamp(void) node_type_socket_templates(&ntype, sh_node_clamp_in, sh_node_clamp_out); node_type_init(&ntype, node_shader_init_clamp); node_type_gpu(&ntype, gpu_shader_clamp); + ntype.expand_in_mf_network = sh_node_clamp_expand_in_mf_network; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_curves.c b/source/blender/nodes/shader/nodes/node_shader_curves.c index 68f252cb092..06aaf9e74cb 100644 --- a/source/blender/nodes/shader/nodes/node_shader_curves.c +++ b/source/blender/nodes/shader/nodes/node_shader_curves.c @@ -168,7 +168,7 @@ static int gpu_shader_curve_rgb(GPUMaterial *mat, CurveMapping *cumap = node->storage; - BKE_curvemapping_initialize(cumap); + BKE_curvemapping_init(cumap); BKE_curvemapping_table_RGBA(cumap, &array, &size); GPUNodeLink *tex = GPU_color_band(mat, size, array, &layer); diff --git a/source/blender/nodes/shader/nodes/node_shader_geometry.c b/source/blender/nodes/shader/nodes/node_shader_geometry.c index deb0ee9037c..30e376f8e09 100644 --- a/source/blender/nodes/shader/nodes/node_shader_geometry.c +++ b/source/blender/nodes/shader/nodes/node_shader_geometry.c @@ -45,6 +45,9 @@ static int node_shader_gpu_geometry(GPUMaterial *mat, float val[4] = {0.0f, 0.0f, 0.0f, 0.0f}; GPUNodeLink *bary_link = (!out[5].hasoutput) ? GPU_constant(val) : GPU_builtin(GPU_BARYCENTRIC_TEXCO); + if (out[5].hasoutput) { + GPU_material_flag_set(mat, GPU_MATFLAG_BARYCENTRIC); + } /* Opti: don't request orco if not needed. */ GPUNodeLink *orco_link = (!out[2].hasoutput) ? GPU_constant(val) : GPU_attribute(mat, CD_ORCO, ""); diff --git a/source/blender/nodes/shader/nodes/node_shader_map_range.c b/source/blender/nodes/shader/nodes/node_shader_map_range.cc index 5db7983e752..4a6c9ec9a4d 100644 --- a/source/blender/nodes/shader/nodes/node_shader_map_range.c +++ b/source/blender/nodes/shader/nodes/node_shader_map_range.cc @@ -50,22 +50,33 @@ static void node_shader_init_map_range(bNodeTree *UNUSED(ntree), bNode *node) node->custom2 = NODE_MAP_RANGE_LINEAR; /* interpolation */ } +static const char *gpu_shader_get_name(int mode) +{ + 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; +} + static int gpu_shader_map_range(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { - static const char *names[] = { - [NODE_MAP_RANGE_LINEAR] = "map_range_linear", - [NODE_MAP_RANGE_STEPPED] = "map_range_stepped", - [NODE_MAP_RANGE_SMOOTHSTEP] = "map_range_smoothstep", - [NODE_MAP_RANGE_SMOOTHERSTEP] = "map_range_smootherstep", - }; + const char *name = gpu_shader_get_name(node->custom2); int ret = 0; - if (node->custom2 < ARRAY_SIZE(names) && names[node->custom2]) { - ret = GPU_stack_link(mat, node, names[node->custom2], in, out); + if (name != nullptr) { + ret = GPU_stack_link(mat, node, name, in, out); } else { ret = GPU_stack_link(mat, node, "map_range_linear", in, out); @@ -77,6 +88,68 @@ static int gpu_shader_map_range(GPUMaterial *mat, return ret; } +class MapRangeFunction : public blender::fn::MultiFunction { + private: + bool clamp_; + + public: + MapRangeFunction(bool clamp) : clamp_(clamp) + { + blender::fn::MFSignatureBuilder signature = this->get_builder("Map Range"); + signature.single_input<float>("Value"); + signature.single_input<float>("From Min"); + signature.single_input<float>("From Max"); + signature.single_input<float>("To Min"); + signature.single_input<float>("To Max"); + signature.single_output<float>("Result"); + } + + void call(blender::IndexMask mask, + blender::fn::MFParams params, + blender::fn::MFContext UNUSED(context)) const override + { + blender::fn::VSpan<float> values = params.readonly_single_input<float>(0, "Value"); + blender::fn::VSpan<float> from_min = params.readonly_single_input<float>(1, "From Min"); + blender::fn::VSpan<float> from_max = params.readonly_single_input<float>(2, "From Max"); + blender::fn::VSpan<float> to_min = params.readonly_single_input<float>(3, "To Min"); + blender::fn::VSpan<float> to_max = params.readonly_single_input<float>(4, "To Max"); + blender::MutableSpan<float> results = params.uninitialized_single_output<float>(5, "Result"); + + for (int64_t i : mask) { + float factor = safe_divide(values[i] - from_min[i], from_max[i] - from_min[i]); + results[i] = to_min[i] + factor * (to_max[i] - to_min[i]); + } + + if (clamp_) { + for (int64_t i : mask) { + CLAMP(results[i], 0.0f, 1.0f); + } + } + } +}; + +static void sh_node_map_range_expand_in_mf_network(blender::nodes::NodeMFNetworkBuilder &builder) +{ + bNode &bnode = builder.bnode(); + bool clamp = bnode.custom1 != 0; + int interpolation_type = bnode.custom2; + + if (interpolation_type == NODE_MAP_RANGE_LINEAR) { + static MapRangeFunction fn_with_clamp{true}; + static MapRangeFunction fn_without_clamp{false}; + + if (clamp) { + builder.set_matching_fn(fn_with_clamp); + } + else { + builder.set_matching_fn(fn_without_clamp); + } + } + else { + builder.set_not_implemented(); + } +} + void register_node_type_sh_map_range(void) { static bNodeType ntype; @@ -86,6 +159,7 @@ void register_node_type_sh_map_range(void) node_type_init(&ntype, node_shader_init_map_range); node_type_update(&ntype, node_shader_update_map_range); node_type_gpu(&ntype, gpu_shader_map_range); + ntype.expand_in_mf_network = sh_node_map_range_expand_in_mf_network; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_math.c b/source/blender/nodes/shader/nodes/node_shader_math.c deleted file mode 100644 index 8abebbf5081..00000000000 --- a/source/blender/nodes/shader/nodes/node_shader_math.c +++ /dev/null @@ -1,115 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2005 Blender Foundation. - * All rights reserved. - */ - -/** \file - * \ingroup shdnodes - */ - -#include "node_shader_util.h" - -/* **************** SCALAR MATH ******************** */ -static bNodeSocketTemplate sh_node_math_in[] = { - {SOCK_FLOAT, N_("Value"), 0.5f, 0.5f, 0.5f, 1.0f, -10000.0f, 10000.0f, PROP_NONE}, - {SOCK_FLOAT, N_("Value"), 0.5f, 0.5f, 0.5f, 1.0f, -10000.0f, 10000.0f, PROP_NONE}, - {SOCK_FLOAT, N_("Value"), 0.0f, 0.5f, 0.5f, 1.0f, -10000.0f, 10000.0f, PROP_NONE}, - {-1, ""}}; - -static bNodeSocketTemplate sh_node_math_out[] = {{SOCK_FLOAT, N_("Value")}, {-1, ""}}; - -static int gpu_shader_math(GPUMaterial *mat, - bNode *node, - bNodeExecData *UNUSED(execdata), - GPUNodeStack *in, - GPUNodeStack *out) -{ - static const char *names[] = { - [NODE_MATH_ADD] = "math_add", - [NODE_MATH_SUBTRACT] = "math_subtract", - [NODE_MATH_MULTIPLY] = "math_multiply", - [NODE_MATH_DIVIDE] = "math_divide", - [NODE_MATH_MULTIPLY_ADD] = "math_multiply_add", - - [NODE_MATH_POWER] = "math_power", - [NODE_MATH_LOGARITHM] = "math_logarithm", - [NODE_MATH_EXPONENT] = "math_exponent", - [NODE_MATH_SQRT] = "math_sqrt", - [NODE_MATH_INV_SQRT] = "math_inversesqrt", - [NODE_MATH_ABSOLUTE] = "math_absolute", - [NODE_MATH_RADIANS] = "math_radians", - [NODE_MATH_DEGREES] = "math_degrees", - - [NODE_MATH_MINIMUM] = "math_minimum", - [NODE_MATH_MAXIMUM] = "math_maximum", - [NODE_MATH_LESS_THAN] = "math_less_than", - [NODE_MATH_GREATER_THAN] = "math_greater_than", - [NODE_MATH_SIGN] = "math_sign", - [NODE_MATH_COMPARE] = "math_compare", - [NODE_MATH_SMOOTH_MIN] = "math_smoothmin", - [NODE_MATH_SMOOTH_MAX] = "math_smoothmax", - - [NODE_MATH_ROUND] = "math_round", - [NODE_MATH_FLOOR] = "math_floor", - [NODE_MATH_CEIL] = "math_ceil", - [NODE_MATH_FRACTION] = "math_fraction", - [NODE_MATH_MODULO] = "math_modulo", - [NODE_MATH_TRUNC] = "math_trunc", - [NODE_MATH_SNAP] = "math_snap", - [NODE_MATH_WRAP] = "math_wrap", - [NODE_MATH_PINGPONG] = "math_pingpong", - - [NODE_MATH_SINE] = "math_sine", - [NODE_MATH_COSINE] = "math_cosine", - [NODE_MATH_TANGENT] = "math_tangent", - [NODE_MATH_SINH] = "math_sinh", - [NODE_MATH_COSH] = "math_cosh", - [NODE_MATH_TANH] = "math_tanh", - [NODE_MATH_ARCSINE] = "math_arcsine", - [NODE_MATH_ARCCOSINE] = "math_arccosine", - [NODE_MATH_ARCTANGENT] = "math_arctangent", - [NODE_MATH_ARCTAN2] = "math_arctan2", - }; - - if (node->custom1 < ARRAY_SIZE(names) && names[node->custom1]) { - int ret = GPU_stack_link(mat, node, names[node->custom1], in, out); - - if (ret && node->custom2 & SHD_MATH_CLAMP) { - float min[3] = {0.0f, 0.0f, 0.0f}; - float max[3] = {1.0f, 1.0f, 1.0f}; - GPU_link( - mat, "clamp_value", out[0].link, GPU_constant(min), GPU_constant(max), &out[0].link); - } - return ret; - } - else { - return 0; - } -} - -void register_node_type_sh_math(void) -{ - static bNodeType ntype; - - sh_fn_node_type_base(&ntype, SH_NODE_MATH, "Math", NODE_CLASS_CONVERTOR, 0); - node_type_socket_templates(&ntype, sh_node_math_in, sh_node_math_out); - node_type_label(&ntype, node_math_label); - node_type_gpu(&ntype, gpu_shader_math); - node_type_update(&ntype, node_math_update); - - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/shader/nodes/node_shader_math.cc b/source/blender/nodes/shader/nodes/node_shader_math.cc new file mode 100644 index 00000000000..c7035da8c70 --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_math.cc @@ -0,0 +1,387 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup shdnodes + */ + +#include "node_shader_util.h" + +/* **************** SCALAR MATH ******************** */ +static bNodeSocketTemplate sh_node_math_in[] = { + {SOCK_FLOAT, N_("Value"), 0.5f, 0.5f, 0.5f, 1.0f, -10000.0f, 10000.0f, PROP_NONE}, + {SOCK_FLOAT, N_("Value"), 0.5f, 0.5f, 0.5f, 1.0f, -10000.0f, 10000.0f, PROP_NONE}, + {SOCK_FLOAT, N_("Value"), 0.0f, 0.5f, 0.5f, 1.0f, -10000.0f, 10000.0f, PROP_NONE}, + {-1, ""}}; + +static bNodeSocketTemplate sh_node_math_out[] = {{SOCK_FLOAT, N_("Value")}, {-1, ""}}; + +static const char *gpu_shader_get_name(int mode) +{ + switch (mode) { + case NODE_MATH_ADD: + return "math_add"; + case NODE_MATH_SUBTRACT: + return "math_subtract"; + case NODE_MATH_MULTIPLY: + return "math_multiply"; + case NODE_MATH_DIVIDE: + return "math_divide"; + case NODE_MATH_MULTIPLY_ADD: + return "math_multiply_add"; + + case NODE_MATH_POWER: + return "math_power"; + case NODE_MATH_LOGARITHM: + return "math_logarithm"; + case NODE_MATH_EXPONENT: + return "math_exponent"; + case NODE_MATH_SQRT: + return "math_sqrt"; + case NODE_MATH_INV_SQRT: + return "math_inversesqrt"; + case NODE_MATH_ABSOLUTE: + return "math_absolute"; + case NODE_MATH_RADIANS: + return "math_radians"; + case NODE_MATH_DEGREES: + return "math_degrees"; + + case NODE_MATH_MINIMUM: + return "math_minimum"; + case NODE_MATH_MAXIMUM: + return "math_maximum"; + case NODE_MATH_LESS_THAN: + return "math_less_than"; + case NODE_MATH_GREATER_THAN: + return "math_greater_than"; + case NODE_MATH_SIGN: + return "math_sign"; + case NODE_MATH_COMPARE: + return "math_compare"; + case NODE_MATH_SMOOTH_MIN: + return "math_smoothmin"; + case NODE_MATH_SMOOTH_MAX: + return "math_smoothmax"; + + case NODE_MATH_ROUND: + return "math_round"; + case NODE_MATH_FLOOR: + return "math_floor"; + case NODE_MATH_CEIL: + return "math_ceil"; + case NODE_MATH_FRACTION: + return "math_fraction"; + case NODE_MATH_MODULO: + return "math_modulo"; + case NODE_MATH_TRUNC: + return "math_trunc"; + case NODE_MATH_SNAP: + return "math_snap"; + case NODE_MATH_WRAP: + return "math_wrap"; + case NODE_MATH_PINGPONG: + return "math_pingpong"; + + case NODE_MATH_SINE: + return "math_sine"; + case NODE_MATH_COSINE: + return "math_cosine"; + case NODE_MATH_TANGENT: + return "math_tangent"; + case NODE_MATH_SINH: + return "math_sinh"; + case NODE_MATH_COSH: + return "math_cosh"; + case NODE_MATH_TANH: + return "math_tanh"; + case NODE_MATH_ARCSINE: + return "math_arcsine"; + case NODE_MATH_ARCCOSINE: + return "math_arccosine"; + case NODE_MATH_ARCTANGENT: + return "math_arctangent"; + case NODE_MATH_ARCTAN2: + return "math_arctan2"; + } + return nullptr; +} + +static int gpu_shader_math(GPUMaterial *mat, + bNode *node, + bNodeExecData *UNUSED(execdata), + GPUNodeStack *in, + GPUNodeStack *out) +{ + const char *name = gpu_shader_get_name(node->custom1); + if (name != nullptr) { + int ret = GPU_stack_link(mat, node, name, in, out); + + if (ret && node->custom2 & SHD_MATH_CLAMP) { + float min[3] = {0.0f, 0.0f, 0.0f}; + float max[3] = {1.0f, 1.0f, 1.0f}; + GPU_link( + mat, "clamp_value", out[0].link, GPU_constant(min), GPU_constant(max), &out[0].link); + } + return ret; + } + else { + return 0; + } +} + +static const blender::fn::MultiFunction &get_base_multi_function( + blender::nodes::NodeMFNetworkBuilder &builder) +{ + const int mode = builder.bnode().custom1; + switch (mode) { + case NODE_MATH_ADD: { + static blender::fn::CustomMF_SI_SI_SO<float, float, float> fn{ + "Add", [](float a, float b) { return a + b; }}; + return fn; + } + case NODE_MATH_SUBTRACT: { + static blender::fn::CustomMF_SI_SI_SO<float, float, float> fn{ + "Subtract", [](float a, float b) { return a - b; }}; + return fn; + } + case NODE_MATH_MULTIPLY: { + static blender::fn::CustomMF_SI_SI_SO<float, float, float> fn{ + "Multiply", [](float a, float b) { return a * b; }}; + return fn; + } + case NODE_MATH_DIVIDE: { + static blender::fn::CustomMF_SI_SI_SO<float, float, float> fn{"Divide", safe_divide}; + return fn; + } + case NODE_MATH_MULTIPLY_ADD: { + static blender::fn::CustomMF_SI_SI_SI_SO<float, float, float, float> fn{ + "Multiply Add", [](float a, float b, float c) { return a * b + c; }}; + return fn; + } + + case NODE_MATH_POWER: { + static blender::fn::CustomMF_SI_SI_SO<float, float, float> fn{"Power", safe_powf}; + return fn; + } + case NODE_MATH_LOGARITHM: { + static blender::fn::CustomMF_SI_SI_SO<float, float, float> fn{"Logarithm", safe_logf}; + return fn; + } + case NODE_MATH_EXPONENT: { + static blender::fn::CustomMF_SI_SO<float, float> fn{"Exponent", expf}; + return fn; + } + case NODE_MATH_SQRT: { + static blender::fn::CustomMF_SI_SO<float, float> fn{"Sqrt", safe_sqrtf}; + return fn; + } + case NODE_MATH_INV_SQRT: { + static blender::fn::CustomMF_SI_SO<float, float> fn{"Inverse Sqrt", safe_inverse_sqrtf}; + return fn; + }; + case NODE_MATH_ABSOLUTE: { + static blender::fn::CustomMF_SI_SO<float, float> fn{"Absolute", + [](float a) { return fabs(a); }}; + return fn; + } + case NODE_MATH_RADIANS: { + static blender::fn::CustomMF_SI_SO<float, float> fn{"Radians", + [](float a) { return DEG2RAD(a); }}; + return fn; + } + case NODE_MATH_DEGREES: { + static blender::fn::CustomMF_SI_SO<float, float> fn{"Degrees", + [](float a) { return RAD2DEG(a); }}; + return fn; + } + + case NODE_MATH_MINIMUM: { + static blender::fn::CustomMF_SI_SI_SO<float, float, float> fn{ + "Minimum", [](float a, float b) { return std::min(a, b); }}; + return fn; + } + case NODE_MATH_MAXIMUM: { + static blender::fn::CustomMF_SI_SI_SO<float, float, float> fn{ + "Maximum", [](float a, float b) { return std::max(a, b); }}; + return fn; + } + case NODE_MATH_LESS_THAN: { + static blender::fn::CustomMF_SI_SI_SO<float, float, float> fn{ + "Less Than", [](float a, float b) { return (float)(a < b); }}; + return fn; + } + case NODE_MATH_GREATER_THAN: { + static blender::fn::CustomMF_SI_SI_SO<float, float, float> fn{ + "Greater Than", [](float a, float b) { return (float)(a > b); }}; + return fn; + } + case NODE_MATH_SIGN: { + static blender::fn::CustomMF_SI_SO<float, float> fn{ + "Sign", [](float a) { return compatible_signf(a); }}; + return fn; + } + case NODE_MATH_COMPARE: { + static blender::fn::CustomMF_SI_SI_SI_SO<float, float, float, float> fn{ + "Compare", [](float a, float b, float c) -> float { + return ((a == b) || (fabsf(a - b) <= fmaxf(c, FLT_EPSILON))) ? 1.0f : 0.0f; + }}; + return fn; + } + case NODE_MATH_SMOOTH_MIN: { + return builder.get_not_implemented_fn(); + } + case NODE_MATH_SMOOTH_MAX: { + return builder.get_not_implemented_fn(); + } + + case NODE_MATH_ROUND: { + static blender::fn::CustomMF_SI_SO<float, float> fn{ + "Round", [](float a) { return floorf(a + 0.5f); }}; + return fn; + } + case NODE_MATH_FLOOR: { + static blender::fn::CustomMF_SI_SO<float, float> fn{"Floor", + [](float a) { return floorf(a); }}; + return fn; + } + case NODE_MATH_CEIL: { + static blender::fn::CustomMF_SI_SO<float, float> fn{"Ceil", + [](float a) { return ceilf(a); }}; + return fn; + } + case NODE_MATH_FRACTION: { + static blender::fn::CustomMF_SI_SO<float, float> fn{"Fraction", + [](float a) { return a - floorf(a); }}; + return fn; + } + case NODE_MATH_MODULO: { + static blender::fn::CustomMF_SI_SI_SO<float, float, float> fn{ + "Modulo", [](float a, float b) { return safe_modf(a, b); }}; + return fn; + } + case NODE_MATH_TRUNC: { + static blender::fn::CustomMF_SI_SO<float, float> fn{ + "Trunc", [](float a) { return a >= 0.0f ? floorf(a) : ceilf(a); }}; + return fn; + } + case NODE_MATH_SNAP: { + static blender::fn::CustomMF_SI_SI_SO<float, float, float> fn{ + "Snap", [](float a, float b) { return floorf(safe_divide(a, b)) * b; }}; + return fn; + } + case NODE_MATH_WRAP: { + return builder.get_not_implemented_fn(); + } + case NODE_MATH_PINGPONG: { + return builder.get_not_implemented_fn(); + } + + case NODE_MATH_SINE: { + static blender::fn::CustomMF_SI_SO<float, float> fn{"Sine", [](float a) { return sinf(a); }}; + return fn; + } + case NODE_MATH_COSINE: { + static blender::fn::CustomMF_SI_SO<float, float> fn{"Cosine", + [](float a) { return cosf(a); }}; + return fn; + } + case NODE_MATH_TANGENT: { + static blender::fn::CustomMF_SI_SO<float, float> fn{"Tangent", + [](float a) { return tanf(a); }}; + return fn; + } + case NODE_MATH_SINH: { + static blender::fn::CustomMF_SI_SO<float, float> fn{"Hyperbolic Sine", + [](float a) { return sinhf(a); }}; + return fn; + } + case NODE_MATH_COSH: { + static blender::fn::CustomMF_SI_SO<float, float> fn{"Hyperbolic Cosine", + [](float a) { return coshf(a); }}; + return fn; + } + case NODE_MATH_TANH: { + static blender::fn::CustomMF_SI_SO<float, float> fn{"Hyperbolic Tangent", + [](float a) { return tanhf(a); }}; + return fn; + } + case NODE_MATH_ARCSINE: { + static blender::fn::CustomMF_SI_SO<float, float> fn{"Arc Sine", safe_asinf}; + return fn; + } + case NODE_MATH_ARCCOSINE: { + static blender::fn::CustomMF_SI_SO<float, float> fn{"Arc Cosine", safe_acosf}; + return fn; + } + case NODE_MATH_ARCTANGENT: { + static blender::fn::CustomMF_SI_SO<float, float> fn{"Arc Tangent", + [](float a) { return atanf(a); }}; + return fn; + } + case NODE_MATH_ARCTAN2: { + static blender::fn::CustomMF_SI_SI_SO<float, float, float> fn{ + "Arc Tangent 2", [](float a, float b) { return atan2f(a, b); }}; + return fn; + } + + default: + BLI_assert(false); + return builder.get_not_implemented_fn(); + } +} + +static void sh_node_math_expand_in_mf_network(blender::nodes::NodeMFNetworkBuilder &builder) +{ + const blender::fn::MultiFunction &base_function = get_base_multi_function(builder); + + const blender::nodes::DNode &dnode = builder.dnode(); + blender::fn::MFNetwork &network = builder.network(); + blender::fn::MFFunctionNode &base_node = network.add_function(base_function); + + builder.network_map().add_try_match(dnode.inputs(), base_node.inputs()); + + const bool clamp_output = builder.bnode().custom2 != 0; + if (clamp_output) { + static blender::fn::CustomMF_SI_SO<float, float> clamp_fn{"Clamp", [](float value) { + CLAMP(value, 0.0f, 1.0f); + return value; + }}; + blender::fn::MFFunctionNode &clamp_node = network.add_function(clamp_fn); + network.add_link(base_node.output(0), clamp_node.input(0)); + builder.network_map().add(dnode.output(0), clamp_node.output(0)); + } + else { + builder.network_map().add(dnode.output(0), base_node.output(0)); + } +} + +void register_node_type_sh_math(void) +{ + static bNodeType ntype; + + sh_fn_node_type_base(&ntype, SH_NODE_MATH, "Math", NODE_CLASS_CONVERTOR, 0); + node_type_socket_templates(&ntype, sh_node_math_in, sh_node_math_out); + node_type_label(&ntype, node_math_label); + node_type_gpu(&ntype, gpu_shader_math); + node_type_update(&ntype, node_math_update); + ntype.expand_in_mf_network = sh_node_math_expand_in_mf_network; + + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/shader/nodes/node_shader_sepcombRGB.c b/source/blender/nodes/shader/nodes/node_shader_sepcombRGB.cc index d0dc45dcedd..c1543f791f1 100644 --- a/source/blender/nodes/shader/nodes/node_shader_sepcombRGB.c +++ b/source/blender/nodes/shader/nodes/node_shader_sepcombRGB.cc @@ -59,6 +59,42 @@ static int gpu_shader_seprgb(GPUMaterial *mat, return GPU_stack_link(mat, node, "separate_rgb", in, out); } +class SeparateRGBFunction : public blender::fn::MultiFunction { + public: + SeparateRGBFunction() + { + blender::fn::MFSignatureBuilder signature = this->get_builder("Separate RGB"); + signature.single_input<blender::Color4f>("Color"); + signature.single_output<float>("R"); + signature.single_output<float>("G"); + signature.single_output<float>("B"); + } + + void call(blender::IndexMask mask, + blender::fn::MFParams params, + blender::fn::MFContext UNUSED(context)) const override + { + blender::fn::VSpan<blender::Color4f> colors = params.readonly_single_input<blender::Color4f>( + 0, "Color"); + blender::MutableSpan<float> rs = params.uninitialized_single_output<float>(1, "R"); + blender::MutableSpan<float> gs = params.uninitialized_single_output<float>(2, "G"); + blender::MutableSpan<float> bs = params.uninitialized_single_output<float>(3, "B"); + + for (int64_t i : mask) { + blender::Color4f color = colors[i]; + rs[i] = color.r; + gs[i] = color.g; + bs[i] = color.b; + } + } +}; + +static void sh_node_seprgb_expand_in_mf_network(blender::nodes::NodeMFNetworkBuilder &builder) +{ + static SeparateRGBFunction fn; + builder.set_matching_fn(fn); +} + void register_node_type_sh_seprgb(void) { static bNodeType ntype; @@ -67,6 +103,7 @@ void register_node_type_sh_seprgb(void) node_type_socket_templates(&ntype, sh_node_seprgb_in, sh_node_seprgb_out); node_type_exec(&ntype, NULL, NULL, node_shader_exec_seprgb); node_type_gpu(&ntype, gpu_shader_seprgb); + ntype.expand_in_mf_network = sh_node_seprgb_expand_in_mf_network; nodeRegisterType(&ntype); } @@ -109,6 +146,13 @@ static int gpu_shader_combrgb(GPUMaterial *mat, return GPU_stack_link(mat, node, "combine_rgb", in, out); } +static void sh_node_combrgb_expand_in_mf_network(blender::nodes::NodeMFNetworkBuilder &builder) +{ + static blender::fn::CustomMF_SI_SI_SI_SO<float, float, float, blender::Color4f> fn{ + "Combine RGB", [](float r, float g, float b) { return blender::Color4f(r, g, b, 1.0f); }}; + builder.set_matching_fn(fn); +} + void register_node_type_sh_combrgb(void) { static bNodeType ntype; @@ -117,6 +161,7 @@ void register_node_type_sh_combrgb(void) node_type_socket_templates(&ntype, sh_node_combrgb_in, sh_node_combrgb_out); node_type_exec(&ntype, NULL, NULL, node_shader_exec_combrgb); node_type_gpu(&ntype, gpu_shader_combrgb); + ntype.expand_in_mf_network = sh_node_combrgb_expand_in_mf_network; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_sepcombXYZ.c b/source/blender/nodes/shader/nodes/node_shader_sepcombXYZ.cc index 429b1a3e818..8b23327460f 100644 --- a/source/blender/nodes/shader/nodes/node_shader_sepcombXYZ.c +++ b/source/blender/nodes/shader/nodes/node_shader_sepcombXYZ.cc @@ -44,6 +44,42 @@ static int gpu_shader_sepxyz(GPUMaterial *mat, return GPU_stack_link(mat, node, "separate_xyz", in, out); } +class MF_SeparateXYZ : public blender::fn::MultiFunction { + public: + MF_SeparateXYZ() + { + blender::fn::MFSignatureBuilder signature = this->get_builder("Separate XYZ"); + signature.single_input<blender::float3>("XYZ"); + signature.single_output<float>("X"); + signature.single_output<float>("Y"); + signature.single_output<float>("Z"); + } + + void call(blender::IndexMask mask, + blender::fn::MFParams params, + blender::fn::MFContext UNUSED(context)) const override + { + blender::fn::VSpan<blender::float3> vectors = params.readonly_single_input<blender::float3>( + 0, "XYZ"); + blender::MutableSpan<float> xs = params.uninitialized_single_output<float>(1, "X"); + blender::MutableSpan<float> ys = params.uninitialized_single_output<float>(2, "Y"); + blender::MutableSpan<float> zs = params.uninitialized_single_output<float>(3, "Z"); + + for (int64_t i : mask) { + blender::float3 xyz = vectors[i]; + xs[i] = xyz.x; + ys[i] = xyz.y; + zs[i] = xyz.z; + } + } +}; + +static void sh_node_sepxyz_expand_in_mf_network(blender::nodes::NodeMFNetworkBuilder &builder) +{ + static MF_SeparateXYZ separate_fn; + builder.set_matching_fn(separate_fn); +} + void register_node_type_sh_sepxyz(void) { static bNodeType ntype; @@ -51,6 +87,7 @@ void register_node_type_sh_sepxyz(void) sh_fn_node_type_base(&ntype, SH_NODE_SEPXYZ, "Separate XYZ", NODE_CLASS_CONVERTOR, 0); node_type_socket_templates(&ntype, sh_node_sepxyz_in, sh_node_sepxyz_out); node_type_gpu(&ntype, gpu_shader_sepxyz); + ntype.expand_in_mf_network = sh_node_sepxyz_expand_in_mf_network; nodeRegisterType(&ntype); } @@ -76,6 +113,13 @@ static int gpu_shader_combxyz(GPUMaterial *mat, return GPU_stack_link(mat, node, "combine_xyz", in, out); } +static void sh_node_combxyz_expand_in_mf_network(blender::nodes::NodeMFNetworkBuilder &builder) +{ + static blender::fn::CustomMF_SI_SI_SI_SO<float, float, float, blender::float3> fn{ + "Combine Vector", [](float x, float y, float z) { return blender::float3(x, y, z); }}; + builder.set_matching_fn(fn); +} + void register_node_type_sh_combxyz(void) { static bNodeType ntype; @@ -83,6 +127,7 @@ void register_node_type_sh_combxyz(void) sh_fn_node_type_base(&ntype, SH_NODE_COMBXYZ, "Combine XYZ", NODE_CLASS_CONVERTOR, 0); node_type_socket_templates(&ntype, sh_node_combxyz_in, sh_node_combxyz_out); node_type_gpu(&ntype, gpu_shader_combxyz); + ntype.expand_in_mf_network = sh_node_combxyz_expand_in_mf_network; nodeRegisterType(&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 0cf4b51f307..38e79ebe94d 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c @@ -19,8 +19,6 @@ #include "../node_shader_util.h" -#include "GPU_draw.h" - /* **************** OUTPUT ******************** */ static bNodeSocketTemplate sh_node_tex_environment_in[] = { @@ -59,7 +57,8 @@ static int node_shader_gpu_tex_environment(GPUMaterial *mat, NodeTexImage *tex_original = node_original->storage; ImageUser *iuser = &tex_original->iuser; eGPUSamplerState sampler = GPU_SAMPLER_REPEAT | GPU_SAMPLER_ANISO | GPU_SAMPLER_FILTER; - if (GPU_get_mipmap()) { + /* TODO(fclem) For now assume mipmap is always enabled. */ + if (true) { sampler |= GPU_SAMPLER_MIPMAP; } diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_image.c b/source/blender/nodes/shader/nodes/node_shader_tex_image.c index cbda72cd228..1a78d2f5bf2 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_image.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_image.c @@ -19,8 +19,6 @@ #include "../node_shader_util.h" -#include "GPU_draw.h" - /* **************** OUTPUT ******************** */ static bNodeSocketTemplate sh_node_tex_image_in[] = { @@ -95,7 +93,8 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, if (tex->interpolation != SHD_INTERP_CLOSEST) { sampler_state |= GPU_SAMPLER_ANISO | GPU_SAMPLER_FILTER; - sampler_state |= GPU_get_mipmap() ? GPU_SAMPLER_MIPMAP : 0; + /* TODO(fclem) For now assume mipmap is always enabled. */ + sampler_state |= true ? GPU_SAMPLER_MIPMAP : 0; } const bool use_cubic = ELEM(tex->interpolation, SHD_INTERP_CUBIC, SHD_INTERP_SMART); diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_sky.c b/source/blender/nodes/shader/nodes/node_shader_tex_sky.c index 0daa948c139..94ffbbe0c55 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_sky.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_sky.c @@ -18,6 +18,7 @@ */ #include "../node_shader_util.h" +#include "sky_model.h" /* **************** OUTPUT ******************** */ @@ -42,10 +43,11 @@ static void node_shader_init_tex_sky(bNodeTree *UNUSED(ntree), bNode *node) tex->turbidity = 2.2f; tex->ground_albedo = 0.3f; tex->sun_disc = true; - tex->sun_size = DEG2RADF(0.545); - tex->sun_elevation = M_PI_2; + tex->sun_size = DEG2RADF(0.545f); + tex->sun_intensity = 1.0f; + tex->sun_elevation = DEG2RADF(15.0f); tex->sun_rotation = 0.0f; - tex->altitude = 0; + tex->altitude = 0.0f; tex->air_density = 1.0f; tex->dust_density = 1.0f; tex->ozone_density = 1.0f; @@ -53,19 +55,172 @@ static void node_shader_init_tex_sky(bNodeTree *UNUSED(ntree), bNode *node) node->storage = tex; } +typedef struct SkyModelPreetham { + float config_Y[5], config_x[5], config_y[5]; /* named after xyY color space */ + float radiance[3]; +} SkyModelPreetham; + +typedef struct XYZ_to_RGB /* transposed imbuf_xyz_to_rgb, passed as 3x vec3 */ +{ + float r[3], g[3], b[3]; +} XYZ_to_RGB; + +static float sky_perez_function(const float *lam, float theta, float gamma) +{ + float ctheta = cosf(theta); + float cgamma = cosf(gamma); + + return (1.0 + lam[0] * expf(lam[1] / ctheta)) * + (1.0 + lam[2] * expf(lam[3] * gamma) + lam[4] * cgamma * cgamma); +} + +static void sky_precompute_old(SkyModelPreetham *sunsky, const float sun_angles[], float turbidity) +{ + float theta = sun_angles[0]; + float theta2 = theta * theta; + float theta3 = theta2 * theta; + float T = turbidity; + float T2 = T * T; + float chi = (4.0f / 9.0f - T / 120.0f) * (M_PI - 2.0f * theta); + + sunsky->radiance[0] = (4.0453f * T - 4.9710f) * tanf(chi) - 0.2155f * T + 2.4192f; + sunsky->radiance[0] *= 0.06f; + + sunsky->radiance[1] = (0.00166f * theta3 - 0.00375f * theta2 + 0.00209f * theta) * T2 + + (-0.02903f * theta3 + 0.06377f * theta2 - 0.03202f * theta + 0.00394f) * + T + + (0.11693f * theta3 - 0.21196f * theta2 + 0.06052f * theta + 0.25886f); + + sunsky->radiance[2] = (0.00275f * theta3 - 0.00610f * theta2 + 0.00317f * theta) * T2 + + (-0.04214f * theta3 + 0.08970f * theta2 - 0.04153f * theta + 0.00516f) * + T + + (0.15346f * theta3 - 0.26756f * theta2 + 0.06670f * theta + 0.26688f); + + sunsky->config_Y[0] = (0.1787f * T - 1.4630f); + sunsky->config_Y[1] = (-0.3554f * T + 0.4275f); + sunsky->config_Y[2] = (-0.0227f * T + 5.3251f); + sunsky->config_Y[3] = (0.1206f * T - 2.5771f); + sunsky->config_Y[4] = (-0.0670f * T + 0.3703f); + + sunsky->config_x[0] = (-0.0193f * T - 0.2592f); + sunsky->config_x[1] = (-0.0665f * T + 0.0008f); + sunsky->config_x[2] = (-0.0004f * T + 0.2125f); + sunsky->config_x[3] = (-0.0641f * T - 0.8989f); + sunsky->config_x[4] = (-0.0033f * T + 0.0452f); + + sunsky->config_y[0] = (-0.0167f * T - 0.2608f); + sunsky->config_y[1] = (-0.0950f * T + 0.0092f); + sunsky->config_y[2] = (-0.0079f * T + 0.2102f); + sunsky->config_y[3] = (-0.0441f * T - 1.6537f); + sunsky->config_y[4] = (-0.0109f * T + 0.0529f); + + sunsky->radiance[0] /= sky_perez_function(sunsky->config_Y, 0, theta); + sunsky->radiance[1] /= sky_perez_function(sunsky->config_x, 0, theta); + sunsky->radiance[2] /= sky_perez_function(sunsky->config_y, 0, theta); +} + +static void get_XYZ_to_RGB_for_gpu(XYZ_to_RGB *data) +{ + const float *xyz_to_rgb = IMB_colormangement_get_xyz_to_rgb(); + data->r[0] = xyz_to_rgb[0]; + data->r[1] = xyz_to_rgb[3]; + data->r[2] = xyz_to_rgb[6]; + data->g[0] = xyz_to_rgb[1]; + data->g[1] = xyz_to_rgb[4]; + data->g[2] = xyz_to_rgb[7]; + data->b[0] = xyz_to_rgb[2]; + data->b[1] = xyz_to_rgb[5]; + data->b[2] = xyz_to_rgb[8]; +} + static int node_shader_gpu_tex_sky(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { - if (!in[0].link) { - in[0].link = GPU_attribute(mat, CD_ORCO, ""); + node_shader_gpu_default_tex_coord(mat, node, &in[0].link); + node_shader_gpu_tex_mapping(mat, node, in, out); + NodeTexSky *tex = (NodeTexSky *)node->storage; + float sun_angles[2]; /* [0]=theta=zenith angle [1]=phi=azimuth */ + sun_angles[0] = acosf(tex->sun_direction[2]); + sun_angles[1] = atan2f(tex->sun_direction[0], tex->sun_direction[1]); + + if (tex->sky_model == 0) { + /* Preetham */ + SkyModelPreetham sunsky; + sky_precompute_old(&sunsky, sun_angles, tex->turbidity); + XYZ_to_RGB xyz_to_rgb; + get_XYZ_to_RGB_for_gpu(&xyz_to_rgb); + return GPU_stack_link(mat, + node, + "node_tex_sky_preetham", + in, + out, + /* Pass config_Y/x/y as 3x(vec4+float) */ + GPU_uniform(&sunsky.config_Y[0]), + GPU_uniform(&sunsky.config_Y[4]), + GPU_uniform(&sunsky.config_x[0]), + GPU_uniform(&sunsky.config_x[4]), + GPU_uniform(&sunsky.config_y[0]), + GPU_uniform(&sunsky.config_y[4]), + GPU_uniform(sun_angles), + GPU_uniform(sunsky.radiance), + GPU_uniform(xyz_to_rgb.r), + GPU_uniform(xyz_to_rgb.g), + GPU_uniform(xyz_to_rgb.b)); + } + else if (tex->sky_model == 1) { + /* Hosek / Wilkie */ + sun_angles[0] = fmin(M_PI_2, sun_angles[0]); /* clamp to horizon */ + SKY_ArHosekSkyModelState *sky_state = SKY_arhosek_xyz_skymodelstate_alloc_init( + tex->turbidity, tex->ground_albedo, fmax(0.0, M_PI_2 - sun_angles[0])); + /* Pass sky_state->configs[3][9] as 3*(vec4+vec4)+vec3 */ + float config_x07[8], config_y07[8], config_z07[8], config_xyz8[3]; + for (int i = 0; i < 8; ++i) { + config_x07[i] = (float)sky_state->configs[0][i]; + config_y07[i] = (float)sky_state->configs[1][i]; + config_z07[i] = (float)sky_state->configs[2][i]; + } + for (int i = 0; i < 3; ++i) { + config_xyz8[i] = (float)sky_state->configs[i][8]; + } + float radiance[3]; + for (int i = 0; i < 3; i++) { + radiance[i] = sky_state->radiances[i] * (2 * M_PI / 683); + } + SKY_arhosekskymodelstate_free(sky_state); + XYZ_to_RGB xyz_to_rgb; + get_XYZ_to_RGB_for_gpu(&xyz_to_rgb); + return GPU_stack_link(mat, + node, + "node_tex_sky_hosekwilkie", + in, + out, + GPU_uniform(&config_x07[0]), + GPU_uniform(&config_x07[4]), + GPU_uniform(&config_y07[0]), + GPU_uniform(&config_y07[4]), + GPU_uniform(&config_z07[0]), + GPU_uniform(&config_z07[4]), + GPU_uniform(config_xyz8), + GPU_uniform(sun_angles), + GPU_uniform(radiance), + GPU_uniform(xyz_to_rgb.r), + GPU_uniform(xyz_to_rgb.g), + GPU_uniform(xyz_to_rgb.b)); + } + else { + return GPU_stack_link(mat, node, "node_tex_sky_nishita", in, out); } +} - node_shader_gpu_tex_mapping(mat, node, in, out); +static void node_shader_update_sky(bNodeTree *UNUSED(ntree), bNode *node) +{ + bNodeSocket *sockVector = nodeFindSocket(node, SOCK_IN, "Vector"); - return GPU_stack_link(mat, node, "node_tex_sky", in, out); + NodeTexSky *tex = (NodeTexSky *)node->storage; + nodeSetSocketAvailability(sockVector, !(tex->sky_model == 2 && tex->sun_disc == 1)); } /* node type definition */ @@ -79,6 +234,8 @@ void register_node_type_sh_tex_sky(void) node_type_init(&ntype, node_shader_init_tex_sky); node_type_storage(&ntype, "NodeTexSky", node_free_standard_storage, node_copy_standard_storage); node_type_gpu(&ntype, node_shader_gpu_tex_sky); + /* remove Vector input for Nishita */ + node_type_update(&ntype, node_shader_update_sky); nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_valToRgb.c b/source/blender/nodes/shader/nodes/node_shader_valToRgb.cc index 20f280d00c3..7f712b0db40 100644 --- a/source/blender/nodes/shader/nodes/node_shader_valToRgb.c +++ b/source/blender/nodes/shader/nodes/node_shader_valToRgb.cc @@ -22,6 +22,11 @@ */ #include "IMB_colormanagement.h" + +#include "DNA_texture_types.h" + +#include "BLI_color.hh" + #include "node_shader_util.h" /* **************** VALTORGB ******************** */ @@ -49,7 +54,7 @@ static void node_shader_exec_valtorgb(void *UNUSED(data), float fac; nodestack_get_vec(&fac, SOCK_FLOAT, in[0]); - BKE_colorband_evaluate(node->storage, fac, out[0]->vec); + BKE_colorband_evaluate((ColorBand *)node->storage, fac, out[0]->vec); out[1]->vec[0] = out[0]->vec[3]; } } @@ -65,7 +70,7 @@ static int gpu_shader_valtorgb(GPUMaterial *mat, GPUNodeStack *in, GPUNodeStack *out) { - struct ColorBand *coba = node->storage; + struct ColorBand *coba = (ColorBand *)node->storage; float *array, layer; int size; @@ -121,6 +126,44 @@ static int gpu_shader_valtorgb(GPUMaterial *mat, } } +class ColorBandFunction : public blender::fn::MultiFunction { + private: + const ColorBand &color_band_; + + public: + ColorBandFunction(const ColorBand &color_band) : color_band_(color_band) + { + blender::fn::MFSignatureBuilder signature = this->get_builder("Color Band"); + signature.single_input<float>("Value"); + signature.single_output<blender::Color4f>("Color"); + signature.single_output<float>("Alpha"); + } + + void call(blender::IndexMask mask, + blender::fn::MFParams params, + blender::fn::MFContext UNUSED(context)) const override + { + blender::fn::VSpan<float> values = params.readonly_single_input<float>(0, "Value"); + blender::MutableSpan<blender::Color4f> colors = + params.uninitialized_single_output<blender::Color4f>(1, "Color"); + blender::MutableSpan<float> alphas = params.uninitialized_single_output<float>(2, "Alpha"); + + for (int64_t i : mask) { + blender::Color4f color; + BKE_colorband_evaluate(&color_band_, values[i], color); + colors[i] = color; + alphas[i] = color.a; + } + } +}; + +static void sh_node_valtorgb_expand_in_mf_network(blender::nodes::NodeMFNetworkBuilder &builder) +{ + bNode &bnode = builder.bnode(); + const ColorBand *color_band = (const ColorBand *)bnode.storage; + builder.construct_and_set_matching_fn<ColorBandFunction>(*color_band); +} + void register_node_type_sh_valtorgb(void) { static bNodeType ntype; @@ -132,6 +175,7 @@ void register_node_type_sh_valtorgb(void) node_type_storage(&ntype, "ColorBand", node_free_standard_storage, node_copy_standard_storage); node_type_exec(&ntype, NULL, NULL, node_shader_exec_valtorgb); node_type_gpu(&ntype, gpu_shader_valtorgb); + ntype.expand_in_mf_network = sh_node_valtorgb_expand_in_mf_network; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_value.c b/source/blender/nodes/shader/nodes/node_shader_value.cc index c32e9e1d581..1d7c3f47233 100644 --- a/source/blender/nodes/shader/nodes/node_shader_value.c +++ b/source/blender/nodes/shader/nodes/node_shader_value.cc @@ -39,13 +39,21 @@ static int gpu_shader_value(GPUMaterial *mat, return GPU_stack_link(mat, node, "set_value", in, out, link); } +static void sh_node_value_expand_in_mf_network(blender::nodes::NodeMFNetworkBuilder &builder) +{ + const bNodeSocket *bsocket = builder.dnode().output(0).bsocket(); + const bNodeSocketValueFloat *value = (const bNodeSocketValueFloat *)bsocket->default_value; + builder.construct_and_set_matching_fn<blender::fn::CustomMF_Constant<float>>(value->value); +} + void register_node_type_sh_value(void) { static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_VALUE, "Value", NODE_CLASS_INPUT, 0); + sh_fn_node_type_base(&ntype, SH_NODE_VALUE, "Value", NODE_CLASS_INPUT, 0); node_type_socket_templates(&ntype, NULL, sh_node_value_out); node_type_gpu(&ntype, gpu_shader_value); + ntype.expand_in_mf_network = sh_node_value_expand_in_mf_network; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_vector_math.c b/source/blender/nodes/shader/nodes/node_shader_vector_math.c deleted file mode 100644 index b719fe03d9b..00000000000 --- a/source/blender/nodes/shader/nodes/node_shader_vector_math.c +++ /dev/null @@ -1,144 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2005 Blender Foundation. - * All rights reserved. - */ - -/** \file - * \ingroup shdnodes - */ - -#include "node_shader_util.h" - -/* **************** VECTOR MATH ******************** */ -static bNodeSocketTemplate sh_node_vector_math_in[] = { - {SOCK_VECTOR, N_("Vector"), 0.0f, 0.0f, 0.0f, 1.0f, -10000.0f, 10000.0f, PROP_NONE}, - {SOCK_VECTOR, N_("Vector"), 0.0f, 0.0f, 0.0f, 1.0f, -10000.0f, 10000.0f, PROP_NONE}, - {SOCK_VECTOR, N_("Vector"), 0.0f, 0.0f, 0.0f, 1.0f, -10000.0f, 10000.0f, PROP_NONE}, - {SOCK_FLOAT, N_("Scale"), 1.0f, 1.0f, 1.0f, 1.0f, -10000.0f, 10000.0f, PROP_NONE}, - {-1, ""}}; - -static bNodeSocketTemplate sh_node_vector_math_out[] = { - {SOCK_VECTOR, N_("Vector")}, {SOCK_FLOAT, N_("Value")}, {-1, ""}}; - -static int gpu_shader_vector_math(GPUMaterial *mat, - bNode *node, - bNodeExecData *UNUSED(execdata), - GPUNodeStack *in, - GPUNodeStack *out) -{ - static const char *names[] = { - [NODE_VECTOR_MATH_ADD] = "vector_math_add", - [NODE_VECTOR_MATH_SUBTRACT] = "vector_math_subtract", - [NODE_VECTOR_MATH_MULTIPLY] = "vector_math_multiply", - [NODE_VECTOR_MATH_DIVIDE] = "vector_math_divide", - - [NODE_VECTOR_MATH_CROSS_PRODUCT] = "vector_math_cross", - [NODE_VECTOR_MATH_PROJECT] = "vector_math_project", - [NODE_VECTOR_MATH_REFLECT] = "vector_math_reflect", - [NODE_VECTOR_MATH_DOT_PRODUCT] = "vector_math_dot", - - [NODE_VECTOR_MATH_DISTANCE] = "vector_math_distance", - [NODE_VECTOR_MATH_LENGTH] = "vector_math_length", - [NODE_VECTOR_MATH_SCALE] = "vector_math_scale", - [NODE_VECTOR_MATH_NORMALIZE] = "vector_math_normalize", - - [NODE_VECTOR_MATH_SNAP] = "vector_math_snap", - [NODE_VECTOR_MATH_FLOOR] = "vector_math_floor", - [NODE_VECTOR_MATH_CEIL] = "vector_math_ceil", - [NODE_VECTOR_MATH_MODULO] = "vector_math_modulo", - [NODE_VECTOR_MATH_FRACTION] = "vector_math_fraction", - [NODE_VECTOR_MATH_ABSOLUTE] = "vector_math_absolute", - [NODE_VECTOR_MATH_MINIMUM] = "vector_math_minimum", - [NODE_VECTOR_MATH_MAXIMUM] = "vector_math_maximum", - [NODE_VECTOR_MATH_WRAP] = "vector_math_wrap", - [NODE_VECTOR_MATH_SINE] = "vector_math_sine", - [NODE_VECTOR_MATH_COSINE] = "vector_math_cosine", - [NODE_VECTOR_MATH_TANGENT] = "vector_math_tangent", - }; - - if (node->custom1 < ARRAY_SIZE(names) && names[node->custom1]) { - return GPU_stack_link(mat, node, names[node->custom1], in, out); - } - else { - return 0; - } -} - -static void node_shader_update_vector_math(bNodeTree *UNUSED(ntree), bNode *node) -{ - bNodeSocket *sockB = BLI_findlink(&node->inputs, 1); - bNodeSocket *sockC = BLI_findlink(&node->inputs, 2); - bNodeSocket *sockScale = nodeFindSocket(node, SOCK_IN, "Scale"); - - bNodeSocket *sockVector = nodeFindSocket(node, SOCK_OUT, "Vector"); - bNodeSocket *sockValue = nodeFindSocket(node, SOCK_OUT, "Value"); - - nodeSetSocketAvailability(sockB, - !ELEM(node->custom1, - NODE_VECTOR_MATH_SINE, - NODE_VECTOR_MATH_COSINE, - NODE_VECTOR_MATH_TANGENT, - NODE_VECTOR_MATH_CEIL, - NODE_VECTOR_MATH_SCALE, - NODE_VECTOR_MATH_FLOOR, - NODE_VECTOR_MATH_LENGTH, - NODE_VECTOR_MATH_ABSOLUTE, - NODE_VECTOR_MATH_FRACTION, - NODE_VECTOR_MATH_NORMALIZE)); - nodeSetSocketAvailability(sockC, ELEM(node->custom1, NODE_VECTOR_MATH_WRAP)); - nodeSetSocketAvailability(sockScale, node->custom1 == NODE_VECTOR_MATH_SCALE); - nodeSetSocketAvailability(sockVector, - !ELEM(node->custom1, - NODE_VECTOR_MATH_LENGTH, - NODE_VECTOR_MATH_DISTANCE, - NODE_VECTOR_MATH_DOT_PRODUCT)); - nodeSetSocketAvailability(sockValue, - ELEM(node->custom1, - NODE_VECTOR_MATH_LENGTH, - NODE_VECTOR_MATH_DISTANCE, - NODE_VECTOR_MATH_DOT_PRODUCT)); - - /* Labels */ - if (sockB->label[0] != '\0') { - sockB->label[0] = '\0'; - } - if (sockC->label[0] != '\0') { - sockC->label[0] = '\0'; - } - switch (node->custom1) { - case NODE_VECTOR_MATH_WRAP: - node_sock_label(sockB, "Max"); - node_sock_label(sockC, "Min"); - break; - case NODE_VECTOR_MATH_SNAP: - node_sock_label(sockB, "Increment"); - break; - } -} - -void register_node_type_sh_vect_math(void) -{ - static bNodeType ntype; - - sh_fn_node_type_base(&ntype, SH_NODE_VECTOR_MATH, "Vector Math", NODE_CLASS_OP_VECTOR, 0); - node_type_socket_templates(&ntype, sh_node_vector_math_in, sh_node_vector_math_out); - node_type_label(&ntype, node_vector_math_label); - node_type_gpu(&ntype, gpu_shader_vector_math); - node_type_update(&ntype, node_shader_update_vector_math); - - nodeRegisterType(&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 new file mode 100644 index 00000000000..c18ad8bb244 --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_vector_math.cc @@ -0,0 +1,292 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup shdnodes + */ + +#include "node_shader_util.h" + +/* **************** VECTOR MATH ******************** */ +static bNodeSocketTemplate sh_node_vector_math_in[] = { + {SOCK_VECTOR, N_("Vector"), 0.0f, 0.0f, 0.0f, 1.0f, -10000.0f, 10000.0f, PROP_NONE}, + {SOCK_VECTOR, N_("Vector"), 0.0f, 0.0f, 0.0f, 1.0f, -10000.0f, 10000.0f, PROP_NONE}, + {SOCK_VECTOR, N_("Vector"), 0.0f, 0.0f, 0.0f, 1.0f, -10000.0f, 10000.0f, PROP_NONE}, + {SOCK_FLOAT, N_("Scale"), 1.0f, 1.0f, 1.0f, 1.0f, -10000.0f, 10000.0f, PROP_NONE}, + {-1, ""}}; + +static bNodeSocketTemplate sh_node_vector_math_out[] = { + {SOCK_VECTOR, N_("Vector")}, {SOCK_FLOAT, N_("Value")}, {-1, ""}}; + +static const char *gpu_shader_get_name(int mode) +{ + switch (mode) { + case NODE_VECTOR_MATH_ADD: + return "vector_math_add"; + case NODE_VECTOR_MATH_SUBTRACT: + return "vector_math_subtract"; + case NODE_VECTOR_MATH_MULTIPLY: + return "vector_math_multiply"; + case NODE_VECTOR_MATH_DIVIDE: + return "vector_math_divide"; + + case NODE_VECTOR_MATH_CROSS_PRODUCT: + return "vector_math_cross"; + case NODE_VECTOR_MATH_PROJECT: + return "vector_math_project"; + case NODE_VECTOR_MATH_REFLECT: + return "vector_math_reflect"; + case NODE_VECTOR_MATH_DOT_PRODUCT: + return "vector_math_dot"; + + case NODE_VECTOR_MATH_DISTANCE: + return "vector_math_distance"; + case NODE_VECTOR_MATH_LENGTH: + return "vector_math_length"; + case NODE_VECTOR_MATH_SCALE: + return "vector_math_scale"; + case NODE_VECTOR_MATH_NORMALIZE: + return "vector_math_normalize"; + + case NODE_VECTOR_MATH_SNAP: + return "vector_math_snap"; + case NODE_VECTOR_MATH_FLOOR: + return "vector_math_floor"; + case NODE_VECTOR_MATH_CEIL: + return "vector_math_ceil"; + case NODE_VECTOR_MATH_MODULO: + return "vector_math_modulo"; + case NODE_VECTOR_MATH_FRACTION: + return "vector_math_fraction"; + case NODE_VECTOR_MATH_ABSOLUTE: + return "vector_math_absolute"; + case NODE_VECTOR_MATH_MINIMUM: + return "vector_math_minimum"; + case NODE_VECTOR_MATH_MAXIMUM: + return "vector_math_maximum"; + case NODE_VECTOR_MATH_WRAP: + return "vector_math_wrap"; + case NODE_VECTOR_MATH_SINE: + return "vector_math_sine"; + case NODE_VECTOR_MATH_COSINE: + return "vector_math_cosine"; + case NODE_VECTOR_MATH_TANGENT: + return "vector_math_tangent"; + } + + return nullptr; +} + +static int gpu_shader_vector_math(GPUMaterial *mat, + bNode *node, + bNodeExecData *UNUSED(execdata), + GPUNodeStack *in, + GPUNodeStack *out) +{ + const char *name = gpu_shader_get_name(node->custom1); + if (name != nullptr) { + return GPU_stack_link(mat, node, name, in, out); + } + else { + return 0; + } +} + +static void node_shader_update_vector_math(bNodeTree *UNUSED(ntree), bNode *node) +{ + bNodeSocket *sockB = (bNodeSocket *)BLI_findlink(&node->inputs, 1); + bNodeSocket *sockC = (bNodeSocket *)BLI_findlink(&node->inputs, 2); + bNodeSocket *sockScale = nodeFindSocket(node, SOCK_IN, "Scale"); + + bNodeSocket *sockVector = nodeFindSocket(node, SOCK_OUT, "Vector"); + bNodeSocket *sockValue = nodeFindSocket(node, SOCK_OUT, "Value"); + + nodeSetSocketAvailability(sockB, + !ELEM(node->custom1, + NODE_VECTOR_MATH_SINE, + NODE_VECTOR_MATH_COSINE, + NODE_VECTOR_MATH_TANGENT, + NODE_VECTOR_MATH_CEIL, + NODE_VECTOR_MATH_SCALE, + NODE_VECTOR_MATH_FLOOR, + NODE_VECTOR_MATH_LENGTH, + NODE_VECTOR_MATH_ABSOLUTE, + NODE_VECTOR_MATH_FRACTION, + NODE_VECTOR_MATH_NORMALIZE)); + nodeSetSocketAvailability(sockC, ELEM(node->custom1, NODE_VECTOR_MATH_WRAP)); + nodeSetSocketAvailability(sockScale, node->custom1 == NODE_VECTOR_MATH_SCALE); + nodeSetSocketAvailability(sockVector, + !ELEM(node->custom1, + NODE_VECTOR_MATH_LENGTH, + NODE_VECTOR_MATH_DISTANCE, + NODE_VECTOR_MATH_DOT_PRODUCT)); + nodeSetSocketAvailability(sockValue, + ELEM(node->custom1, + NODE_VECTOR_MATH_LENGTH, + NODE_VECTOR_MATH_DISTANCE, + NODE_VECTOR_MATH_DOT_PRODUCT)); + + /* Labels */ + if (sockB->label[0] != '\0') { + sockB->label[0] = '\0'; + } + if (sockC->label[0] != '\0') { + sockC->label[0] = '\0'; + } + switch (node->custom1) { + case NODE_VECTOR_MATH_WRAP: + node_sock_label(sockB, "Max"); + node_sock_label(sockC, "Min"); + break; + case NODE_VECTOR_MATH_SNAP: + node_sock_label(sockB, "Increment"); + break; + } +} + +static const blender::fn::MultiFunction &get_multi_function( + blender::nodes::NodeMFNetworkBuilder &builder) +{ + using blender::float3; + + const int mode = builder.bnode().custom1; + switch (mode) { + case NODE_VECTOR_MATH_ADD: { + static blender::fn::CustomMF_SI_SI_SO<float3, float3, float3> fn{ + "Add", [](float3 a, float3 b) { return a + b; }}; + return fn; + } + case NODE_VECTOR_MATH_SUBTRACT: { + static blender::fn::CustomMF_SI_SI_SO<float3, float3, float3> fn{ + "Subtract", [](float3 a, float3 b) { return a - b; }}; + return fn; + } + case NODE_VECTOR_MATH_MULTIPLY: { + static blender::fn::CustomMF_SI_SI_SO<float3, float3, float3> fn{ + "Multiply", [](float3 a, float3 b) { return a * b; }}; + return fn; + } + case NODE_VECTOR_MATH_DIVIDE: { + static blender::fn::CustomMF_SI_SI_SO<float3, float3, float3> fn{ + "Divide", [](float3 a, float3 b) { return float3::safe_divide(a, b); }}; + return fn; + } + + case NODE_VECTOR_MATH_CROSS_PRODUCT: { + static blender::fn::CustomMF_SI_SI_SO<float3, float3, float3> fn{ + "Cross Product", float3::cross_high_precision}; + return fn; + } + case NODE_VECTOR_MATH_PROJECT: { + static blender::fn::CustomMF_SI_SI_SO<float3, float3, float3> fn{"Project", float3::project}; + return fn; + } + case NODE_VECTOR_MATH_REFLECT: { + static blender::fn::CustomMF_SI_SI_SO<float3, float3, float3> fn{ + "Reflect", [](float3 a, float3 b) { return a.reflected(b); }}; + return fn; + } + case NODE_VECTOR_MATH_DOT_PRODUCT: { + static blender::fn::CustomMF_SI_SI_SO<float3, float3, float> fn{"Dot Product", float3::dot}; + return fn; + } + + case NODE_VECTOR_MATH_DISTANCE: { + static blender::fn::CustomMF_SI_SI_SO<float3, float3, float> fn{"Distance", + float3::distance}; + return fn; + } + case NODE_VECTOR_MATH_LENGTH: { + static blender::fn::CustomMF_SI_SO<float3, float> fn{"Length", + [](float3 a) { return a.length(); }}; + return fn; + } + case NODE_VECTOR_MATH_SCALE: { + static blender::fn::CustomMF_SI_SI_SO<float3, float, float3> fn{ + "Scale", [](float3 a, float factor) { return a * factor; }}; + return fn; + } + case NODE_VECTOR_MATH_NORMALIZE: { + static blender::fn::CustomMF_SI_SO<float3, float3> fn{ + "Normalize", [](float3 a) { return a.normalized(); }}; + return fn; + } + + case NODE_VECTOR_MATH_SNAP: { + return builder.get_not_implemented_fn(); + } + case NODE_VECTOR_MATH_FLOOR: { + return builder.get_not_implemented_fn(); + } + case NODE_VECTOR_MATH_CEIL: { + return builder.get_not_implemented_fn(); + } + case NODE_VECTOR_MATH_MODULO: { + return builder.get_not_implemented_fn(); + } + case NODE_VECTOR_MATH_FRACTION: { + return builder.get_not_implemented_fn(); + } + case NODE_VECTOR_MATH_ABSOLUTE: { + return builder.get_not_implemented_fn(); + } + case NODE_VECTOR_MATH_MINIMUM: { + return builder.get_not_implemented_fn(); + } + case NODE_VECTOR_MATH_MAXIMUM: { + return builder.get_not_implemented_fn(); + } + case NODE_VECTOR_MATH_WRAP: { + return builder.get_not_implemented_fn(); + } + case NODE_VECTOR_MATH_SINE: { + return builder.get_not_implemented_fn(); + } + case NODE_VECTOR_MATH_COSINE: { + return builder.get_not_implemented_fn(); + } + case NODE_VECTOR_MATH_TANGENT: { + return builder.get_not_implemented_fn(); + } + + default: + BLI_assert(false); + return builder.get_not_implemented_fn(); + }; +} + +static void sh_node_vector_math_expand_in_mf_network(blender::nodes::NodeMFNetworkBuilder &builder) +{ + const blender::fn::MultiFunction &fn = get_multi_function(builder); + builder.set_matching_fn(fn); +} + +void register_node_type_sh_vect_math(void) +{ + static bNodeType ntype; + + sh_fn_node_type_base(&ntype, SH_NODE_VECTOR_MATH, "Vector Math", NODE_CLASS_OP_VECTOR, 0); + node_type_socket_templates(&ntype, sh_node_vector_math_in, sh_node_vector_math_out); + node_type_label(&ntype, node_vector_math_label); + node_type_gpu(&ntype, gpu_shader_vector_math); + node_type_update(&ntype, node_shader_update_vector_math); + ntype.expand_in_mf_network = sh_node_vector_math_expand_in_mf_network; + + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/shader/nodes/node_shader_vertex_color.c b/source/blender/nodes/shader/nodes/node_shader_vertex_color.c index 70c924a7f85..40576b68dd5 100644 --- a/source/blender/nodes/shader/nodes/node_shader_vertex_color.c +++ b/source/blender/nodes/shader/nodes/node_shader_vertex_color.c @@ -39,6 +39,10 @@ static int node_shader_gpu_vertex_color(GPUMaterial *mat, GPUNodeStack *out) { NodeShaderVertexColor *vertexColor = (NodeShaderVertexColor *)node->storage; + if (U.experimental.use_sculpt_vertex_colors) { + GPUNodeLink *vertexColorLink = GPU_attribute(mat, CD_PROP_COLOR, vertexColor->layer_name); + return GPU_stack_link(mat, node, "node_vertex_color", in, out, vertexColorLink); + } GPUNodeLink *vertexColorLink = GPU_attribute(mat, CD_MCOL, vertexColor->layer_name); return GPU_stack_link(mat, node, "node_vertex_color", in, out, vertexColorLink); } diff --git a/source/blender/nodes/shader/nodes/node_shader_wireframe.c b/source/blender/nodes/shader/nodes/node_shader_wireframe.c index e1da1cd34e4..d1ed13e1ffd 100644 --- a/source/blender/nodes/shader/nodes/node_shader_wireframe.c +++ b/source/blender/nodes/shader/nodes/node_shader_wireframe.c @@ -36,6 +36,7 @@ static int node_shader_gpu_wireframe(GPUMaterial *mat, GPUNodeStack *in, GPUNodeStack *out) { + GPU_material_flag_set(mat, GPU_MATFLAG_BARYCENTRIC); /* node->custom1 is use_pixel_size */ if (node->custom1) { return GPU_stack_link( |