Realtime Compositor: Support variable scaling #120314

Merged
Omar Emara merged 3 commits from OmarEmaraDev/blender:gpu-scale-variable into main 2024-04-09 16:02:57 +02:00
5 changed files with 92 additions and 3 deletions

View File

@ -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

View File

@ -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));
}

View File

@ -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);

View File

@ -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<decl::Float>("Y")
.default_value(1.0f)
.min(0.0001f)
.max(CMP_SCALE_MAX)
.compositor_expects_single_value();
.compositor_domain_priority(2);
b.add_output<decl::Color>("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;

@ -1 +1 @@
Subproject commit ce850ef056c57d0e4127eda48a514b2c4a651435
Subproject commit 19d97256ecb50b77b1abe4685ccb7eae0d0f2df4