Compositor: Implement sampled motion blur for plane track deform node
Quite striaghtforward change, and in theory we can even try supporting motion blur for the corner pin node (which is tricky because coordinates actually coming from sockets, but with some black magic should be doable).
This commit is contained in:
parent
c69458985c
commit
1dddcfbaff
Notes:
blender-bot
2023-02-14 09:33:11 +01:00
Referenced by issue #43476, 2.73 crashes on startup
|
@ -542,4 +542,21 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
|
|||
part->child_flag |= PART_CHILD_USE_ROUGH_CURVE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!DNA_struct_elem_find(fd->filesdna, "NodePlaneTrackDeformData", "char", "flag")) {
|
||||
FOREACH_NODETREE(main, ntree, id) {
|
||||
if (ntree->type == NTREE_COMPOSIT) {
|
||||
bNode *node;
|
||||
for (node = ntree->nodes.first; node; node = node->next) {
|
||||
if (ELEM(node->type, CMP_NODE_PLANETRACKDEFORM)) {
|
||||
NodePlaneTrackDeformData *data = node->storage;
|
||||
data->flag = 0;
|
||||
data->motion_blur_samples = 16;
|
||||
data->motion_blur_shutter = 0.5f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
FOREACH_NODETREE_END
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,6 +54,10 @@ void PlaneTrackDeformNode::convertToOperations(NodeConverter &converter, const C
|
|||
warp_image_operation->setTrackingObject(data->tracking_object);
|
||||
warp_image_operation->setPlaneTrackName(data->plane_track_name);
|
||||
warp_image_operation->setFramenumber(frame_number);
|
||||
if (data->flag & CMP_NODEFLAG_PLANETRACKDEFORM_MOTION_BLUR) {
|
||||
warp_image_operation->setMotionBlurSamples(data->motion_blur_samples);
|
||||
warp_image_operation->setMotionBlurShutter(data->motion_blur_shutter);
|
||||
}
|
||||
converter.addOperation(warp_image_operation);
|
||||
|
||||
converter.mapInputSocket(input_image, warp_image_operation->getInputSocket(0));
|
||||
|
@ -64,6 +68,10 @@ void PlaneTrackDeformNode::convertToOperations(NodeConverter &converter, const C
|
|||
plane_mask_operation->setTrackingObject(data->tracking_object);
|
||||
plane_mask_operation->setPlaneTrackName(data->plane_track_name);
|
||||
plane_mask_operation->setFramenumber(frame_number);
|
||||
if (data->flag & CMP_NODEFLAG_PLANETRACKDEFORM_MOTION_BLUR) {
|
||||
plane_mask_operation->setMotionBlurSamples(data->motion_blur_samples);
|
||||
plane_mask_operation->setMotionBlurShutter(data->motion_blur_shutter);
|
||||
}
|
||||
converter.addOperation(plane_mask_operation);
|
||||
|
||||
converter.mapOutputSocket(output_plane, plane_mask_operation->getOutputSocket());
|
||||
|
|
|
@ -135,7 +135,7 @@ void *PlaneCornerPinMaskOperation::initializeTileData(rcti *rect)
|
|||
getInputSocketReader(3) };
|
||||
float corners[4][2];
|
||||
readCornersFromSockets(rect, readers, corners);
|
||||
calculateCorners(corners, true);
|
||||
calculateCorners(corners, true, 0);
|
||||
|
||||
m_corners_ready = true;
|
||||
}
|
||||
|
@ -194,8 +194,7 @@ void *PlaneCornerPinWarpImageOperation::initializeTileData(rcti *rect)
|
|||
getInputSocketReader(4) };
|
||||
float corners[4][2];
|
||||
readCornersFromSockets(rect, readers, corners);
|
||||
calculateCorners(corners, true);
|
||||
calculatePerspectiveMatrix();
|
||||
calculateCorners(corners, true, 0);
|
||||
|
||||
m_corners_ready = true;
|
||||
}
|
||||
|
|
|
@ -56,36 +56,38 @@ PlaneDistortWarpImageOperation::PlaneDistortWarpImageOperation() :
|
|||
this->addInputSocket(COM_DT_COLOR, COM_SC_NO_RESIZE);
|
||||
this->addOutputSocket(COM_DT_COLOR);
|
||||
this->m_pixelReader = NULL;
|
||||
this->m_motion_blur_samples = 1;
|
||||
this->m_motion_blur_shutter = 0.5f;
|
||||
this->setComplex(true);
|
||||
}
|
||||
|
||||
void PlaneDistortWarpImageOperation::calculateCorners(const float corners[4][2], bool normalized)
|
||||
{
|
||||
if (normalized) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
this->m_frameSpaceCorners[i][0] = corners[i][0] * this->getWidth();
|
||||
this->m_frameSpaceCorners[i][1] = corners[i][1] * this->getHeight();
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
this->m_frameSpaceCorners[i][0] = corners[i][0];
|
||||
this->m_frameSpaceCorners[i][1] = corners[i][1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PlaneDistortWarpImageOperation::calculatePerspectiveMatrix()
|
||||
void PlaneDistortWarpImageOperation::calculateCorners(const float corners[4][2],
|
||||
bool normalized,
|
||||
int sample)
|
||||
{
|
||||
BLI_assert(sample < this->m_motion_blur_samples);
|
||||
const int width = this->m_pixelReader->getWidth();
|
||||
const int height = this->m_pixelReader->getHeight();
|
||||
float frame_corners[4][2] = {{0.0f, 0.0f},
|
||||
{(float) width, 0.0f},
|
||||
{(float) width, (float) height},
|
||||
{0.0f, (float) height}};
|
||||
BKE_tracking_homography_between_two_quads(this->m_frameSpaceCorners,
|
||||
MotionSample *sample_data = &this->m_samples[sample];
|
||||
if (normalized) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
sample_data->frameSpaceCorners[i][0] = corners[i][0] * this->getWidth();
|
||||
sample_data->frameSpaceCorners[i][1] = corners[i][1] * this->getHeight();
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
sample_data->frameSpaceCorners[i][0] = corners[i][0];
|
||||
sample_data->frameSpaceCorners[i][1] = corners[i][1];
|
||||
}
|
||||
}
|
||||
BKE_tracking_homography_between_two_quads(sample_data->frameSpaceCorners,
|
||||
frame_corners,
|
||||
this->m_perspectiveMatrix);
|
||||
sample_data->perspectiveMatrix);
|
||||
}
|
||||
|
||||
void PlaneDistortWarpImageOperation::initExecution()
|
||||
|
@ -100,35 +102,47 @@ void PlaneDistortWarpImageOperation::deinitExecution()
|
|||
|
||||
void PlaneDistortWarpImageOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
|
||||
{
|
||||
float xy[2] = {x, y};
|
||||
float uv[2];
|
||||
float deriv[2][2];
|
||||
|
||||
pixelTransform(xy, uv, deriv);
|
||||
|
||||
m_pixelReader->readFiltered(output, uv[0], uv[1], deriv[0], deriv[1], COM_PS_BILINEAR);
|
||||
}
|
||||
|
||||
void PlaneDistortWarpImageOperation::pixelTransform(const float xy[2], float r_uv[2], float r_deriv[2][2])
|
||||
{
|
||||
warpCoord(xy[0], xy[1], m_perspectiveMatrix, r_uv, r_deriv);
|
||||
if (this->m_motion_blur_samples == 1) {
|
||||
warpCoord(x, y, this->m_samples[0].perspectiveMatrix, uv, deriv);
|
||||
m_pixelReader->readFiltered(output,
|
||||
uv[0], uv[1],
|
||||
deriv[0], deriv[1],
|
||||
COM_PS_BILINEAR);
|
||||
}
|
||||
else {
|
||||
zero_v4(output);
|
||||
for (int sample = 0; sample < this->m_motion_blur_samples; ++sample) {
|
||||
float color[4];
|
||||
warpCoord(x, y, this->m_samples[sample].perspectiveMatrix, uv, deriv);
|
||||
m_pixelReader->readFiltered(color,
|
||||
uv[0], uv[1],
|
||||
deriv[0], deriv[1],
|
||||
COM_PS_BILINEAR);
|
||||
add_v4_v4(output, color);
|
||||
}
|
||||
mul_v4_fl(output, 1.0f / (float)this->m_motion_blur_samples);
|
||||
}
|
||||
}
|
||||
|
||||
bool PlaneDistortWarpImageOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output)
|
||||
{
|
||||
float UVs[4][2];
|
||||
float deriv[2][2];
|
||||
|
||||
/* TODO(sergey): figure out proper way to do this. */
|
||||
warpCoord(input->xmin - 2, input->ymin - 2, this->m_perspectiveMatrix, UVs[0], deriv);
|
||||
warpCoord(input->xmax + 2, input->ymin - 2, this->m_perspectiveMatrix, UVs[1], deriv);
|
||||
warpCoord(input->xmax + 2, input->ymax + 2, this->m_perspectiveMatrix, UVs[2], deriv);
|
||||
warpCoord(input->xmin - 2, input->ymax + 2, this->m_perspectiveMatrix, UVs[3], deriv);
|
||||
|
||||
float min[2], max[2];
|
||||
INIT_MINMAX2(min, max);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
minmax_v2v2_v2(min, max, UVs[i]);
|
||||
|
||||
for (int sample = 0; sample < this->m_motion_blur_samples; ++sample) {
|
||||
float UVs[4][2];
|
||||
float deriv[2][2];
|
||||
MotionSample *sample_data = &this->m_samples[sample];
|
||||
/* TODO(sergey): figure out proper way to do this. */
|
||||
warpCoord(input->xmin - 2, input->ymin - 2, sample_data->perspectiveMatrix, UVs[0], deriv);
|
||||
warpCoord(input->xmax + 2, input->ymin - 2, sample_data->perspectiveMatrix, UVs[1], deriv);
|
||||
warpCoord(input->xmax + 2, input->ymax + 2, sample_data->perspectiveMatrix, UVs[2], deriv);
|
||||
warpCoord(input->xmin - 2, input->ymax + 2, sample_data->perspectiveMatrix, UVs[3], deriv);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
minmax_v2v2_v2(min, max, UVs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
rcti newInput;
|
||||
|
@ -151,20 +165,26 @@ PlaneDistortMaskOperation::PlaneDistortMaskOperation() :
|
|||
|
||||
/* Currently hardcoded to 8 samples. */
|
||||
m_osa = 8;
|
||||
this->m_motion_blur_samples = 1;
|
||||
this->m_motion_blur_shutter = 0.5f;
|
||||
}
|
||||
|
||||
void PlaneDistortMaskOperation::calculateCorners(const float corners[4][2], bool normalized)
|
||||
void PlaneDistortMaskOperation::calculateCorners(const float corners[4][2],
|
||||
bool normalized,
|
||||
int sample)
|
||||
{
|
||||
BLI_assert(sample < this->m_motion_blur_samples);
|
||||
MotionSample *sample_data = &this->m_samples[sample];
|
||||
if (normalized) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
this->m_frameSpaceCorners[i][0] = corners[i][0] * this->getWidth();
|
||||
this->m_frameSpaceCorners[i][1] = corners[i][1] * this->getHeight();
|
||||
sample_data->frameSpaceCorners[i][0] = corners[i][0] * this->getWidth();
|
||||
sample_data->frameSpaceCorners[i][1] = corners[i][1] * this->getHeight();
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
this->m_frameSpaceCorners[i][0] = corners[i][0];
|
||||
this->m_frameSpaceCorners[i][1] = corners[i][1];
|
||||
sample_data->frameSpaceCorners[i][0] = corners[i][0];
|
||||
sample_data->frameSpaceCorners[i][1] = corners[i][1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -177,18 +197,44 @@ void PlaneDistortMaskOperation::initExecution()
|
|||
void PlaneDistortMaskOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
|
||||
{
|
||||
float point[2];
|
||||
|
||||
int inside_counter = 0;
|
||||
for (int sample = 0; sample < this->m_osa; sample++) {
|
||||
point[0] = x + this->m_jitter[sample][0];
|
||||
point[1] = y + this->m_jitter[sample][1];
|
||||
|
||||
if (isect_point_tri_v2(point, this->m_frameSpaceCorners[0], this->m_frameSpaceCorners[1], this->m_frameSpaceCorners[2]) ||
|
||||
isect_point_tri_v2(point, this->m_frameSpaceCorners[0], this->m_frameSpaceCorners[2], this->m_frameSpaceCorners[3]))
|
||||
{
|
||||
inside_counter++;
|
||||
if (this->m_motion_blur_samples == 1) {
|
||||
MotionSample *sample_data = &this->m_samples[0];
|
||||
for (int sample = 0; sample < this->m_osa; sample++) {
|
||||
point[0] = x + this->m_jitter[sample][0];
|
||||
point[1] = y + this->m_jitter[sample][1];
|
||||
if (isect_point_tri_v2(point, sample_data->frameSpaceCorners[0],
|
||||
sample_data->frameSpaceCorners[1],
|
||||
sample_data->frameSpaceCorners[2]) ||
|
||||
isect_point_tri_v2(point, sample_data->frameSpaceCorners[0],
|
||||
sample_data->frameSpaceCorners[2],
|
||||
sample_data->frameSpaceCorners[3]))
|
||||
{
|
||||
inside_counter++;
|
||||
}
|
||||
}
|
||||
output[0] = (float)inside_counter / this->m_osa;
|
||||
}
|
||||
else {
|
||||
for (int motion_sample = 0;
|
||||
motion_sample < this->m_motion_blur_samples;
|
||||
++motion_sample)
|
||||
{
|
||||
MotionSample *sample_data = &this->m_samples[motion_sample];
|
||||
for (int osa_sample = 0; osa_sample < this->m_osa; ++osa_sample) {
|
||||
point[0] = x + this->m_jitter[osa_sample][0];
|
||||
point[1] = y + this->m_jitter[osa_sample][1];
|
||||
if (isect_point_tri_v2(point, sample_data->frameSpaceCorners[0],
|
||||
sample_data->frameSpaceCorners[1],
|
||||
sample_data->frameSpaceCorners[2]) ||
|
||||
isect_point_tri_v2(point, sample_data->frameSpaceCorners[0],
|
||||
sample_data->frameSpaceCorners[2],
|
||||
sample_data->frameSpaceCorners[3]))
|
||||
{
|
||||
inside_counter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
output[0] = (float)inside_counter / (this->m_osa * this->m_motion_blur_samples);
|
||||
}
|
||||
|
||||
output[0] = (float) inside_counter / this->m_osa;
|
||||
}
|
||||
|
|
|
@ -33,43 +33,68 @@
|
|||
#include "BLI_listbase.h"
|
||||
#include "BLI_string.h"
|
||||
|
||||
#define PLANE_DISTORT_MAX_SAMPLES 64
|
||||
|
||||
class PlaneDistortWarpImageOperation : public NodeOperation {
|
||||
protected:
|
||||
struct MotionSample {
|
||||
float frameSpaceCorners[4][2]; /* Corners coordinates in pixel space. */
|
||||
float perspectiveMatrix[3][3];
|
||||
};
|
||||
SocketReader *m_pixelReader;
|
||||
float m_frameSpaceCorners[4][2]; /* Corners coordinates in pixel space. */
|
||||
float m_perspectiveMatrix[3][3];
|
||||
MotionSample m_samples[PLANE_DISTORT_MAX_SAMPLES];
|
||||
int m_motion_blur_samples;
|
||||
float m_motion_blur_shutter;
|
||||
|
||||
public:
|
||||
PlaneDistortWarpImageOperation();
|
||||
|
||||
void calculateCorners(const float corners[4][2], bool normalized);
|
||||
void calculatePerspectiveMatrix();
|
||||
void calculateCorners(const float corners[4][2],
|
||||
bool normalized,
|
||||
int sample);
|
||||
|
||||
void initExecution();
|
||||
void deinitExecution();
|
||||
|
||||
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
|
||||
void pixelTransform(const float xy[2], float r_uv[2], float r_deriv[2][2]);
|
||||
|
||||
bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output);
|
||||
|
||||
void setMotionBlurSamples(int samples) {
|
||||
BLI_assert(samples <= PLANE_DISTORT_MAX_SAMPLES);
|
||||
this->m_motion_blur_samples = samples;
|
||||
}
|
||||
void setMotionBlurShutter(float shutter) { this->m_motion_blur_shutter = shutter; }
|
||||
};
|
||||
|
||||
|
||||
class PlaneDistortMaskOperation : public NodeOperation {
|
||||
protected:
|
||||
struct MotionSample {
|
||||
float frameSpaceCorners[4][2]; /* Corners coordinates in pixel space. */
|
||||
};
|
||||
int m_osa;
|
||||
MotionSample m_samples[PLANE_DISTORT_MAX_SAMPLES];
|
||||
float m_jitter[32][2];
|
||||
float m_frameSpaceCorners[4][2]; /* Corners coordinates in pixel space. */
|
||||
int m_motion_blur_samples;
|
||||
float m_motion_blur_shutter;
|
||||
|
||||
public:
|
||||
PlaneDistortMaskOperation();
|
||||
|
||||
void calculateCorners(const float corners[4][2], bool normalized);
|
||||
void calculateCorners(const float corners[4][2],
|
||||
bool normalized,
|
||||
int sample);
|
||||
|
||||
void initExecution();
|
||||
|
||||
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
|
||||
|
||||
void setMotionBlurSamples(int samples) {
|
||||
BLI_assert(samples <= PLANE_DISTORT_MAX_SAMPLES);
|
||||
this->m_motion_blur_samples = samples;
|
||||
}
|
||||
void setMotionBlurShutter(float shutter) { this->m_motion_blur_shutter = shutter; }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -46,7 +46,7 @@ PlaneTrackCommon::PlaneTrackCommon()
|
|||
this->m_planeTrackName[0] = '\0';
|
||||
}
|
||||
|
||||
void PlaneTrackCommon::readCornersFromTrack(float corners[4][2])
|
||||
void PlaneTrackCommon::readCornersFromTrack(float corners[4][2], float frame)
|
||||
{
|
||||
MovieTracking *tracking;
|
||||
MovieTrackingObject *object;
|
||||
|
@ -64,13 +64,13 @@ void PlaneTrackCommon::readCornersFromTrack(float corners[4][2])
|
|||
|
||||
if (plane_track) {
|
||||
MovieTrackingPlaneMarker *plane_marker;
|
||||
int clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(this->m_movieClip, this->m_framenumber);
|
||||
|
||||
float clip_framenr =
|
||||
BKE_movieclip_remap_scene_to_clip_frame(this->m_movieClip,
|
||||
frame);
|
||||
plane_marker = BKE_tracking_plane_marker_get(plane_track, clip_framenr);
|
||||
copy_v2_v2(corners[0], plane_marker->corners[0]);
|
||||
copy_v2_v2(corners[1], plane_marker->corners[1]);
|
||||
copy_v2_v2(corners[2], plane_marker->corners[2]);
|
||||
copy_v2_v2(corners[3], plane_marker->corners[3]);
|
||||
BKE_tracking_plane_marker_get_subframe_corners(plane_track,
|
||||
clip_framenr,
|
||||
corners);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -98,10 +98,21 @@ void PlaneTrackCommon::determineResolution(unsigned int resolution[2], unsigned
|
|||
void PlaneTrackMaskOperation::initExecution()
|
||||
{
|
||||
PlaneDistortMaskOperation::initExecution();
|
||||
|
||||
float corners[4][2];
|
||||
readCornersFromTrack(corners);
|
||||
calculateCorners(corners, true);
|
||||
if (this->m_motion_blur_samples == 1) {
|
||||
readCornersFromTrack(corners, this->m_framenumber);
|
||||
calculateCorners(corners, true, 0);
|
||||
}
|
||||
else {
|
||||
const float frame = (float)this->m_framenumber - this->m_motion_blur_shutter;
|
||||
const float frame_step = (this->m_motion_blur_shutter * 2.0f) / this->m_motion_blur_samples;
|
||||
float frame_iter = frame;
|
||||
for (int sample = 0; sample < this->m_motion_blur_samples; ++sample) {
|
||||
readCornersFromTrack(corners, frame_iter);
|
||||
calculateCorners(corners, true, sample);
|
||||
frame_iter += frame_step;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ******** PlaneTrackWarpImageOperation ******** */
|
||||
|
@ -109,9 +120,20 @@ void PlaneTrackMaskOperation::initExecution()
|
|||
void PlaneTrackWarpImageOperation::initExecution()
|
||||
{
|
||||
PlaneDistortWarpImageOperation::initExecution();
|
||||
|
||||
/* TODO(sergey): De-duplicate with mask operation. */
|
||||
float corners[4][2];
|
||||
readCornersFromTrack(corners);
|
||||
calculateCorners(corners, true);
|
||||
calculatePerspectiveMatrix();
|
||||
if (this->m_motion_blur_samples == 1) {
|
||||
readCornersFromTrack(corners, this->m_framenumber);
|
||||
calculateCorners(corners, true, 0);
|
||||
}
|
||||
else {
|
||||
const float frame = (float)this->m_framenumber - this->m_motion_blur_shutter;
|
||||
const float frame_step = (this->m_motion_blur_shutter * 2.0f) / this->m_motion_blur_samples;
|
||||
float frame_iter = frame;
|
||||
for (int sample = 0; sample < this->m_motion_blur_samples; ++sample) {
|
||||
readCornersFromTrack(corners, frame_iter);
|
||||
calculateCorners(corners, true, sample);
|
||||
frame_iter += frame_step;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ protected:
|
|||
/* note: this class is not an operation itself (to prevent virtual inheritance issues)
|
||||
* implementation classes must make wrappers to use these methods, see below.
|
||||
*/
|
||||
void readCornersFromTrack(float corners[4][2]);
|
||||
void readCornersFromTrack(float corners[4][2], float frame);
|
||||
void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
|
||||
|
||||
public:
|
||||
|
|
|
@ -2314,6 +2314,7 @@ static void node_composit_buts_trackpos(uiLayout *layout, bContext *C, PointerRN
|
|||
static void node_composit_buts_planetrackdeform(uiLayout *layout, bContext *C, PointerRNA *ptr)
|
||||
{
|
||||
bNode *node = ptr->data;
|
||||
NodePlaneTrackDeformData *data = node->storage;
|
||||
|
||||
uiTemplateID(layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL);
|
||||
|
||||
|
@ -2342,6 +2343,12 @@ static void node_composit_buts_planetrackdeform(uiLayout *layout, bContext *C, P
|
|||
uiItemR(layout, ptr, "plane_track_name", 0, "", ICON_ANIM_DATA);
|
||||
}
|
||||
}
|
||||
|
||||
uiItemR(layout, ptr, "use_motion_blur", 0, NULL, ICON_NONE);
|
||||
if (data->flag & CMP_NODEFLAG_PLANETRACKDEFORM_MOTION_BLUR) {
|
||||
uiItemR(layout, ptr, "motion_blur_samples", 0, NULL, ICON_NONE);
|
||||
uiItemR(layout, ptr, "motion_blur_shutter", 0, NULL, ICON_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
static void node_composit_buts_cornerpin(uiLayout *UNUSED(layout), bContext *UNUSED(C), PointerRNA *UNUSED(ptr))
|
||||
|
|
|
@ -825,6 +825,10 @@ typedef struct NodeTranslateData {
|
|||
typedef struct NodePlaneTrackDeformData {
|
||||
char tracking_object[64];
|
||||
char plane_track_name[64];
|
||||
char flag;
|
||||
char motion_blur_samples;
|
||||
char pad[2];
|
||||
float motion_blur_shutter;
|
||||
} NodePlaneTrackDeformData;
|
||||
|
||||
typedef struct NodeShaderScript {
|
||||
|
@ -1080,4 +1084,11 @@ enum {
|
|||
/* viewer and cmposite output */
|
||||
#define CMP_NODE_OUTPUT_IGNORE_ALPHA 1
|
||||
|
||||
/* Plane track deform node */
|
||||
enum {
|
||||
CMP_NODEFLAG_PLANETRACKDEFORM_MOTION_BLUR = 1,
|
||||
};
|
||||
|
||||
#define CMP_NODE_PLANETRACKDEFORM_MBLUR_SAMPLES_MAX 64
|
||||
|
||||
#endif
|
||||
|
|
|
@ -6231,6 +6231,21 @@ static void def_cmp_planetrackdeform(StructRNA *srna)
|
|||
RNA_def_property_string_sdna(prop, NULL, "plane_track_name");
|
||||
RNA_def_property_ui_text(prop, "Plane Track", "");
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
|
||||
|
||||
prop = RNA_def_property(srna, "use_motion_blur", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", CMP_NODEFLAG_PLANETRACKDEFORM_MOTION_BLUR);
|
||||
RNA_def_property_ui_text(prop, "Motion Blur", "Use multi-sampled motion blur of the mask");
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
|
||||
|
||||
prop = RNA_def_property(srna, "motion_blur_samples", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_range(prop, 1, CMP_NODE_PLANETRACKDEFORM_MBLUR_SAMPLES_MAX);
|
||||
RNA_def_property_ui_text(prop, "Samples", "Number of motion blur samples");
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
|
||||
|
||||
prop = RNA_def_property(srna, "motion_blur_shutter", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_range(prop, 0.0, 1.0f);
|
||||
RNA_def_property_ui_text(prop, "Shutter", "Exposure for motion blur as a factor of FPS");
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
|
||||
}
|
||||
|
||||
static void def_cmp_sunbeams(StructRNA *srna)
|
||||
|
|
|
@ -47,7 +47,8 @@ static bNodeSocketTemplate cmp_node_planetrackdeform_out[] = {
|
|||
static void init(bNodeTree *UNUSED(ntree), bNode *node)
|
||||
{
|
||||
NodePlaneTrackDeformData *data = MEM_callocN(sizeof(NodePlaneTrackDeformData), "node plane track deform data");
|
||||
|
||||
data->motion_blur_samples = 16;
|
||||
data->motion_blur_shutter = 0.5f;
|
||||
node->storage = data;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue