29 b.use_custom_socket_order();
30 b.allow_any_socket_order();
32 .default_value({1.0f, 1.0f, 1.0f, 1.0f})
35 b.add_output<
decl::Color>(
"Image").structure_type(StructureType::Dynamic).align_with_previous();
38 "The size of the inpaint in pixels");
67 flooded_boundary, filled_region, distance_to_boundary, smoothing_radius);
86 if (this->
context().use_gpu()) {
100 input.bind_as_texture(shader,
"input_tx");
109 input.unbind_as_texture();
113 return inpainting_boundary;
134 bool has_transparent_neighbors = false;
135 for (int j = -1; j <= 1; j++) {
136 for (int i = -1; i <= 1; i++) {
137 int2 offset = int2(i, j);
140 if (offset != int2(0)) {
141 if (input.load_pixel_extended<float4>(texel + offset).w < 1.0f) {
142 has_transparent_neighbors = true;
150 bool is_opaque =
input.load_pixel<
float4>(texel).w == 1.0f;
151 bool is_boundary_pixel = is_opaque && has_transparent_neighbors;
166 Result &distance_to_boundary,
169 if (this->
context().use_gpu()) {
171 flooded_boundary, filled_region, distance_to_boundary, smoothing_radius);
175 flooded_boundary, filled_region, distance_to_boundary, smoothing_radius);
181 Result &distance_to_boundary,
190 input.bind_as_texture(shader,
"input_tx");
199 distance_to_boundary.
bind_as_image(shader,
"distance_to_boundary_img");
202 smoothing_radius.
bind_as_image(shader,
"smoothing_radius_img");
206 input.unbind_as_texture();
216 Result &distance_to_boundary_image,
217 Result &smoothing_radius_image)
232 float4 color = input.load_pixel<float4>(texel);
235 if (color.w == 1.0f) {
236 filled_region.store_pixel(texel, color);
237 smoothing_radius_image.store_pixel(texel, 0.0f);
238 distance_to_boundary_image.store_pixel(texel, 0.0f);
244 distance_to_boundary_image.
store_pixel(texel, distance_to_boundary);
254 float blur_window_size =
math::min(
float(max_distance), distance_to_boundary) /
256 bool skip_smoothing = distance_to_boundary > (max_distance * 2.0f);
257 float smoothing_radius = skip_smoothing ? 0.0f : blur_window_size;
258 smoothing_radius_image.
store_pixel(texel, smoothing_radius);
270 const Result &distance_to_boundary)
272 if (this->
context().use_gpu()) {
281 const Result &distance_to_boundary)
289 input.bind_as_texture(shader,
"input_tx");
292 distance_to_boundary.
bind_as_texture(shader,
"distance_to_boundary_tx");
296 output.allocate_texture(domain);
297 output.bind_as_image(shader,
"output_img");
301 input.unbind_as_texture();
309 const Result &distance_to_boundary_image)
317 output.allocate_texture(domain);
320 float4 color = input.load_pixel<float4>(texel);
323 if (color.w == 1.0f) {
324 output.store_pixel(texel, color);
328 float distance_to_boundary = distance_to_boundary_image.
load_pixel<
float>(texel);
332 if (distance_to_boundary > max_distance) {
366 ntype.
ui_description =
"Extend borders of an image into transparent or masked regions";
369 ntype.
declare = file_ns::cmp_node_inpaint_declare;
#define NODE_CLASS_OP_FILTER
void GPU_shader_bind(blender::gpu::Shader *shader, const blender::gpu::shader::SpecializationConstants *constants_state=nullptr)
void GPU_shader_uniform_1i(blender::gpu::Shader *sh, const char *name, int value)
#define NOD_REGISTER_NODE(REGISTER_FUNC)
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
virtual Domain compute_domain()
void share_data(const Result &source)
void store_pixel(const int2 &texel, const T &pixel_value)
void allocate_texture(const Domain domain, const bool from_pool=true, const std::optional< ResultStorageType > storage_type=std::nullopt)
void unbind_as_texture() const
void bind_as_texture(gpu::Shader *shader, const char *texture_name) const
T load_pixel(const int2 &texel) const
void unbind_as_image() const
void bind_as_image(gpu::Shader *shader, const char *image_name, bool read=false) const
bool is_single_value() const
StructureType structure_type
void fill_inpainting_region(const Result &flooded_boundary, Result &filled_region, Result &distance_to_boundary, Result &smoothing_radius)
Result compute_inpainting_boundary()
void compute_inpainting_region_gpu(const Result &inpainted_region, const Result &distance_to_boundary)
void compute_inpainting_region_cpu(const Result &inpainted_region, const Result &distance_to_boundary_image)
void fill_inpainting_region_cpu(const Result &flooded_boundary, Result &filled_region, Result &distance_to_boundary_image, Result &smoothing_radius_image)
void fill_inpainting_region_gpu(const Result &flooded_boundary, Result &filled_region, Result &distance_to_boundary, Result &smoothing_radius)
Result compute_inpainting_boundary_gpu()
void compute_inpainting_region(const Result &inpainted_region, const Result &distance_to_boundary)
NodeOperation(Context &context, DNode node)
Result compute_inpainting_boundary_cpu()
VecBase< float, 4 > float4
void node_register_type(bNodeType &ntype)
void compute_dispatch_threads_at_least(gpu::Shader *shader, int2 threads_range, int2 local_size=int2(16))
int2 initialize_jump_flooding_value(const int2 &texel, const bool is_seed)
void symmetric_separable_blur_variable_size(Context &context, const Result &input, const Result &radius, Result &output, const int weights_resolution=128, const int filter_type=R_FILTER_GAUSS)
void jump_flooding(Context &context, Result &input, Result &output)
void parallel_for(const int2 range, const Function &function)
T distance(const T &a, const T &b)
T min(const T &a, const T &b)
T interpolate(const T &a, const T &b, const FactorT &t)
T max(const T &a, const T &b)
static void cmp_node_inpaint_declare(NodeDeclarationBuilder &b)
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_inpaint()
void cmp_node_type_base(blender::bke::bNodeType *ntype, std::string idname, const std::optional< int16_t > legacy_type)
VecBase< T, 3 > xyz() const
std::string ui_description
NodeGetCompositorOperationFunction get_compositor_operation
const char * enum_name_legacy
NodeDeclareFunction declare
static pxr::UsdShadeInput get_input(const pxr::UsdShadeShader &usd_shader, const pxr::TfToken &input_name)