Blender V4.3
node_composite_planetrackdeform.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2013 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include "BLI_array.hh"
12#include "BLI_string.h"
13
14#include "DNA_defaults.h"
15#include "DNA_movieclip_types.h"
16#include "DNA_tracking_types.h"
17
18#include "BKE_context.hh"
19#include "BKE_lib_id.hh"
20#include "BKE_movieclip.h"
21#include "BKE_tracking.h"
22
23#include "RNA_access.hh"
24#include "RNA_prototypes.hh"
25
26#include "UI_interface.hh"
27#include "UI_resources.hh"
28
29#include "GPU_shader.hh"
30#include "GPU_texture.hh"
31#include "GPU_uniform_buffer.hh"
32
33#include "COM_algorithm_smaa.hh"
34#include "COM_node_operation.hh"
35#include "COM_utilities.hh"
36
38
40
42
44{
45 b.add_input<decl::Color>("Image").compositor_realization_options(
47 b.add_output<decl::Color>("Image");
48 b.add_output<decl::Float>("Plane");
49}
50
51static void init(const bContext *C, PointerRNA *ptr)
52{
53 bNode *node = (bNode *)ptr->data;
54
55 NodePlaneTrackDeformData *data = MEM_cnew<NodePlaneTrackDeformData>(__func__);
56 data->motion_blur_samples = 16;
57 data->motion_blur_shutter = 0.5f;
58 node->storage = data;
59
60 const Scene *scene = CTX_data_scene(C);
61 if (scene->clip) {
62 MovieClip *clip = scene->clip;
63 MovieTracking *tracking = &clip->tracking;
64
65 node->id = &clip->id;
66 id_us_plus(&clip->id);
67
68 const MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(tracking);
69 STRNCPY(data->tracking_object, tracking_object->name);
70
71 if (tracking_object->active_plane_track) {
72 STRNCPY(data->plane_track_name, tracking_object->active_plane_track->name);
73 }
74 }
75}
76
78{
79 bNode *node = (bNode *)ptr->data;
81
82 uiTemplateID(layout, C, ptr, "clip", nullptr, "CLIP_OT_open", nullptr);
83
84 if (node->id) {
85 MovieClip *clip = (MovieClip *)node->id;
86 MovieTracking *tracking = &clip->tracking;
87 MovieTrackingObject *tracking_object;
89 PointerRNA tracking_ptr = RNA_pointer_create(&clip->id, &RNA_MovieTracking, tracking);
90
91 col = uiLayoutColumn(layout, false);
92 uiItemPointerR(col, ptr, "tracking_object", &tracking_ptr, "objects", "", ICON_OBJECT_DATA);
93
94 tracking_object = BKE_tracking_object_get_named(tracking, data->tracking_object);
95 if (tracking_object) {
96 PointerRNA object_ptr = RNA_pointer_create(
97 &clip->id, &RNA_MovieTrackingObject, tracking_object);
98
100 col, ptr, "plane_track_name", &object_ptr, "plane_tracks", "", ICON_ANIM_DATA);
101 }
102 else {
103 uiItemR(layout, ptr, "plane_track_name", UI_ITEM_NONE, "", ICON_ANIM_DATA);
104 }
105 }
106
107 uiItemR(layout, ptr, "use_motion_blur", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE);
109 uiItemR(layout, ptr, "motion_blur_samples", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE);
110 uiItemR(layout, ptr, "motion_blur_shutter", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE);
111 }
112}
113
114using namespace blender::realtime_compositor;
115
117 public:
119
120 void execute() override
121 {
123
124 Result &input_image = get_input("Image");
125 Result &output_image = get_result("Image");
126 Result &output_mask = get_result("Plane");
127 if (input_image.is_single_value() || !plane_track) {
128 if (output_image.should_compute()) {
129 input_image.pass_through(output_image);
130 }
131 if (output_mask.should_compute()) {
132 output_mask.allocate_single_value();
133 output_mask.set_float_value(1.0f);
134 }
135 return;
136 }
137
138 const Array<float4x4> homography_matrices = compute_homography_matrices(plane_track);
139 GPUUniformBuf *homography_matrices_buffer = GPU_uniformbuf_create_ex(
140 homography_matrices.size() * sizeof(float4x4),
141 homography_matrices.data(),
142 "Plane Track Deform Homography Matrices");
143
144 Result plane_mask = compute_plane_mask(homography_matrices, homography_matrices_buffer);
145 Result anti_aliased_plane_mask = context().create_result(ResultType::Float);
146 smaa(context(), plane_mask, anti_aliased_plane_mask);
147 plane_mask.release();
148
149 if (output_image.should_compute()) {
150 compute_plane(homography_matrices, homography_matrices_buffer, anti_aliased_plane_mask);
151 }
152
153 if (output_mask.should_compute()) {
154 output_mask.steal_data(anti_aliased_plane_mask);
155 }
156 else {
157 anti_aliased_plane_mask.release();
158 }
159
160 GPU_uniformbuf_free(homography_matrices_buffer);
161 }
162
163 void compute_plane(const Array<float4x4> &homography_matrices,
164 GPUUniformBuf *homography_matrices_buffer,
165 Result &plane_mask)
166 {
167 GPUShader *shader = context().get_shader("compositor_plane_deform_motion_blur");
168 GPU_shader_bind(shader);
169
170 GPU_shader_uniform_1i(shader, "number_of_motion_blur_samples", homography_matrices.size());
171
172 const int ubo_location = GPU_shader_get_ubo_binding(shader, "homography_matrices");
173 GPU_uniformbuf_bind(homography_matrices_buffer, ubo_location);
174
175 Result &input_image = get_input("Image");
176 GPU_texture_mipmap_mode(input_image, true, true);
177 GPU_texture_anisotropic_filter(input_image, true);
179 input_image.bind_as_texture(shader, "input_tx");
180
181 plane_mask.bind_as_texture(shader, "mask_tx");
182
183 const Domain domain = compute_domain();
184 Result &output_image = get_result("Image");
185 output_image.allocate_texture(domain);
186 output_image.bind_as_image(shader, "output_img");
187
188 compute_dispatch_threads_at_least(shader, domain.size);
189
190 input_image.unbind_as_texture();
191 plane_mask.unbind_as_texture();
192 output_image.unbind_as_image();
193 GPU_uniformbuf_unbind(homography_matrices_buffer);
195 }
196
197 Result compute_plane_mask(const Array<float4x4> &homography_matrices,
198 GPUUniformBuf *homography_matrices_buffer)
199 {
200 GPUShader *shader = context().get_shader("compositor_plane_deform_motion_blur_mask");
201 GPU_shader_bind(shader);
202
203 GPU_shader_uniform_1i(shader, "number_of_motion_blur_samples", homography_matrices.size());
204
205 const int ubo_location = GPU_shader_get_ubo_binding(shader, "homography_matrices");
206 GPU_uniformbuf_bind(homography_matrices_buffer, ubo_location);
207
208 const Domain domain = compute_domain();
209 Result plane_mask = context().create_result(ResultType::Float);
210 plane_mask.allocate_texture(domain);
211 plane_mask.bind_as_image(shader, "mask_img");
212
213 compute_dispatch_threads_at_least(shader, domain.size);
214
215 plane_mask.unbind_as_image();
216 GPU_uniformbuf_unbind(homography_matrices_buffer);
218
219 return plane_mask;
220 }
221
223 {
225
226 Result &input_image = get_input("Image");
227 if (input_image.is_single_value() || !plane_track) {
228 return input_image.domain();
229 }
230
231 return Domain(get_movie_clip_size());
232 }
233
235 {
236 /* We evaluate at the frames in the range [frame - shutter, frame + shutter], if no motion blur
237 * is enabled or the motion blur samples is set to 1, we just evaluate at the current frame. */
238 const int samples = use_motion_blur() ? node_storage(bnode()).motion_blur_samples : 1;
239 const float shutter = samples != 1 ? node_storage(bnode()).motion_blur_shutter : 0.0f;
240 const float start_frame = context().get_frame_number() - shutter;
241 const float frame_step = (shutter * 2.0f) / samples;
242
243 Array<float4x4> matrices(samples);
244 for (int i = 0; i < samples; i++) {
245 const float frame = start_frame + frame_step * i;
246 const float clip_frame = BKE_movieclip_remap_scene_to_clip_frame(get_movie_clip(), frame);
247
248 float corners[4][2];
249 BKE_tracking_plane_marker_get_subframe_corners(plane_track, clip_frame, corners);
250
251 /* Compute a 2D projection matrix that projects from the corners of the image in normalized
252 * coordinates into the corners of the tracking plane. */
253 float3x3 homography_matrix;
254 float identity_corners[4][2] = {{0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 1.0f}};
256 corners, identity_corners, homography_matrix.ptr());
257
258 /* Store in a 4x4 matrix due to the alignment requirements of GPU uniform buffers. */
259 matrices[i] = float4x4(homography_matrix);
260 }
261
262 return matrices;
263 }
264
266 {
267 MovieClip *movie_clip = get_movie_clip();
268
269 if (!movie_clip) {
270 return nullptr;
271 }
272
274 &movie_clip->tracking, node_storage(bnode()).tracking_object);
275
276 if (!tracking_object) {
277 return nullptr;
278 }
279
281 node_storage(bnode()).plane_track_name);
282 }
283
285 {
287 BKE_movieclip_user_set_frame(&user, context().get_frame_number());
288
289 int2 size;
290 BKE_movieclip_get_size(get_movie_clip(), &user, &size.x, &size.y);
291 return size;
292 }
293
298
300 {
301 return static_cast<CMPNodePlaneTrackDeformFlags>(node_storage(bnode()).flag);
302 }
303
305 {
306 return reinterpret_cast<MovieClip *>(bnode().id);
307 }
308};
309
311{
312 return new PlaneTrackDeformOperation(context, node);
313}
314
315} // namespace blender::nodes::node_composite_planetrackdeform_cc
316
318{
320
321 static blender::bke::bNodeType ntype;
322
323 cmp_node_type_base(&ntype, CMP_NODE_PLANETRACKDEFORM, "Plane Track Deform", NODE_CLASS_DISTORT);
324 ntype.declare = file_ns::cmp_node_planetrackdeform_declare;
325 ntype.draw_buttons = file_ns::node_composit_buts_planetrackdeform;
326 ntype.initfunc_api = file_ns::init;
328 &ntype, "NodePlaneTrackDeformData", node_free_standard_storage, node_copy_standard_storage);
329 ntype.get_compositor_operation = file_ns::get_compositor_operation;
330
332}
Scene * CTX_data_scene(const bContext *C)
void id_us_plus(ID *id)
Definition lib_id.cc:351
float BKE_movieclip_remap_scene_to_clip_frame(const struct MovieClip *clip, float framenr)
void BKE_movieclip_user_set_frame(struct MovieClipUser *user, int framenr)
void BKE_movieclip_get_size(struct MovieClip *clip, const struct MovieClipUser *user, int *r_width, int *r_height)
#define NODE_STORAGE_FUNCS(StorageT)
Definition BKE_node.hh:1799
#define NODE_CLASS_DISTORT
Definition BKE_node.hh:412
struct MovieTrackingPlaneTrack * BKE_tracking_object_find_plane_track_with_name(struct MovieTrackingObject *tracking_object, const char *name)
Definition tracking.cc:2005
struct MovieTrackingObject * BKE_tracking_object_get_named(struct MovieTracking *tracking, const char *name)
Definition tracking.cc:1966
struct MovieTrackingObject * BKE_tracking_object_get_active(const struct MovieTracking *tracking)
void BKE_tracking_plane_marker_get_subframe_corners(struct MovieTrackingPlaneTrack *plane_track, float framenr, float corners[4][2])
Definition tracking.cc:1866
void BKE_tracking_homography_between_two_quads(float reference_corners[4][2], float corners[4][2], float H[3][3])
#define STRNCPY(dst, src)
Definition BLI_string.h:593
#define DNA_struct_default_get(struct_name)
CMPNodePlaneTrackDeformFlags
@ CMP_NODE_PLANE_TRACK_DEFORM_FLAG_MOTION_BLUR
void GPU_shader_uniform_1i(GPUShader *sh, const char *name, int value)
int GPU_shader_get_ubo_binding(GPUShader *shader, const char *name)
void GPU_shader_bind(GPUShader *shader)
void GPU_shader_unbind()
void GPU_texture_anisotropic_filter(GPUTexture *texture, bool use_aniso)
void GPU_texture_extend_mode(GPUTexture *texture, GPUSamplerExtendMode extend_mode)
@ GPU_SAMPLER_EXTEND_MODE_EXTEND
void GPU_texture_mipmap_mode(GPUTexture *texture, bool use_mipmap, bool use_filter)
GPUUniformBuf * GPU_uniformbuf_create_ex(size_t size, const void *data, const char *name)
void GPU_uniformbuf_unbind(GPUUniformBuf *ubo)
void GPU_uniformbuf_free(GPUUniformBuf *ubo)
void GPU_uniformbuf_bind(GPUUniformBuf *ubo, int slot)
#define UI_ITEM_NONE
void uiItemPointerR(uiLayout *layout, PointerRNA *ptr, const char *propname, PointerRNA *searchptr, const char *searchpropname, const char *name, int icon)
void uiTemplateID(uiLayout *layout, const bContext *C, PointerRNA *ptr, const char *propname, const char *newop, const char *openop, const char *unlinkop, int filter=UI_TEMPLATE_ID_FILTER_ALL, bool live_icon=false, const char *text=nullptr)
uiLayout * uiLayoutColumn(uiLayout *layout, bool align)
void uiItemR(uiLayout *layout, PointerRNA *ptr, const char *propname, eUI_Item_Flag flag, const char *name, int icon)
@ UI_ITEM_R_SPLIT_EMPTY_NAME
struct GPUShader GPUShader
void init()
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
int64_t size() const
Definition BLI_array.hh:245
const T * data() const
Definition BLI_array.hh:301
Result compute_plane_mask(const Array< float4x4 > &homography_matrices, GPUUniformBuf *homography_matrices_buffer)
void compute_plane(const Array< float4x4 > &homography_matrices, GPUUniformBuf *homography_matrices_buffer, Result &plane_mask)
GPUShader * get_shader(const char *info_name, ResultPrecision precision)
Result create_result(ResultType type, ResultPrecision precision)
NodeOperation(Context &context, DNode node)
Result & get_input(StringRef identifier) const
Definition operation.cc:144
Result & get_result(StringRef identifier)
Definition operation.cc:46
void bind_as_image(GPUShader *shader, const char *image_name, bool read=false) const
Definition result.cc:264
void pass_through(Result &target)
Definition result.cc:289
const Domain & domain() const
Definition result.cc:712
void set_float_value(float value)
Definition result.cc:467
void allocate_texture(Domain domain, bool from_pool=true)
Definition result.cc:204
void steal_data(Result &source)
Definition result.cc:304
void bind_as_texture(GPUShader *shader, const char *texture_name) const
Definition result.cc:253
local_group_size(16, 16) .push_constant(Type b
uint col
void node_type_storage(bNodeType *ntype, const char *storagename, void(*freefunc)(bNode *node), void(*copyfunc)(bNodeTree *dest_ntree, bNode *dest_node, const bNode *src_node))
Definition node.cc:4632
void node_register_type(bNodeType *ntype)
Definition node.cc:1708
static NodeOperation * get_compositor_operation(Context &context, DNode node)
static void cmp_node_planetrackdeform_declare(NodeDeclarationBuilder &b)
static void node_composit_buts_planetrackdeform(uiLayout *layout, bContext *C, PointerRNA *ptr)
void smaa(Context &context, Result &input, Result &output, float threshold=0.1f, float local_contrast_adaptation_factor=2.0f, int corner_rounding=25)
Definition smaa.cc:160
void compute_dispatch_threads_at_least(GPUShader *shader, int2 threads_range, int2 local_size=int2(16))
Definition utilities.cc:131
MatBase< float, 4, 4 > float4x4
void register_node_type_cmp_planetrackdeform()
void cmp_node_type_base(blender::bke::bNodeType *ntype, int type, const char *name, short nclass)
void node_free_standard_storage(bNode *node)
Definition node_util.cc:46
void node_copy_standard_storage(bNodeTree *, bNode *dest_node, const bNode *src_node)
Definition node_util.cc:58
PointerRNA RNA_pointer_create(ID *id, StructRNA *type, void *data)
struct MovieTracking tracking
MovieTrackingPlaneTrack * active_plane_track
void * data
Definition RNA_types.hh:42
struct ID * id
const c_style_mat & ptr() const
Defines a node type.
Definition BKE_node.hh:218
NodeGetCompositorOperationFunction get_compositor_operation
Definition BKE_node.hh:324
void(* draw_buttons)(uiLayout *, bContext *C, PointerRNA *ptr)
Definition BKE_node.hh:238
NodeDeclareFunction declare
Definition BKE_node.hh:347
void(* initfunc_api)(const bContext *C, PointerRNA *ptr)
Definition BKE_node.hh:280
PointerRNA * ptr
Definition wm_files.cc:4126