41 {0,
nullptr, 0,
nullptr,
nullptr},
46 b.use_custom_socket_order();
47 b.allow_any_socket_order();
49 .default_value({1.0f, 1.0f, 1.0f, 1.0f})
52 b.add_output<
decl::Color>(
"Image").structure_type(StructureType::Dynamic).align_with_previous();
58 .structure_type(StructureType::Dynamic);
63 b.add_input<
decl::Bool>(
"Extend Bounds").default_value(
false);
67 "Use faster approximation by blurring along the horizontal and vertical directions "
147 if (this->
context().use_gpu()) {
160 input.bind_as_texture(shader,
"input_tx");
169 output.allocate_texture(domain);
170 output.bind_as_image(shader,
"output_img");
176 input.unbind_as_texture();
187 output.allocate_texture(domain);
190 float4 accumulated_color = float4(0.0f);
193 float4 center_color = input.load_pixel_extended<float4>(texel);
194 accumulated_color += center_color * weights.load_pixel<float>(int2(0));
196 int2 weights_size = weights.domain().size;
202 for (int x = 1; x < weights_size.x; x++) {
203 float weight = weights.load_pixel<float>(int2(x, 0));
204 accumulated_color += input.load_pixel_extended<float4>(texel + int2(x, 0)) * weight;
205 accumulated_color += input.load_pixel_extended<float4>(texel + int2(-x, 0)) * weight;
212 for (
int y = 1;
y < weights_size.y;
y++) {
214 accumulated_color +=
input.load_pixel_extended<
float4>(texel +
int2(0,
y)) * weight;
215 accumulated_color +=
input.load_pixel_extended<
float4>(texel +
int2(0, -
y)) * weight;
222 for (
int y = 1;
y < weights_size.y;
y++) {
223 for (
int x = 1;
x < weights_size.x;
x++) {
225 accumulated_color +=
input.load_pixel_extended<
float4>(texel +
int2(
x,
y)) * weight;
226 accumulated_color +=
input.load_pixel_extended<
float4>(texel +
int2(-
x,
y)) * weight;
227 accumulated_color +=
input.load_pixel_extended<
float4>(texel +
int2(
x, -
y)) * weight;
228 accumulated_color +=
input.load_pixel_extended<
float4>(texel +
int2(-
x, -
y)) * weight;
232 output.store_pixel(texel, accumulated_color);
238 if (this->
context().use_gpu()) {
249 const Result &weights =
context().cache_manager().symmetric_blur_weights.get(
252 gpu::Shader *shader =
context().get_shader(
"compositor_symmetric_blur_variable_size");
255 input.bind_as_texture(shader,
"input_tx");
260 output.allocate_texture(domain);
261 output.bind_as_image(shader,
"output_img");
267 input.unbind_as_texture();
275 const Result &weights = this->
context().cache_manager().symmetric_blur_weights.get(
279 output.allocate_texture(domain);
282 float4 accumulated_color = float4(0.0f);
283 float4 accumulated_weight = float4(0.0f);
285 const float2 size = math::max(float2(0.0f), size_input.load_pixel_extended<float2>(texel));
286 int2 radius = int2(math::ceil(size));
287 float2 coordinates_scale = float2(1.0f) / (size + float2(1.0f));
290 float4 center_color = input.load_pixel_extended<float4>(texel);
291 float center_weight = weights.load_pixel<float>(int2(0));
292 accumulated_color += center_color * center_weight;
293 accumulated_weight += center_weight;
299 for (int x = 1; x <= radius.x; x++) {
300 float weight_coordinates = (x + 0.5f) * coordinates_scale.x;
301 float weight = weights.sample_bilinear_extended(float2(weight_coordinates, 0.0f)).x;
302 accumulated_color += input.load_pixel_extended<float4>(texel + int2(x, 0)) * weight;
303 accumulated_color += input.load_pixel_extended<float4>(texel + int2(-x, 0)) * weight;
304 accumulated_weight += weight * 2.0f;
311 for (
int y = 1;
y <= radius.y;
y++) {
312 float weight_coordinates = (
y + 0.5f) * coordinates_scale.y;
314 accumulated_color +=
input.load_pixel_extended<
float4>(texel +
int2(0,
y)) * weight;
315 accumulated_color +=
input.load_pixel_extended<
float4>(texel +
int2(0, -
y)) * weight;
316 accumulated_weight += weight * 2.0f;
323 for (
int y = 1;
y <= radius.y;
y++) {
324 for (
int x = 1;
x <= radius.x;
x++) {
327 accumulated_color +=
input.load_pixel_extended<
float4>(texel +
int2(
x,
y)) * weight;
328 accumulated_color +=
input.load_pixel_extended<
float4>(texel +
int2(-
x,
y)) * weight;
329 accumulated_color +=
input.load_pixel_extended<
float4>(texel +
int2(
x, -
y)) * weight;
330 accumulated_color +=
input.load_pixel_extended<
float4>(texel +
int2(-
x, -
y)) * weight;
331 accumulated_weight += weight * 4.0f;
337 output.store_pixel(texel, accumulated_color);
395 return this->
get_input(
"Separable").get_single_value_default(
true);
400 return this->
get_input(
"Extend Bounds").get_single_value_default(
false);
407 const MenuValue menu_value =
input.get_single_value_default(default_menu_value);
408 return menu_value.
value;
430 ntype.
declare = file_ns::cmp_node_blur_declare;
432 ntype.
initfunc = file_ns::node_composit_init_blur;
#define NODE_CLASS_OP_FILTER
void GPU_shader_bind(blender::gpu::Shader *shader, const blender::gpu::shader::SpecializationConstants *constants_state=nullptr)
#define NOD_REGISTER_NODE(REGISTER_FUNC)
int pad[32 - sizeof(int)]
BMesh const char void * data
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
StaticCacheManager & cache_manager()
Result create_result(ResultType type, ResultPrecision precision)
gpu::Shader * get_shader(const char *info_name, ResultPrecision precision)
NodeOperation(Context &context, DNode node)
Result & get_result(StringRef identifier)
Context & context() const
Result & get_input(StringRef identifier) const
void share_data(const Result &source)
void unbind_as_texture() const
void bind_as_texture(gpu::Shader *shader, const char *texture_name) const
T load_pixel(const int2 &texel) const
float4 sample_bilinear_extended(const float2 &coordinates) const
bool is_single_value() const
SymmetricBlurWeightsContainer symmetric_blur_weights
Result & get(Context &context, int type, float2 radius)
StructureType structure_type
void execute_variable_size_cpu(const Result &input, const Result &size_input, Result &output)
bool use_separable_filter()
void execute_constant_size_gpu(const Result &input, Result &output)
float2 compute_maximum_blur_size()
void execute_variable_size(const Result &input, const Result &size, Result &output)
void execute_blur(const Result &input, const Result &size)
void execute_constant_size(const Result &input, Result &output)
int2 compute_extended_boundary_size(const Result &size)
void execute_constant_size_cpu(const Result &input, Result &output)
void execute_variable_size_gpu(const Result &input, const Result &size_input, Result &output)
NodeOperation(Context &context, DNode node)
VecBase< float, 2 > float2
void * MEM_callocN(size_t len, const char *str)
void node_register_type(bNodeType &ntype)
void node_type_storage(bNodeType &ntype, std::optional< StringRefNull > storagename, void(*freefunc)(bNode *node), void(*copyfunc)(bNodeTree *dest_ntree, bNode *dest_node, const bNode *src_node))
void symmetric_separable_blur(Context &context, const Result &input, Result &output, const float2 &radius, const int filter_type=R_FILTER_GAUSS)
void compute_dispatch_threads_at_least(gpu::Shader *shader, int2 threads_range, int2 local_size=int2(16))
void recursive_gaussian_blur(Context &context, const Result &input, Result &output, const float2 &radius)
float2 maximum_float2(Context &context, const Result &result)
void parallel_for(const int2 range, const Function &function)
T safe_divide(const T &a, const T &b)
T max(const T &a, const T &b)
static const EnumPropertyItem type_items[]
static void cmp_node_blur_declare(NodeDeclarationBuilder &b)
static void node_composit_init_blur(bNodeTree *, bNode *node)
static NodeOperation * get_compositor_operation(Context &context, DNode node)
VecBase< float, 4 > float4
VecBase< int32_t, 2 > int2
VecBase< float, 2 > float2
static void register_node_type_cmp_blur()
void cmp_node_type_base(blender::bke::bNodeType *ntype, std::string idname, const std::optional< int16_t > legacy_type)
void node_free_standard_storage(bNode *node)
void node_copy_standard_storage(bNodeTree *, bNode *dest_node, const bNode *src_node)
std::string ui_description
NodeGetCompositorOperationFunction get_compositor_operation
void(* initfunc)(bNodeTree *ntree, bNode *node)
const char * enum_name_legacy
NodeDeclareFunction declare
static pxr::UsdShadeInput get_input(const pxr::UsdShadeShader &usd_shader, const pxr::TfToken &input_name)