diff --git a/source/blender/compositor/realtime_compositor/CMakeLists.txt b/source/blender/compositor/realtime_compositor/CMakeLists.txt index df9440ef414..ab584423dd1 100644 --- a/source/blender/compositor/realtime_compositor/CMakeLists.txt +++ b/source/blender/compositor/realtime_compositor/CMakeLists.txt @@ -118,6 +118,7 @@ set(GLSL_SRC shaders/compositor_glare_simple_star_vertical_pass.glsl shaders/compositor_glare_streaks_accumulate.glsl shaders/compositor_glare_streaks_filter.glsl + shaders/compositor_id_mask.glsl shaders/compositor_image_crop.glsl shaders/compositor_map_uv.glsl shaders/compositor_morphological_distance.glsl @@ -215,6 +216,7 @@ set(SRC_SHADER_CREATE_INFOS shaders/infos/compositor_filter_info.hh shaders/infos/compositor_flip_info.hh shaders/infos/compositor_glare_info.hh + shaders/infos/compositor_id_mask_info.hh shaders/infos/compositor_image_crop_info.hh shaders/infos/compositor_map_uv_info.hh shaders/infos/compositor_morphological_distance_feather_info.hh diff --git a/source/blender/compositor/realtime_compositor/shaders/compositor_id_mask.glsl b/source/blender/compositor/realtime_compositor/shaders/compositor_id_mask.glsl new file mode 100644 index 00000000000..d7411586b5e --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/compositor_id_mask.glsl @@ -0,0 +1,11 @@ +#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) + +void main() +{ + ivec2 texel = ivec2(gl_GlobalInvocationID.xy); + + float input_mask_value = texture_load(input_mask_tx, texel).x; + float mask = int(round(input_mask_value)) == index ? 1.0 : 0.0; + + imageStore(output_mask_img, texel, vec4(mask)); +} diff --git a/source/blender/compositor/realtime_compositor/shaders/infos/compositor_id_mask_info.hh b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_id_mask_info.hh new file mode 100644 index 00000000000..ce4fb8f6325 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_id_mask_info.hh @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "gpu_shader_create_info.hh" + +GPU_SHADER_CREATE_INFO(compositor_id_mask) + .local_group_size(16, 16) + .push_constant(Type::INT, "index") + .sampler(0, ImageType::FLOAT_2D, "input_mask_tx") + .image(0, GPU_R16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_mask_img") + .compute_source("compositor_id_mask.glsl") + .do_static_compilation(true); diff --git a/source/blender/nodes/composite/nodes/node_composite_id_mask.cc b/source/blender/nodes/composite/nodes/node_composite_id_mask.cc index 1a0a200062d..3e536f056f4 100644 --- a/source/blender/nodes/composite/nodes/node_composite_id_mask.cc +++ b/source/blender/nodes/composite/nodes/node_composite_id_mask.cc @@ -5,11 +5,16 @@ * \ingroup cmpnodes */ +#include + #include "BLT_translation.h" #include "UI_interface.h" #include "UI_resources.h" +#include "GPU_shader.h" + +#include "COM_algorithm_smaa.hh" #include "COM_node_operation.hh" #include "node_composite_util.hh" @@ -20,7 +25,11 @@ namespace blender::nodes::node_composite_id_mask_cc { static void cmp_node_idmask_declare(NodeDeclarationBuilder &b) { - b.add_input(N_("ID value")).default_value(1.0f).min(0.0f).max(1.0f); + b.add_input(N_("ID value")) + .default_value(1.0f) + .min(0.0f) + .max(1.0f) + .compositor_domain_priority(0); b.add_output(N_("Alpha")); } @@ -38,8 +47,56 @@ class IDMaskOperation : public NodeOperation { void execute() override { - get_input("ID value").pass_through(get_result("Alpha")); - context().set_info_message("Viewport compositor setup not fully supported"); + const Result &input_mask = get_input("ID value"); + if (input_mask.is_single_value()) { + execute_single_value(); + return; + } + + GPUShader *shader = shader_manager().get("compositor_id_mask"); + GPU_shader_bind(shader); + + GPU_shader_uniform_1i(shader, "index", get_index()); + + input_mask.bind_as_texture(shader, "input_mask_tx"); + + /* If anti-aliasing is disabled, write to the output directly, otherwise, write to a temporary + * result to later perform anti-aliasing. */ + Result non_anti_aliased_mask = Result::Temporary(ResultType::Float, texture_pool()); + Result &output_mask = use_anti_aliasing() ? non_anti_aliased_mask : get_result("Alpha"); + + const Domain domain = compute_domain(); + output_mask.allocate_texture(domain); + output_mask.bind_as_image(shader, "output_mask_img"); + + compute_dispatch_threads_at_least(shader, domain.size); + + input_mask.unbind_as_texture(); + output_mask.unbind_as_image(); + GPU_shader_unbind(); + + if (use_anti_aliasing()) { + smaa(context(), non_anti_aliased_mask, get_result("Alpha")); + non_anti_aliased_mask.release(); + } + } + + void execute_single_value() + { + const float input_mask_value = get_input("ID value").get_float_value(); + const float mask = int(round(input_mask_value)) == get_index() ? 1.0f : 0.0f; + get_result("Alpha").allocate_single_value(); + get_result("Alpha").set_float_value(mask); + } + + int get_index() + { + return bnode().custom1; + } + + bool use_anti_aliasing() + { + return bnode().custom2 != 0; } }; @@ -60,8 +117,6 @@ void register_node_type_cmp_idmask() ntype.declare = file_ns::cmp_node_idmask_declare; ntype.draw_buttons = file_ns::node_composit_buts_id_mask; ntype.get_compositor_operation = file_ns::get_compositor_operation; - ntype.realtime_compositor_unsupported_message = N_( - "Node not supported in the Viewport compositor"); nodeRegisterType(&ntype); }