Blender V4.5
morphological_distance_feather_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 <cmath>
6#include <cstdint>
7#include <memory>
8
9#include "BLI_array.hh"
10#include "BLI_hash.hh"
11#include "BLI_index_range.hh"
12
13#include "RE_pipeline.h"
14
15#include "DNA_scene_types.h"
16
17#include "GPU_texture.hh"
18
19#include "COM_context.hh"
21#include "COM_result.hh"
22
23namespace blender::compositor {
24
25/* --------------------------------------------------------------------
26 * Morphological Distance Feather Weights Key.
27 */
28
34
39
42{
43 return a.type == b.type && a.radius == b.radius;
44}
45
46/* --------------------------------------------------------------------
47 * Morphological Distance Feather Weights.
48 */
49
51 int type,
52 int radius)
53 : weights_result(context.create_result(ResultType::Float)),
54 falloffs_result(context.create_result(ResultType::Float))
55{
56 this->compute_weights(radius);
57 this->compute_distance_falloffs(type, radius);
58
59 if (context.use_gpu()) {
60 this->weights_result.allocate_texture(Domain(int2(weights_.size(), 1)), false);
61 this->falloffs_result.allocate_texture(Domain(int2(falloffs_.size(), 1)), false);
62 GPU_texture_update(this->weights_result, GPU_DATA_FLOAT, weights_.data());
63 GPU_texture_update(this->falloffs_result, GPU_DATA_FLOAT, falloffs_.data());
64
65 /* CPU-side data no longer needed, so free it. */
66 weights_ = Array<float>();
67 falloffs_ = Array<float>();
68 }
69 else {
70 this->weights_result.wrap_external(weights_.data(), int2(weights_.size(), 1));
71 this->falloffs_result.wrap_external(falloffs_.data(), int2(falloffs_.size(), 1));
72 }
73}
74
80
81void MorphologicalDistanceFeatherWeights::compute_weights(int radius)
82{
83 /* The size of filter is double the radius plus 1, but since the filter is symmetric, we only
84 * compute half of it and no doubling happens. We add 1 to make sure the filter size is always
85 * odd and there is a center weight. */
86 const int size = radius + 1;
87 weights_ = Array<float>(size);
88
89 float sum = 0.0f;
90
91 /* First, compute the center weight. */
92 const float center_weight = RE_filter_value(R_FILTER_GAUSS, 0.0f);
93 weights_[0] = center_weight;
94 sum += center_weight;
95
96 /* Second, compute the other weights in the positive direction, making sure to add double the
97 * weight to the sum of weights because the filter is symmetric and we only loop over half of
98 * it. Skip the center weight already computed by dropping the front index. */
99 const float scale = radius > 0.0f ? 1.0f / radius : 0.0f;
100 for (const int i : weights_.index_range().drop_front(1)) {
101 const float weight = RE_filter_value(R_FILTER_GAUSS, i * scale);
102 weights_[i] = weight;
103 sum += weight * 2.0f;
104 }
105
106 /* Finally, normalize the weights. */
107 for (const int i : weights_.index_range()) {
108 weights_[i] /= sum;
109 }
110}
111
112/* Computes a falloff that is equal to 1 at an input of zero and decrease to zero at an input of 1,
113 * with the rate of decrease depending on the falloff type. */
114static float compute_distance_falloff(int type, float x)
115{
116 x = 1.0f - x;
117
118 switch (type) {
119 case PROP_SMOOTH:
120 return 3.0f * x * x - 2.0f * x * x * x;
121 case PROP_SPHERE:
122 return std::sqrt(2.0f * x - x * x);
123 case PROP_ROOT:
124 return std::sqrt(x);
125 case PROP_SHARP:
126 return x * x;
127 case PROP_INVSQUARE:
128 return x * (2.0f - x);
129 case PROP_LIN:
130 return x;
131 default:
133 return x;
134 }
135}
136
137void MorphologicalDistanceFeatherWeights::compute_distance_falloffs(int type, int radius)
138{
139 /* The size of the distance falloffs is double the radius plus 1, but since the falloffs are
140 * symmetric, we only compute half of them and no doubling happens. We add 1 to make sure the
141 * falloffs size is always odd and there is a center falloff. */
142 const int size = radius + 1;
143 falloffs_ = Array<float>(size);
144
145 /* Compute the distance falloffs in the positive direction only, because the falloffs are
146 * symmetric. */
147 const float scale = radius > 0.0f ? 1.0f / radius : 0.0f;
148 for (const int i : falloffs_.index_range()) {
149 falloffs_[i] = compute_distance_falloff(type, i * scale);
150 }
151}
152
153/* --------------------------------------------------------------------
154 * Morphological Distance Feather Weights Container.
155 */
156
158{
159 /* First, delete all resources that are no longer needed. */
160 map_.remove_if([](auto item) { return !item.value->needed; });
161
162 /* Second, reset the needed status of the remaining resources to false to ready them to track
163 * their needed status for the next evaluation. */
164 for (auto &value : map_.values()) {
165 value->needed = false;
166 }
167}
168
170 Context &context, int type, int radius)
171{
172 const MorphologicalDistanceFeatherWeightsKey key(type, radius);
173
174 auto &weights = *map_.lookup_or_add_cb(key, [&]() {
175 return std::make_unique<MorphologicalDistanceFeatherWeights>(context, type, radius);
176 });
177
178 weights.needed = true;
179 return weights;
180}
181
182} // namespace blender::compositor
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
@ R_FILTER_GAUSS
@ PROP_SMOOTH
@ PROP_ROOT
@ PROP_SHARP
@ PROP_LIN
@ PROP_INVSQUARE
@ PROP_SPHERE
@ GPU_DATA_FLOAT
void GPU_texture_update(GPUTexture *texture, eGPUDataFormat data_format, const void *data)
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)
IndexRange index_range() const
Definition BLI_array.hh:349
constexpr IndexRange drop_front(int64_t n) const
MorphologicalDistanceFeatherWeights & get(Context &context, int type, int radius)
float RE_filter_value(int type, float x)
bool operator==(const BokehKernelKey &a, const BokehKernelKey &b)
static float compute_distance_falloff(int type, float x)
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