diff --git a/source/blender/compositor/realtime_compositor/CMakeLists.txt b/source/blender/compositor/realtime_compositor/CMakeLists.txt index df90fddbb79..68939457e35 100644 --- a/source/blender/compositor/realtime_compositor/CMakeLists.txt +++ b/source/blender/compositor/realtime_compositor/CMakeLists.txt @@ -198,6 +198,7 @@ set(GLSL_SRC shaders/compositor_projector_lens_distortion.glsl shaders/compositor_read_input.glsl shaders/compositor_realize_on_domain.glsl + shaders/compositor_scale_variable.glsl shaders/compositor_screen_lens_distortion.glsl shaders/compositor_smaa_blending_weight_calculation.glsl shaders/compositor_smaa_edge_detection.glsl @@ -321,6 +322,7 @@ set(SRC_SHADER_CREATE_INFOS shaders/infos/compositor_projector_lens_distortion_info.hh shaders/infos/compositor_read_input_info.hh shaders/infos/compositor_realize_on_domain_info.hh + shaders/infos/compositor_scale_variable_info.hh shaders/infos/compositor_screen_lens_distortion_info.hh shaders/infos/compositor_smaa_info.hh shaders/infos/compositor_split_info.hh diff --git a/source/blender/compositor/realtime_compositor/shaders/compositor_scale_variable.glsl b/source/blender/compositor/realtime_compositor/shaders/compositor_scale_variable.glsl new file mode 100644 index 00000000000..63f6aaa4f06 --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/compositor_scale_variable.glsl @@ -0,0 +1,19 @@ +/* SPDX-FileCopyrightText: 2024 Blender Authors + * + * SPDX-License-Identifier: GPL-2.0-or-later */ + +#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) + +void main() +{ + ivec2 texel = ivec2(gl_GlobalInvocationID.xy); + ivec2 input_size = texture_size(input_tx); + + vec2 coordinates = (vec2(texel) + vec2(0.5)) / vec2(input_size); + vec2 center = vec2(0.5); + + vec2 scale = vec2(texture_load(x_scale_tx, texel).x, texture_load(y_scale_tx, texel).x); + vec2 scaled_coordinates = center + (coordinates - center) / max(scale, 0.0001); + + imageStore(output_img, texel, texture(input_tx, scaled_coordinates)); +} diff --git a/source/blender/compositor/realtime_compositor/shaders/infos/compositor_scale_variable_info.hh b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_scale_variable_info.hh new file mode 100644 index 00000000000..327ded2efab --- /dev/null +++ b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_scale_variable_info.hh @@ -0,0 +1,14 @@ +/* SPDX-FileCopyrightText: 2024 Blender Authors + * + * SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "gpu_shader_create_info.hh" + +GPU_SHADER_CREATE_INFO(compositor_scale_variable) + .local_group_size(16, 16) + .sampler(0, ImageType::FLOAT_2D, "input_tx") + .sampler(1, ImageType::FLOAT_2D, "x_scale_tx") + .sampler(2, ImageType::FLOAT_2D, "y_scale_tx") + .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .compute_source("compositor_scale_variable.glsl") + .do_static_compilation(true); diff --git a/source/blender/nodes/composite/nodes/node_composite_scale.cc b/source/blender/nodes/composite/nodes/node_composite_scale.cc index 57e5e5abc25..fda2d815b37 100644 --- a/source/blender/nodes/composite/nodes/node_composite_scale.cc +++ b/source/blender/nodes/composite/nodes/node_composite_scale.cc @@ -19,8 +19,12 @@ #include "UI_interface.hh" #include "UI_resources.hh" +#include "GPU_shader.hh" +#include "GPU_texture.hh" + #include "COM_algorithm_transform.hh" #include "COM_node_operation.hh" +#include "COM_utilities.hh" #include "node_composite_util.hh" @@ -37,12 +41,12 @@ static void cmp_node_scale_declare(NodeDeclarationBuilder &b) .default_value(1.0f) .min(0.0001f) .max(CMP_SCALE_MAX) - .compositor_expects_single_value(); + .compositor_domain_priority(1); b.add_input("Y") .default_value(1.0f) .min(0.0001f) .max(CMP_SCALE_MAX) - .compositor_expects_single_value(); + .compositor_domain_priority(2); b.add_output("Image"); } @@ -83,6 +87,16 @@ class ScaleOperation : public NodeOperation { using NodeOperation::NodeOperation; void execute() override + { + if (is_variable_size()) { + execute_variable_size(); + } + else { + execute_constant_size(); + } + } + + void execute_constant_size() { Result &input = get_input("Image"); Result &output = get_result("Image"); @@ -96,6 +110,36 @@ class ScaleOperation : public NodeOperation { transform(context(), input, output, transformation, input.get_realization_options()); } + void execute_variable_size() + { + GPUShader *shader = context().get_shader("compositor_scale_variable"); + GPU_shader_bind(shader); + + Result &input = get_input("Image"); + GPU_texture_filter_mode(input.texture(), true); + GPU_texture_extend_mode(input.texture(), GPU_SAMPLER_EXTEND_MODE_CLAMP_TO_BORDER); + input.bind_as_texture(shader, "input_tx"); + + Result &x_scale = get_input("X"); + x_scale.bind_as_texture(shader, "x_scale_tx"); + + Result &y_scale = get_input("Y"); + y_scale.bind_as_texture(shader, "y_scale_tx"); + + Result &output = get_result("Image"); + const Domain domain = compute_domain(); + output.allocate_texture(domain); + output.bind_as_image(shader, "output_img"); + + compute_dispatch_threads_at_least(shader, domain.size); + + input.unbind_as_texture(); + x_scale.unbind_as_texture(); + y_scale.unbind_as_texture(); + output.unbind_as_image(); + GPU_shader_unbind(); + } + float2 get_scale() { switch (get_scale_method()) { @@ -199,6 +243,16 @@ class ScaleOperation : public NodeOperation { return get_offset() * input_size * get_scale(); } + bool is_variable_size() + { + /* Only relative scaling can be variable. */ + if (get_scale_method() != CMP_NODE_SCALE_RELATIVE) { + return false; + } + + return !get_input("X").is_single_value() || !get_input("Y").is_single_value(); + } + CMPNodeScaleMethod get_scale_method() { return (CMPNodeScaleMethod)bnode().custom1; diff --git a/tests/data b/tests/data index ce850ef056c..19d97256ecb 160000 --- a/tests/data +++ b/tests/data @@ -1 +1 @@ -Subproject commit ce850ef056c57d0e4127eda48a514b2c4a651435 +Subproject commit 19d97256ecb50b77b1abe4685ccb7eae0d0f2df4