Blender V5.0
symmetric_separable_blur_weights.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include <cstdint>
6#include <memory>
7
8#include "BLI_hash.hh"
9#include "BLI_index_range.hh"
10#include "BLI_math_base.hh"
11
12#include "RE_pipeline.h"
13
14#include "COM_context.hh"
15#include "COM_result.hh"
17
18namespace blender::compositor {
19
20/* --------------------------------------------------------------------
21 * Symmetric Separable Blur Weights Key.
22 */
23
28
33
36{
37 return a.type == b.type && a.radius == b.radius;
38}
39
40/* --------------------------------------------------------------------
41 * Symmetric Separable Blur Weights.
42 */
43
45 int type,
46 float radius)
47 : result(context.create_result(ResultType::Float))
48{
49 /* The size of filter is double the radius plus 1, but since the filter is symmetric, we only
50 * compute half of it and no doubling happens. We add 1 to make sure the filter size is always
51 * odd and there is a center weight. */
52 const int size = math::ceil(radius) + 1;
53 this->result.allocate_texture(Domain(int2(size, 1)), false, ResultStorageType::CPU);
54
55 float sum = 0.0f;
56
57 /* First, compute the center weight. */
58 const float center_weight = RE_filter_value(type, 0.0f);
59 this->result.store_pixel(int2(0, 0), center_weight);
60 sum += center_weight;
61
62 /* Second, compute the other weights in the positive direction, making sure to add double the
63 * weight to the sum of weights because the filter is symmetric and we only loop over half of
64 * it. Skip the center weight already computed by dropping the front index. */
65 const float scale = radius > 0.0f ? 1.0f / radius : 0.0f;
66 for (const int i : IndexRange(size).drop_front(1)) {
67 const float weight = RE_filter_value(type, i * scale);
68 this->result.store_pixel(int2(i, 0), weight);
69 sum += weight * 2.0f;
70 }
71
72 /* Finally, normalize the weights. */
73 for (const int i : IndexRange(size)) {
74 const int2 texel = int2(i, 0);
75 this->result.store_pixel(texel, this->result.load_pixel<float>(texel) / sum);
76 }
77
78 if (context.use_gpu()) {
79 const Result gpu_result = this->result.upload_to_gpu(false);
80 this->result.release();
81 this->result = gpu_result;
82 }
83}
84
89
90/* --------------------------------------------------------------------
91 * Symmetric Separable Blur Weights Container.
92 */
93
95{
96 /* First, delete all resources that are no longer needed. */
97 map_.remove_if([](auto item) { return !item.value->needed; });
98
99 /* Second, reset the needed status of the remaining resources to false to ready them to track
100 * their needed status for the next evaluation. */
101 for (auto &value : map_.values()) {
102 value->needed = false;
103 }
104}
105
107{
108 const SymmetricSeparableBlurWeightsKey key(type, radius);
109
110 auto &weights = *map_.lookup_or_add_cb(key, [&]() {
111 return std::make_unique<SymmetricSeparableBlurWeights>(context, type, radius);
112 });
113
114 weights.needed = true;
115 return weights.result;
116}
117
118} // namespace blender::compositor
unsigned long long int uint64_t
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
static T sum(const btAlignedObjectArray< T > &items)
SymmetricSeparableBlurWeights(Context &context, int type, float radius)
float RE_filter_value(int type, float x)
bool operator==(const BokehKernelKey &a, const BokehKernelKey &b)
T ceil(const T &a)
uint64_t get_default_hash(const T &v, const Args &...args)
Definition BLI_hash.hh:233
VecBase< int32_t, 2 > int2
i
Definition text_draw.cc:230