41 b.use_custom_socket_order();
54 .compositor_domain_priority(1);
56 .default_value({1.0f, 1.0f, 1.0f, 1.0f})
57 .compositor_domain_priority(0);
64 .description(
"Correction for shadows");
66 .default_value({1.0f, 1.0f, 1.0f, 1.0f})
67 .description(
"Correction for shadows");
73 .description(
"Correction for midtones");
75 .default_value({1.0f, 1.0f, 1.0f, 1.0f})
76 .description(
"Correction for midtones");
82 .description(
"Correction for highlights");
84 .default_value({1.0f, 1.0f, 1.0f, 1.0f})
85 .description(
"Correction for highlights");
92 .description(
"Correction for shadows");
94 .default_value({0.0f, 0.0f, 0.0f, 1.0f})
95 .description(
"Correction for shadows");
101 .description(
"Correction for midtones");
103 .default_value({1.0f, 1.0f, 1.0f, 1.0f})
104 .description(
"Correction for midtones");
110 .description(
"Correction for highlights");
112 .default_value({1.0f, 1.0f, 1.0f, 1.0f})
113 .description(
"Correction for highlights");
117 .default_value(6500.0f)
121 .description(
"Color temperature of the input's white point");
123 .default_value(10.0f)
127 .description(
"Color tint of the input's white point (the default of 10 matches daylight)");
135 .default_value(6500.0f)
139 .description(
"Color temperature of the output's white point");
141 .default_value(10.0f)
145 .description(
"Color tint of the output's white point (the default of 10 matches daylight)");
189 *node,
SOCK_IN,
"Input Temperature");
192 *node,
SOCK_IN,
"Output Temperature");
201 const float input_tint,
202 const float output_temperature,
203 const float output_tint)
210 return xyz_to_scene * adaption * scene_to_xyz;
225 material, node,
"node_composite_color_balance_asc_cdl",
inputs,
outputs);
228 const bNodeSocket &input_temperature = node->input_by_identifier(
"Input Temperature");
229 const bNodeSocket &input_tint = node->input_by_identifier(
"Input Tint");
230 const bNodeSocket &output_temperature = node->input_by_identifier(
"Output Temperature");
231 const bNodeSocket &output_tint = node->input_by_identifier(
"Output Tint");
235 if (input_temperature.is_directly_linked() && input_tint.is_directly_linked() &&
236 output_temperature.is_directly_linked() && output_tint.is_directly_linked())
245 "node_composite_color_balance_white_point_constant",
255 "node_composite_color_balance_white_point_variable",
268 const float &base_lift,
270 const float &base_gamma,
271 const float4 &color_gamma,
272 const float &base_gain,
278 const float3 lift = base_lift + color_lift.
xyz();
279 const float3 lift_balanced = ((srgb_color - 1.0f) * (2.0f - lift)) + 1.0f;
281 const float3 gain = base_gain * color_gain.
xyz();
282 float3 gain_balanced = lift_balanced * gain;
288 const float3 gamma = base_gamma * color_gamma.
xyz();
296 const float &base_offset,
297 const float4 &color_offset,
298 const float &base_power,
299 const float4 &color_power,
300 const float &base_slope,
301 const float4 &color_slope)
303 const float3 slope = base_slope * color_slope.
xyz();
306 const float3 offset = base_offset + color_offset.
xyz();
307 const float3 offset_balanced = slope_balanced + offset;
319 const float3 balanced = white_point_matrix *
color.xyz();
325 const float input_temperature,
326 const float input_tint,
327 const float output_temperature,
328 const float output_tint,
335 const float3x3 white_point_matrix = xyz_to_scene * adaption * scene_to_xyz;
337 const float3 balanced = white_point_matrix *
color.xyz();
345 static const mf::Signature
signature = []() {
347 mf::SignatureBuilder builder{
"Color Balance White Point",
signature};
348 builder.single_input<
float>(
"Factor");
349 builder.single_input<
float4>(
"Color");
350 builder.single_input<
float>(
"Input Temperature");
351 builder.single_input<
float>(
"Input Tint");
352 builder.single_input<
float>(
"Output Temperature");
353 builder.single_input<
float>(
"Output Tint");
354 builder.single_output<
float4>(
"Result");
365 2,
"Input Temperature");
366 const VArray<float> input_tint_array =
params.readonly_single_input<
float>(3,
"Input Tint");
368 4,
"Output Temperature");
369 const VArray<float> output_tint_array =
params.readonly_single_input<
float>(5,
"Output Tint");
373 const std::optional<float> input_temperature_single = input_temperature_array.get_if_single();
374 const std::optional<float> input_tint_single = input_tint_array.get_if_single();
375 const std::optional<float> output_temperature_single =
376 output_temperature_array.get_if_single();
377 const std::optional<float> output_tint_single = output_tint_array.get_if_single();
379 if (input_temperature_single.has_value() && input_tint_single.has_value() &&
380 output_temperature_single.has_value() && output_tint_single.has_value())
383 input_tint_single.value(),
384 output_temperature_single.value(),
385 output_tint_single.value());
388 factor_array[
i], color_array[
i], white_point_matrix);
398 input_temperature_array[
i],
400 output_temperature_array[
i],
401 output_tint_array[
i],
415 SI8_SO<float, float4, float, float4, float, float4, float, float4, float4>(
417 [=](
const float factor,
419 const float base_lift,
421 const float base_gamma,
422 const float4 &color_gamma,
423 const float base_gain,
434 mf::build::exec_presets::SomeSpanOrSingle<1>());
441 SI8_SO<float, float4, float, float4, float, float4, float, float4, float4>(
442 "Color Balance ASC CDL",
443 [=](
const float factor,
445 const float base_offset,
446 const float4 &color_offset,
447 const float base_power,
448 const float4 &color_power,
449 const float base_slope,
460 mf::build::exec_presets::SomeSpanOrSingle<1>());
481 ntype.
ui_name =
"Color Balance";
485 ntype.
declare = file_ns::cmp_node_colorbalance_declare;
487 ntype.
gpu_fn = file_ns::node_gpu_material;
#define NODE_CLASS_OP_COLOR
#define CMP_NODE_COLORBALANCE
void linearrgb_to_srgb_v3_v3(float srgb[3], const float linear[3])
void srgb_to_linearrgb_v3_v3(float linear[3], const float srgb[3])
CMPNodeColorBalanceMethod
@ CMP_NODE_COLOR_BALANCE_LGG
@ CMP_NODE_COLOR_BALANCE_ASC_CDL
@ CMP_NODE_COLOR_BALANCE_WHITEPOINT
static void split(const char *text, const char *seps, char ***str, int *count)
bool GPU_stack_link(GPUMaterial *mat, const bNode *node, const char *name, GPUNodeStack *in, GPUNodeStack *out,...)
GPUNodeLink * GPU_uniform(const float *num)
blender::float3x3 IMB_colormanagement_get_scene_linear_to_xyz()
blender::float3x3 IMB_colormanagement_get_xyz_to_scene_linear()
#define NOD_REGISTER_NODE(REGISTER_FUNC)
void uiTemplateCryptoPicker(uiLayout *layout, PointerRNA *ptr, blender::StringRefNull propname, int icon)
@ UI_ITEM_R_SPLIT_EMPTY_NAME
const Signature & signature() const
void set_signature(const Signature *signature)
void add_layout(std::function< void(uiLayout *, bContext *, PointerRNA *)> draw)
DeclType::Builder & add_input(StringRef name, StringRef identifier="")
void set_matching_fn(const mf::MultiFunction *fn)
void construct_and_set_matching_fn_cb(Fn &&create_multi_function)
void call(const IndexMask &mask, mf::Params params, mf::Context) const override
ColorBalanceWhitePointFunction()
ccl_device_inline float2 power(const float2 v, const float e)
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
bNodeSocket * node_find_socket(bNode &node, eNodeSocketInOut in_out, StringRef identifier)
void node_register_type(bNodeType &ntype)
void node_set_socket_availability(bNodeTree &ntree, bNodeSocket &sock, bool is_available)
T pow(const T &x, const T &power)
float3 whitepoint_from_temp_tint(float temperature, float tint)
T min(const T &a, const T &b)
T interpolate(const T &a, const T &b, const FactorT &t)
float3x3 chromatic_adaption_matrix(const float3 &from_XYZ, const float3 &to_XYZ)
T max(const T &a, const T &b)
static void cmp_node_colorbalance_declare(NodeDeclarationBuilder &b)
static void node_update(bNodeTree *ntree, bNode *node)
static float4 color_balance_white_point_constant(const float factor, const float4 &color, const float3x3 &white_point_matrix)
static float4 color_balance_lgg(const float factor, const float4 &color, const float &base_lift, const float4 &color_lift, const float &base_gamma, const float4 &color_gamma, const float &base_gain, const float4 &color_gain)
static float4 color_balance_asc_cdl(const float factor, const float4 &color, const float &base_offset, const float4 &color_offset, const float &base_power, const float4 &color_power, const float &base_slope, const float4 &color_slope)
static CMPNodeColorBalanceMethod get_color_balance_method(const bNode &node)
static void node_build_multi_function(blender::nodes::NodeMultiFunctionBuilder &builder)
static float4 color_balance_white_point_variable(const float factor, const float4 &color, const float input_temperature, const float input_tint, const float output_temperature, const float output_tint, const float3x3 &scene_to_xyz, const float3x3 &xyz_to_scene)
static float3x3 get_white_point_matrix(const float input_temperature, const float input_tint, const float output_temperature, const float output_tint)
static int node_gpu_material(GPUMaterial *material, bNode *node, bNodeExecData *, GPUNodeStack *inputs, GPUNodeStack *outputs)
MatBase< float, 4, 4 > float4x4
VecBase< float, 4 > float4
MatBase< float, 3, 3 > float3x3
VecBase< float, 3 > float3
static void register_node_type_cmp_colorbalance()
void cmp_node_type_base(blender::bke::bNodeType *ntype, std::string idname, const std::optional< int16_t > legacy_type)
static blender::bke::bNodeSocketTemplate outputs[]
static blender::bke::bNodeSocketTemplate inputs[]
VecBase< T, 3 > xyz() const
std::string ui_description
NodeGPUExecFunction gpu_fn
NodeMultiFunctionBuildFunction build_multi_function
const char * enum_name_legacy
NodeDeclareFunction declare
void(* updatefunc)(bNodeTree *ntree, bNode *node)
uiLayout & split(float percentage, bool align)
void prop(PointerRNA *ptr, PropertyRNA *prop, int index, int value, eUI_Item_Flag flag, std::optional< blender::StringRef > name_opt, int icon, std::optional< blender::StringRef > placeholder=std::nullopt)