Files
test2/source/blender/sequencer/intern/modifiers/MOD_mask.cc
Aras Pranckevicius 1973bad86c Fix #147636: VSE compositor modifier output translation has no effect
The final image produced by the compositor can have domain translation
on it (e.g. caused by a Translate or Transform node). Similar to how
the regular compositor viewer node remembers the output domain
translation, do the same in the compositor modifier.

Bubble back that translation up to VSE rendering code, where it is
then added to regular strip transform.

In order to make this "bubble up" part easier, refactored modifiers
so that instead of soup of parameters they all get a struct
ModifierApplyContext with all the relevant data.

Added a new VSE render test that covers various compositor
transformation nodes (translate, rotate, transform, corner pin).

Pull Request: https://projects.blender.org/blender/blender/pulls/147695
2025-10-09 18:36:44 +02:00

100 lines
2.7 KiB
C++

/* SPDX-FileCopyrightText: 2025 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup sequencer
*/
#include "BLI_math_base.h"
#include "BLI_math_matrix.hh"
#include "BLT_translation.hh"
#include "DNA_scene_types.h"
#include "DNA_sequence_types.h"
#include "SEQ_modifier.hh"
#include "SEQ_render.hh"
#include "SEQ_transform.hh"
#include "UI_interface.hh"
#include "UI_interface_layout.hh"
#include "modifier.hh"
namespace blender::seq {
struct MaskApplyOp {
template<typename ImageT, typename MaskSampler>
void apply(ImageT *image, MaskSampler &mask, int image_x, IndexRange y_range)
{
image += y_range.first() * image_x * 4;
for (int64_t y : y_range) {
mask.begin_row(y);
for ([[maybe_unused]] int64_t x : IndexRange(image_x)) {
float m = mask.load_mask_min();
if constexpr (std::is_same_v<ImageT, uchar>) {
/* Byte buffer is straight, so only affect on alpha itself, this is
* the only way to alpha-over byte strip after applying mask modifier. */
image[3] = uchar(image[3] * m);
}
else if constexpr (std::is_same_v<ImageT, float>) {
/* Float buffers are premultiplied, so need to premul color as well to make it
* easy to alpha-over masked strip. */
float4 pix(image);
pix *= m;
*reinterpret_cast<float4 *>(image) = pix;
}
image += 4;
}
}
}
};
static void maskmodifier_apply(ModifierApplyContext &context,
StripModifierData * /*smd*/,
ImBuf *mask)
{
if (mask == nullptr || (mask->byte_buffer.data == nullptr && mask->float_buffer.data == nullptr))
{
return;
}
MaskApplyOp op;
apply_modifier_op(op, context.image, mask, context.transform);
/* Image has gained transparency. */
context.image->planes = R_IMF_PLANES_RGBA;
}
static void maskmodifier_panel_draw(const bContext *C, Panel *panel)
{
uiLayout *layout = panel->layout;
PointerRNA *ptr = UI_panel_custom_data_get(panel);
draw_mask_input_type_settings(C, layout, ptr);
}
static void maskmodifier_register(ARegionType *region_type)
{
modifier_panel_register(region_type, eSeqModifierType_Mask, maskmodifier_panel_draw);
}
StripModifierTypeInfo seqModifierType_Mask = {
/*idname*/ "Mask",
/*name*/ CTX_N_(BLT_I18NCONTEXT_ID_SEQUENCE, "Mask"),
/*struct_name*/ "SequencerMaskModifierData",
/*struct_size*/ sizeof(SequencerMaskModifierData),
/*init_data*/ nullptr,
/*free_data*/ nullptr,
/*copy_data*/ nullptr,
/*apply*/ maskmodifier_apply,
/*panel_register*/ maskmodifier_register,
/*blend_write*/ nullptr,
/*blend_read*/ nullptr,
};
}; // namespace blender::seq