Realtime Compositor: Implement Sun Beams node #108718
|
@ -145,6 +145,7 @@ set(GLSL_SRC
|
|||
shaders/compositor_smaa_edge_detection.glsl
|
||||
shaders/compositor_smaa_neighborhood_blending.glsl
|
||||
shaders/compositor_split_viewer.glsl
|
||||
shaders/compositor_sun_beams.glsl
|
||||
shaders/compositor_symmetric_blur.glsl
|
||||
shaders/compositor_symmetric_blur_variable_size.glsl
|
||||
shaders/compositor_symmetric_separable_blur.glsl
|
||||
|
@ -244,6 +245,7 @@ set(SRC_SHADER_CREATE_INFOS
|
|||
shaders/infos/compositor_screen_lens_distortion_info.hh
|
||||
shaders/infos/compositor_smaa_info.hh
|
||||
shaders/infos/compositor_split_viewer_info.hh
|
||||
shaders/infos/compositor_sun_beams_info.hh
|
||||
shaders/infos/compositor_symmetric_blur_info.hh
|
||||
shaders/infos/compositor_symmetric_blur_variable_size_info.hh
|
||||
shaders/infos/compositor_symmetric_separable_blur_info.hh
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
#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 vector_to_source = source - coordinates;
|
||||
float distance_to_source = length(vector_to_source);
|
||||
vec2 direction_to_source = vector_to_source / distance_to_source;
|
||||
|
||||
/* We integrate from the current pixel to the source pixel, but up until the user specified
|
||||
* maximum ray length. The number of integration steps is roughly equivalent to the number of
|
||||
* pixels along the integration path. Assume a minimum number of steps of 1 to avoid zero
|
||||
* division handling and return source pixels as is. */
|
||||
float integration_length = min(distance_to_source, max_ray_length);
|
||||
float integration_length_in_pixels = length(input_size) * integration_length;
|
||||
int steps = max(1, int(integration_length_in_pixels));
|
||||
vec2 step_vector = (direction_to_source * integration_length) / steps;
|
||||
|
||||
vec4 accumulated_color = vec4(0.0);
|
||||
for (int i = 0; i < steps; i++) {
|
||||
/* Attenuate the contributions of pixels that are further away from the source using a
|
||||
* quadratic falloff. */
|
||||
float weight = pow(1.0f - i / integration_length_in_pixels, 2.0);
|
||||
accumulated_color += texture(input_tx, coordinates + i * step_vector) * weight;
|
||||
}
|
||||
|
||||
imageStore(output_img, texel, accumulated_color / steps);
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "gpu_shader_create_info.hh"
|
||||
|
||||
GPU_SHADER_CREATE_INFO(compositor_sun_beams)
|
||||
.local_group_size(16, 16)
|
||||
.push_constant(Type::VEC2, "source")
|
||||
.push_constant(Type::FLOAT, "max_ray_length")
|
||||
.sampler(0, ImageType::FLOAT_2D, "input_tx")
|
||||
.image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img")
|
||||
.compute_source("compositor_sun_beams.glsl")
|
||||
.do_static_compilation(true);
|
|
@ -9,15 +9,22 @@
|
|||
#include "UI_interface.h"
|
||||
#include "UI_resources.h"
|
||||
|
||||
#include "GPU_shader.h"
|
||||
|
||||
#include "COM_node_operation.hh"
|
||||
#include "COM_utilities.hh"
|
||||
|
||||
#include "node_composite_util.hh"
|
||||
|
||||
namespace blender::nodes::node_composite_sunbeams_cc {
|
||||
|
||||
NODE_STORAGE_FUNCS(NodeSunBeams)
|
||||
|
||||
static void cmp_node_sunbeams_declare(NodeDeclarationBuilder &b)
|
||||
{
|
||||
b.add_input<decl::Color>("Image").default_value({1.0f, 1.0f, 1.0f, 1.0f});
|
||||
b.add_input<decl::Color>("Image")
|
||||
.default_value({1.0f, 1.0f, 1.0f, 1.0f})
|
||||
.compositor_domain_priority(0);
|
||||
b.add_output<decl::Color>("Image");
|
||||
}
|
||||
|
||||
|
@ -49,8 +56,27 @@ class SunBeamsOperation : public NodeOperation {
|
|||
|
||||
void execute() override
|
||||
{
|
||||
get_input("Image").pass_through(get_result("Image"));
|
||||
context().set_info_message("Viewport compositor setup not fully supported");
|
||||
GPUShader *shader = shader_manager().get("compositor_sun_beams");
|
||||
GPU_shader_bind(shader);
|
||||
|
||||
GPU_shader_uniform_2fv(shader, "source", node_storage(bnode()).source);
|
||||
GPU_shader_uniform_1f(shader, "max_ray_length", node_storage(bnode()).ray_length);
|
||||
|
||||
const Result &input_image = get_input("Image");
|
||||
GPU_texture_filter_mode(input_image.texture(), true);
|
||||
GPU_texture_extend_mode(input_image.texture(), GPU_SAMPLER_EXTEND_MODE_CLAMP_TO_BORDER);
|
||||
input_image.bind_as_texture(shader, "input_tx");
|
||||
|
||||
const Domain domain = compute_domain();
|
||||
Result &output_image = get_result("Image");
|
||||
output_image.allocate_texture(domain);
|
||||
output_image.bind_as_image(shader, "output_img");
|
||||
|
||||
compute_dispatch_threads_at_least(shader, domain.size);
|
||||
|
||||
GPU_shader_unbind();
|
||||
output_image.unbind_as_image();
|
||||
input_image.unbind_as_texture();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -74,8 +100,6 @@ void register_node_type_cmp_sunbeams()
|
|||
node_type_storage(
|
||||
&ntype, "NodeSunBeams", node_free_standard_storage, node_copy_standard_storage);
|
||||
ntype.get_compositor_operation = file_ns::get_compositor_operation;
|
||||
ntype.realtime_compositor_unsupported_message = N_(
|
||||
"Node not supported in the Viewport compositor");
|
||||
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue