Blender V5.0
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
8
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>("Factor", "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 .compositor_domain_priority(1);
32 b.add_input<decl::Vector>("Vector")
33 .min(-1.0f)
34 .max(1.0f)
35 .description("Vector which would be mapped to the curve")
36 .compositor_domain_priority(0);
37 b.add_output<decl::Vector>("Vector");
38}
39
40static void node_shader_init_curve_vec(bNodeTree * /*ntree*/, bNode *node)
41{
42 node->storage = BKE_curvemapping_add(3, -1.0f, -1.0f, 1.0f, 1.0f);
43}
44
46 bNode *node,
47 bNodeExecData * /*execdata*/,
50{
51 CurveMapping *curve_mapping = (CurveMapping *)node->storage;
52
53 BKE_curvemapping_init(curve_mapping);
54 float *band_values;
55 int band_size;
56 BKE_curvemapping_table_RGBA(curve_mapping, &band_values, &band_size);
57 float band_layer;
58 GPUNodeLink *band_texture = GPU_color_band(mat, band_size, band_values, &band_layer);
59
60 float start_slopes[CM_TOT];
61 float end_slopes[CM_TOT];
62 BKE_curvemapping_compute_slopes(curve_mapping, start_slopes, end_slopes);
63 float range_minimums[CM_TOT];
64 BKE_curvemapping_get_range_minimums(curve_mapping, range_minimums);
65 float range_dividers[CM_TOT];
66 BKE_curvemapping_compute_range_dividers(curve_mapping, range_dividers);
67
68 return GPU_stack_link(mat,
69 node,
70 "curves_vector_mixed",
71 in,
72 out,
73 band_texture,
74 GPU_constant(&band_layer),
75 GPU_uniform(range_minimums),
76 GPU_uniform(range_dividers),
77 GPU_uniform(start_slopes),
78 GPU_uniform(end_slopes));
79}
80
81class CurveVecFunction : public mf::MultiFunction {
82 private:
83 const CurveMapping &cumap_;
84
85 public:
86 CurveVecFunction(const CurveMapping &cumap) : cumap_(cumap)
87 {
88 static const mf::Signature signature = []() {
89 mf::Signature signature;
90 mf::SignatureBuilder builder{"Curve Vec", signature};
91 builder.single_input<float>("Fac");
92 builder.single_input<float3>("Vector");
93 builder.single_output<float3>("Vector");
94 return signature;
95 }();
96 this->set_signature(&signature);
97 }
98
99 void call(const IndexMask &mask, mf::Params params, mf::Context /*context*/) const override
100 {
101 const VArray<float> &fac = params.readonly_single_input<float>(0, "Fac");
102 const VArray<float3> &vec_in = params.readonly_single_input<float3>(1, "Vector");
103 MutableSpan<float3> vec_out = params.uninitialized_single_output<float3>(2, "Vector");
104
105 mask.foreach_index([&](const int64_t i) {
106 BKE_curvemapping_evaluate3F(&cumap_, vec_out[i], vec_in[i]);
107 if (fac[i] != 1.0f) {
108 interp_v3_v3v3(vec_out[i], vec_in[i], vec_out[i], fac[i]);
109 }
110 });
111 }
112};
113
115{
116 const bNode &bnode = builder.node();
117 CurveMapping *cumap = (CurveMapping *)bnode.storage;
120}
121
123#ifdef WITH_MATERIALX
124{
125 /* TODO: implement */
126 return get_input_value("Vector", NodeItem::Type::Vector3);
127}
128#endif
130
131} // namespace blender::nodes::node_shader_curves_cc::vec
132
134{
136
137 static blender::bke::bNodeType ntype;
138
139 common_node_type_base(&ntype, "ShaderNodeVectorCurve", SH_NODE_CURVE_VEC);
140 ntype.ui_name = "Vector Curves";
141 ntype.ui_description = "Map input vector components with curves";
142 ntype.enum_name_legacy = "CURVE_VEC";
144 ntype.declare = file_ns::sh_node_curve_vec_declare;
145 ntype.initfunc = file_ns::node_shader_init_curve_vec;
148 ntype.gpu_fn = file_ns::gpu_shader_curve_vec;
149 ntype.build_multi_function = file_ns::sh_node_curve_vec_build_multi_function;
150 ntype.materialx_fn = file_ns::node_shader_materialx;
151
153}
154
155/* **************** CURVE RGB ******************** */
156
158
160{
161 b.is_function_node();
162 b.add_input<decl::Float>("Factor", "Fac")
163 .min(0.0f)
164 .max(1.0f)
165 .default_value(1.0f)
166 .subtype(PROP_FACTOR)
167 .no_muted_links()
168 .description("Amount of influence the node exerts on the output color")
169 .compositor_domain_priority(1);
170 b.add_input<decl::Color>("Color")
171 .default_value({1.0f, 1.0f, 1.0f, 1.0f})
172 .description("Color input on which correction will be applied")
174 b.add_output<decl::Color>("Color");
175}
176
177static void node_shader_init_curve_rgb(bNodeTree * /*ntree*/, bNode *node)
178{
179 node->storage = BKE_curvemapping_add(4, 0.0f, 0.0f, 1.0f, 1.0f);
180}
181
183 bNode *node,
184 bNodeExecData * /*execdata*/,
187{
188 CurveMapping *curve_mapping = (CurveMapping *)node->storage;
189
190 BKE_curvemapping_init(curve_mapping);
191 float *band_values;
192 int band_size;
193 BKE_curvemapping_table_RGBA(curve_mapping, &band_values, &band_size);
194 float band_layer;
195 GPUNodeLink *band_texture = GPU_color_band(mat, band_size, band_values, &band_layer);
196
197 float start_slopes[CM_TOT];
198 float end_slopes[CM_TOT];
199 BKE_curvemapping_compute_slopes(curve_mapping, start_slopes, end_slopes);
200 float range_minimums[CM_TOT];
201 BKE_curvemapping_get_range_minimums(curve_mapping, range_minimums);
202 float range_dividers[CM_TOT];
203 BKE_curvemapping_compute_range_dividers(curve_mapping, range_dividers);
204
205 /* Shader nodes don't do white balancing. */
206 float black_level[4] = {0.0f, 0.0f, 0.0f, 1.0f};
207 float white_level[4] = {1.0f, 1.0f, 1.0f, 1.0f};
208
209 /* If the RGB curves do nothing, use a function that skips RGB computations. */
210 if (BKE_curvemapping_is_map_identity(curve_mapping, 0) &&
211 BKE_curvemapping_is_map_identity(curve_mapping, 1) &&
212 BKE_curvemapping_is_map_identity(curve_mapping, 2))
213 {
214 return GPU_stack_link(mat,
215 node,
216 "curves_combined_only",
217 in,
218 out,
219 GPU_constant(black_level),
220 GPU_constant(white_level),
221 band_texture,
222 GPU_constant(&band_layer),
223 GPU_uniform(&range_minimums[3]),
224 GPU_uniform(&range_dividers[3]),
225 GPU_uniform(&start_slopes[3]),
226 GPU_uniform(&end_slopes[3]));
227 }
228
229 return GPU_stack_link(mat,
230 node,
231 "curves_combined_rgb",
232 in,
233 out,
234 GPU_constant(black_level),
235 GPU_constant(white_level),
236 band_texture,
237 GPU_constant(&band_layer),
238 GPU_uniform(range_minimums),
239 GPU_uniform(range_dividers),
240 GPU_uniform(start_slopes),
241 GPU_uniform(end_slopes));
242}
243
244class CurveRGBFunction : public mf::MultiFunction {
245 private:
246 const CurveMapping &cumap_;
247
248 public:
249 CurveRGBFunction(const CurveMapping &cumap) : cumap_(cumap)
250 {
251 static const mf::Signature signature = []() {
252 mf::Signature signature;
253 mf::SignatureBuilder builder{"Curve RGB", signature};
254 builder.single_input<float>("Fac");
255 builder.single_input<ColorGeometry4f>("Color");
256 builder.single_output<ColorGeometry4f>("Color");
257 return signature;
258 }();
259 this->set_signature(&signature);
260 }
261
262 void call(const IndexMask &mask, mf::Params params, mf::Context /*context*/) const override
263 {
264 const VArray<float> &fac = params.readonly_single_input<float>(0, "Fac");
265 const VArray<ColorGeometry4f> &col_in = params.readonly_single_input<ColorGeometry4f>(1,
266 "Color");
267 MutableSpan<ColorGeometry4f> col_out = params.uninitialized_single_output<ColorGeometry4f>(
268 2, "Color");
269
270 mask.foreach_index([&](const int64_t i) {
271 BKE_curvemapping_evaluateRGBF(&cumap_, col_out[i], col_in[i]);
272 if (fac[i] != 1.0f) {
273 interp_v3_v3v3(col_out[i], col_in[i], col_out[i], fac[i]);
274 }
275 col_out[i].a = 1.0f;
276 });
277 }
278};
279
281{
282 const bNode &bnode = builder.node();
283 CurveMapping *cumap = (CurveMapping *)bnode.storage;
286}
287
289#ifdef WITH_MATERIALX
290{
291 /* TODO: implement */
292 return get_input_value("Color", NodeItem::Type::Color3);
293}
294#endif
296
297} // namespace blender::nodes::node_shader_curves_cc::rgb
298
300{
302
303 static blender::bke::bNodeType ntype;
304
305 common_node_type_base(&ntype, "ShaderNodeRGBCurve", SH_NODE_CURVE_RGB);
306 ntype.ui_name = "RGB Curves";
307 ntype.ui_description = "Apply color corrections for each color channel";
308 ntype.enum_name_legacy = "CURVE_RGB";
310 ntype.declare = file_ns::sh_node_curve_rgb_declare;
311 ntype.initfunc = file_ns::node_shader_init_curve_rgb;
314 ntype.gpu_fn = file_ns::gpu_shader_curve_rgb;
315 ntype.build_multi_function = file_ns::sh_node_curve_rgb_build_multi_function;
316 ntype.materialx_fn = file_ns::node_shader_materialx;
317
319}
320
321/* **************** CURVE FLOAT ******************** */
322
324
326{
327 b.is_function_node();
328 b.add_input<decl::Float>("Factor")
329 .min(0.0f)
330 .max(1.0f)
331 .default_value(1.0f)
332 .subtype(PROP_FACTOR)
333 .no_muted_links()
334 .compositor_domain_priority(1);
335 b.add_input<decl::Float>("Value")
336 .default_value(1.0f)
338 .compositor_domain_priority(0);
339 b.add_output<decl::Float>("Value");
340}
341
342static void node_shader_init_curve_float(bNodeTree * /*ntree*/, bNode *node)
343{
344 node->storage = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
345}
346
348 bNode *node,
349 bNodeExecData * /*execdata*/,
352{
353 CurveMapping *curve_mapping = (CurveMapping *)node->storage;
354
355 BKE_curvemapping_init(curve_mapping);
356 float *band_values;
357 int band_size;
358 BKE_curvemapping_table_RGBA(curve_mapping, &band_values, &band_size);
359 float band_layer;
360 GPUNodeLink *band_texture = GPU_color_band(mat, band_size, band_values, &band_layer);
361
362 float start_slopes[CM_TOT];
363 float end_slopes[CM_TOT];
364 BKE_curvemapping_compute_slopes(curve_mapping, start_slopes, end_slopes);
365 float range_minimums[CM_TOT];
366 BKE_curvemapping_get_range_minimums(curve_mapping, range_minimums);
367 float range_dividers[CM_TOT];
368 BKE_curvemapping_compute_range_dividers(curve_mapping, range_dividers);
369
370 return GPU_stack_link(mat,
371 node,
372 "curves_float_mixed",
373 in,
374 out,
375 band_texture,
376 GPU_constant(&band_layer),
377 GPU_uniform(range_minimums),
378 GPU_uniform(range_dividers),
379 GPU_uniform(start_slopes),
380 GPU_uniform(end_slopes));
381}
382
383class CurveFloatFunction : public mf::MultiFunction {
384 private:
385 const CurveMapping &cumap_;
386
387 public:
388 CurveFloatFunction(const CurveMapping &cumap) : cumap_(cumap)
389 {
390 static const mf::Signature signature = []() {
391 mf::Signature signature;
392 mf::SignatureBuilder builder{"Curve Float", signature};
393 builder.single_input<float>("Factor");
394 builder.single_input<float>("Value");
395 builder.single_output<float>("Value");
396 return signature;
397 }();
398 this->set_signature(&signature);
399 }
400
401 void call(const IndexMask &mask, mf::Params params, mf::Context /*context*/) const override
402 {
403 const VArray<float> &fac = params.readonly_single_input<float>(0, "Factor");
404 const VArray<float> &val_in = params.readonly_single_input<float>(1, "Value");
405 MutableSpan<float> val_out = params.uninitialized_single_output<float>(2, "Value");
406
407 mask.foreach_index([&](const int64_t i) {
408 val_out[i] = BKE_curvemapping_evaluateF(&cumap_, 0, val_in[i]);
409 if (fac[i] != 1.0f) {
410 val_out[i] = (1.0f - fac[i]) * val_in[i] + fac[i] * val_out[i];
411 }
412 });
413 }
414};
415
417{
418 const bNode &bnode = builder.node();
419 CurveMapping *cumap = (CurveMapping *)bnode.storage;
422}
423
425#ifdef WITH_MATERIALX
426{
427 /* TODO: implement */
428 return get_input_value("Value", NodeItem::Type::Float);
429}
430#endif
432
433} // namespace blender::nodes::node_shader_curves_cc::flt
434
436{
438
439 static blender::bke::bNodeType ntype;
440
441 common_node_type_base(&ntype, "ShaderNodeFloatCurve", SH_NODE_CURVE_FLOAT);
442 ntype.ui_name = "Float Curve";
443 ntype.ui_description = "Map an input float to a curve and outputs a float value";
444 ntype.enum_name_legacy = "CURVE_FLOAT";
446 ntype.declare = file_ns::sh_node_curve_float_declare;
447 ntype.initfunc = file_ns::node_shader_init_curve_float;
450 ntype.gpu_fn = file_ns::gpu_shader_curve_float;
451 ntype.build_multi_function = file_ns::sh_node_curve_float_build_multi_function;
452 ntype.materialx_fn = file_ns::node_shader_materialx;
453
455}
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:89
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 NODE_CLASS_CONVERTER
Definition BKE_node.hh:453
#define NODE_CLASS_OP_VECTOR
Definition BKE_node.hh:450
#define NODE_CLASS_OP_COLOR
Definition BKE_node.hh:449
#define SH_NODE_CURVE_FLOAT
#define SH_NODE_CURVE_VEC
#define SH_NODE_CURVE_RGB
void interp_v3_v3v3(float r[3], const float a[3], const float b[3], float t)
#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:251
long long int int64_t
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
#define in
#define out
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
void node_register_type(bNodeType &ntype)
Definition node.cc:2416
void node_type_storage(bNodeType &ntype, std::optional< StringRefNull > storagename, void(*freefunc)(bNode *node), void(*copyfunc)(bNodeTree *dest_ntree, bNode *dest_node, const bNode *src_node))
Definition node.cc:5414
void node_type_size_preset(bNodeType &ntype, eNodeSizePreset size)
Definition node.cc:5396
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)
ColorSceneLinear4f< eAlpha::Premultiplied > ColorGeometry4f
VecBase< float, 3 > float3
#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 common_node_type_base(blender::bke::bNodeType *ntype, std::string idname, const std::optional< int16_t > legacy_type)
void node_copy_curves(bNodeTree *, bNode *dest_node, const bNode *src_node)
Definition node_util.cc:49
void node_free_curves(bNode *node)
Definition node_util.cc:37
#define min(a, b)
Definition sort.cc:36
void * storage
Defines a node type.
Definition BKE_node.hh:238
NodeMaterialXFunction materialx_fn
Definition BKE_node.hh:344
std::string ui_description
Definition BKE_node.hh:244
void(* initfunc)(bNodeTree *ntree, bNode *node)
Definition BKE_node.hh:289
NodeGPUExecFunction gpu_fn
Definition BKE_node.hh:342
NodeMultiFunctionBuildFunction build_multi_function
Definition BKE_node.hh:351
const char * enum_name_legacy
Definition BKE_node.hh:247
NodeDeclareFunction declare
Definition BKE_node.hh:362
i
Definition text_draw.cc:230