Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/nodes/shader')
-rw-r--r--source/blender/nodes/shader/node_shader_tree.c14
-rw-r--r--source/blender/nodes/shader/node_shader_util.h13
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_clamp.cc (renamed from source/blender/nodes/shader/nodes/node_shader_clamp.c)25
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_curves.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_geometry.c3
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_map_range.cc (renamed from source/blender/nodes/shader/nodes/node_shader_map_range.c)90
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_math.c115
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_math.cc387
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_sepcombRGB.cc (renamed from source/blender/nodes/shader/nodes/node_shader_sepcombRGB.c)45
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_sepcombXYZ.cc (renamed from source/blender/nodes/shader/nodes/node_shader_sepcombXYZ.c)45
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_environment.c5
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_image.c5
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_sky.c171
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_valToRgb.cc (renamed from source/blender/nodes/shader/nodes/node_shader_valToRgb.c)48
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_value.cc (renamed from source/blender/nodes/shader/nodes/node_shader_value.c)10
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_vector_math.c144
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_vector_math.cc292
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_vertex_color.c4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_wireframe.c1
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(