blur: implement radial and directional blur methods

This commit is contained in:
itsmattkc
2022-05-08 16:53:04 -07:00
parent bdb917c591
commit f910117a58
10 changed files with 270 additions and 52 deletions
+108 -11
View File
@@ -29,25 +29,50 @@ const QString BlurFilterNode::kHorizInput = QStringLiteral("horiz_in");
const QString BlurFilterNode::kVertInput = QStringLiteral("vert_in");
const QString BlurFilterNode::kRepeatEdgePixelsInput = QStringLiteral("repeat_edge_pixels_in");
const QString BlurFilterNode::kDirectionalDegreesInput = QStringLiteral("directional_degrees_in");
const QString BlurFilterNode::kRadialCenterInput = QStringLiteral("radial_center_in");
#define super Node
BlurFilterNode::BlurFilterNode()
{
AddInput(kTextureInput, NodeValue::kTexture, InputFlags(kInputFlagNotKeyframable));
AddInput(kMethodInput, NodeValue::kCombo, 1); // Default to gaussian
Method default_method = kGaussian;
AddInput(kMethodInput, NodeValue::kCombo, default_method, InputFlags(kInputFlagNotKeyframable | kInputFlagNotConnectable));
AddInput(kRadiusInput, NodeValue::kFloat, 10.0);
SetInputProperty(kRadiusInput, QStringLiteral("min"), 0.0);
AddInput(kHorizInput, NodeValue::kBoolean, true);
{
// Box and gaussian only
AddInput(kHorizInput, NodeValue::kBoolean, true);
AddInput(kVertInput, NodeValue::kBoolean, true);
}
AddInput(kVertInput, NodeValue::kBoolean, true);
{
// Directional only
AddInput(kDirectionalDegreesInput, NodeValue::kFloat, 0.0);
}
{
// Radial only
AddInput(kRadialCenterInput, NodeValue::kVec2, QVector2D(0, 0));
}
UpdateInputs(default_method);
AddInput(kRepeatEdgePixelsInput, NodeValue::kBoolean, true);
SetFlags(kVideoEffect);
SetEffectInput(kTextureInput);
radial_center_gizmo_ = AddDraggableGizmo<PointGizmo>();
radial_center_gizmo_->SetShape(PointGizmo::kAnchorPoint);
radial_center_gizmo_->AddInput(NodeKeyframeTrackReference(NodeInput(this, kRadialCenterInput), 0));
radial_center_gizmo_->AddInput(NodeKeyframeTrackReference(NodeInput(this, kRadialCenterInput), 1));
}
QString BlurFilterNode::Name() const
@@ -76,11 +101,14 @@ void BlurFilterNode::Retranslate()
SetInputName(kTextureInput, tr("Input"));
SetInputName(kMethodInput, tr("Method"));
SetComboBoxStrings(kMethodInput, { tr("Box"), tr("Gaussian") });
SetComboBoxStrings(kMethodInput, { tr("Box"), tr("Gaussian"), tr("Directional"), tr("Radial") });
SetInputName(kRadiusInput, tr("Radius"));
SetInputName(kHorizInput, tr("Horizontal"));
SetInputName(kVertInput, tr("Vertical"));
SetInputName(kRepeatEdgePixelsInput, tr("Repeat Edge Pixels"));
SetInputName(kDirectionalDegreesInput, tr("Direction"));
SetInputName(kRadialCenterInput, tr("Center"));
}
ShaderCode BlurFilterNode::GetShaderCode(const ShaderRequest &request) const
@@ -96,25 +124,47 @@ void BlurFilterNode::Value(const NodeValueRow &value, const NodeGlobals &globals
job.InsertValue(value);
job.InsertValue(QStringLiteral("resolution_in"), NodeValue(NodeValue::kVec2, globals.resolution(), this));
Method method = static_cast<Method>(job.GetValue(kMethodInput).data().toInt());
// If there's no texture, no need to run an operation
if (!job.GetValue(kTextureInput).data().isNull()) {
// Check if radius > 0, and both "horiz" and/or "vert" are enabled
if ((job.GetValue(kHorizInput).data().toBool() || job.GetValue(kVertInput).data().toBool())
&& job.GetValue(kRadiusInput).data().toDouble() > 0.0) {
bool can_push_job = true;
// Set iteration count to 2 if we're blurring both horizontally and vertically
if (job.GetValue(kHorizInput).data().toBool() && job.GetValue(kVertInput).data().toBool()) {
job.SetIterations(2, kTextureInput);
// Check if radius is > 0
if (job.GetValue(kRadiusInput).data().toDouble() > 0.0) {
// Method-specific considerations
switch (method) {
case kBox:
case kGaussian:
{
bool horiz = job.GetValue(kHorizInput).data().toBool();
bool vert = job.GetValue(kVertInput).data().toBool();
if (!horiz && !vert) {
// Disable job if horiz and vert are unchecked
can_push_job = false;
} else if (horiz && vert) {
// Set iteration count to 2 if we're blurring both horizontally and vertically
job.SetIterations(2, kTextureInput);
}
break;
}
case kDirectional:
case kRadial:
break;
}
} else {
can_push_job = false;
}
if (can_push_job) {
// If we're not repeating pixels, expect an alpha channel to appear
if (!job.GetValue(kRepeatEdgePixelsInput).data().toBool()) {
job.SetAlphaChannelRequired(GenerateJob::kAlphaForceOn);
}
table->Push(NodeValue::kTexture, QVariant::fromValue(job), this);
} else {
// If we're not performing the blur job, just push the texture
table->Push(job.GetValue(kTextureInput));
@@ -123,4 +173,51 @@ void BlurFilterNode::Value(const NodeValueRow &value, const NodeGlobals &globals
}
}
void BlurFilterNode::UpdateGizmoPositions(const NodeValueRow &row, const NodeGlobals &globals)
{
if (row[kMethodInput].data().toInt() == kRadial) {
const QVector2D &sequence_res = globals.resolution();
QVector2D sequence_half_res = sequence_res * 0.5;
radial_center_gizmo_->SetVisible(true);
radial_center_gizmo_->SetPoint(sequence_half_res.toPointF() + row[kRadialCenterInput].value<QVector2D>().toPointF());
SetInputProperty(kRadialCenterInput, QStringLiteral("offset"), sequence_half_res);
} else{
radial_center_gizmo_->SetVisible(false);
}
}
void BlurFilterNode::GizmoDragMove(double x, double y, const Qt::KeyboardModifiers &modifiers)
{
DraggableGizmo *gizmo = static_cast<DraggableGizmo*>(sender());
if (gizmo == radial_center_gizmo_) {
NodeInputDragger &x_drag = gizmo->GetDraggers()[0];
NodeInputDragger &y_drag = gizmo->GetDraggers()[1];
x_drag.Drag(x_drag.GetStartValue().toDouble() + x);
y_drag.Drag(y_drag.GetStartValue().toDouble() + y);
}
}
void BlurFilterNode::InputValueChangedEvent(const QString &input, int element)
{
if (input == kMethodInput) {
UpdateInputs(GetMethod());
}
super::InputValueChangedEvent(input, element);
}
void BlurFilterNode::UpdateInputs(Method method)
{
SetInputFlags(kHorizInput, (method == kBox || method == kGaussian) ? InputFlags() : InputFlags(kInputFlagHidden));
SetInputFlags(kVertInput, (method == kBox || method == kGaussian) ? InputFlags() : InputFlags(kInputFlagHidden));
SetInputFlags(kDirectionalDegreesInput, (method == kDirectional) ? InputFlags() : InputFlags(kInputFlagHidden));
SetInputFlags(kRadialCenterInput, (method == kRadial) ? InputFlags() : InputFlags(kInputFlagHidden));
}
}
+30
View File
@@ -21,6 +21,7 @@
#ifndef BLURFILTERNODE_H
#define BLURFILTERNODE_H
#include "node/gizmo/point.h"
#include "node/node.h"
namespace olive {
@@ -31,6 +32,13 @@ class BlurFilterNode : public Node
public:
BlurFilterNode();
enum Method {
kBox,
kGaussian,
kDirectional,
kRadial
};
NODE_DEFAULT_FUNCTIONS(BlurFilterNode)
virtual QString Name() const override;
@@ -43,6 +51,13 @@ public:
virtual ShaderCode GetShaderCode(const ShaderRequest &request) const override;
virtual void Value(const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override;
Method GetMethod() const
{
return static_cast<Method>(GetStandardValue(kMethodInput).toInt());
}
virtual void UpdateGizmoPositions(const NodeValueRow &row, const NodeGlobals &globals) override;
static const QString kTextureInput;
static const QString kMethodInput;
static const QString kRadiusInput;
@@ -50,6 +65,21 @@ public:
static const QString kVertInput;
static const QString kRepeatEdgePixelsInput;
static const QString kDirectionalDegreesInput;
static const QString kRadialCenterInput;
protected slots:
virtual void GizmoDragMove(double x, double y, const Qt::KeyboardModifiers &modifiers) override;
protected:
virtual void InputValueChangedEvent(const QString& input, int element) override;
private:
void UpdateInputs(Method method);
PointGizmo *radial_center_gizmo_;
};
}
+2 -1
View File
@@ -22,7 +22,8 @@
namespace olive {
NodeGizmo::NodeGizmo(QObject *parent)
NodeGizmo::NodeGizmo(QObject *parent) :
visible_(true)
{
setParent(parent);
}
+5
View File
@@ -39,11 +39,16 @@ public:
const NodeGlobals &GetGlobals() const { return globals_; }
void SetGlobals(const NodeGlobals &globals) { globals_ = globals; }
bool IsVisible() const { return visible_; }
void SetVisible(bool e) { visible_ = e; }
signals:
private:
NodeGlobals globals_;
bool visible_;
};
}
+1
View File
@@ -917,6 +917,7 @@ void Node::SetInputFlags(const QString &input, const InputFlags &f)
if (i) {
i->flags = f;
emit InputFlagsChanged(input, i->flags);
} else {
ReportInvalidInput("set flags of", input);
}
+2
View File
@@ -1168,6 +1168,8 @@ signals:
void NodeRemovedFromContext(Node *node);
void InputFlagsChanged(const QString &input, const InputFlags &flags);
private:
class ArrayInsertCommand : public UndoCommand
{