From 213e989271150634317281303e3e3a97bd6c44d1 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Thu, 30 Aug 2018 10:38:05 +1000 Subject: [PATCH] implemented low quality gaussian blur --- effects/audio/audionoiseeffect.cpp | 3 ++ effects/effect.cpp | 12 ++++++-- effects/effect.h | 4 +++ effects/video/gaussianblureffect.cpp | 44 +++++++++++++++++++++------- effects/video/gaussianblureffect.h | 6 ++++ effects/video/transformeffect.cpp | 27 ++++------------- project/clip.cpp | 36 ++++++++++++++++++++++- project/clip.h | 2 ++ ui/viewerwidget.cpp | 6 ++-- 9 files changed, 103 insertions(+), 37 deletions(-) diff --git a/effects/audio/audionoiseeffect.cpp b/effects/audio/audionoiseeffect.cpp index b5c6e79dc..5a90c2ace 100644 --- a/effects/audio/audionoiseeffect.cpp +++ b/effects/audio/audionoiseeffect.cpp @@ -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) { diff --git a/effects/effect.cpp b/effects/effect.cpp index d1cca4f23..91985d6b5 100644 --- a/effects/effect.cpp +++ b/effects/effect.cpp @@ -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); diff --git a/effects/effect.h b/effects/effect.h index 9748c53f1..99bdea52e 100644 --- a/effects/effect.h +++ b/effects/effect.h @@ -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 rows; QGridLayout* ui_layout; QWidget* ui; + int iterations; }; #endif // EFFECT_H diff --git a/effects/video/gaussianblureffect.cpp b/effects/video/gaussianblureffect.cpp index 0399038c2..cf7937e8a 100644 --- a/effects/video/gaussianblureffect.cpp +++ b/effects/video/gaussianblureffect.cpp @@ -1,18 +1,35 @@ #include "gaussianblureffect.h" +#include "project/clip.h" + #include -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(); } diff --git a/effects/video/gaussianblureffect.h b/effects/video/gaussianblureffect.h index 89fc0190c..7212d8876 100644 --- a/effects/video/gaussianblureffect.h +++ b/effects/video/gaussianblureffect.h @@ -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 diff --git a/effects/video/transformeffect.cpp b/effects/video/transformeffect.cpp index 8c3d9c2cb..8db50431f 100644 --- a/effects/video/transformeffect.cpp +++ b/effects/video/transformeffect.cpp @@ -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(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(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); diff --git a/project/clip.cpp b/project/clip.cpp index b99f3b15c..53a69241f 100644 --- a/project/clip.cpp +++ b/project/clip.cpp @@ -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)->get_stream_from_file_index(track < 0, media_stream); + if (ms != NULL) return ms->video_width; + } + case MEDIA_TYPE_SEQUENCE: + { + Sequence* s = static_cast(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)->get_stream_from_file_index(track < 0, media_stream); + if (ms != NULL) return ms->video_height; + } + case MEDIA_TYPE_SEQUENCE: + { + Sequence* s = static_cast(media); + return s->height; + } + } + return 0; } diff --git a/project/clip.h b/project/clip.h index 8e112f4ba..4e7193ed4 100644 --- a/project/clip.h +++ b/project/clip.h @@ -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 effects; diff --git a/ui/viewerwidget.cpp b/ui/viewerwidget.cpp index cc5455414..7d41fd1eb 100644 --- a/ui/viewerwidget.cpp +++ b/ui/viewerwidget.cpp @@ -218,8 +218,10 @@ GLuint ViewerWidget::compose_sequence(Clip* nest, bool render_audio) { // EFFECT CODE START for (int j=0;jeffects.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;keffects.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); + } } }