32 b.use_custom_socket_order();
33 b.allow_any_socket_order();
35 b.add_input<
decl::Color>(
"Image").default_value({1.0f, 1.0f, 1.0f, 1.0f}).hide_value();
36 b.add_output<
decl::Color>(
"Image").align_with_previous();
38 b.add_input<
decl::Float>(
"Mask").default_value(1.0f).min(0.0f).max(1.0f);
46 .description(
"Controls the saturation of the entire image");
52 .description(
"Controls the contrast of the entire image");
58 .description(
"Controls the gamma of the entire image");
64 .description(
"Controls the gain of the entire image");
70 .description(
"Controls the offset of the entire image");
78 .description(
"Controls the saturation of the highlights");
84 .description(
"Controls the contrast of the highlights");
90 .description(
"Controls the gamma of the highlights");
96 .description(
"Controls the gain of the highlights");
102 .description(
"Controls the offset of the highlights");
110 .description(
"Controls the saturation of the midtones");
116 .description(
"Controls the contrast of the midtones");
122 .description(
"Controls the gamma of the midtones");
128 .description(
"Controls the gain of the midtones");
134 .description(
"Controls the offset of the midtones");
142 .description(
"Controls the saturation of the shadows");
148 .description(
"Controls the contrast of the shadows");
154 .description(
"Controls the gamma of the shadows");
160 .description(
"Controls the gain of the shadows");
166 .description(
"Controls the offset of the shadows");
175 "Specifies the luminance at which the midtones of the image start and the shadows end");
182 "Specifies the luminance at which the midtones of the image end and the highlights "
188 .
description(
"If true, the correction will be applied on the red channel");
191 .
description(
"If true, the correction will be applied on the green channel");
194 .
description(
"If true, the correction will be applied on the blue channel");
205 float luminance_coefficients[3];
210 "node_composite_color_correction",
218 const float &master_saturation,
219 const float &master_contrast,
220 const float &master_gamma,
221 const float &master_gain,
222 const float &master_offset,
223 const float &highlights_saturation,
224 const float &highlights_contrast,
225 const float &highlights_gamma,
226 const float &highlights_gain,
227 const float &highlights_offset,
228 const float &midtones_saturation,
229 const float &midtones_contrast,
230 const float &midtones_gamma,
231 const float &midtones_gain,
232 const float &midtones_offset,
233 const float &shadows_saturation,
234 const float &shadows_contrast,
235 const float &shadows_gamma,
236 const float &shadows_gain,
237 const float &shadows_offset,
238 const float &start_midtones,
239 const float &end_midtones,
240 const bool &apply_on_red,
241 const bool &apply_on_green,
242 const bool &apply_on_blue,
243 const float3 &luminance_coefficients)
245 const float margin = 0.10f;
246 const float margin_divider = 0.5f / margin;
248 float level_shadows = 0.0f;
249 float level_midtones = 0.0f;
250 float level_highlights = 0.0f;
251 if (level < (start_midtones - margin)) {
252 level_shadows = 1.0f;
254 else if (level < (start_midtones + margin)) {
255 level_midtones = ((level - start_midtones) * margin_divider) + 0.5f;
256 level_shadows = 1.0f - level_midtones;
258 else if (level < (end_midtones - margin)) {
259 level_midtones = 1.0f;
261 else if (level < (end_midtones + margin)) {
262 level_highlights = ((level - end_midtones) * margin_divider) + 0.5f;
263 level_midtones = 1.0f - level_highlights;
266 level_highlights = 1.0f;
269 float contrast = level_shadows * shadows_contrast;
270 contrast += level_midtones * midtones_contrast;
271 contrast += level_highlights * highlights_contrast;
272 contrast *= master_contrast;
273 float saturation = level_shadows * shadows_saturation;
274 saturation += level_midtones * midtones_saturation;
275 saturation += level_highlights * highlights_saturation;
276 saturation *= master_saturation;
277 float gamma = level_shadows * shadows_gamma;
278 gamma += level_midtones * midtones_gamma;
279 gamma += level_highlights * highlights_gamma;
280 gamma *= master_gamma;
281 float gain = level_shadows * shadows_gain;
282 gain += level_midtones * midtones_gain;
283 gain += level_highlights * highlights_gain;
285 float offset = level_shadows * shadows_offset;
286 offset += level_midtones * midtones_offset;
287 offset += level_highlights * highlights_offset;
288 offset += master_offset;
290 float inverse_gamma = 1.0f / gamma;
293 float3 corrected = luma + saturation * (
color.xyz() - luma);
294 corrected = 0.5f + (corrected - 0.5f) * contrast;
298 return float4(apply_on_red ? corrected.x :
color.x,
299 apply_on_green ? corrected.y :
color.y,
300 apply_on_blue ? corrected.z :
color.z,
306 float3 luminance_coefficients;
310 return mf::build::detail::build_multi_function_with_n_inputs_one_output<float4>(
314 const float &master_saturation,
315 const float &master_contrast,
316 const float &master_gamma,
317 const float &master_gain,
318 const float &master_offset,
319 const float &highlights_saturation,
320 const float &highlights_contrast,
321 const float &highlights_gamma,
322 const float &highlights_gain,
323 const float &highlights_offset,
324 const float &midtones_saturation,
325 const float &midtones_contrast,
326 const float &midtones_gamma,
327 const float &midtones_gain,
328 const float &midtones_offset,
329 const float &shadows_saturation,
330 const float &shadows_contrast,
331 const float &shadows_gamma,
332 const float &shadows_gain,
333 const float &shadows_offset,
334 const float &start_midtones,
335 const float &end_midtones,
336 const bool &apply_on_red,
337 const bool &apply_on_green,
338 const bool &apply_on_blue) ->
float4 {
346 highlights_saturation,
366 luminance_coefficients);
368 mf::build::exec_presets::SomeSpanOrSingle<0>(),
408 ntype.
ui_name =
"Color Correction";
410 "Adjust the color of an image, separately in several tonal ranges (highlights, midtones and "
414 ntype.
declare = file_ns::cmp_node_colorcorrection_declare;
415 ntype.
gpu_fn = file_ns::node_gpu_material;
#define NODE_CLASS_OP_COLOR
#define CMP_NODE_COLORCORRECTION
bool GPU_stack_link(GPUMaterial *mat, const bNode *node, const char *name, GPUNodeStack *in, GPUNodeStack *out,...)
GPUNodeLink * GPU_constant(const float *num)
BLI_INLINE void IMB_colormanagement_get_luminance_coefficients(float r_rgb[3])
#define NOD_REGISTER_NODE(REGISTER_FUNC)
DeclType::Builder & add_input(StringRef name, StringRef identifier="")
void construct_and_set_matching_fn_cb(Fn &&create_multi_function)
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
void node_register_type(bNodeType &ntype)
T dot(const QuaternionBase< T > &a, const QuaternionBase< T > &b)
T min(const T &a, const T &b)
T interpolate(const T &a, const T &b, const FactorT &t)
T fallback_pow(const T &x, const T &power, const T &fallback)
static void node_build_multi_function(blender::nodes::NodeMultiFunctionBuilder &builder)
static int node_gpu_material(GPUMaterial *material, bNode *node, bNodeExecData *, GPUNodeStack *inputs, GPUNodeStack *outputs)
static void cmp_node_colorcorrection_declare(NodeDeclarationBuilder &b)
static float4 color_correction(const float4 &color, const float &mask, const float &master_saturation, const float &master_contrast, const float &master_gamma, const float &master_gain, const float &master_offset, const float &highlights_saturation, const float &highlights_contrast, const float &highlights_gamma, const float &highlights_gain, const float &highlights_offset, const float &midtones_saturation, const float &midtones_contrast, const float &midtones_gamma, const float &midtones_gain, const float &midtones_offset, const float &shadows_saturation, const float &shadows_contrast, const float &shadows_gamma, const float &shadows_gain, const float &shadows_offset, const float &start_midtones, const float &end_midtones, const bool &apply_on_red, const bool &apply_on_green, const bool &apply_on_blue, const float3 &luminance_coefficients)
VecBase< float, 4 > float4
VecBase< float, 3 > float3
static void register_node_type_cmp_colorcorrection()
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[]
std::string ui_description
NodeGPUExecFunction gpu_fn
NodeMultiFunctionBuildFunction build_multi_function
const char * enum_name_legacy
NodeDeclareFunction declare