From d1ff0264246744d4308c117c3f2d593f9fe186a1 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Mon, 28 Jan 2019 02:31:12 +1100 Subject: [PATCH] added full blending pipeline --- effects/internal/blending.frag | 209 ++++++++++++++++++++++++++- effects/internal/transformeffect.cpp | 6 +- effects/test.frag | 10 ++ effects/test.xml | 7 + project/effect.cpp | 2 +- project/sourcescommon.cpp | 36 ++--- ui/renderfunctions.cpp | 191 ++++++++++++++---------- ui/renderfunctions.h | 1 + ui/renderthread.cpp | 9 +- ui/timelinewidget.cpp | 6 +- 10 files changed, 373 insertions(+), 104 deletions(-) create mode 100644 effects/test.frag create mode 100644 effects/test.xml diff --git a/effects/internal/blending.frag b/effects/internal/blending.frag index 3507705c5..ab6171b73 100644 --- a/effects/internal/blending.frag +++ b/effects/internal/blending.frag @@ -28,10 +28,213 @@ const int BLEND_MODE_SUBTRACT = 24; const int BLEND_MODE_VIVIDLIGHT = 25; uniform sampler2D background; -uniform sampler2D texture; +uniform sampler2D foreground; + +uniform int blendmode; +uniform float opacity; + varying vec2 vTexCoord; +// float blending functions +float blend_color_burn(float base, float blend) { + return (blend==0.0)?blend:max((1.0-((1.0-base)/blend)),0.0); +} + +float blend_color_dodge(float base, float blend) { + return (blend==1.0)?blend:min(base/(1.0-blend),1.0); +} + +float blend_vivid_light(float base, float blend) { + return (blend<0.5)?blend_color_burn(base,(2.0*blend)):blend_color_dodge(base,(2.0*(blend-0.5))); +} + +vec3 blend_vivid_light(vec3 base, vec3 blend) { + return vec3(blend_vivid_light(base.r,blend.r),blend_vivid_light(base.g,blend.g),blend_vivid_light(base.b,blend.b)); +} + +float blend_hard_mix(float base, float blend) { + return (blend_vivid_light(base,blend)<0.5)?0.0:1.0; +} + +float blend_lighten(float base, float blend) { + return max(blend,base); +} + +float blend_overlay(float base, float blend) { + return base<0.5?(2.0*base*blend):(1.0-2.0*(1.0-base)*(1.0-blend)); +} + +vec3 blend_overlay(vec3 base, vec3 blend) { + return vec3(blend_overlay(base.r,blend.r),blend_overlay(base.g,blend.g),blend_overlay(base.b,blend.b)); +} + +float blend_darken(float base, float blend) { + return min(blend, base); +} + +float blend_linear_burn(float base, float blend) { + return max(base+blend-1.0,0.0); +} + +vec3 blend_linear_burn(vec3 base, vec3 blend) { + return max(base+blend-vec3(1.0),vec3(0.0)); +} + +float blend_linear_dodge(float base, float blend) { + return min(base+blend,1.0); +} + +vec3 blend_linear_dodge(vec3 base, vec3 blend) { + return min(base+blend,vec3(1.0)); +} + +float blend_linear_light(float base, float blend) { + return blend<0.5?blend_linear_burn(base,(2.0*blend)):blend_linear_dodge(base,(2.0*(blend-0.5))); +} + +float blend_pin_light(float base, float blend) { + return (blend<0.5)?blend_darken(base,(2.0*blend)):blend_lighten(base,(2.0*(blend-0.5))); +} + +float blend_reflect(float base, float blend) { + return (blend==1.0)?blend:min(base*base/(1.0-blend),1.0); +} + +vec3 blend_reflect(vec3 base, vec3 blend) { + return vec3(blend_reflect(base.r,blend.r),blend_reflect(base.g,blend.g),blend_reflect(base.b,blend.b)); +} + +float blend_screen(float base, float blend) { + return 1.0-((1.0-base)*(1.0-blend)); +} + +float blend_substract(float base, float blend) { + return max(base+blend-1.0,0.0); +} + +float blend_soft_light(float base, float blend) { + return (blend<0.5)?(2.0*base*blend+base*base*(1.0-2.0*blend)):(sqrt(base)*(2.0*blend-1.0)+2.0*base*(1.0-blend)); +} + +// adapted from https://github.com/jamieowen/glsl-blend +// RGB blending function, alpha is handled below +vec3 blend(vec3 base, vec3 blend) { + switch (blendmode) { + + case BLEND_MODE_AVERAGE: + return (base+blend)/2.0; + + case BLEND_MODE_COLORBURN: + return vec3(blend_color_burn(base.r, blend.r), blend_color_burn(base.g, blend.g), blend_color_burn(base.b, blend.b)); + + case BLEND_MODE_COLORDODGE: + return vec3(blend_color_dodge(base.r, blend.r), blend_color_dodge(base.g, blend.g), blend_color_dodge(base.b, blend.b)); + + case BLEND_MODE_DARKEN: + return vec3(blend_darken(base.r, blend.r), blend_darken(base.g, blend.g), blend_darken(base.b, blend.b)); + + case BLEND_MODE_DIFFERENCE: + return abs(base-blend); + + case BLEND_MODE_EXCLUSION: + return base+blend-2.0*base*blend; + + case BLEND_MODE_GLOW: + return blend_reflect(blend, base); + + case BLEND_MODE_HARDLIGHT: + return blend_overlay(blend,base); + + case BLEND_MODE_HARDMIX: + return vec3(blend_hard_mix(base.r,blend.r),blend_hard_mix(base.g,blend.g),blend_hard_mix(base.b,blend.b)); + + case BLEND_MODE_LIGHTEN: + return vec3(blend_lighten(base.r,blend.r),blend_lighten(base.g,blend.g),blend_lighten(base.b,blend.b)); + + case BLEND_MODE_LINEARBURN: + case BLEND_MODE_SUBTRACT: + return blend_linear_burn(base, blend); + + case BLEND_MODE_ADD: + case BLEND_MODE_LINEARDODGE: + return blend_linear_dodge(base, blend); + + case BLEND_MODE_LINEARLIGHT: + return vec3(blend_linear_light(base.r,blend.r),blend_linear_light(base.g,blend.g),blend_linear_light(base.b,blend.b)); + + case BLEND_MODE_MULTIPLY: + return (base * blend); + + case BLEND_MODE_NEGATION: + return vec3(1.0)-abs(vec3(1.0)-base-blend); + + case BLEND_MODE_OVERLAY: + return blend_overlay(base, blend); + + case BLEND_MODE_PHOENIX: + return min(base,blend)-max(base,blend)+vec3(1.0); + + case BLEND_MODE_PINLIGHT: + return vec3(blend_pin_light(base.r,blend.r),blend_pin_light(base.g,blend.g),blend_pin_light(base.b,blend.b)); + + case BLEND_MODE_REFLECT: + return blend_reflect(base, blend); + + case BLEND_MODE_SCREEN: + return vec3(blend_screen(base.r,blend.r),blend_screen(base.g,blend.g),blend_screen(base.b,blend.b)); + + case BLEND_MODE_SUBSTRACT: + return max(base+blend-vec3(1.0),vec3(0.0)); + + case BLEND_MODE_SOFTLIGHT: + return vec3(blend_soft_light(base.r,blend.r),blend_soft_light(base.g,blend.g),blend_soft_light(base.b,blend.b)); + + case BLEND_MODE_VIVIDLIGHT: + return vec3(blend_vivid_light(base.r,blend.r),blend_vivid_light(base.g,blend.g),blend_vivid_light(base.b,blend.b)); + + case BLEND_MODE_NORMAL: + default: + return blend; + + } +} + void main(void) { - // gl_FragColor = texture2D(background, vTexCoord); - gl_FragColor = texture2D(texture, vTexCoord); + vec4 bg_color = texture2D(background, vTexCoord); + vec4 fg_color = texture2D(foreground, vTexCoord); + + // blend textures together + vec3 composite = blend(bg_color.rgb, fg_color.rgb); + + // add foreground and background alpha's together + vec4 full_composite = vec4(composite, bg_color.a + fg_color.a); + + // restore background texture based on foreground's alpha + bool restore_bg = true; + + // some blend modes don't need this + switch (blendmode) { + case BLEND_MODE_SCREEN: + case BLEND_MODE_LIGHTEN: + case BLEND_MODE_COLORDODGE: + case BLEND_MODE_LINEARDODGE: + case BLEND_MODE_ADD: + // case BLEND_MODE_OVERLAY: + case BLEND_MODE_SOFTLIGHT: + case BLEND_MODE_DIFFERENCE: + case BLEND_MODE_AVERAGE: + case BLEND_MODE_NEGATION: + case BLEND_MODE_PHOENIX: + restore_bg = false; + } + + if (restore_bg) { + full_composite += vec4(bg_color.rgb*(1.0-fg_color.a), 0.0); + } + + // mix via opacity + full_composite = mix(bg_color, full_composite, opacity); + + // output to color + gl_FragColor = full_composite; } \ No newline at end of file diff --git a/effects/internal/transformeffect.cpp b/effects/internal/transformeffect.cpp index 6bbcf1cfe..a095b3f5a 100644 --- a/effects/internal/transformeffect.cpp +++ b/effects/internal/transformeffect.cpp @@ -63,7 +63,7 @@ TransformEffect::TransformEffect(Clip* c, const EffectMeta* em) : Effect(c, em) blend_mode_box->add_combo_item(tr("Lighten"), BLEND_MODE_LIGHTEN); blend_mode_box->add_combo_item(tr("Screen"), BLEND_MODE_SCREEN); blend_mode_box->add_combo_item(tr("Color Dodge"), BLEND_MODE_COLORDODGE); - blend_mode_box->add_combo_item(tr("Linear Dodge"), BLEND_MODE_LINEARDODGE); + blend_mode_box->add_combo_item(tr("Linear Dodge (Add)"), BLEND_MODE_LINEARDODGE); blend_mode_box->add_combo_item(tr("Overlay"), BLEND_MODE_OVERLAY); blend_mode_box->add_combo_item(tr("Soft Light"), BLEND_MODE_SOFTLIGHT); blend_mode_box->add_combo_item(tr("Hard Light"), BLEND_MODE_HARDLIGHT); @@ -74,9 +74,9 @@ TransformEffect::TransformEffect(Clip* c, const EffectMeta* em) : Effect(c, em) blend_mode_box->add_combo_item(tr("Difference"), BLEND_MODE_DIFFERENCE); blend_mode_box->add_combo_item(tr("Exclusion"), BLEND_MODE_EXCLUSION); blend_mode_box->add_combo_item(tr("Reflect"), BLEND_MODE_REFLECT); - blend_mode_box->add_combo_item(tr("Subtract"), BLEND_MODE_SUBTRACT); +// blend_mode_box->add_combo_item(tr("Subtract"), BLEND_MODE_SUBTRACT); blend_mode_box->add_combo_item(tr("Substract"), BLEND_MODE_SUBSTRACT); - blend_mode_box->add_combo_item(tr("Add"), BLEND_MODE_ADD); +// blend_mode_box->add_combo_item(tr("Add"), BLEND_MODE_ADD); blend_mode_box->add_combo_item(tr("Average"), BLEND_MODE_AVERAGE); blend_mode_box->add_combo_item(tr("Glow"), BLEND_MODE_GLOW); blend_mode_box->add_combo_item(tr("Negation"), BLEND_MODE_NEGATION); diff --git a/effects/test.frag b/effects/test.frag new file mode 100644 index 000000000..bc16e5cb4 --- /dev/null +++ b/effects/test.frag @@ -0,0 +1,10 @@ +#version 110 + +uniform sampler2D tex; +varying vec2 vTexCoord; + +void main(void) { + vec4 c = texture2D(tex, vTexCoord); + c.rgb *= c.a; + gl_FragColor = c; +} \ No newline at end of file diff --git a/effects/test.xml b/effects/test.xml new file mode 100644 index 000000000..87d1bd6a2 --- /dev/null +++ b/effects/test.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/project/effect.cpp b/project/effect.cpp index b47fa5c6b..2beee31f7 100644 --- a/project/effect.cpp +++ b/project/effect.cpp @@ -500,7 +500,7 @@ void Effect::load(QXmlStreamReader& stream) { for (int l=0;lfieldCount();l++) { if (row->field(l)->id == attr.value()) { field_number = l; - qInfo() << "Found field by ID"; +// qInfo() << "Found field by ID"; break; } } diff --git a/project/sourcescommon.cpp b/project/sourcescommon.cpp index 31734b339..bb557381a 100644 --- a/project/sourcescommon.cpp +++ b/project/sourcescommon.cpp @@ -56,6 +56,24 @@ void SourcesCommon::show_context_menu(QWidget* parent, const QModelIndexList& it QMenu* new_menu = menu.addMenu(tr("New")); mainWindow->make_new_menu(new_menu); + QMenu* view_menu = menu.addMenu(tr("View")); + + QAction* tree_view_action = view_menu->addAction(tr("Tree View")); + connect(tree_view_action, SIGNAL(triggered(bool)), project_parent, SLOT(set_tree_view())); + + QAction* icon_view_action = view_menu->addAction(tr("Icon View")); + connect(icon_view_action, SIGNAL(triggered(bool)), project_parent, SLOT(set_icon_view())); + + QAction* toolbar_action = view_menu->addAction(tr("Show Toolbar")); + toolbar_action->setCheckable(true); + toolbar_action->setChecked(project_parent->toolbar_widget->isVisible()); + connect(toolbar_action, SIGNAL(triggered(bool)), project_parent->toolbar_widget, SLOT(setVisible(bool))); + + QAction* show_sequences = view_menu->addAction(tr("Show Sequences")); + show_sequences->setCheckable(true); + show_sequences->setChecked(panel_project->sorter->get_show_sequences()); + connect(show_sequences, SIGNAL(triggered(bool)), panel_project->sorter, SLOT(set_show_sequences(bool))); + if (items.size() > 0) { Media* m = project_parent->item_to_media(items.at(0)); @@ -120,24 +138,6 @@ void SourcesCommon::show_context_menu(QWidget* parent, const QModelIndexList& it } } - menu.addSeparator(); - - QAction* tree_view_action = menu.addAction(tr("Tree View")); - connect(tree_view_action, SIGNAL(triggered(bool)), project_parent, SLOT(set_tree_view())); - - QAction* icon_view_action = menu.addAction(tr("Icon View")); - connect(icon_view_action, SIGNAL(triggered(bool)), project_parent, SLOT(set_icon_view())); - - QAction* toolbar_action = menu.addAction(tr("Show Toolbar")); - toolbar_action->setCheckable(true); - toolbar_action->setChecked(project_parent->toolbar_widget->isVisible()); - connect(toolbar_action, SIGNAL(triggered(bool)), project_parent->toolbar_widget, SLOT(setVisible(bool))); - - QAction* show_sequences = menu.addAction(tr("Show Sequences")); - show_sequences->setCheckable(true); - show_sequences->setChecked(panel_project->sorter->get_show_sequences()); - connect(show_sequences, SIGNAL(triggered(bool)), panel_project->sorter, SLOT(set_show_sequences(bool))); - menu.exec(QCursor::pos()); } diff --git a/ui/renderfunctions.cpp b/ui/renderfunctions.cpp index d0697056a..261eb2602 100644 --- a/ui/renderfunctions.cpp +++ b/ui/renderfunctions.cpp @@ -28,18 +28,11 @@ extern "C" { #include } -GLuint draw_clip(QOpenGLFramebufferObject* fbo, GLuint texture, bool clear) { +void full_blit() { glPushMatrix(); glLoadIdentity(); glOrtho(0, 1, 0, 1, -1, 1); - fbo->bind(); - - if (clear) { - glClear(GL_COLOR_BUFFER_BIT); - } - - glBindTexture(GL_TEXTURE_2D, texture); glBegin(GL_QUADS); glTexCoord2f(0, 0); // top left glVertex2f(0, 0); // top left @@ -50,9 +43,41 @@ GLuint draw_clip(QOpenGLFramebufferObject* fbo, GLuint texture, bool clear) { glTexCoord2f(0, 1); // bottom left glVertex2f(0, 1); // bottom left glEnd(); - glBindTexture(GL_TEXTURE_2D, 0); glPopMatrix(); +} + +void draw_clip(QOpenGLContext* ctx, GLuint fbo, GLuint texture, bool clear) { + ctx->functions()->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo); + + if (clear) { + glClear(GL_COLOR_BUFFER_BIT); + } + + glBindTexture(GL_TEXTURE_2D, texture); + + full_blit(); + + glBindTexture(GL_TEXTURE_2D, 0); + + ctx->functions()->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); +} + +GLuint draw_clip(QOpenGLFramebufferObject* fbo, GLuint texture, bool clear) { + fbo->bind(); + + if (clear) { + glClear(GL_COLOR_BUFFER_BIT); + } + + glBindTexture(GL_TEXTURE_2D, texture); + + full_blit(); + + glBindTexture(GL_TEXTURE_2D, 0); + + fbo->release(); + return fbo->texture(); } @@ -78,8 +103,6 @@ void process_effect(Clip* c, } if (e->enable_superimpose) { GLuint superimpose_texture = e->process_superimpose(timecode); - qDebug() << "superimpose texture was:" << superimpose_texture; - qDebug() << "composite texture was:" << composite_texture; if (superimpose_texture == 0) { qWarning() << "Superimpose texture was nullptr, retrying..."; @@ -88,7 +111,6 @@ void process_effect(Clip* c, // if there is no previous texture, just return the superimposes texture // UNLESS this is a shader-extended superimpose effect in which case, // we'll need to draw it below - qDebug() << "returning superimpose directly"; composite_texture = superimpose_texture; } else { // if the source texture is not already a framebuffer texture, @@ -361,7 +383,6 @@ GLuint compose_sequence(ComposeSequenceParams ¶ms) { if (e->container->selected) selected_effect = e; } } - qDebug() << "texture ID:" << textureID; // using gizmo data, set definitive gizmo if (selected_effect != nullptr) { @@ -388,87 +409,111 @@ GLuint compose_sequence(ComposeSequenceParams ¶ms) { // == EFFECT CODE END == - // == START FINAL DRAW ON SEQUENCE BUFFER == - if (textureID > 0) { - // bind framebuffer - params.ctx->functions()->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, final_fbo); - // set viewport to sequence size - glViewport(0, 0, s->width, s->height); + params.ctx->functions()->glViewport(0, 0, s->width, s->height); - // bind final texture + + + // == START RENDER CLIP IN CONTEXT OF SEQUENCE == + + + + // render a backbuffer + params.ctx->functions()->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, params.backend_buffer1); + + glClearColor(0.0, 0.0, 0.0, 0.0); + glClear(GL_COLOR_BUFFER_BIT); + + // bind final clip texture glBindTexture(GL_TEXTURE_2D, textureID); // set texture filter to bilinear - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + params.ctx->functions()->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + params.ctx->functions()->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + // draw clip on screen according to gl coordinates + glBegin(GL_QUADS); + + glTexCoord2f(coords.textureTopLeftX, coords.textureTopLeftY); // top left + glVertex2f(coords.vertexTopLeftX, coords.vertexTopLeftY); // top left + glTexCoord2f(coords.textureTopRightX, coords.textureTopRightY); // top right + glVertex2f(coords.vertexTopRightX, coords.vertexTopRightY); // top right + glTexCoord2f(coords.textureBottomRightX, coords.textureBottomRightY); // bottom right + glVertex2f(coords.vertexBottomRightX, coords.vertexBottomRightY); // bottom right + glTexCoord2f(coords.textureBottomLeftX, coords.textureBottomLeftY); // bottom left + glVertex2f(coords.vertexBottomLeftX, coords.vertexBottomLeftY); // bottom left + + glEnd(); + + // release final clip texture + glBindTexture(GL_TEXTURE_2D, 0); + + params.ctx->functions()->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + + + + // == END RENDER CLIP IN CONTEXT OF SEQUENCE == + + + + // + // + // PROCESS POST-SHADERS + // + // + + + + // copy front buffer to back buffer + draw_clip(params.ctx, params.backend_buffer2, params.main_attachment, true); + + + + // == START FINAL DRAW ON SEQUENCE BUFFER == + + + + // bind front buffer as draw buffer + params.ctx->functions()->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, final_fbo); + + // load background texture into texture unit 0 + params.ctx->functions()->glActiveTexture(GL_TEXTURE0 + 0); // Texture unit 0 + params.ctx->functions()->glBindTexture(GL_TEXTURE_2D, params.backend_attachment2); + + // load foreground texture into texture unit 1 + params.ctx->functions()->glActiveTexture(GL_TEXTURE0 + 1); // Texture unit 1 + params.ctx->functions()->glBindTexture(GL_TEXTURE_2D, params.backend_attachment1); // bind and configure blending mode shader params.blend_mode_program->bind(); - params.blend_mode_program->setUniformValue("blend_mode", coords.blendmode); + params.blend_mode_program->setUniformValue("blendmode", coords.blendmode); params.blend_mode_program->setUniformValue("opacity", coords.opacity); + params.blend_mode_program->setUniformValue("background", 0); + params.blend_mode_program->setUniformValue("foreground", 1); - // draw clip on screen - glBegin(GL_QUADS); + glClear(GL_COLOR_BUFFER_BIT); - if (coords.grid_size <= 1) { - glTexCoord2f(coords.textureTopLeftX, coords.textureTopLeftY); // top left - glVertex2f(coords.vertexTopLeftX, coords.vertexTopLeftY); // top left - glTexCoord2f(coords.textureTopRightX, coords.textureTopRightY); // top right - glVertex2f(coords.vertexTopRightX, coords.vertexTopRightY); // top right - glTexCoord2f(coords.textureBottomRightX, coords.textureBottomRightY); // bottom right - glVertex2f(coords.vertexBottomRightX, coords.vertexBottomRightY); // bottom right - glTexCoord2f(coords.textureBottomLeftX, coords.textureBottomLeftY); // bottom left - glVertex2f(coords.vertexBottomLeftX, coords.vertexBottomLeftY); // bottom left - } else { - float rows = coords.grid_size; - float cols = coords.grid_size; - - for (int k=0;krelease(); - // unbind texture - glBindTexture(GL_TEXTURE_2D, 0); + // unbind texture from texture unit 1 + params.ctx->functions()->glBindTexture(GL_TEXTURE_2D, 0); + + // unbind texture from texture unit 0 + params.ctx->functions()->glActiveTexture(GL_TEXTURE0 + 0); // Texture unit 0 + params.ctx->functions()->glBindTexture(GL_TEXTURE_2D, 0); // unbind framebuffer - params.ctx->functions()->glBindFramebuffer(GL_TEXTURE_2D, 0); + params.ctx->functions()->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + + + // == END FINAL DRAW ON SEQUENCE BUFFER == } - // == END FINAL DRAW ON SEQUENCE BUFFER == - // prepare gizmos if ((*params.gizmos) != nullptr && params.nests.isEmpty() diff --git a/ui/renderfunctions.h b/ui/renderfunctions.h index 852c2a2fe..0830d6cb4 100644 --- a/ui/renderfunctions.h +++ b/ui/renderfunctions.h @@ -24,6 +24,7 @@ struct ComposeSequenceParams { QOpenGLShaderProgram* blend_mode_program; QOpenGLShaderProgram* premultiply_program; GLuint main_buffer; + GLuint main_attachment; GLuint backend_buffer1; GLuint backend_attachment1; GLuint backend_buffer2; diff --git a/ui/renderthread.cpp b/ui/renderthread.cpp index 37face307..a8ef4fee5 100644 --- a/ui/renderthread.cpp +++ b/ui/renderthread.cpp @@ -70,11 +70,11 @@ void RenderThread::run() { // create texture glGenTextures(1, &front_texture); - glGenTextures(1, &back_buffer_1); - glGenTextures(1, &back_buffer_2); + glGenTextures(1, &back_texture_1); + glGenTextures(1, &back_texture_2); GLuint fbos[3] = {front_buffer, back_buffer_1, back_buffer_2}; - GLuint textures[3] = {front_buffer, back_buffer_1, back_buffer_2}; + GLuint textures[3] = {front_texture, back_texture_1, back_texture_2}; for (int i=0;i<3;i++) { // bind framebuffer for attaching @@ -85,7 +85,7 @@ void RenderThread::run() { // allocate storage for texture glTexImage2D( - GL_TEXTURE_2D, 0, GL_RGB, seq->width, seq->height, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr + GL_TEXTURE_2D, 0, GL_RGBA, seq->width, seq->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr ); // set texture filtering to bilinear @@ -174,6 +174,7 @@ void RenderThread::paint() { params.backend_attachment1 = back_texture_1; params.backend_attachment2 = back_texture_2; params.main_buffer = front_buffer; + params.main_attachment = front_texture; compose_sequence(params); texture_failed = params.texture_failed; diff --git a/ui/timelinewidget.cpp b/ui/timelinewidget.cpp index bacc19133..0d6bb4a2a 100644 --- a/ui/timelinewidget.cpp +++ b/ui/timelinewidget.cpp @@ -869,7 +869,6 @@ void TimelineWidget::mouseReleaseEvent(QMouseEvent *event) { // default audio effects (after custom effects) c->effects.append(create_effect(c, get_internal_meta(EFFECT_INTERNAL_VOLUME, EFFECT_TYPE_EFFECT))); c->effects.append(create_effect(c, get_internal_meta(EFFECT_INTERNAL_PAN, EFFECT_TYPE_EFFECT))); - //c->media_type = MEDIA_TYPE_TONE; } push_undo = true; @@ -884,7 +883,10 @@ void TimelineWidget::mouseReleaseEvent(QMouseEvent *event) { for (int i=0;ighosts.size();i++) { const Ghost& g = panel_timeline->ghosts.at(i); - if (g.in != g.old_in || g.out != g.old_out || g.clip_in != g.old_clip_in) { + if (g.in != g.old_in + || g.out != g.old_out + || g.clip_in != g.old_clip_in + || g.track != g.old_track) { process_moving = true; break; }