43 .compositor_expects_single_value()
45 "Use faster approximation by blurring along the horizontal and vertical directions "
78 if (!this->
get_input(
"Size").is_single_value()) {
89 node_storage(
bnode()).filtertype,
99 if (this->
context().use_gpu()) {
114 input.bind_as_texture(shader,
"input_tx");
119 context(), node_storage(
bnode()).filtertype, blur_radius);
128 output.allocate_texture(domain);
129 output.bind_as_image(shader,
"output_img");
135 input.unbind_as_texture();
143 this->
context(), node_storage(this->
bnode()).filtertype, blur_radius);
152 output.allocate_texture(domain);
155 return this->
load_input(input, weights, texel, extend_bounds);
159 float4 accumulated_color = float4(0.0f);
162 float4 center_color = load_input(texel);
163 accumulated_color += center_color * weights.load_pixel<float>(int2(0));
165 int2 weights_size = weights.domain().size;
171 for (int x = 1; x < weights_size.x; x++) {
172 float weight = weights.load_pixel<float>(int2(x, 0));
173 accumulated_color += load_input(texel + int2(x, 0)) * weight;
174 accumulated_color += load_input(texel + int2(-x, 0)) * weight;
181 for (
int y = 1;
y < weights_size.y;
y++) {
191 for (
int y = 1;
y < weights_size.y;
y++) {
192 for (
int x = 1;
x < weights_size.x;
x++) {
201 output.store_pixel(texel, accumulated_color);
207 if (this->
context().use_gpu()) {
218 const Result &weights =
context().cache_manager().symmetric_blur_weights.get(
219 context(), node_storage(
bnode()).filtertype, blur_radius);
221 GPUShader *shader =
context().get_shader(
"compositor_symmetric_blur_variable_size");
226 input.bind_as_texture(shader,
"input_tx");
239 output.allocate_texture(domain);
240 output.bind_as_image(shader,
"output_img");
246 input.unbind_as_texture();
254 const Result &weights = this->
context().cache_manager().symmetric_blur_weights.get(
255 this->
context(), node_storage(this->
bnode()).filtertype, blur_radius);
264 output.allocate_texture(domain);
273 auto load_size = [&](
const int2 texel) {
275 int2 offset = extend_bounds ? blur_radius :
int2(0);
280 float4 accumulated_color = float4(0.0f);
281 float4 accumulated_weight = float4(0.0f);
283 const float2 size = load_size(texel);
284 int2 radius = int2(math::ceil(size));
285 float2 coordinates_scale = float2(1.0f) / (size + float2(1.0f));
288 float4 center_color = load_input(texel);
289 float center_weight = weights.load_pixel<float>(int2(0));
290 accumulated_color += center_color * center_weight;
291 accumulated_weight += center_weight;
297 for (int x = 1; x <= radius.x; x++) {
298 float weight_coordinates = (x + 0.5f) * coordinates_scale.x;
299 float weight = weights.sample_bilinear_extended(float2(weight_coordinates, 0.0f)).x;
300 accumulated_color += load_input(texel + int2(x, 0)) * weight;
301 accumulated_color += load_input(texel + int2(-x, 0)) * weight;
302 accumulated_weight += weight * 2.0f;
309 for (
int y = 1;
y <= radius.y;
y++) {
310 float weight_coordinates = (
y + 0.5f) * coordinates_scale.y;
314 accumulated_weight += weight * 2.0f;
321 for (
int y = 1;
y <= radius.y;
y++) {
322 for (
int x = 1;
x <= radius.x;
x++) {
329 accumulated_weight += weight * 4.0f;
335 output.store_pixel(texel, accumulated_color);
353 const bool extend_bounds)
401 switch (node_storage(
bnode()).filtertype) {
418 return this->
get_input(
"Separable").get_single_value_default(
true);
423 return this->
get_input(
"Extend Bounds").get_single_value_default(
false);
445 ntype.
declare = file_ns::cmp_node_blur_declare;
448 ntype.
initfunc = file_ns::node_composit_init_blur;
#define NODE_STORAGE_FUNCS(StorageT)
#define NODE_CLASS_OP_FILTER
void GPU_shader_bind(GPUShader *shader, const blender::gpu::shader::SpecializationConstants *constants_state=nullptr)
void GPU_shader_uniform_1b(GPUShader *sh, const char *name, bool value)
#define NOD_REGISTER_NODE(REGISTER_FUNC)
@ UI_ITEM_R_SPLIT_EMPTY_NAME
for(;discarded_id_iter !=nullptr;discarded_id_iter=static_cast< ID * >(discarded_id_iter->next))
BMesh const char void * data
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
StaticCacheManager & cache_manager()
GPUShader * get_shader(const char *info_name, ResultPrecision precision)
const bNode & bnode() const
NodeOperation(Context &context, DNode node)
Result & get_result(StringRef identifier)
Context & context() const
Result & get_input(StringRef identifier) const
virtual Domain compute_domain()
void share_data(const Result &source)
void unbind_as_texture() const
void bind_as_texture(GPUShader *shader, const char *texture_name) const
const Domain & domain() 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)
ColorGeometry4f default_value
bool use_separable_filter()
void execute_constant_size_gpu(const Result &input, Result &output)
float2 compute_maximum_blur_size()
void execute_constant_size(const Result &input, Result &output)
void execute_variable_size_gpu(const Result &input, Result &output)
float4 load_input(const Result &input, const Result &weights, const int2 texel, const bool extend_bounds)
void execute_variable_size_cpu(const Result &input, Result &output)
void execute_constant_size_cpu(const Result &input, Result &output)
void execute_variable_size(const Result &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 recursive_gaussian_blur(Context &context, const Result &input, Result &output, const float2 &radius)
void compute_dispatch_threads_at_least(GPUShader *shader, int2 threads_range, int2 local_size=int2(16))
void symmetric_separable_blur(Context &context, const Result &input, Result &output, const float2 &radius, const int filter_type=R_FILTER_GAUSS, const bool extend_bounds=false)
float3 maximum_float3(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 void cmp_node_blur_declare(NodeDeclarationBuilder &b)
static void node_composit_init_blur(bNodeTree *, bNode *node)
static void node_composit_buts_blur(uiLayout *layout, bContext *, PointerRNA *ptr)
static NodeOperation * get_compositor_operation(Context &context, DNode node)
VecBase< float, 4 > float4
VecBase< int32_t, 2 > int2
VecBase< float, 2 > float2
VecBase< float, 3 > float3
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
void(* draw_buttons)(uiLayout *, bContext *C, PointerRNA *ptr)
NodeDeclareFunction declare
void prop(PointerRNA *ptr, PropertyRNA *prop, int index, int value, eUI_Item_Flag flag, std::optional< blender::StringRef > name_opt, int icon, std::optional< blender::StringRef > placeholder=std::nullopt)
static pxr::UsdShadeInput get_input(const pxr::UsdShadeShader &usd_shader, const pxr::TfToken &input_name)