blur: merged box and gaussian blurs into one node
While these are two separate blur effects, merging them into one node will allow quick swapping of blur methods.
This commit is contained in:
@@ -47,8 +47,7 @@ void NodeFactory::Initialize()
|
||||
library_.append(CreateInternal(static_cast<InternalID>(i)));
|
||||
}
|
||||
|
||||
library_.append(new ExternalNode(":/shaders/gaussianblur.xml"));
|
||||
library_.append(new ExternalNode(":/shaders/boxblur.xml"));
|
||||
library_.append(new ExternalNode(":/shaders/blur.xml"));
|
||||
library_.append(new ExternalNode(":/shaders/opacity.xml"));
|
||||
library_.append(new ExternalNode(":/shaders/solid.xml"));
|
||||
library_.append(new ExternalNode(":/shaders/stroke.xml"));
|
||||
@@ -60,9 +59,7 @@ void NodeFactory::Initialize()
|
||||
|
||||
void NodeFactory::Destroy()
|
||||
{
|
||||
foreach (Node* n, library_) {
|
||||
delete n;
|
||||
}
|
||||
qDeleteAll(library_);
|
||||
library_.clear();
|
||||
}
|
||||
|
||||
|
||||
+108
-69
@@ -22,6 +22,7 @@
|
||||
|
||||
#include <QFile>
|
||||
|
||||
#include "common/xmlutils.h"
|
||||
#include "config/config.h"
|
||||
#include "node.h"
|
||||
|
||||
@@ -37,11 +38,11 @@ NodeMetaReader::NodeMetaReader(const QString &xml_meta_filename) :
|
||||
if (metadata_file.open(QFile::ReadOnly)) {
|
||||
QXmlStreamReader reader(&metadata_file);
|
||||
|
||||
while (!reader.atEnd()) {
|
||||
reader.readNext();
|
||||
|
||||
if (reader.isStartElement() && reader.name() == "effect") {
|
||||
while (XMLReadNextStartElement(&reader)) {
|
||||
if (reader.name() == QStringLiteral("effect")) {
|
||||
XMLReadEffect(&reader);
|
||||
} else {
|
||||
reader.skipCurrentElement();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,23 +104,42 @@ const QList<NodeInput *> &NodeMetaReader::inputs() const
|
||||
|
||||
void NodeMetaReader::Retranslate()
|
||||
{
|
||||
QMap<QString, QMap<QString, QString> >::const_iterator iterator;
|
||||
{
|
||||
// Re-translate every parameter name
|
||||
QMap<QString, LanguageMap>::const_iterator iterator;
|
||||
|
||||
// Iterate through parameter language tables that we have
|
||||
for (iterator=param_names_.begin();iterator!=param_names_.end();iterator++) {
|
||||
NodeInput* this_input = GetInputWithID(iterator.key());
|
||||
this_input->set_name(GetStringForCurrentLanguage(&iterator.value()));
|
||||
// Iterate through parameter language tables that we have
|
||||
for (iterator=param_names_.begin();iterator!=param_names_.end();iterator++) {
|
||||
NodeInput* this_input = GetInputWithID(iterator.key());
|
||||
this_input->set_name(GetStringForCurrentLanguage(&iterator.value()));
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// Re-translate any combobox items
|
||||
QMap<QString, QList<LanguageMap> >::const_iterator param_it;
|
||||
|
||||
for (param_it=combo_names_.begin(); param_it!=combo_names_.end(); param_it++) {
|
||||
NodeInput* input = GetInputWithID(param_it.key());
|
||||
|
||||
QStringList combo_items;
|
||||
|
||||
foreach (const LanguageMap& lang_map, param_it.value()) {
|
||||
combo_items.append(GetStringForCurrentLanguage(&lang_map));
|
||||
}
|
||||
|
||||
input->set_combobox_strings(combo_items);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NodeMetaReader::XMLReadLanguageString(QXmlStreamReader* reader, QMap<QString, QString>* map)
|
||||
void NodeMetaReader::XMLReadLanguageString(QXmlStreamReader* reader, LanguageMap* map)
|
||||
{
|
||||
QString lang;
|
||||
|
||||
// Traverse through name attributes for its language
|
||||
QXmlStreamAttributes attrs = reader->attributes();
|
||||
foreach (const QXmlStreamAttribute& attr, attrs) {
|
||||
if (attr.name() == "lang") {
|
||||
XMLAttributeLoop(reader, attr) {
|
||||
if (attr.name() == QStringLiteral("lang")) {
|
||||
lang = attr.value().toString();
|
||||
|
||||
// We don't recognize any other "name" attributes at this time
|
||||
@@ -134,9 +154,8 @@ void NodeMetaReader::XMLReadLanguageString(QXmlStreamReader* reader, QMap<QStrin
|
||||
void NodeMetaReader::XMLReadEffect(QXmlStreamReader* reader)
|
||||
{
|
||||
// Traverse through effect attributes for an ID
|
||||
QXmlStreamAttributes attrs = reader->attributes();
|
||||
foreach (const QXmlStreamAttribute& attr, attrs) {
|
||||
if (attr.name() == "id") {
|
||||
XMLAttributeLoop(reader, attr) {
|
||||
if (attr.name() == QStringLiteral("id")) {
|
||||
id_ = attr.value().toString();
|
||||
|
||||
// We don't recognize any other "effect" attributes at this time
|
||||
@@ -150,32 +169,30 @@ void NodeMetaReader::XMLReadEffect(QXmlStreamReader* reader)
|
||||
}
|
||||
|
||||
// Continue reading for other metadata
|
||||
while (!reader->atEnd() && !(reader->isEndElement() && reader->name() == "effect")) {
|
||||
reader->readNext();
|
||||
|
||||
if (reader->isStartElement()) {
|
||||
if (reader->name() == "name") {
|
||||
// Pick up name
|
||||
XMLReadLanguageString(reader, &names_);
|
||||
} else if (reader->name() == "category") {
|
||||
// Pick up category
|
||||
XMLReadLanguageString(reader, &categories_);
|
||||
} else if (reader->name() == "description") {
|
||||
// Pick up description
|
||||
XMLReadLanguageString(reader, &descriptions_);
|
||||
} else if (reader->name() == "iterations") {
|
||||
// Pick up iterations
|
||||
XMLReadIterations(reader);
|
||||
} else if (reader->name() == "fragment") {
|
||||
// Pick up fragment shader code
|
||||
XMLReadShader(reader, frag_code_);
|
||||
} else if (reader->name() == "vertex") {
|
||||
// Pick up vertex shader code
|
||||
XMLReadShader(reader, vert_code_);
|
||||
} else if (reader->name() == "param") {
|
||||
// Pick up a parameter
|
||||
XMLReadParam(reader);
|
||||
}
|
||||
while (XMLReadNextStartElement(reader)) {
|
||||
if (reader->name() == QStringLiteral("name")) {
|
||||
// Pick up name
|
||||
XMLReadLanguageString(reader, &names_);
|
||||
} else if (reader->name() == QStringLiteral("category")) {
|
||||
// Pick up category
|
||||
XMLReadLanguageString(reader, &categories_);
|
||||
} else if (reader->name() == QStringLiteral("description")) {
|
||||
// Pick up description
|
||||
XMLReadLanguageString(reader, &descriptions_);
|
||||
} else if (reader->name() == QStringLiteral("iterations")) {
|
||||
// Pick up iterations
|
||||
XMLReadIterations(reader);
|
||||
} else if (reader->name() == QStringLiteral("fragment")) {
|
||||
// Pick up fragment shader code
|
||||
XMLReadShader(reader, frag_code_);
|
||||
} else if (reader->name() == QStringLiteral("vertex")) {
|
||||
// Pick up vertex shader code
|
||||
XMLReadShader(reader, vert_code_);
|
||||
} else if (reader->name() == QStringLiteral("param")) {
|
||||
// Pick up a parameter
|
||||
XMLReadParam(reader);
|
||||
} else {
|
||||
reader->skipCurrentElement();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -199,13 +216,12 @@ void NodeMetaReader::XMLReadParam(QXmlStreamReader *reader)
|
||||
bool is_iterative = false;
|
||||
|
||||
// Traverse through parameter attributes for an ID
|
||||
QXmlStreamAttributes attrs = reader->attributes();
|
||||
foreach (const QXmlStreamAttribute& attr, attrs) {
|
||||
if (attr.name() == "id") {
|
||||
XMLAttributeLoop(reader, attr) {
|
||||
if (attr.name() == QStringLiteral("id")) {
|
||||
param_id = attr.value().toString();
|
||||
} else if (attr.name() == "type") {
|
||||
} else if (attr.name() == QStringLiteral("type")) {
|
||||
param_type = NodeParam::StringToDataType(attr.value().toString());
|
||||
} else if (attr.name() == "iterative_input") {
|
||||
} else if (attr.name() == QStringLiteral("iterative_input")) {
|
||||
is_iterative = true;
|
||||
}
|
||||
}
|
||||
@@ -217,32 +233,56 @@ void NodeMetaReader::XMLReadParam(QXmlStreamReader *reader)
|
||||
|
||||
QVariant default_val;
|
||||
QHash<QString, QVariant> properties;
|
||||
LanguageMap param_names;
|
||||
QList<LanguageMap> combo_names;
|
||||
QList<LanguageMap> combo_descriptions;
|
||||
|
||||
// Traverse through param contents for more data
|
||||
while (!reader->atEnd() && !(reader->isEndElement() && reader->name() == "param")) {
|
||||
reader->readNext();
|
||||
while (XMLReadNextStartElement(reader)) {
|
||||
// NOTE: readElementText() returns a string, but for number types (which min and max apply to), QVariant will
|
||||
// convert them automatically
|
||||
if (reader->name() == QStringLiteral("name")) {
|
||||
|
||||
if (reader->isStartElement()) {
|
||||
// NOTE: readElementText() returns a string, but for number types (which min and max apply to), QVariant will
|
||||
// convert them automatically
|
||||
if (reader->name() == "name") {
|
||||
// Insert language into map
|
||||
XMLReadLanguageString(reader, ¶m_names);
|
||||
|
||||
// See if we've already made a table for this param before
|
||||
if (!param_names_.contains(param_id)) {
|
||||
param_names_.insert(param_id, QMap<QString, QString>());
|
||||
} else if (reader->name() == QStringLiteral("default")) {
|
||||
|
||||
// Reads the default value
|
||||
default_val = NodeInput::StringToValue(param_type, reader->readElementText());
|
||||
|
||||
} else if (reader->name() == QStringLiteral("option")) {
|
||||
|
||||
// Read names and descriptions
|
||||
LanguageMap names;
|
||||
LanguageMap descriptions;
|
||||
|
||||
while (XMLReadNextStartElement(reader)) {
|
||||
if (reader->name() == QStringLiteral("name")) {
|
||||
XMLReadLanguageString(reader, &names);
|
||||
} else if (reader->name() == QStringLiteral("description")) {
|
||||
XMLReadLanguageString(reader, &descriptions);
|
||||
} else {
|
||||
reader->skipCurrentElement();
|
||||
}
|
||||
|
||||
// Insert language into table
|
||||
XMLReadLanguageString(reader, ¶m_names_[param_id]);
|
||||
|
||||
} else if (reader->name() == "default") {
|
||||
default_val = NodeInput::StringToValue(param_type, reader->readElementText());
|
||||
} else {
|
||||
properties.insert(reader->name().toString(), reader->readElementText());
|
||||
}
|
||||
|
||||
combo_names.append(names);
|
||||
combo_descriptions.append(descriptions);
|
||||
|
||||
} else {
|
||||
properties.insert(reader->name().toString(), reader->readElementText());
|
||||
}
|
||||
}
|
||||
|
||||
param_names_.insert(param_id, param_names);
|
||||
|
||||
// Insert combo options if they exist
|
||||
if (!combo_names.isEmpty()) {
|
||||
combo_names_.insert(param_id, combo_names);
|
||||
combo_descriptions_.insert(param_id, combo_descriptions);
|
||||
}
|
||||
|
||||
NodeInput* input = new NodeInput(param_id, param_type, default_val);
|
||||
|
||||
QHash<QString, QVariant>::const_iterator iterator;
|
||||
@@ -263,9 +303,8 @@ void NodeMetaReader::XMLReadShader(QXmlStreamReader *reader, QString &destinatio
|
||||
QString code_url;
|
||||
|
||||
// Traverse through parameter attributes for an ID
|
||||
QXmlStreamAttributes attrs = reader->attributes();
|
||||
foreach (const QXmlStreamAttribute& attr, attrs) {
|
||||
if (attr.name() == "url") {
|
||||
XMLAttributeLoop(reader, attr) {
|
||||
if (attr.name() == QStringLiteral("url")) {
|
||||
code_url = attr.value().toString();
|
||||
|
||||
// We don't recognize any other "shader" attributes at this time
|
||||
@@ -285,7 +324,7 @@ void NodeMetaReader::XMLReadShader(QXmlStreamReader *reader, QString &destinatio
|
||||
}
|
||||
}
|
||||
|
||||
QString NodeMetaReader::GetStringForCurrentLanguage(const QMap<QString, QString> *language_map)
|
||||
QString NodeMetaReader::GetStringForCurrentLanguage(const LanguageMap *language_map)
|
||||
{
|
||||
if (language_map->isEmpty()) {
|
||||
// There are no entries for this map, this must be an empty string
|
||||
@@ -293,7 +332,7 @@ QString NodeMetaReader::GetStringForCurrentLanguage(const QMap<QString, QString>
|
||||
}
|
||||
|
||||
// Get current language config
|
||||
QString language = Config::Current()["Language"].toString();
|
||||
QString language = Config::Current()[QStringLiteral("Language")].toString();
|
||||
|
||||
// See if our map has an exact language match
|
||||
QString str_for_lang = language_map->value(language);
|
||||
|
||||
+10
-6
@@ -52,22 +52,26 @@ public:
|
||||
void Retranslate();
|
||||
|
||||
private:
|
||||
void XMLReadLanguageString(QXmlStreamReader* reader, QMap<QString, QString>* map);
|
||||
using LanguageMap = QMap<QString, QString>;
|
||||
|
||||
void XMLReadLanguageString(QXmlStreamReader* reader, LanguageMap *map);
|
||||
void XMLReadEffect(QXmlStreamReader *reader);
|
||||
void XMLReadIterations(QXmlStreamReader* reader);
|
||||
void XMLReadParam(QXmlStreamReader* reader);
|
||||
void XMLReadShader(QXmlStreamReader* reader, QString& destination);
|
||||
|
||||
static QString GetStringForCurrentLanguage(const QMap<QString, QString> *language_map);
|
||||
static QString GetStringForCurrentLanguage(const LanguageMap *language_map);
|
||||
|
||||
NodeInput* GetInputWithID(const QString& id) const;
|
||||
|
||||
QString xml_filename_;
|
||||
|
||||
QMap<QString, QString> names_;
|
||||
QMap<QString, QString> descriptions_;
|
||||
QMap<QString, QString> categories_;
|
||||
QMap<QString, QMap<QString, QString> > param_names_;
|
||||
LanguageMap names_;
|
||||
LanguageMap descriptions_;
|
||||
LanguageMap categories_;
|
||||
QMap<QString, LanguageMap > param_names_;
|
||||
QMap<QString, QList<LanguageMap> > combo_names_;
|
||||
QMap<QString, QList<LanguageMap> > combo_descriptions_;
|
||||
|
||||
QString id_;
|
||||
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
#version 110
|
||||
|
||||
// Standard inputs
|
||||
uniform vec2 ove_resolution;
|
||||
varying vec2 ove_texcoord;
|
||||
uniform int ove_iteration;
|
||||
|
||||
// Node parameter inputs
|
||||
uniform sampler2D tex_in;
|
||||
uniform float sigma_in;
|
||||
uniform int method_in;
|
||||
uniform float radius_in;
|
||||
uniform bool horiz_in;
|
||||
uniform bool vert_in;
|
||||
uniform bool repeat_edge_pixels_in;
|
||||
@@ -15,6 +14,10 @@ uniform bool repeat_edge_pixels_in;
|
||||
// Gaussian function uses PI
|
||||
#define M_PI 3.1415926535897932384626433832795
|
||||
|
||||
// Methods
|
||||
#define METHOD_BOX_BLUR 0
|
||||
#define METHOD_GAUSSIAN_BLUR 1
|
||||
|
||||
// Single gaussian formula (unused, mainly here for documentation/just in case)
|
||||
//float gaussian(float x, float sigma) {
|
||||
// return (1.0/(sigma*sqrt(2.0*M_PI)))*exp(-0.5*pow(x/sigma, 2.0));
|
||||
@@ -27,35 +30,49 @@ float gaussian2(float x, float y, float sigma) {
|
||||
}
|
||||
|
||||
void main(void) {
|
||||
// Determine this iteration should process anything or not
|
||||
if (sigma_in == 0.0 // If the radius is zero
|
||||
|| (ove_iteration == 0 && !horiz_in) // Or this iteration (horizontal) is disabled
|
||||
|| (ove_iteration == 1 && !vert_in)) { // Or this iteration (vertical) is disabled
|
||||
// No-op, do nothing
|
||||
if (radius_in == 0.0
|
||||
|| (ove_iteration == 0 && !horiz_in)
|
||||
|| (ove_iteration == 1 && !vert_in)) {
|
||||
gl_FragColor = texture2D(tex_in, ove_texcoord);
|
||||
return;
|
||||
}
|
||||
|
||||
// We only sample on hard pixels, so we don't accept decimal radii
|
||||
float real_radius = ceil(radius_in);
|
||||
|
||||
// Using (3 * sigma) because 3 standard deviations covers 97% of the blur according to this document:
|
||||
// http://chemaguerra.com/gaussian-filter-radius/
|
||||
float radius = ceil(3.0 * sigma_in);
|
||||
vec4 composite = vec4(0.0);
|
||||
|
||||
float divider, sigma;
|
||||
|
||||
if (method_in == METHOD_BOX_BLUR) {
|
||||
|
||||
// Calculate the weight of each pixel based on the radius
|
||||
divider = 1.0 / real_radius;
|
||||
|
||||
} else if (method_in == METHOD_GAUSSIAN_BLUR) {
|
||||
|
||||
// Using (radius = 3 * sigma) because 3 standard deviations covers 97% of the blur according to this document:
|
||||
// http://chemaguerra.com/gaussian-filter-radius/
|
||||
sigma = real_radius;
|
||||
real_radius *= 3.0;
|
||||
|
||||
// Use gaussian formula to calculate the weight of all pixels
|
||||
divider = 0.0;
|
||||
for (float i=-real_radius+0.5;i<=real_radius;i+=2.0) {
|
||||
divider += gaussian2(i, 0.0, sigma);
|
||||
}
|
||||
|
||||
// Use gaussian formula to calculate the weight of all pixels
|
||||
float sum = 0.0;
|
||||
for (float i=-radius+0.5;i<=radius;i+=2.0) {
|
||||
sum += gaussian2(i, 0.0, sigma_in);
|
||||
}
|
||||
|
||||
// We can take advantage of OpenGL's linear interpolation by sampling between pixels. This produces a mathematically
|
||||
// identical result while allowing us to sample the texture half as many times.
|
||||
vec4 composite = vec4(0.0);
|
||||
for (float i=-radius+0.5;i<=radius;i+=2.0) {
|
||||
// Calculate weight of this pixel using gaussian
|
||||
float weight = (gaussian2(i, 0.0, sigma_in)/sum);
|
||||
for (float i=-real_radius+0.5;i<=real_radius;i+=2.0) {
|
||||
float weight;
|
||||
|
||||
if (method_in == METHOD_BOX_BLUR) {
|
||||
weight = divider;
|
||||
} else if (method_in == METHOD_GAUSSIAN_BLUR) {
|
||||
weight = gaussian2(i, 0.0, sigma)/divider;
|
||||
}
|
||||
|
||||
// Determine pixel coordinate based on iteration
|
||||
// We use two iterations horizontally and vertically since that produces a mathematically identical result and
|
||||
// (2*radius) is much faster than (radius^2)
|
||||
vec2 pixel_coord = ove_texcoord;
|
||||
if (ove_iteration == 0) {
|
||||
pixel_coord.x += i/ove_resolution.x;
|
||||
@@ -71,5 +88,6 @@ void main(void) {
|
||||
composite += texture2D(tex_in, pixel_coord) * weight;
|
||||
}
|
||||
}
|
||||
|
||||
gl_FragColor = composite;
|
||||
}
|
||||
@@ -1,14 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<effect id="org.olivevideoeditor.Olive.boxblur">
|
||||
<effect id="org.olivevideoeditor.Olive.blur">
|
||||
<!-- Effect Name -->
|
||||
<name lang="en_US">Box Blur</name>
|
||||
<name lang="en_US">Blur</name>
|
||||
|
||||
<!-- Effect Category -->
|
||||
<category lang="en_US">Blur</category>
|
||||
|
||||
<!-- Effect Description -->
|
||||
<description lang="en_US">
|
||||
A fast blur calculated by averaging a square of pixels around each pixel. Fast, but can have a "striated" look to it.
|
||||
Blurs an image.
|
||||
</description>
|
||||
|
||||
<!-- Parameter: Texture Input -->
|
||||
@@ -16,6 +16,19 @@
|
||||
<name lang="en_US">Input</name>
|
||||
</param>
|
||||
|
||||
<!-- Parameter: Method Input -->
|
||||
<param id="method_in" type="combo">
|
||||
<name lang="en_US">Method</name>
|
||||
<option>
|
||||
<name lang="en_US">Box</name>
|
||||
<description lang="en_US">A fast blur calculated by averaging a square of pixels around each pixel. Fast, but can have a "striated" look to it.</description>
|
||||
</option>
|
||||
<option>
|
||||
<name lang="en_US">Gaussian</name>
|
||||
<description lang="en_US">A smooth blur using the gaussian function. Slower than box blur but much prettier.</description>
|
||||
</option>
|
||||
</param>
|
||||
|
||||
<!-- Parameter: Radius Input -->
|
||||
<param id="radius_in" type="float">
|
||||
<name lang="en_US">Radius</name>
|
||||
@@ -42,7 +55,7 @@
|
||||
</param>
|
||||
|
||||
<!-- Qt Resource path to fragment shader -->
|
||||
<fragment url=":/shaders/boxblur.frag"/>
|
||||
<fragment url=":/shaders/blur.frag"/>
|
||||
|
||||
<!-- Blur uses two iterations for horizontal and vertical since calculating 2*radius is faster than radius^2 -->
|
||||
<iterations>2</iterations>
|
||||
@@ -1,45 +0,0 @@
|
||||
#version 110
|
||||
|
||||
uniform vec2 ove_resolution;
|
||||
varying vec2 ove_texcoord;
|
||||
uniform int ove_iteration;
|
||||
|
||||
uniform sampler2D tex_in;
|
||||
uniform float radius_in;
|
||||
uniform bool horiz_in;
|
||||
uniform bool vert_in;
|
||||
uniform bool repeat_edge_pixels_in;
|
||||
|
||||
void main(void) {
|
||||
if (radius_in == 0.0
|
||||
|| (ove_iteration == 0 && !horiz_in)
|
||||
|| (ove_iteration == 1 && !vert_in)) {
|
||||
gl_FragColor = texture2D(tex_in, ove_texcoord);
|
||||
return;
|
||||
}
|
||||
|
||||
// We only sample on hard pixels, so we don't accept decimal radii
|
||||
float real_radius = ceil(radius_in);
|
||||
|
||||
// Calculate the weight of each pixel based on the radius
|
||||
float divider = 1.0 / real_radius;
|
||||
|
||||
vec4 composite = vec4(0.0);
|
||||
for (float i=-real_radius+0.5;i<=real_radius;i+=2.0) {
|
||||
vec2 pixel_coord = ove_texcoord;
|
||||
if (ove_iteration == 0) {
|
||||
pixel_coord.x += i/ove_resolution.x;
|
||||
} else if (ove_iteration == 1) {
|
||||
pixel_coord.y += i/ove_resolution.y;
|
||||
}
|
||||
|
||||
if (repeat_edge_pixels_in
|
||||
|| (pixel_coord.x >= 0.0
|
||||
&& pixel_coord.x < 1.0
|
||||
&& pixel_coord.y >= 0.0
|
||||
&& pixel_coord.y < 1.0)) {
|
||||
composite += texture2D(tex_in, pixel_coord) * divider;
|
||||
}
|
||||
}
|
||||
gl_FragColor = composite;
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<effect id="org.olivevideoeditor.Olive.gaussianblur">
|
||||
<!-- Effect Name -->
|
||||
<name lang="en_US">Gaussian Blur</name>
|
||||
|
||||
<!-- Effect Category -->
|
||||
<category lang="en_US">Blur</category>
|
||||
|
||||
<!-- Effect Description -->
|
||||
<description lang="en_US">
|
||||
A smooth blur using the gaussian function. Slower than box blur but also prettier.
|
||||
</description>
|
||||
|
||||
<!-- Parameter: Texture Input -->
|
||||
<param id="tex_in" type="texture" iterative_input="1">
|
||||
<name lang="en_US">Input</name>
|
||||
</param>
|
||||
|
||||
<!-- Parameter: Sigma Value -->
|
||||
<param id="sigma_in" type="float">
|
||||
<name lang="en_US">Sigma</name>
|
||||
<min>0</min>
|
||||
<default>5.5</default>
|
||||
</param>
|
||||
|
||||
<!-- Parameter: Horizontal Enable -->
|
||||
<param id="horiz_in" type="bool">
|
||||
<name lang="en_US">Horizontal</name>
|
||||
<default>1</default>
|
||||
</param>
|
||||
|
||||
<!-- Parameter: Vertical Enable -->
|
||||
<param id="vert_in" type="bool">
|
||||
<name lang="en_US">Vertical</name>
|
||||
<default>1</default>
|
||||
</param>
|
||||
|
||||
<!-- Parameter: Repeat Edge Pixels -->
|
||||
<param id="repeat_edge_pixels_in" type="bool">
|
||||
<name lang="en_US">Repeat Edge Pixels</name>
|
||||
<default>0</default>
|
||||
</param>
|
||||
|
||||
<!-- Qt Resource path to fragment shader -->
|
||||
<fragment url=":/shaders/gaussianblur.frag" />
|
||||
|
||||
<!-- Blur uses two iterations for horizontal and vertical since calculating 2*radius is faster than radius^2 -->
|
||||
<iterations>2</iterations>
|
||||
</effect>
|
||||
@@ -2,8 +2,8 @@
|
||||
<qresource prefix="/shaders">
|
||||
<file>alphaover.frag</file>
|
||||
<file>alphaover.xml</file>
|
||||
<file>boxblur.frag</file>
|
||||
<file>boxblur.xml</file>
|
||||
<file>blur.frag</file>
|
||||
<file>blur.xml</file>
|
||||
<file>colorgradient.frag</file>
|
||||
<file>colorwheel.frag</file>
|
||||
<file>crossdissolve.frag</file>
|
||||
@@ -12,8 +12,6 @@
|
||||
<file>dropshadow.xml</file>
|
||||
<file>diptoblack.frag</file>
|
||||
<file>diptoblack.xml</file>
|
||||
<file>gaussianblur.frag</file>
|
||||
<file>gaussianblur.xml</file>
|
||||
<file>opacity.frag</file>
|
||||
<file>opacity.xml</file>
|
||||
<file>solid.frag</file>
|
||||
|
||||
Reference in New Issue
Block a user