implemented low quality gaussian blur

This commit is contained in:
itsmattkc
2018-08-30 10:38:05 +10:00
parent bc3dd338db
commit 213e989271
9 changed files with 103 additions and 37 deletions
+3
View File
@@ -12,6 +12,9 @@ AudioNoiseEffect::AudioNoiseEffect(Clip* c) : Effect(c, EFFECT_TYPE_AUDIO, AUDIO
mix_val->set_bool_value(true);
srand(QDateTime::currentMSecsSinceEpoch());
connect(amount_val, SIGNAL(changed()), this, SLOT(field_changed()));
connect(mix_val, SIGNAL(changed()), this, SLOT(field_changed()));
}
void AudioNoiseEffect::process_audio(double timecode_start, double timecode_end, quint8 *samples, int nb_bytes, int) {
+10 -2
View File
@@ -92,8 +92,8 @@ Effect::Effect(Clip* c, int t, int i) :
type(t),
id(i),
enable_image(false),
enable_opengl(false)
enable_opengl(false),
iterations(1)
{
container = new CollapsibleWidget();
if (type == EFFECT_TYPE_VIDEO) {
@@ -290,6 +290,14 @@ void Effect::save(QXmlStreamWriter& stream) {
}
}
int Effect::getIterations() {
return iterations;
}
void Effect::setIterations(int i) {
iterations = qMax(i, 1);
}
Effect* Effect::copy(Clip* c) {
Effect* copy = create_effect(id, c);
copy_field_keyframes(copy);
+4
View File
@@ -194,6 +194,9 @@ public:
bool enable_image;
bool enable_opengl;
int getIterations();
void setIterations(int i);
const char* ffmpeg_filter;
virtual void process_image(double timecode, uint8_t* data, int width, int height);
@@ -206,6 +209,7 @@ private:
QVector<EffectRow*> rows;
QGridLayout* ui_layout;
QWidget* ui;
int iterations;
};
#endif // EFFECT_H
+34 -10
View File
@@ -1,18 +1,35 @@
#include "gaussianblureffect.h"
#include "project/clip.h"
#include <QImage>
GaussianBlurEffect::GaussianBlurEffect(Clip *c) : Effect(c, EFFECT_TYPE_VIDEO, VIDEO_GAUSSIANBLUR_EFFECT), frag(QOpenGLShader::Fragment), vert(QOpenGLShader::Vertex) {
GaussianBlurEffect::GaussianBlurEffect(Clip *c) : Effect(c, EFFECT_TYPE_VIDEO, VIDEO_GAUSSIANBLUR_EFFECT), frag(QOpenGLShader::Fragment), vert(QOpenGLShader::Vertex), bound(false) {
enable_opengl = true;
enable_image = false;
amount_val = add_row("Amount:")->add_field(EFFECT_FIELD_DOUBLE);
horiz_val = add_row("Horizontal:")->add_field(EFFECT_FIELD_BOOL);
vert_val = add_row("Vertical:")->add_field(EFFECT_FIELD_BOOL);
amount_val->set_double_minimum_value(0);
amount_val->set_double_default_value(20);
horiz_val->set_bool_value(true);
vert_val->set_bool_value(true);
vert.compileSourceCode("void main() {\ngl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n}");
// vert.compileSourceCode("#version 330 core\nin vec2 VertexPosition;\nvoid main(void) {\ngl_Position = vec4(VertexPosition, 0.0, 1.0);\n}");
frag.compileSourceCode("#version 330 core\n\nuniform sampler2D image;\n\nout vec4 FragmentColor;\n\nuniform float offset[3] = float[]( 0.0, 1.3846153846, 3.2307692308 );\nuniform float weight[3] = float[]( 0.2270270270, 0.3162162162, 0.0702702703 );\n\nvoid main(void)\n{\n FragmentColor = texture2D( image, vec2(gl_FragCoord)/vec2(640.0, 360.0) ) * weight[0];\n for (int i=1; i<3; i++) {\n FragmentColor += texture2D( image, ( vec2(gl_FragCoord)+vec2(offset[i], 0.0) )/vec2(640.0, 360.0) ) * weight[i];\n FragmentColor += texture2D( image, ( vec2(gl_FragCoord)-vec2(offset[i], 0.0) )/vec2(640.0, 360.0) ) * weight[i];\n }\n}");
// frag.compileSourceCode("#version 330 core\n\nuniform sampler2D image;\n\nout vec4 FragmentColor;\n\nvoid main(void)\n{\n FragmentColor = texture2D( image, vec2(gl_FragCoord)/vec2(640.0, 360.0) );\n}");
program.addShader(&frag);
// frag.compileSourceCode("#version 330 core\n\nuniform sampler2D image;\n\nout vec4 FragmentColor;\n\nuniform float offset[3] = float[]( 0.0, 1.3846153846, 3.2307692308 );\nuniform float weight[3] = float[]( 0.2270270270, 0.3162162162, 0.0702702703 );\n\nvoid main(void)\n{\n FragmentColor = texture2D( image, vec2(gl_FragCoord)/vec2(640.0, 360.0) ) * weight[0];\n for (int i=1; i<3; i++) {\n FragmentColor += texture2D( image, ( vec2(gl_FragCoord)+vec2(offset[i], 0.0) )/vec2(640.0, 360.0) ) * weight[i];\n FragmentColor += texture2D( image, ( vec2(gl_FragCoord)-vec2(offset[i], 0.0) )/vec2(640.0, 360.0) ) * weight[i];\n }\n}");
frag.compileSourceCode("#version 330 core\n\nuniform sampler2D image;\n\nout vec4 FragmentColor;\n\nuniform float offset[3] = float[]( 0.0, 1.3846153846, 3.2307692308 );\nuniform float weight[3] = float[]( 0.2270270270, 0.3162162162, 0.0702702703 );\nuniform float halfweight[3] = float[]( 0.1135135135, 0.1581081081, 0.03513513515 );\n\nuniform vec2 resolution;\nuniform bool horiz_blur;\nuniform bool vert_blur;\n\nvoid main(void) {\n FragmentColor = texture2D( image, vec2(gl_FragCoord)/resolution ) * weight[0];\n for (int i=1; i<3; i++) {\n float weight = (horiz_blur && vert_blur) ? halfweight[i] : weight[i];\n\n if (horiz_blur) {\n FragmentColor += texture2D( image, ( vec2(gl_FragCoord)+vec2(offset[i], 0.0) )/resolution ) * weight;\n FragmentColor += texture2D( image, ( vec2(gl_FragCoord)-vec2(offset[i], 0.0) )/resolution ) * weight;\n }\n \n if (vert_blur) {\n FragmentColor += texture2D( image, ( vec2(gl_FragCoord)+vec2(0.0, offset[i]) )/resolution ) * weight;\n FragmentColor += texture2D( image, ( vec2(gl_FragCoord)-vec2(0.0, offset[i]) )/resolution ) * weight;\n } \n }\n}");
program.addShader(&vert);
program.addShader(&frag);
program.link();
connect(amount_val, SIGNAL(changed()), this, SLOT(field_changed()));
connect(horiz_val, SIGNAL(changed()), this, SLOT(field_changed()));
connect(vert_val, SIGNAL(changed()), this, SLOT(field_changed()));
refresh();
}
void GaussianBlurEffect::process_image(double timecode, uint8_t *data, int width, int height) {
@@ -80,12 +97,19 @@ void GaussianBlurEffect::process_image(double timecode, uint8_t *data, int width
}
void GaussianBlurEffect::process_gl(double timecode, GLTextureCoords &coords) {
program.bind();
program.setUniformValue("resolution", 1920, 1080, 0);
program.setUniformValue("flip", false);
program.setUniformValue("direction", 0, 20);
bound = false;
bool horiz = horiz_val->get_bool_value(timecode);
bool vert = vert_val->get_bool_value(timecode);
int iterationCount = amount_val->get_double_value(timecode);
if (iterationCount > 0 && (horiz || vert)) {
bound = program.bind();
setIterations(iterationCount);
program.setUniformValue("resolution", parent_clip->getWidth(), parent_clip->getHeight());
program.setUniformValue("horiz_blur", horiz);
program.setUniformValue("vert_blur", vert);
}
}
void GaussianBlurEffect::clean_gl() {
program.release();
void GaussianBlurEffect::clean_gl() {
if (bound) program.release();
}
+6
View File
@@ -14,6 +14,12 @@ private:
QOpenGLShaderProgram program;
QOpenGLShader vert;
QOpenGLShader frag;
EffectField* amount_val;
EffectField* horiz_val;
EffectField* vert_val;
bool bound;
};
#endif // GAUSSIANBLUREFFECT_H
+5 -22
View File
@@ -88,28 +88,11 @@ void TransformEffect::refresh() {
scale_x->set_double_default_value(100);
scale_y->set_double_default_value(100);
default_anchor_x = default_pos_x;
default_anchor_y = default_pos_y;
if (parent_clip->media != NULL) {
switch (parent_clip->media_type) {
case MEDIA_TYPE_FOOTAGE:
{
MediaStream* ms = static_cast<Media*>(parent_clip->media)->get_stream_from_file_index(parent_clip->track < 0, parent_clip->media_stream);
if (ms != NULL) {
default_anchor_x = ms->video_width/2;
default_anchor_y = ms->video_height/2;
}
break;
}
case MEDIA_TYPE_SEQUENCE:
{
Sequence* s = static_cast<Sequence*>(parent_clip->media);
default_anchor_x = s->width/2;
default_anchor_y = s->height/2;
break;
}
}
}
default_anchor_x = parent_clip->getWidth()/2;
default_anchor_y = parent_clip->getHeight()/2;
if (default_anchor_x == 0) default_anchor_x = default_pos_x;
if (default_anchor_y == 0) default_anchor_y = default_pos_y;
anchor_x_box->set_double_default_value(default_anchor_x);
anchor_y_box->set_double_default_value(default_anchor_y);
+35 -1
View File
@@ -182,5 +182,39 @@ long Clip::getMediaLength(double framerate) {
}
break;
}
return 0;
return 0;
}
int Clip::getWidth() {
if (media == NULL && sequence != NULL) return sequence->width;
switch (media_type) {
case MEDIA_TYPE_FOOTAGE:
{
MediaStream* ms = static_cast<Media*>(media)->get_stream_from_file_index(track < 0, media_stream);
if (ms != NULL) return ms->video_width;
}
case MEDIA_TYPE_SEQUENCE:
{
Sequence* s = static_cast<Sequence*>(media);
return s->width;
}
}
return 0;
}
int Clip::getHeight() {
if (media == NULL && sequence != NULL) return sequence->height;
switch (media_type) {
case MEDIA_TYPE_FOOTAGE:
{
MediaStream* ms = static_cast<Media*>(media)->get_stream_from_file_index(track < 0, media_stream);
if (ms != NULL) return ms->video_height;
}
case MEDIA_TYPE_SEQUENCE:
{
Sequence* s = static_cast<Sequence*>(media);
return s->height;
}
}
return 0;
}
+2
View File
@@ -65,6 +65,8 @@ struct Clip
void* media; // attached media
int media_type;
int media_stream;
int getWidth();
int getHeight();
// other variables (should be "duplicated" in copy())
QList<Effect*> effects;
+4 -2
View File
@@ -218,8 +218,10 @@ GLuint ViewerWidget::compose_sequence(Clip* nest, bool render_audio) {
// EFFECT CODE START
for (int j=0;j<c->effects.size();j++) {
if (c->effects.at(j)->enable_opengl && c->effects.at(j)->is_enabled()) {
c->effects.at(j)->process_gl(((double)(panel_timeline->playhead-c->timeline_in+c->clip_in)/(double)sequence->frame_rate), coords);
composite_texture = draw_clip(c, composite_texture);
for (int k=0;k<c->effects.at(j)->getIterations();k++) {
c->effects.at(j)->process_gl(((double)(panel_timeline->playhead-c->timeline_in+c->clip_in)/(double)sequence->frame_rate), coords);
composite_texture = draw_clip(c, composite_texture);
}
}
}