Blender V4.3
COM_SunBeamsOperation.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2014 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include "BLI_math_base.hh"
6#include "BLI_math_vector.h"
7#include "BLI_math_vector.hh"
9
10#include "MEM_guardedalloc.h"
11
13
14namespace blender::compositor {
15
22
24 const rcti &area,
26{
27 MemoryBuffer *input = inputs[0];
28
29 const float2 input_size = float2(input->get_width(), input->get_height());
30 const int max_steps = int(data_.ray_length * math::length(input_size));
31 const float2 source = float2(data_.source);
32
33 for (int y = area.ymin; y < area.ymax; y++) {
34 for (int x = area.xmin; x < area.xmax; x++) {
35 if (max_steps == 0) {
36 copy_v4_v4(output->get_elem(x, y), input->get_elem(x, y));
37 continue;
38 }
39
40 const float2 texel = float2(x, y);
41
42 /* The number of steps is the distance in pixels from the source to the current texel. With
43 * at least a single step and at most the user specified maximum ray length, which is
44 * proportional to the diagonal pixel count. */
45 const float unbounded_steps = math::max(1.0f, math::distance(texel, source * input_size));
46 const int steps = math::min(max_steps, int(unbounded_steps));
47
48 /* We integrate from the current pixel to the source pixel, so compute the start coordinates
49 * and step vector in the direction to source. Notice that the step vector is still computed
50 * from the unbounded steps, such that the total integration length becomes limited by the
51 * bounded steps, and thus by the maximum ray length. */
52 const float2 coordinates = (texel + float2(0.5f)) / input_size;
53 const float2 vector_to_source = source - coordinates;
54 const float2 step_vector = vector_to_source / unbounded_steps;
55
56 float accumulated_weight = 0.0f;
57 float4 accumulated_color = float4(0.0f);
58 for (int i = 0; i <= steps; i++) {
59 float2 position = coordinates + i * step_vector;
60
61 /* We are already past the image boundaries, and any future steps are also past the image
62 * boundaries, so break. */
63 if (position.x < 0.0f || position.y < 0.0f || position.x > 1.0f || position.y > 1.0f) {
64 break;
65 }
66
67 const float4 sample_color = input->texture_bilinear_extend(position);
68
69 /* Attenuate the contributions of pixels that are further away from the source using a
70 * quadratic falloff. */
71 const float weight = math::square(1.0f - i / float(steps));
72
73 accumulated_weight += weight;
74 accumulated_color += sample_color * weight;
75 }
76
77 accumulated_color /= accumulated_weight != 0.0f ? accumulated_weight : 1.0f;
78 copy_v4_v4(output->get_elem(x, y), accumulated_color);
79 }
80 }
81}
82
83} // namespace blender::compositor
MINLINE void copy_v4_v4(float r[4], const float a[4])
Read Guarded memory(de)allocation.
a MemoryBuffer contains access to the data
void add_output_socket(DataType datatype)
void add_input_socket(DataType datatype, ResizeMode resize_mode=ResizeMode::Center)
void set_canvas_input_index(unsigned int index)
set the index of the input socket that will determine the canvas of this operation
void update_memory_buffer_partial(MemoryBuffer *output, const rcti &area, Span< MemoryBuffer * > inputs) override
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
T distance(const T &a, const T &b)
T length(const VecBase< T, Size > &a)
T min(const T &a, const T &b)
T square(const T &a)
T max(const T &a, const T &b)
VecBase< float, 4 > float4
VecBase< float, 2 > float2
static const int steps