Blender V4.3
node_shader_curves.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2005 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include "node_shader_util.hh"
10
11#include "BKE_colortools.hh"
12
13#include "BLI_math_vector.h"
14
15#include "NOD_multi_function.hh"
16
17#include "node_util.hh"
18
20
22{
23 b.is_function_node();
24 b.add_input<decl::Float>("Fac")
25 .min(0.0f)
26 .max(1.0f)
27 .default_value(1.0f)
28 .subtype(PROP_FACTOR)
29 .no_muted_links()
30 .description("Amount of influence the node exerts on the output vector");
31 b.add_input<decl::Vector>("Vector").min(-1.0f).max(1.0f).description(
32 "Vector which would be mapped to the curve");
33 b.add_output<decl::Vector>("Vector");
34}
35
36static void node_shader_init_curve_vec(bNodeTree * /*ntree*/, bNode *node)
37{
38 node->storage = BKE_curvemapping_add(3, -1.0f, -1.0f, 1.0f, 1.0f);
39}
40
42 bNode *node,
43 bNodeExecData * /*execdata*/,
44 GPUNodeStack *in,
45 GPUNodeStack *out)
46{
47 CurveMapping *curve_mapping = (CurveMapping *)node->storage;
48
49 BKE_curvemapping_init(curve_mapping);
50 float *band_values;
51 int band_size;
52 BKE_curvemapping_table_RGBA(curve_mapping, &band_values, &band_size);
53 float band_layer;
54 GPUNodeLink *band_texture = GPU_color_band(mat, band_size, band_values, &band_layer);
55
56 float start_slopes[CM_TOT];
57 float end_slopes[CM_TOT];
58 BKE_curvemapping_compute_slopes(curve_mapping, start_slopes, end_slopes);
59 float range_minimums[CM_TOT];
60 BKE_curvemapping_get_range_minimums(curve_mapping, range_minimums);
61 float range_dividers[CM_TOT];
62 BKE_curvemapping_compute_range_dividers(curve_mapping, range_dividers);
63
64 return GPU_stack_link(mat,
65 node,
66 "curves_vector_mixed",
67 in,
68 out,
69 band_texture,
70 GPU_constant(&band_layer),
71 GPU_uniform(range_minimums),
72 GPU_uniform(range_dividers),
73 GPU_uniform(start_slopes),
74 GPU_uniform(end_slopes));
75}
76
78 private:
79 const CurveMapping &cumap_;
80
81 public:
82 CurveVecFunction(const CurveMapping &cumap) : cumap_(cumap)
83 {
84 static const mf::Signature signature = []() {
86 mf::SignatureBuilder builder{"Curve Vec", signature};
87 builder.single_input<float>("Fac");
88 builder.single_input<float3>("Vector");
89 builder.single_output<float3>("Vector");
90 return signature;
91 }();
92 this->set_signature(&signature);
93 }
94
95 void call(const IndexMask &mask, mf::Params params, mf::Context /*context*/) const override
96 {
97 const VArray<float> &fac = params.readonly_single_input<float>(0, "Fac");
98 const VArray<float3> &vec_in = params.readonly_single_input<float3>(1, "Vector");
99 MutableSpan<float3> vec_out = params.uninitialized_single_output<float3>(2, "Vector");
100
101 mask.foreach_index([&](const int64_t i) {
102 BKE_curvemapping_evaluate3F(&cumap_, vec_out[i], vec_in[i]);
103 if (fac[i] != 1.0f) {
104 interp_v3_v3v3(vec_out[i], vec_in[i], vec_out[i], fac[i]);
105 }
106 });
107 }
108};
109
111{
112 const bNode &bnode = builder.node();
113 CurveMapping *cumap = (CurveMapping *)bnode.storage;
116}
117
119#ifdef WITH_MATERIALX
120{
121 /* TODO: implement */
122 return get_input_value("Vector", NodeItem::Type::Vector3);
123}
124#endif
126
127} // namespace blender::nodes::node_shader_curves_cc::vec
128
130{
132
133 static blender::bke::bNodeType ntype;
134
136 ntype.declare = file_ns::sh_node_curve_vec_declare;
137 ntype.initfunc = file_ns::node_shader_init_curve_vec;
140 ntype.gpu_fn = file_ns::gpu_shader_curve_vec;
141 ntype.build_multi_function = file_ns::sh_node_curve_vec_build_multi_function;
142 ntype.materialx_fn = file_ns::node_shader_materialx;
143
145}
146
147/* **************** CURVE RGB ******************** */
148
150
152{
153 b.is_function_node();
154 b.add_input<decl::Float>("Fac")
155 .min(0.0f)
156 .max(1.0f)
157 .default_value(1.0f)
158 .subtype(PROP_FACTOR)
159 .no_muted_links()
160 .description("Amount of influence the node exerts on the output color");
161 b.add_input<decl::Color>("Color")
162 .default_value({1.0f, 1.0f, 1.0f, 1.0f})
163 .description("Color input on which correction will be applied");
164 b.add_output<decl::Color>("Color");
165}
166
167static void node_shader_init_curve_rgb(bNodeTree * /*ntree*/, bNode *node)
168{
169 node->storage = BKE_curvemapping_add(4, 0.0f, 0.0f, 1.0f, 1.0f);
170}
171
173 bNode *node,
174 bNodeExecData * /*execdata*/,
175 GPUNodeStack *in,
176 GPUNodeStack *out)
177{
178 CurveMapping *curve_mapping = (CurveMapping *)node->storage;
179
180 BKE_curvemapping_init(curve_mapping);
181 float *band_values;
182 int band_size;
183 BKE_curvemapping_table_RGBA(curve_mapping, &band_values, &band_size);
184 float band_layer;
185 GPUNodeLink *band_texture = GPU_color_band(mat, band_size, band_values, &band_layer);
186
187 float start_slopes[CM_TOT];
188 float end_slopes[CM_TOT];
189 BKE_curvemapping_compute_slopes(curve_mapping, start_slopes, end_slopes);
190 float range_minimums[CM_TOT];
191 BKE_curvemapping_get_range_minimums(curve_mapping, range_minimums);
192 float range_dividers[CM_TOT];
193 BKE_curvemapping_compute_range_dividers(curve_mapping, range_dividers);
194
195 /* Shader nodes don't do white balancing. */
196 float black_level[4] = {0.0f, 0.0f, 0.0f, 1.0f};
197 float white_level[4] = {1.0f, 1.0f, 1.0f, 1.0f};
198
199 /* If the RGB curves do nothing, use a function that skips RGB computations. */
200 if (BKE_curvemapping_is_map_identity(curve_mapping, 0) &&
201 BKE_curvemapping_is_map_identity(curve_mapping, 1) &&
202 BKE_curvemapping_is_map_identity(curve_mapping, 2))
203 {
204 return GPU_stack_link(mat,
205 node,
206 "curves_combined_only",
207 in,
208 out,
209 GPU_constant(black_level),
210 GPU_constant(white_level),
211 band_texture,
212 GPU_constant(&band_layer),
213 GPU_uniform(&range_minimums[3]),
214 GPU_uniform(&range_dividers[3]),
215 GPU_uniform(&start_slopes[3]),
216 GPU_uniform(&end_slopes[3]));
217 }
218
219 return GPU_stack_link(mat,
220 node,
221 "curves_combined_rgb",
222 in,
223 out,
224 GPU_constant(black_level),
225 GPU_constant(white_level),
226 band_texture,
227 GPU_constant(&band_layer),
228 GPU_uniform(range_minimums),
229 GPU_uniform(range_dividers),
230 GPU_uniform(start_slopes),
231 GPU_uniform(end_slopes));
232}
233
235 private:
236 const CurveMapping &cumap_;
237
238 public:
239 CurveRGBFunction(const CurveMapping &cumap) : cumap_(cumap)
240 {
241 static const mf::Signature signature = []() {
243 mf::SignatureBuilder builder{"Curve RGB", signature};
244 builder.single_input<float>("Fac");
245 builder.single_input<ColorGeometry4f>("Color");
246 builder.single_output<ColorGeometry4f>("Color");
247 return signature;
248 }();
249 this->set_signature(&signature);
250 }
251
252 void call(const IndexMask &mask, mf::Params params, mf::Context /*context*/) const override
253 {
254 const VArray<float> &fac = params.readonly_single_input<float>(0, "Fac");
255 const VArray<ColorGeometry4f> &col_in = params.readonly_single_input<ColorGeometry4f>(1,
256 "Color");
257 MutableSpan<ColorGeometry4f> col_out = params.uninitialized_single_output<ColorGeometry4f>(
258 2, "Color");
259
260 mask.foreach_index([&](const int64_t i) {
261 BKE_curvemapping_evaluateRGBF(&cumap_, col_out[i], col_in[i]);
262 if (fac[i] != 1.0f) {
263 interp_v3_v3v3(col_out[i], col_in[i], col_out[i], fac[i]);
264 }
265 col_out[i].a = 1.0f;
266 });
267 }
268};
269
271{
272 const bNode &bnode = builder.node();
273 CurveMapping *cumap = (CurveMapping *)bnode.storage;
276}
277
279#ifdef WITH_MATERIALX
280{
281 /* TODO: implement */
282 return get_input_value("Color", NodeItem::Type::Color4);
283}
284#endif
286
287} // namespace blender::nodes::node_shader_curves_cc::rgb
288
290{
292
293 static blender::bke::bNodeType ntype;
294
296 ntype.declare = file_ns::sh_node_curve_rgb_declare;
297 ntype.initfunc = file_ns::node_shader_init_curve_rgb;
300 ntype.gpu_fn = file_ns::gpu_shader_curve_rgb;
301 ntype.build_multi_function = file_ns::sh_node_curve_rgb_build_multi_function;
302 ntype.materialx_fn = file_ns::node_shader_materialx;
303
305}
306
307/* **************** CURVE FLOAT ******************** */
308
310
312{
313 b.is_function_node();
314 b.add_input<decl::Float>("Factor")
315 .min(0.0f)
316 .max(1.0f)
317 .default_value(1.0f)
318 .subtype(PROP_FACTOR)
319 .no_muted_links();
320 b.add_input<decl::Float>("Value").default_value(1.0f).is_default_link_socket();
321 b.add_output<decl::Float>("Value");
322}
323
324static void node_shader_init_curve_float(bNodeTree * /*ntree*/, bNode *node)
325{
326 node->storage = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
327}
328
330 bNode *node,
331 bNodeExecData * /*execdata*/,
332 GPUNodeStack *in,
333 GPUNodeStack *out)
334{
335 CurveMapping *curve_mapping = (CurveMapping *)node->storage;
336
337 BKE_curvemapping_init(curve_mapping);
338 float *band_values;
339 int band_size;
340 BKE_curvemapping_table_RGBA(curve_mapping, &band_values, &band_size);
341 float band_layer;
342 GPUNodeLink *band_texture = GPU_color_band(mat, band_size, band_values, &band_layer);
343
344 float start_slopes[CM_TOT];
345 float end_slopes[CM_TOT];
346 BKE_curvemapping_compute_slopes(curve_mapping, start_slopes, end_slopes);
347 float range_minimums[CM_TOT];
348 BKE_curvemapping_get_range_minimums(curve_mapping, range_minimums);
349 float range_dividers[CM_TOT];
350 BKE_curvemapping_compute_range_dividers(curve_mapping, range_dividers);
351
352 return GPU_stack_link(mat,
353 node,
354 "curves_float_mixed",
355 in,
356 out,
357 band_texture,
358 GPU_constant(&band_layer),
359 GPU_uniform(range_minimums),
360 GPU_uniform(range_dividers),
361 GPU_uniform(start_slopes),
362 GPU_uniform(end_slopes));
363}
364
366 private:
367 const CurveMapping &cumap_;
368
369 public:
370 CurveFloatFunction(const CurveMapping &cumap) : cumap_(cumap)
371 {
372 static const mf::Signature signature = []() {
374 mf::SignatureBuilder builder{"Curve Float", signature};
375 builder.single_input<float>("Factor");
376 builder.single_input<float>("Value");
377 builder.single_output<float>("Value");
378 return signature;
379 }();
380 this->set_signature(&signature);
381 }
382
383 void call(const IndexMask &mask, mf::Params params, mf::Context /*context*/) const override
384 {
385 const VArray<float> &fac = params.readonly_single_input<float>(0, "Factor");
386 const VArray<float> &val_in = params.readonly_single_input<float>(1, "Value");
387 MutableSpan<float> val_out = params.uninitialized_single_output<float>(2, "Value");
388
389 mask.foreach_index([&](const int64_t i) {
390 val_out[i] = BKE_curvemapping_evaluateF(&cumap_, 0, val_in[i]);
391 if (fac[i] != 1.0f) {
392 val_out[i] = (1.0f - fac[i]) * val_in[i] + fac[i] * val_out[i];
393 }
394 });
395 }
396};
397
399{
400 const bNode &bnode = builder.node();
401 CurveMapping *cumap = (CurveMapping *)bnode.storage;
404}
405
407#ifdef WITH_MATERIALX
408{
409 /* TODO: implement */
410 return get_input_value("Value", NodeItem::Type::Float);
411}
412#endif
414
415} // namespace blender::nodes::node_shader_curves_cc::flt
416
418{
420
421 static blender::bke::bNodeType ntype;
422
424 ntype.declare = file_ns::sh_node_curve_float_declare;
425 ntype.initfunc = file_ns::node_shader_init_curve_float;
428 ntype.gpu_fn = file_ns::gpu_shader_curve_float;
429 ntype.build_multi_function = file_ns::sh_node_curve_float_build_multi_function;
430 ntype.materialx_fn = file_ns::node_shader_materialx;
431
433}
void BKE_curvemapping_compute_range_dividers(const CurveMapping *curve_mapping, float dividers[4])
void BKE_curvemapping_get_range_minimums(const CurveMapping *curve_mapping, float minimums[4])
bool BKE_curvemapping_is_map_identity(const CurveMapping *curve_mapping, int index)
float BKE_curvemapping_evaluateF(const CurveMapping *cumap, int cur, float value)
void BKE_curvemapping_evaluateRGBF(const CurveMapping *cumap, float vecout[3], const float vecin[3])
void BKE_curvemapping_init(CurveMapping *cumap)
CurveMapping * BKE_curvemapping_add(int tot, float minx, float miny, float maxx, float maxy)
Definition colortools.cc:90
void BKE_curvemapping_table_RGBA(const CurveMapping *cumap, float **array, int *size)
void BKE_curvemapping_evaluate3F(const CurveMapping *cumap, float vecout[3], const float vecin[3])
void BKE_curvemapping_compute_slopes(const CurveMapping *curve_mapping, float start_slopes[4], float end_slopes[4])
#define SH_NODE_CURVE_FLOAT
Definition BKE_node.hh:992
#define NODE_CLASS_CONVERTER
Definition BKE_node.hh:410
#define SH_NODE_CURVE_VEC
Definition BKE_node.hh:901
#define NODE_CLASS_OP_VECTOR
Definition BKE_node.hh:407
#define SH_NODE_CURVE_RGB
Definition BKE_node.hh:902
#define NODE_CLASS_OP_COLOR
Definition BKE_node.hh:406
void interp_v3_v3v3(float r[3], const float a[3], const float b[3], float t)
Definition math_vector.c:36
#define CM_TOT
bool GPU_stack_link(GPUMaterial *mat, const bNode *node, const char *name, GPUNodeStack *in, GPUNodeStack *out,...)
GPUNodeLink * GPU_constant(const float *num)
GPUNodeLink * GPU_color_band(GPUMaterial *mat, int size, float *pixels, float *r_row)
GPUNodeLink * GPU_uniform(const float *num)
@ PROP_FACTOR
Definition RNA_types.hh:154
void set_signature(const Signature *signature)
void call(const IndexMask &mask, mf::Params params, mf::Context) const override
void call(const IndexMask &mask, mf::Params params, mf::Context) const override
void call(const IndexMask &mask, mf::Params params, mf::Context) const override
local_group_size(16, 16) .push_constant(Type b
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
void node_type_size_preset(bNodeType *ntype, eNodeSizePreset size)
Definition node.cc:4614
void node_type_storage(bNodeType *ntype, const char *storagename, void(*freefunc)(bNode *node), void(*copyfunc)(bNodeTree *dest_ntree, bNode *dest_node, const bNode *src_node))
Definition node.cc:4632
void node_register_type(bNodeType *ntype)
Definition node.cc:1708
static void sh_node_curve_float_declare(NodeDeclarationBuilder &b)
static void sh_node_curve_float_build_multi_function(NodeMultiFunctionBuilder &builder)
static void node_shader_init_curve_float(bNodeTree *, bNode *node)
static int gpu_shader_curve_float(GPUMaterial *mat, bNode *node, bNodeExecData *, GPUNodeStack *in, GPUNodeStack *out)
static void sh_node_curve_rgb_build_multi_function(NodeMultiFunctionBuilder &builder)
static int gpu_shader_curve_rgb(GPUMaterial *mat, bNode *node, bNodeExecData *, GPUNodeStack *in, GPUNodeStack *out)
static void sh_node_curve_rgb_declare(NodeDeclarationBuilder &b)
static void node_shader_init_curve_rgb(bNodeTree *, bNode *node)
static void node_shader_init_curve_vec(bNodeTree *, bNode *node)
static int gpu_shader_curve_vec(GPUMaterial *mat, bNode *node, bNodeExecData *, GPUNodeStack *in, GPUNodeStack *out)
static void sh_node_curve_vec_declare(NodeDeclarationBuilder &b)
static void sh_node_curve_vec_build_multi_function(NodeMultiFunctionBuilder &builder)
#define NODE_SHADER_MATERIALX_BEGIN
#define NODE_SHADER_MATERIALX_END
void register_node_type_sh_curve_float()
void register_node_type_sh_curve_rgb()
void register_node_type_sh_curve_vec()
void sh_fn_node_type_base(blender::bke::bNodeType *ntype, int type, const char *name, short nclass)
void node_copy_curves(bNodeTree *, bNode *dest_node, const bNode *src_node)
Definition node_util.cc:53
void node_free_curves(bNode *node)
Definition node_util.cc:41
#define min(a, b)
Definition sort.c:32
__int64 int64_t
Definition stdint.h:89
void * storage
Defines a node type.
Definition BKE_node.hh:218
NodeMaterialXFunction materialx_fn
Definition BKE_node.hh:320
void(* initfunc)(bNodeTree *ntree, bNode *node)
Definition BKE_node.hh:267
NodeGPUExecFunction gpu_fn
Definition BKE_node.hh:318
NodeMultiFunctionBuildFunction build_multi_function
Definition BKE_node.hh:336
NodeDeclareFunction declare
Definition BKE_node.hh:347