diff options
author | Omar Emara <mail@OmarEmara.dev> | 2022-08-10 10:58:44 +0300 |
---|---|---|
committer | Omar Emara <mail@OmarEmara.dev> | 2022-08-10 10:58:44 +0300 |
commit | 6109ad6cce9186bd6e8ff4dbfb281ae8f6742119 (patch) | |
tree | 4308957d11abb889c2dd17e931f4b97623df4098 /source/blender/nodes | |
parent | 865204fef06b1f4e73a3ad82202fe8221d1efae5 (diff) |
Realtime Compositor: Add basic color nodes
This patch implements the following nodes for the realtime compositor:
- Alpha over node.
- Bright contrast node.
- Color balance node.
- Color correction node.
- Exposure node.
- Gamma node.
- Hue correct node.
- Hue saturation value node.
- Invert node.
- Mix node.
- Posterize node.
- Time curve node.
- Vector curve node.
Differential Revision: https://developer.blender.org/D15228
Reviewed By: Clement Foucault
Diffstat (limited to 'source/blender/nodes')
13 files changed, 878 insertions, 54 deletions
diff --git a/source/blender/nodes/composite/nodes/node_composite_alpha_over.cc b/source/blender/nodes/composite/nodes/node_composite_alpha_over.cc index d392b810bc1..64c59eb24e3 100644 --- a/source/blender/nodes/composite/nodes/node_composite_alpha_over.cc +++ b/source/blender/nodes/composite/nodes/node_composite_alpha_over.cc @@ -8,6 +8,10 @@ #include "UI_interface.h" #include "UI_resources.h" +#include "GPU_material.h" + +#include "COM_shader_node.hh" + #include "node_composite_util.hh" /* **************** ALPHAOVER ******************** */ @@ -16,9 +20,18 @@ namespace blender::nodes::node_composite_alpha_over_cc { static void cmp_node_alphaover_declare(NodeDeclarationBuilder &b) { - b.add_input<decl::Float>(N_("Fac")).default_value(1.0f).min(0.0f).max(1.0f).subtype(PROP_FACTOR); - b.add_input<decl::Color>(N_("Image")).default_value({1.0f, 1.0f, 1.0f, 1.0f}); - b.add_input<decl::Color>(N_("Image"), "Image_001").default_value({1.0f, 1.0f, 1.0f, 1.0f}); + b.add_input<decl::Float>(N_("Fac")) + .default_value(1.0f) + .min(0.0f) + .max(1.0f) + .subtype(PROP_FACTOR) + .compositor_domain_priority(2); + b.add_input<decl::Color>(N_("Image")) + .default_value({1.0f, 1.0f, 1.0f, 1.0f}) + .compositor_domain_priority(0); + b.add_input<decl::Color>(N_("Image"), "Image_001") + .default_value({1.0f, 1.0f, 1.0f, 1.0f}) + .compositor_domain_priority(1); b.add_output<decl::Color>(N_("Image")); } @@ -36,6 +49,52 @@ static void node_composit_buts_alphaover(uiLayout *layout, bContext *UNUSED(C), uiItemR(col, ptr, "premul", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE); } +using namespace blender::realtime_compositor; + +class AlphaOverShaderNode : public ShaderNode { + public: + using ShaderNode::ShaderNode; + + void compile(GPUMaterial *material) override + { + GPUNodeStack *inputs = get_inputs_array(); + GPUNodeStack *outputs = get_outputs_array(); + + const float premultiply_factor = get_premultiply_factor(); + if (premultiply_factor != 0.0f) { + GPU_stack_link(material, + &bnode(), + "node_composite_alpha_over_mixed", + inputs, + outputs, + GPU_uniform(&premultiply_factor)); + return; + } + + if (get_use_premultiply()) { + GPU_stack_link(material, &bnode(), "node_composite_alpha_over_key", inputs, outputs); + return; + } + + GPU_stack_link(material, &bnode(), "node_composite_alpha_over_premultiply", inputs, outputs); + } + + bool get_use_premultiply() + { + return bnode().custom1; + } + + float get_premultiply_factor() + { + return ((NodeTwoFloats *)bnode().storage)->x; + } +}; + +static ShaderNode *get_compositor_shader_node(DNode node) +{ + return new AlphaOverShaderNode(node); +} + } // namespace blender::nodes::node_composite_alpha_over_cc void register_node_type_cmp_alphaover() @@ -50,6 +109,7 @@ void register_node_type_cmp_alphaover() node_type_init(&ntype, file_ns::node_alphaover_init); node_type_storage( &ntype, "NodeTwoFloats", node_free_standard_storage, node_copy_standard_storage); + ntype.get_compositor_shader_node = file_ns::get_compositor_shader_node; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_brightness.cc b/source/blender/nodes/composite/nodes/node_composite_brightness.cc index 65ed2885d9b..fa22f551de6 100644 --- a/source/blender/nodes/composite/nodes/node_composite_brightness.cc +++ b/source/blender/nodes/composite/nodes/node_composite_brightness.cc @@ -8,6 +8,10 @@ #include "UI_interface.h" #include "UI_resources.h" +#include "GPU_material.h" + +#include "COM_shader_node.hh" + #include "node_composite_util.hh" /* **************** Bright and Contrast ******************** */ @@ -16,9 +20,11 @@ namespace blender::nodes::node_composite_brightness_cc { static void cmp_node_brightcontrast_declare(NodeDeclarationBuilder &b) { - b.add_input<decl::Color>(N_("Image")).default_value({1.0f, 1.0f, 1.0f, 1.0f}); - b.add_input<decl::Float>(N_("Bright")).min(-100.0f).max(100.0f); - b.add_input<decl::Float>(N_("Contrast")).min(-100.0f).max(100.0f); + b.add_input<decl::Color>(N_("Image")) + .default_value({1.0f, 1.0f, 1.0f, 1.0f}) + .compositor_domain_priority(0); + b.add_input<decl::Float>(N_("Bright")).min(-100.0f).max(100.0f).compositor_domain_priority(1); + b.add_input<decl::Float>(N_("Contrast")).min(-100.0f).max(100.0f).compositor_domain_priority(2); b.add_output<decl::Color>(N_("Image")); } @@ -34,6 +40,38 @@ static void node_composit_buts_brightcontrast(uiLayout *layout, uiItemR(layout, ptr, "use_premultiply", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE); } +using namespace blender::realtime_compositor; + +class BrightContrastShaderNode : public ShaderNode { + public: + using ShaderNode::ShaderNode; + + void compile(GPUMaterial *material) override + { + GPUNodeStack *inputs = get_inputs_array(); + GPUNodeStack *outputs = get_outputs_array(); + + const float use_premultiply = get_use_premultiply(); + + GPU_stack_link(material, + &bnode(), + "node_composite_bright_contrast", + inputs, + outputs, + GPU_constant(&use_premultiply)); + } + + bool get_use_premultiply() + { + return bnode().custom1; + } +}; + +static ShaderNode *get_compositor_shader_node(DNode node) +{ + return new BrightContrastShaderNode(node); +} + } // namespace blender::nodes::node_composite_brightness_cc void register_node_type_cmp_brightcontrast() @@ -46,6 +84,7 @@ void register_node_type_cmp_brightcontrast() ntype.declare = file_ns::cmp_node_brightcontrast_declare; ntype.draw_buttons = file_ns::node_composit_buts_brightcontrast; node_type_init(&ntype, file_ns::node_composit_init_brightcontrast); + ntype.get_compositor_shader_node = file_ns::get_compositor_shader_node; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_colorbalance.cc b/source/blender/nodes/composite/nodes/node_composite_colorbalance.cc index dd081c8fc12..95675169c76 100644 --- a/source/blender/nodes/composite/nodes/node_composite_colorbalance.cc +++ b/source/blender/nodes/composite/nodes/node_composite_colorbalance.cc @@ -10,6 +10,10 @@ #include "UI_interface.h" #include "UI_resources.h" +#include "GPU_material.h" + +#include "COM_shader_node.hh" + #include "node_composite_util.hh" /* ******************* Color Balance ********************************* */ @@ -46,8 +50,15 @@ namespace blender::nodes::node_composite_colorbalance_cc { static void cmp_node_colorbalance_declare(NodeDeclarationBuilder &b) { - b.add_input<decl::Float>(N_("Fac")).default_value(1.0f).min(0.0f).max(1.0f).subtype(PROP_FACTOR); - b.add_input<decl::Color>(N_("Image")).default_value({1.0f, 1.0f, 1.0f, 1.0f}); + b.add_input<decl::Float>(N_("Fac")) + .default_value(1.0f) + .min(0.0f) + .max(1.0f) + .subtype(PROP_FACTOR) + .compositor_domain_priority(1); + b.add_input<decl::Color>(N_("Image")) + .default_value({1.0f, 1.0f, 1.0f, 1.0f}) + .compositor_domain_priority(0); b.add_output<decl::Color>(N_("Image")); } @@ -71,7 +82,7 @@ static void node_composit_buts_colorbalance(uiLayout *layout, bContext *UNUSED(C uiItemR(layout, ptr, "correction_method", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE); - if (RNA_enum_get(ptr, "correction_method") == 0) { + if (RNA_enum_get(ptr, "correction_method") == CMP_NODE_COLOR_BALANCE_LGG) { split = uiLayoutSplit(layout, 0.0f, false); col = uiLayoutColumn(split, false); @@ -116,7 +127,7 @@ static void node_composit_buts_colorbalance_ex(uiLayout *layout, { uiItemR(layout, ptr, "correction_method", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE); - if (RNA_enum_get(ptr, "correction_method") == 0) { + if (RNA_enum_get(ptr, "correction_method") == CMP_NODE_COLOR_BALANCE_LGG) { uiTemplateColorPicker(layout, ptr, "lift", true, true, false, true); uiItemR(layout, ptr, "lift", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE); @@ -139,6 +150,58 @@ static void node_composit_buts_colorbalance_ex(uiLayout *layout, } } +using namespace blender::realtime_compositor; + +class ColorBalanceShaderNode : public ShaderNode { + public: + using ShaderNode::ShaderNode; + + void compile(GPUMaterial *material) override + { + GPUNodeStack *inputs = get_inputs_array(); + GPUNodeStack *outputs = get_outputs_array(); + + const NodeColorBalance *node_color_balance = get_node_color_balance(); + + if (get_color_balance_method() == CMP_NODE_COLOR_BALANCE_LGG) { + GPU_stack_link(material, + &bnode(), + "node_composite_color_balance_lgg", + inputs, + outputs, + GPU_uniform(node_color_balance->lift), + GPU_uniform(node_color_balance->gamma), + GPU_uniform(node_color_balance->gain)); + return; + } + + GPU_stack_link(material, + &bnode(), + "node_composite_color_balance_asc_cdl", + inputs, + outputs, + GPU_uniform(node_color_balance->offset), + GPU_uniform(node_color_balance->power), + GPU_uniform(node_color_balance->slope), + GPU_uniform(&node_color_balance->offset_basis)); + } + + CMPNodeColorBalanceMethod get_color_balance_method() + { + return (CMPNodeColorBalanceMethod)bnode().custom1; + } + + NodeColorBalance *get_node_color_balance() + { + return static_cast<NodeColorBalance *>(bnode().storage); + } +}; + +static ShaderNode *get_compositor_shader_node(DNode node) +{ + return new ColorBalanceShaderNode(node); +} + } // namespace blender::nodes::node_composite_colorbalance_cc void register_node_type_cmp_colorbalance() @@ -155,6 +218,7 @@ void register_node_type_cmp_colorbalance() node_type_init(&ntype, file_ns::node_composit_init_colorbalance); node_type_storage( &ntype, "NodeColorBalance", node_free_standard_storage, node_copy_standard_storage); + ntype.get_compositor_shader_node = file_ns::get_compositor_shader_node; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_colorcorrection.cc b/source/blender/nodes/composite/nodes/node_composite_colorcorrection.cc index 39ecd277cec..36e6672ce1c 100644 --- a/source/blender/nodes/composite/nodes/node_composite_colorcorrection.cc +++ b/source/blender/nodes/composite/nodes/node_composite_colorcorrection.cc @@ -5,9 +5,15 @@ * \ingroup cmpnodes */ +#include "IMB_colormanagement.h" + #include "UI_interface.h" #include "UI_resources.h" +#include "GPU_material.h" + +#include "COM_shader_node.hh" + #include "node_composite_util.hh" /* ******************* Color Correction ********************************* */ @@ -16,8 +22,14 @@ namespace blender::nodes::node_composite_colorcorrection_cc { static void cmp_node_colorcorrection_declare(NodeDeclarationBuilder &b) { - b.add_input<decl::Color>(N_("Image")).default_value({1.0f, 1.0f, 1.0f, 1.0f}); - b.add_input<decl::Float>(N_("Mask")).default_value(1.0f).min(0.0f).max(1.0f); + b.add_input<decl::Color>(N_("Image")) + .default_value({1.0f, 1.0f, 1.0f, 1.0f}) + .compositor_domain_priority(0); + b.add_input<decl::Float>(N_("Mask")) + .default_value(1.0f) + .min(0.0f) + .max(1.0f) + .compositor_domain_priority(1); b.add_output<decl::Color>(N_("Image")); } @@ -266,6 +278,73 @@ static void node_composit_buts_colorcorrection_ex(uiLayout *layout, uiItemR(row, ptr, "midtones_end", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE); } +using namespace blender::realtime_compositor; + +class ColorCorrectionShaderNode : public ShaderNode { + public: + using ShaderNode::ShaderNode; + + void compile(GPUMaterial *material) override + { + GPUNodeStack *inputs = get_inputs_array(); + GPUNodeStack *outputs = get_outputs_array(); + + float enabled_channels[3]; + get_enabled_channels(enabled_channels); + float luminance_coefficients[3]; + IMB_colormanagement_get_luminance_coefficients(luminance_coefficients); + + const NodeColorCorrection *node_color_correction = get_node_color_correction(); + + GPU_stack_link(material, + &bnode(), + "node_composite_color_correction", + inputs, + outputs, + GPU_constant(enabled_channels), + GPU_uniform(&node_color_correction->startmidtones), + GPU_uniform(&node_color_correction->endmidtones), + GPU_uniform(&node_color_correction->master.saturation), + GPU_uniform(&node_color_correction->master.contrast), + GPU_uniform(&node_color_correction->master.gamma), + GPU_uniform(&node_color_correction->master.gain), + GPU_uniform(&node_color_correction->master.lift), + GPU_uniform(&node_color_correction->shadows.saturation), + GPU_uniform(&node_color_correction->shadows.contrast), + GPU_uniform(&node_color_correction->shadows.gamma), + GPU_uniform(&node_color_correction->shadows.gain), + GPU_uniform(&node_color_correction->shadows.lift), + GPU_uniform(&node_color_correction->midtones.saturation), + GPU_uniform(&node_color_correction->midtones.contrast), + GPU_uniform(&node_color_correction->midtones.gamma), + GPU_uniform(&node_color_correction->midtones.gain), + GPU_uniform(&node_color_correction->midtones.lift), + GPU_uniform(&node_color_correction->highlights.saturation), + GPU_uniform(&node_color_correction->highlights.contrast), + GPU_uniform(&node_color_correction->highlights.gamma), + GPU_uniform(&node_color_correction->highlights.gain), + GPU_uniform(&node_color_correction->highlights.lift), + GPU_constant(luminance_coefficients)); + } + + void get_enabled_channels(float enabled_channels[3]) + { + for (int i = 0; i < 3; i++) { + enabled_channels[i] = (bnode().custom1 & (1 << i)) ? 1.0f : 0.0f; + } + } + + NodeColorCorrection *get_node_color_correction() + { + return static_cast<NodeColorCorrection *>(bnode().storage); + } +}; + +static ShaderNode *get_compositor_shader_node(DNode node) +{ + return new ColorCorrectionShaderNode(node); +} + } // namespace blender::nodes::node_composite_colorcorrection_cc void register_node_type_cmp_colorcorrection() @@ -282,6 +361,7 @@ void register_node_type_cmp_colorcorrection() node_type_init(&ntype, file_ns::node_composit_init_colorcorrection); node_type_storage( &ntype, "NodeColorCorrection", node_free_standard_storage, node_copy_standard_storage); + ntype.get_compositor_shader_node = file_ns::get_compositor_shader_node; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_curves.cc b/source/blender/nodes/composite/nodes/node_composite_curves.cc index 802664d7934..c5d303c576a 100644 --- a/source/blender/nodes/composite/nodes/node_composite_curves.cc +++ b/source/blender/nodes/composite/nodes/node_composite_curves.cc @@ -5,16 +5,23 @@ * \ingroup cmpnodes */ +#include "BLI_math_base.h" + #include "BKE_colortools.h" #include "UI_interface.h" #include "UI_resources.h" +#include "GPU_material.h" + +#include "COM_node_operation.hh" +#include "COM_shader_node.hh" + #include "node_composite_util.hh" /* **************** CURVE Time ******************** */ -namespace blender::nodes::node_composite_curves_cc { +namespace blender::nodes::node_composite_time_curves_cc { static void cmp_node_time_declare(NodeDeclarationBuilder &b) { @@ -29,11 +36,65 @@ static void node_composit_init_curves_time(bNodeTree *UNUSED(ntree), bNode *node node->storage = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); } -} // namespace blender::nodes::node_composite_curves_cc +using namespace blender::realtime_compositor; + +class TimeCurveOperation : public NodeOperation { + public: + using NodeOperation::NodeOperation; + + void execute() override + { + Result &result = get_result("Fac"); + result.allocate_single_value(); + + CurveMapping *curve_mapping = get_curve_mapping(); + BKE_curvemapping_init(curve_mapping); + const float time = BKE_curvemapping_evaluateF(curve_mapping, 0, compute_normalized_time()); + result.set_float_value(clamp_f(time, 0.0f, 1.0f)); + } + + CurveMapping *get_curve_mapping() + { + return static_cast<CurveMapping *>(bnode().storage); + } + + int get_start_time() + { + return bnode().custom1; + } + + int get_end_time() + { + return bnode().custom2; + } + + float compute_normalized_time() + { + const int frame_number = context().get_frame_number(); + if (frame_number < get_start_time()) { + return 0.0f; + } + if (frame_number > get_end_time()) { + return 1.0f; + } + if (get_start_time() == get_end_time()) { + return 0.0f; + } + return static_cast<float>(frame_number - get_start_time()) / + static_cast<float>(get_end_time() - get_start_time()); + } +}; + +static NodeOperation *get_compositor_operation(Context &context, DNode node) +{ + return new TimeCurveOperation(context, node); +} + +} // namespace blender::nodes::node_composite_time_curves_cc void register_node_type_cmp_curve_time() { - namespace file_ns = blender::nodes::node_composite_curves_cc; + namespace file_ns = blender::nodes::node_composite_time_curves_cc; static bNodeType ntype; @@ -42,17 +103,22 @@ void register_node_type_cmp_curve_time() node_type_size(&ntype, 200, 140, 320); node_type_init(&ntype, file_ns::node_composit_init_curves_time); node_type_storage(&ntype, "CurveMapping", node_free_curves, node_copy_curves); + ntype.get_compositor_operation = file_ns::get_compositor_operation; nodeRegisterType(&ntype); } /* **************** CURVE VEC ******************** */ -namespace blender::nodes::node_composite_curves_cc { +namespace blender::nodes::node_composite_vector_curves_cc { static void cmp_node_curve_vec_declare(NodeDeclarationBuilder &b) { - b.add_input<decl::Vector>(N_("Vector")).default_value({0.0f, 0.0f, 0.0f}).min(-1.0f).max(1.0f); + b.add_input<decl::Vector>(N_("Vector")) + .default_value({0.0f, 0.0f, 0.0f}) + .min(-1.0f) + .max(1.0f) + .compositor_domain_priority(0); b.add_output<decl::Vector>(N_("Vector")); } @@ -66,11 +132,63 @@ static void node_buts_curvevec(uiLayout *layout, bContext *UNUSED(C), PointerRNA uiTemplateCurveMapping(layout, ptr, "mapping", 'v', false, false, false, false); } -} // namespace blender::nodes::node_composite_curves_cc +using namespace blender::realtime_compositor; + +class VectorCurvesShaderNode : public ShaderNode { + public: + using ShaderNode::ShaderNode; + + void compile(GPUMaterial *material) override + { + GPUNodeStack *inputs = get_inputs_array(); + GPUNodeStack *outputs = get_outputs_array(); + + CurveMapping *curve_mapping = get_curve_mapping(); + + BKE_curvemapping_init(curve_mapping); + float *band_values; + int band_size; + BKE_curvemapping_table_RGBA(curve_mapping, &band_values, &band_size); + float band_layer; + GPUNodeLink *band_texture = GPU_color_band(material, band_size, band_values, &band_layer); + + float start_slopes[CM_TOT]; + float end_slopes[CM_TOT]; + BKE_curvemapping_compute_slopes(curve_mapping, start_slopes, end_slopes); + float range_minimums[CM_TOT]; + BKE_curvemapping_get_range_minimums(curve_mapping, range_minimums); + float range_dividers[CM_TOT]; + BKE_curvemapping_compute_range_dividers(curve_mapping, range_dividers); + + GPU_stack_link(material, + &bnode(), + "curves_vector", + inputs, + outputs, + band_texture, + GPU_constant(&band_layer), + GPU_uniform(range_minimums), + GPU_uniform(range_dividers), + GPU_uniform(start_slopes), + GPU_uniform(end_slopes)); + } + + CurveMapping *get_curve_mapping() + { + return static_cast<CurveMapping *>(bnode().storage); + } +}; + +static ShaderNode *get_compositor_shader_node(DNode node) +{ + return new VectorCurvesShaderNode(node); +} + +} // namespace blender::nodes::node_composite_vector_curves_cc void register_node_type_cmp_curve_vec() { - namespace file_ns = blender::nodes::node_composite_curves_cc; + namespace file_ns = blender::nodes::node_composite_vector_curves_cc; static bNodeType ntype; @@ -80,19 +198,26 @@ void register_node_type_cmp_curve_vec() node_type_size(&ntype, 200, 140, 320); node_type_init(&ntype, file_ns::node_composit_init_curve_vec); node_type_storage(&ntype, "CurveMapping", node_free_curves, node_copy_curves); + ntype.get_compositor_shader_node = file_ns::get_compositor_shader_node; nodeRegisterType(&ntype); } /* **************** CURVE RGB ******************** */ -namespace blender::nodes::node_composite_curves_cc { +namespace blender::nodes::node_composite_rgb_curves_cc { static void cmp_node_rgbcurves_declare(NodeDeclarationBuilder &b) { - b.add_input<decl::Float>(N_("Fac")).default_value(1.0f).min(-1.0f).max(1.0f).subtype( - PROP_FACTOR); - b.add_input<decl::Color>(N_("Image")).default_value({1.0f, 1.0f, 1.0f, 1.0f}); + b.add_input<decl::Float>(N_("Fac")) + .default_value(1.0f) + .min(-1.0f) + .max(1.0f) + .subtype(PROP_FACTOR) + .compositor_domain_priority(1); + b.add_input<decl::Color>(N_("Image")) + .default_value({1.0f, 1.0f, 1.0f, 1.0f}) + .compositor_domain_priority(0); b.add_input<decl::Color>(N_("Black Level")).default_value({0.0f, 0.0f, 0.0f, 1.0f}); b.add_input<decl::Color>(N_("White Level")).default_value({1.0f, 1.0f, 1.0f, 1.0f}); b.add_output<decl::Color>(N_("Image")); @@ -103,11 +228,105 @@ static void node_composit_init_curve_rgb(bNodeTree *UNUSED(ntree), bNode *node) node->storage = BKE_curvemapping_add(4, 0.0f, 0.0f, 1.0f, 1.0f); } -} // namespace blender::nodes::node_composite_curves_cc +using namespace blender::realtime_compositor; + +class RGBCurvesShaderNode : public ShaderNode { + public: + using ShaderNode::ShaderNode; + + void compile(GPUMaterial *material) override + { + GPUNodeStack *inputs = get_inputs_array(); + GPUNodeStack *outputs = get_outputs_array(); + + CurveMapping *curve_mapping = get_curve_mapping(); + + BKE_curvemapping_init(curve_mapping); + float *band_values; + int band_size; + BKE_curvemapping_table_RGBA(curve_mapping, &band_values, &band_size); + float band_layer; + GPUNodeLink *band_texture = GPU_color_band(material, band_size, band_values, &band_layer); + + float start_slopes[CM_TOT]; + float end_slopes[CM_TOT]; + BKE_curvemapping_compute_slopes(curve_mapping, start_slopes, end_slopes); + float range_minimums[CM_TOT]; + BKE_curvemapping_get_range_minimums(curve_mapping, range_minimums); + float range_dividers[CM_TOT]; + BKE_curvemapping_compute_range_dividers(curve_mapping, range_dividers); + + if (curve_mapping->tone == CURVE_TONE_FILMLIKE) { + GPU_stack_link(material, + &bnode(), + "curves_film_like", + inputs, + outputs, + band_texture, + GPU_constant(&band_layer), + GPU_uniform(&range_minimums[3]), + GPU_uniform(&range_dividers[3]), + GPU_uniform(&start_slopes[3]), + GPU_uniform(&end_slopes[3])); + return; + } + + const float min = 0.0f; + const float max = 1.0f; + GPU_link(material, + "clamp_value", + get_input_link("Fac"), + GPU_constant(&min), + GPU_constant(&max), + &get_input("Fac").link); + + /* If the RGB curves do nothing, use a function that skips RGB computations. */ + if (BKE_curvemapping_is_map_identity(curve_mapping, 0) && + BKE_curvemapping_is_map_identity(curve_mapping, 1) && + BKE_curvemapping_is_map_identity(curve_mapping, 2)) { + GPU_stack_link(material, + &bnode(), + "curves_combined_only", + inputs, + outputs, + band_texture, + GPU_constant(&band_layer), + GPU_uniform(&range_minimums[3]), + GPU_uniform(&range_dividers[3]), + GPU_uniform(&start_slopes[3]), + GPU_uniform(&end_slopes[3])); + return; + } + + GPU_stack_link(material, + &bnode(), + "curves_combined_rgb", + inputs, + outputs, + band_texture, + GPU_constant(&band_layer), + GPU_uniform(range_minimums), + GPU_uniform(range_dividers), + GPU_uniform(start_slopes), + GPU_uniform(end_slopes)); + } + + CurveMapping *get_curve_mapping() + { + return static_cast<CurveMapping *>(bnode().storage); + } +}; + +static ShaderNode *get_compositor_shader_node(DNode node) +{ + return new RGBCurvesShaderNode(node); +} + +} // namespace blender::nodes::node_composite_rgb_curves_cc void register_node_type_cmp_curve_rgb() { - namespace file_ns = blender::nodes::node_composite_curves_cc; + namespace file_ns = blender::nodes::node_composite_rgb_curves_cc; static bNodeType ntype; @@ -116,6 +335,7 @@ void register_node_type_cmp_curve_rgb() node_type_size(&ntype, 200, 140, 320); node_type_init(&ntype, file_ns::node_composit_init_curve_rgb); node_type_storage(&ntype, "CurveMapping", node_free_curves, node_copy_curves); + ntype.get_compositor_shader_node = file_ns::get_compositor_shader_node; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_exposure.cc b/source/blender/nodes/composite/nodes/node_composite_exposure.cc index 881cfc11058..19b93680ff6 100644 --- a/source/blender/nodes/composite/nodes/node_composite_exposure.cc +++ b/source/blender/nodes/composite/nodes/node_composite_exposure.cc @@ -5,6 +5,10 @@ * \ingroup cmpnodes */ +#include "GPU_material.h" + +#include "COM_shader_node.hh" + #include "node_composite_util.hh" /* **************** Exposure ******************** */ @@ -13,11 +17,33 @@ namespace blender::nodes::node_composite_exposure_cc { static void cmp_node_exposure_declare(NodeDeclarationBuilder &b) { - b.add_input<decl::Color>(N_("Image")).default_value({1.0f, 1.0f, 1.0f, 1.0f}); - b.add_input<decl::Float>(N_("Exposure")).min(-10.0f).max(10.0f); + b.add_input<decl::Color>(N_("Image")) + .default_value({1.0f, 1.0f, 1.0f, 1.0f}) + .compositor_domain_priority(0); + b.add_input<decl::Float>(N_("Exposure")).min(-10.0f).max(10.0f).compositor_domain_priority(1); b.add_output<decl::Color>(N_("Image")); } +using namespace blender::realtime_compositor; + +class ExposureShaderNode : public ShaderNode { + public: + using ShaderNode::ShaderNode; + + void compile(GPUMaterial *material) override + { + GPUNodeStack *inputs = get_inputs_array(); + GPUNodeStack *outputs = get_outputs_array(); + + GPU_stack_link(material, &bnode(), "node_composite_exposure", inputs, outputs); + } +}; + +static ShaderNode *get_compositor_shader_node(DNode node) +{ + return new ExposureShaderNode(node); +} + } // namespace blender::nodes::node_composite_exposure_cc void register_node_type_cmp_exposure() @@ -28,6 +54,7 @@ void register_node_type_cmp_exposure() cmp_node_type_base(&ntype, CMP_NODE_EXPOSURE, "Exposure", NODE_CLASS_OP_COLOR); ntype.declare = file_ns::cmp_node_exposure_declare; + ntype.get_compositor_shader_node = file_ns::get_compositor_shader_node; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_gamma.cc b/source/blender/nodes/composite/nodes/node_composite_gamma.cc index b4b8502e915..660d8068231 100644 --- a/source/blender/nodes/composite/nodes/node_composite_gamma.cc +++ b/source/blender/nodes/composite/nodes/node_composite_gamma.cc @@ -5,6 +5,10 @@ * \ingroup cmpnodes */ +#include "GPU_material.h" + +#include "COM_shader_node.hh" + #include "node_composite_util.hh" /* **************** Gamma Tools ******************** */ @@ -13,15 +17,38 @@ namespace blender::nodes::node_composite_gamma_cc { static void cmp_node_gamma_declare(NodeDeclarationBuilder &b) { - b.add_input<decl::Color>(N_("Image")).default_value({1.0f, 1.0f, 1.0f, 1.0f}); + b.add_input<decl::Color>(N_("Image")) + .default_value({1.0f, 1.0f, 1.0f, 1.0f}) + .compositor_domain_priority(0); b.add_input<decl::Float>(N_("Gamma")) .default_value(1.0f) .min(0.001f) .max(10.0f) - .subtype(PROP_UNSIGNED); + .subtype(PROP_UNSIGNED) + .compositor_domain_priority(1); b.add_output<decl::Color>(N_("Image")); } +using namespace blender::realtime_compositor; + +class GammaShaderNode : public ShaderNode { + public: + using ShaderNode::ShaderNode; + + void compile(GPUMaterial *material) override + { + GPUNodeStack *inputs = get_inputs_array(); + GPUNodeStack *outputs = get_outputs_array(); + + GPU_stack_link(material, &bnode(), "node_composite_gamma", inputs, outputs); + } +}; + +static ShaderNode *get_compositor_shader_node(DNode node) +{ + return new GammaShaderNode(node); +} + } // namespace blender::nodes::node_composite_gamma_cc void register_node_type_cmp_gamma() @@ -32,6 +59,7 @@ void register_node_type_cmp_gamma() cmp_node_type_base(&ntype, CMP_NODE_GAMMA, "Gamma", NODE_CLASS_OP_COLOR); ntype.declare = file_ns::cmp_node_gamma_declare; + ntype.get_compositor_shader_node = file_ns::get_compositor_shader_node; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_hue_sat_val.cc b/source/blender/nodes/composite/nodes/node_composite_hue_sat_val.cc index 08a048829df..091864a06f7 100644 --- a/source/blender/nodes/composite/nodes/node_composite_hue_sat_val.cc +++ b/source/blender/nodes/composite/nodes/node_composite_hue_sat_val.cc @@ -5,6 +5,10 @@ * \ingroup cmpnodes */ +#include "GPU_material.h" + +#include "COM_shader_node.hh" + #include "node_composite_util.hh" /* **************** Hue Saturation ******************** */ @@ -13,22 +17,56 @@ namespace blender::nodes::node_composite_hue_sat_val_cc { static void cmp_node_huesatval_declare(NodeDeclarationBuilder &b) { - b.add_input<decl::Color>(N_("Image")).default_value({1.0f, 1.0f, 1.0f, 1.0f}); - b.add_input<decl::Float>(N_("Hue")).default_value(0.5f).min(0.0f).max(1.0f).subtype(PROP_FACTOR); + b.add_input<decl::Color>(N_("Image")) + .default_value({1.0f, 1.0f, 1.0f, 1.0f}) + .compositor_domain_priority(0); + b.add_input<decl::Float>(N_("Hue")) + .default_value(0.5f) + .min(0.0f) + .max(1.0f) + .subtype(PROP_FACTOR) + .compositor_domain_priority(1); b.add_input<decl::Float>(N_("Saturation")) .default_value(1.0f) .min(0.0f) .max(2.0f) - .subtype(PROP_FACTOR); + .subtype(PROP_FACTOR) + .compositor_domain_priority(2); b.add_input<decl::Float>(N_("Value")) .default_value(1.0f) .min(0.0f) .max(2.0f) - .subtype(PROP_FACTOR); - b.add_input<decl::Float>(N_("Fac")).default_value(1.0f).min(0.0f).max(1.0f).subtype(PROP_FACTOR); + .subtype(PROP_FACTOR) + .compositor_domain_priority(3); + b.add_input<decl::Float>(N_("Fac")) + .default_value(1.0f) + .min(0.0f) + .max(1.0f) + .subtype(PROP_FACTOR) + .compositor_domain_priority(4); b.add_output<decl::Color>(N_("Image")); } +using namespace blender::realtime_compositor; + +class HueSaturationValueShaderNode : public ShaderNode { + public: + using ShaderNode::ShaderNode; + + void compile(GPUMaterial *material) override + { + GPUNodeStack *inputs = get_inputs_array(); + GPUNodeStack *outputs = get_outputs_array(); + + GPU_stack_link(material, &bnode(), "node_composite_hue_saturation_value", inputs, outputs); + } +}; + +static ShaderNode *get_compositor_shader_node(DNode node) +{ + return new HueSaturationValueShaderNode(node); +} + } // namespace blender::nodes::node_composite_hue_sat_val_cc void register_node_type_cmp_hue_sat() @@ -39,6 +77,7 @@ void register_node_type_cmp_hue_sat() cmp_node_type_base(&ntype, CMP_NODE_HUE_SAT, "Hue Saturation Value", NODE_CLASS_OP_COLOR); ntype.declare = file_ns::cmp_node_huesatval_declare; + ntype.get_compositor_shader_node = file_ns::get_compositor_shader_node; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_huecorrect.cc b/source/blender/nodes/composite/nodes/node_composite_huecorrect.cc index d252d96f8c3..a84420231aa 100644 --- a/source/blender/nodes/composite/nodes/node_composite_huecorrect.cc +++ b/source/blender/nodes/composite/nodes/node_composite_huecorrect.cc @@ -5,6 +5,12 @@ * \ingroup cmpnodes */ +#include "BKE_colortools.h" + +#include "GPU_material.h" + +#include "COM_shader_node.hh" + #include "node_composite_util.hh" #include "BKE_colortools.h" @@ -13,8 +19,15 @@ namespace blender::nodes::node_composite_huecorrect_cc { static void cmp_node_huecorrect_declare(NodeDeclarationBuilder &b) { - b.add_input<decl::Float>(N_("Fac")).default_value(1.0f).min(0.0f).max(1.0f).subtype(PROP_FACTOR); - b.add_input<decl::Color>(N_("Image")).default_value({1.0f, 1.0f, 1.0f, 1.0f}); + b.add_input<decl::Float>(N_("Fac")) + .default_value(1.0f) + .min(0.0f) + .max(1.0f) + .subtype(PROP_FACTOR) + .compositor_domain_priority(1); + b.add_input<decl::Color>(N_("Image")) + .default_value({1.0f, 1.0f, 1.0f, 1.0f}) + .compositor_domain_priority(0); b.add_output<decl::Color>(N_("Image")); } @@ -35,6 +48,53 @@ static void node_composit_init_huecorrect(bNodeTree *UNUSED(ntree), bNode *node) cumapping->cur = 1; } +using namespace blender::realtime_compositor; + +class HueCorrectShaderNode : public ShaderNode { + public: + using ShaderNode::ShaderNode; + + void compile(GPUMaterial *material) override + { + GPUNodeStack *inputs = get_inputs_array(); + GPUNodeStack *outputs = get_outputs_array(); + + CurveMapping *curve_mapping = get_curve_mapping(); + + BKE_curvemapping_init(curve_mapping); + float *band_values; + int band_size; + BKE_curvemapping_table_RGBA(curve_mapping, &band_values, &band_size); + float band_layer; + GPUNodeLink *band_texture = GPU_color_band(material, band_size, band_values, &band_layer); + + float range_minimums[CM_TOT]; + BKE_curvemapping_get_range_minimums(curve_mapping, range_minimums); + float range_dividers[CM_TOT]; + BKE_curvemapping_compute_range_dividers(curve_mapping, range_dividers); + + GPU_stack_link(material, + &bnode(), + "node_composite_hue_correct", + inputs, + outputs, + band_texture, + GPU_constant(&band_layer), + GPU_uniform(range_minimums), + GPU_uniform(range_dividers)); + } + + CurveMapping *get_curve_mapping() + { + return static_cast<CurveMapping *>(bnode().storage); + } +}; + +static ShaderNode *get_compositor_shader_node(DNode node) +{ + return new HueCorrectShaderNode(node); +} + } // namespace blender::nodes::node_composite_huecorrect_cc void register_node_type_cmp_huecorrect() @@ -48,6 +108,7 @@ void register_node_type_cmp_huecorrect() node_type_size(&ntype, 320, 140, 500); node_type_init(&ntype, file_ns::node_composit_init_huecorrect); node_type_storage(&ntype, "CurveMapping", node_free_curves, node_copy_curves); + ntype.get_compositor_shader_node = file_ns::get_compositor_shader_node; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_invert.cc b/source/blender/nodes/composite/nodes/node_composite_invert.cc index 6dff043537a..4bfcc7b6b9c 100644 --- a/source/blender/nodes/composite/nodes/node_composite_invert.cc +++ b/source/blender/nodes/composite/nodes/node_composite_invert.cc @@ -8,6 +8,10 @@ #include "UI_interface.h" #include "UI_resources.h" +#include "GPU_material.h" + +#include "COM_shader_node.hh" + #include "node_composite_util.hh" /* **************** INVERT ******************** */ @@ -16,8 +20,15 @@ namespace blender::nodes::node_composite_invert_cc { static void cmp_node_invert_declare(NodeDeclarationBuilder &b) { - b.add_input<decl::Float>(N_("Fac")).default_value(1.0f).min(0.0f).max(1.0f).subtype(PROP_FACTOR); - b.add_input<decl::Color>(N_("Color")).default_value({1.0f, 1.0f, 1.0f, 1.0f}); + b.add_input<decl::Float>(N_("Fac")) + .default_value(1.0f) + .min(0.0f) + .max(1.0f) + .subtype(PROP_FACTOR) + .compositor_domain_priority(1); + b.add_input<decl::Color>(N_("Color")) + .default_value({1.0f, 1.0f, 1.0f, 1.0f}) + .compositor_domain_priority(0); b.add_output<decl::Color>(N_("Color")); } @@ -35,6 +46,45 @@ static void node_composit_buts_invert(uiLayout *layout, bContext *UNUSED(C), Poi uiItemR(col, ptr, "invert_alpha", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE); } +using namespace blender::realtime_compositor; + +class InvertShaderNode : public ShaderNode { + public: + using ShaderNode::ShaderNode; + + void compile(GPUMaterial *material) override + { + GPUNodeStack *inputs = get_inputs_array(); + GPUNodeStack *outputs = get_outputs_array(); + + const float do_rgb = get_do_rgb(); + const float do_alpha = get_do_alpha(); + + GPU_stack_link(material, + &bnode(), + "node_composite_invert", + inputs, + outputs, + GPU_constant(&do_rgb), + GPU_constant(&do_alpha)); + } + + bool get_do_rgb() + { + return bnode().custom1 & CMP_CHAN_RGB; + } + + bool get_do_alpha() + { + return bnode().custom1 & CMP_CHAN_A; + } +}; + +static ShaderNode *get_compositor_shader_node(DNode node) +{ + return new InvertShaderNode(node); +} + } // namespace blender::nodes::node_composite_invert_cc void register_node_type_cmp_invert() @@ -47,6 +97,7 @@ void register_node_type_cmp_invert() ntype.declare = file_ns::cmp_node_invert_declare; ntype.draw_buttons = file_ns::node_composit_buts_invert; node_type_init(&ntype, file_ns::node_composit_init_invert); + ntype.get_compositor_shader_node = file_ns::get_compositor_shader_node; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_mixrgb.cc b/source/blender/nodes/composite/nodes/node_composite_mixrgb.cc index fc11aa188b0..a1fbbfe7d40 100644 --- a/source/blender/nodes/composite/nodes/node_composite_mixrgb.cc +++ b/source/blender/nodes/composite/nodes/node_composite_mixrgb.cc @@ -5,6 +5,14 @@ * \ingroup cmpnodes */ +#include "BLI_assert.h" + +#include "DNA_material_types.h" + +#include "GPU_material.h" + +#include "COM_shader_node.hh" + #include "node_composite_util.hh" /* **************** MIX RGB ******************** */ @@ -13,12 +21,122 @@ namespace blender::nodes::node_composite_mixrgb_cc { static void cmp_node_mixrgb_declare(NodeDeclarationBuilder &b) { - b.add_input<decl::Float>(N_("Fac")).default_value(1.0f).min(0.0f).max(1.0f).subtype(PROP_FACTOR); - b.add_input<decl::Color>(N_("Image")).default_value({1.0f, 1.0f, 1.0f, 1.0f}); - b.add_input<decl::Color>(N_("Image"), "Image_001").default_value({1.0f, 1.0f, 1.0f, 1.0f}); + b.add_input<decl::Float>(N_("Fac")) + .default_value(1.0f) + .min(0.0f) + .max(1.0f) + .subtype(PROP_FACTOR) + .compositor_domain_priority(2); + b.add_input<decl::Color>(N_("Image")) + .default_value({1.0f, 1.0f, 1.0f, 1.0f}) + .compositor_domain_priority(0); + b.add_input<decl::Color>(N_("Image"), "Image_001") + .default_value({1.0f, 1.0f, 1.0f, 1.0f}) + .compositor_domain_priority(1); b.add_output<decl::Color>(N_("Image")); } +using namespace blender::realtime_compositor; + +class MixRGBShaderNode : public ShaderNode { + public: + using ShaderNode::ShaderNode; + + void compile(GPUMaterial *material) override + { + GPUNodeStack *inputs = get_inputs_array(); + GPUNodeStack *outputs = get_outputs_array(); + + if (get_use_alpha()) { + GPU_link(material, + "multiply_by_alpha", + get_input_link("Fac"), + get_input_link("Image_001"), + &get_input("Fac").link); + } + + GPU_stack_link(material, &bnode(), get_shader_function_name(), inputs, outputs); + + if (!get_should_clamp()) { + return; + } + + const float min[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + const float max[4] = {1.0f, 1.0f, 1.0f, 1.0f}; + GPU_link(material, + "clamp_color", + get_output("Image").link, + GPU_constant(min), + GPU_constant(max), + &get_output("Image").link); + } + + int get_mode() + { + return bnode().custom1; + } + + const char *get_shader_function_name() + { + switch (get_mode()) { + case MA_RAMP_BLEND: + return "mix_blend"; + case MA_RAMP_ADD: + return "mix_add"; + case MA_RAMP_MULT: + return "mix_mult"; + case MA_RAMP_SUB: + return "mix_sub"; + case MA_RAMP_SCREEN: + return "mix_screen"; + case MA_RAMP_DIV: + return "mix_div"; + case MA_RAMP_DIFF: + return "mix_diff"; + case MA_RAMP_DARK: + return "mix_dark"; + case MA_RAMP_LIGHT: + return "mix_light"; + case MA_RAMP_OVERLAY: + return "mix_overlay"; + case MA_RAMP_DODGE: + return "mix_dodge"; + case MA_RAMP_BURN: + return "mix_burn"; + case MA_RAMP_HUE: + return "mix_hue"; + case MA_RAMP_SAT: + return "mix_sat"; + case MA_RAMP_VAL: + return "mix_val"; + case MA_RAMP_COLOR: + return "mix_color"; + case MA_RAMP_SOFT: + return "mix_soft"; + case MA_RAMP_LINEAR: + return "mix_linear"; + } + + BLI_assert_unreachable(); + return nullptr; + } + + bool get_use_alpha() + { + return bnode().custom2 & SHD_MIXRGB_USE_ALPHA; + } + + bool get_should_clamp() + { + return bnode().custom2 & SHD_MIXRGB_CLAMP; + } +}; + +static ShaderNode *get_compositor_shader_node(DNode node) +{ + return new MixRGBShaderNode(node); +} + } // namespace blender::nodes::node_composite_mixrgb_cc void register_node_type_cmp_mix_rgb() @@ -31,6 +149,7 @@ void register_node_type_cmp_mix_rgb() ntype.flag |= NODE_PREVIEW; ntype.declare = file_ns::cmp_node_mixrgb_declare; ntype.labelfunc = node_blend_label; + ntype.get_compositor_shader_node = file_ns::get_compositor_shader_node; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_posterize.cc b/source/blender/nodes/composite/nodes/node_composite_posterize.cc index c97035d55ea..1268219e7e2 100644 --- a/source/blender/nodes/composite/nodes/node_composite_posterize.cc +++ b/source/blender/nodes/composite/nodes/node_composite_posterize.cc @@ -5,6 +5,10 @@ * \ingroup cmpnodes */ +#include "GPU_material.h" + +#include "COM_shader_node.hh" + #include "node_composite_util.hh" /* **************** Posterize ******************** */ @@ -13,11 +17,37 @@ namespace blender::nodes::node_composite_posterize_cc { static void cmp_node_posterize_declare(NodeDeclarationBuilder &b) { - b.add_input<decl::Color>(N_("Image")).default_value({1.0f, 1.0f, 1.0f, 1.0f}); - b.add_input<decl::Float>(N_("Steps")).default_value(8.0f).min(2.0f).max(1024.0f); + b.add_input<decl::Color>(N_("Image")) + .default_value({1.0f, 1.0f, 1.0f, 1.0f}) + .compositor_domain_priority(0); + b.add_input<decl::Float>(N_("Steps")) + .default_value(8.0f) + .min(2.0f) + .max(1024.0f) + .compositor_domain_priority(1); b.add_output<decl::Color>(N_("Image")); } +using namespace blender::realtime_compositor; + +class PosterizeShaderNode : public ShaderNode { + public: + using ShaderNode::ShaderNode; + + void compile(GPUMaterial *material) override + { + GPUNodeStack *inputs = get_inputs_array(); + GPUNodeStack *outputs = get_outputs_array(); + + GPU_stack_link(material, &bnode(), "node_composite_posterize", inputs, outputs); + } +}; + +static ShaderNode *get_compositor_shader_node(DNode node) +{ + return new PosterizeShaderNode(node); +} + } // namespace blender::nodes::node_composite_posterize_cc void register_node_type_cmp_posterize() @@ -28,6 +58,7 @@ void register_node_type_cmp_posterize() cmp_node_type_base(&ntype, CMP_NODE_POSTERIZE, "Posterize", NODE_CLASS_OP_COLOR); ntype.declare = file_ns::cmp_node_posterize_declare; + ntype.get_compositor_shader_node = file_ns::get_compositor_shader_node; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_mix_rgb.cc b/source/blender/nodes/shader/nodes/node_shader_mix_rgb.cc index 12707623049..478a6812c36 100644 --- a/source/blender/nodes/shader/nodes/node_shader_mix_rgb.cc +++ b/source/blender/nodes/shader/nodes/node_shader_mix_rgb.cc @@ -32,7 +32,7 @@ static const char *gpu_shader_get_name(int mode) case MA_RAMP_SCREEN: return "mix_screen"; case MA_RAMP_DIV: - return "mix_div"; + return "mix_div_fallback"; case MA_RAMP_DIFF: return "mix_diff"; case MA_RAMP_DARK: @@ -70,18 +70,23 @@ static int gpu_shader_mix_rgb(GPUMaterial *mat, { 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_MIXRGB_CLAMP) { - const float min[3] = {0.0f, 0.0f, 0.0f}; - const float max[3] = {1.0f, 1.0f, 1.0f}; - GPU_link( - mat, "clamp_color", out[0].link, GPU_constant(min), GPU_constant(max), &out[0].link); - } - return ret; + if (name == nullptr) { + return 0; } - return 0; + const float min = 0.0f; + const float max = 1.0f; + const GPUNodeLink *factor_link = in[0].link ? in[0].link : GPU_uniform(in[0].vec); + GPU_link(mat, "clamp_value", factor_link, GPU_constant(&min), GPU_constant(&max), &in[0].link); + + int ret = GPU_stack_link(mat, node, name, in, out); + + if (ret && node->custom2 & SHD_MIXRGB_CLAMP) { + const float min[3] = {0.0f, 0.0f, 0.0f}; + const float max[3] = {1.0f, 1.0f, 1.0f}; + GPU_link(mat, "clamp_color", out[0].link, GPU_constant(min), GPU_constant(max), &out[0].link); + } + return ret; } class MixRGBFunction : public fn::MultiFunction { |