diff --git a/effects/effect.cpp b/effects/effect.cpp
index 230c5a115..9336ef3c8 100644
--- a/effects/effect.cpp
+++ b/effects/effect.cpp
@@ -873,6 +873,7 @@ bool Effect::valueHasChanged(double timecode) {
void Effect::delete_texture() {
if (texture != NULL) {
+ texture->destroy();
delete texture;
texture = NULL;
}
diff --git a/effects/effects/bulge.frag b/effects/effects/bulge.frag
new file mode 100644
index 000000000..98f44d3fd
--- /dev/null
+++ b/effects/effects/bulge.frag
@@ -0,0 +1,31 @@
+#version 110
+
+uniform float amount;
+
+uniform sampler2D myTexture;
+varying vec2 vTexCoord;
+
+void main(void) {
+ float x = vTexCoord.x;
+ float y = vTexCoord.y;
+
+ float r = sqrt(pow(x - 0.5, 2.0) + pow(y - 0.5, 2.0));
+ float a = atan(y - 0.5, x - 0.5);
+ float rn = pow(r, (amount*0.1))/0.5;
+ //float a = atan(x - 0.5, y - 0.5);
+
+ x = rn * cos(a) + 0.5;
+ y = rn * sin(a) + 0.5;
+
+ if (y < 0.0 || y > 1.0 || x < 0.0 || x > 1.0) {
+ gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
+ } else {
+ vec4 textureColor = texture2D(myTexture, vec2(x, y));
+ gl_FragColor = vec4(
+ textureColor.r,
+ textureColor.g,
+ textureColor.b,
+ textureColor.a
+ );
+ }
+}
\ No newline at end of file
diff --git a/effects/effects/bulge.xml b/effects/effects/bulge.xml
new file mode 100644
index 000000000..c49b15df9
--- /dev/null
+++ b/effects/effects/bulge.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/effects/effects/colorcorrection.frag b/effects/effects/colorcorrection.frag
new file mode 100644
index 000000000..46f2713f6
--- /dev/null
+++ b/effects/effects/colorcorrection.frag
@@ -0,0 +1,74 @@
+#version 110
+
+uniform float temperature;
+uniform float tint;
+uniform float exposure;
+uniform float contrast;
+uniform float highlights;
+uniform float shadows;
+uniform float whites;
+uniform float blacks;
+uniform float saturation;
+
+uniform sampler2D myTexture;
+varying vec2 vTexCoord;
+
+void main(void) {
+ vec4 textureColor = texture2D(myTexture, vTexCoord);
+
+ vec3 rgb = textureColor.rgb;
+
+ // temperature
+ float temp = temperature * 0.01;
+ float redTemp = (temp <= 66.0) ? 1.0 : min(1.0, max(0.0,
+ (1.2929361861 * pow(temp - 60.0, -0.1332047592))
+ ));
+ float greenTemp = min(1.0, max(0.0,
+ (temp <= 66.0) ? (0.3900815788 * log(temp) - 0.6318414438) : (1.1298908609 * pow(temp - 60.0, -0.0755148492))
+ ));
+ float blueTemp = (temp >= 66.0) ? 1.0 : min(1.0, max(0.0,
+ (0.5432067891 * log(temp - 10.0) - 1.1962540891)
+ ));
+ rgb *= vec3(redTemp, greenTemp, blueTemp);
+
+ // tint
+ rgb.g *= ((tint*0.01)+1.0);
+
+ // exposure
+ rgb *= pow(2.0, exposure*0.01);
+
+ // contrast
+ float contr_val = (contrast*0.01);
+ rgb = (rgb*contr_val)-((contr_val-1.0)*0.5);
+
+
+ // shadows/highlights
+ //float luma = 0.33*rgb.r + 0.5*rgb.g + 0.16*rgb.b;
+ if (rgb.r < 0.5 && rgb.g < 0.5 && rgb.b < 0.5) {
+ float shadow_val = 1.0-(shadows*0.01);
+ rgb = vec3(pow(rgb.r*2.0, shadow_val)*0.5, pow(rgb.g*2.0, shadow_val)*0.5, pow(rgb.b*2.0, shadow_val)*0.5);
+ } else if (rgb.r > 0.5 && rgb.g > 0.5 && rgb.b > 0.5) {
+ float highlight_val = 1.0-(highlights*0.01);
+ rgb = vec3((pow((rgb.r-0.5)*2.0, highlight_val)*0.5)+0.5, (pow((rgb.g-0.5)*2.0, highlight_val)*0.5)+0.5, (pow((rgb.b-0.5)*2.0, highlight_val)*0.5)+0.5);
+ }
+
+
+ // whites
+ rgb *= (whites*0.01);
+
+ // blacks
+ float black_val = 2.0-(blacks*0.01);
+ rgb = (rgb*black_val)-(black_val-1.0);
+
+ // saturation
+ const vec3 W = vec3(0.2125, 0.7154, 0.0721);
+ vec3 intensity = vec3(dot(rgb, W));
+ rgb = mix(intensity, rgb, saturation*0.01);
+
+ gl_FragColor = vec4(
+ rgb.r,
+ rgb.g,
+ rgb.b,
+ textureColor.a
+ );
+}
diff --git a/effects/effects/colorcorrection.xml b/effects/effects/colorcorrection.xml
new file mode 100644
index 000000000..f103f3d82
--- /dev/null
+++ b/effects/effects/colorcorrection.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/effects/effects/common.frag b/effects/effects/common.frag
new file mode 100644
index 000000000..ec9d3f905
--- /dev/null
+++ b/effects/effects/common.frag
@@ -0,0 +1,14 @@
+#version 110
+
+uniform sampler2D myTexture;
+varying vec2 vTexCoord;
+
+void main(void) {
+ vec4 textureColor = texture2D(myTexture, vec2(vTexCoord.x, vTexCoord.y));
+ gl_FragColor = vec4(
+ textureColor.r,
+ textureColor.g,
+ textureColor.b,
+ textureColor.a
+ );
+}
\ No newline at end of file
diff --git a/effects/effects/flip.frag b/effects/effects/flip.frag
new file mode 100644
index 000000000..6a55cc8ca
--- /dev/null
+++ b/effects/effects/flip.frag
@@ -0,0 +1,23 @@
+#version 110
+
+uniform bool horiz;
+uniform bool vert;
+
+uniform sampler2D myTexture;
+varying vec2 vTexCoord;
+
+void main(void) {
+ float x = vTexCoord.x;
+ float y = vTexCoord.y;
+
+ if (horiz) x = 1.0 - x;
+ if (vert) y = 1.0 - y;
+
+ vec4 textureColor = texture2D(myTexture, vec2(x, y));
+ gl_FragColor = vec4(
+ textureColor.r,
+ textureColor.g,
+ textureColor.b,
+ textureColor.a
+ );
+}
\ No newline at end of file
diff --git a/effects/effects/flip.xml b/effects/effects/flip.xml
new file mode 100644
index 000000000..f3d762733
--- /dev/null
+++ b/effects/effects/flip.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/panels/effectcontrols.cpp b/panels/effectcontrols.cpp
index 59866e70d..7e2826225 100644
--- a/panels/effectcontrols.cpp
+++ b/panels/effectcontrols.cpp
@@ -296,7 +296,7 @@ void EffectControls::load_effects() {
}
}
if (selected_clips.size() > 0) {
- ui->verticalScrollBar->setMaximum(qMax(0, ui->effects_area->height() - ui->keyframeView->height() - ui->headers->height()));
+ ui->verticalScrollBar->setMaximum(qMax(0, ui->effects_area->sizeHint().height() - ui->headers->height() + ui->scrollArea->horizontalScrollBar()->height()/* - ui->keyframeView->height() - ui->headers->height()*/));
ui->keyframeView->setEnabled(true);
ui->headers->setVisible(true);
ui->keyframeView->update();
diff --git a/ui/viewerwidget.cpp b/ui/viewerwidget.cpp
index 48163a31f..7d9e43b1c 100644
--- a/ui/viewerwidget.cpp
+++ b/ui/viewerwidget.cpp
@@ -176,6 +176,8 @@ GLuint ViewerWidget::draw_clip(QOpenGLFramebufferObject* fbo, GLuint texture) {
fbo->bind();
+ glClear(GL_COLOR_BUFFER_BIT);
+
glBindTexture(GL_TEXTURE_2D, texture);
glBegin(GL_QUADS);
glTexCoord2f(0, 0); // top left
@@ -301,140 +303,138 @@ GLuint ViewerWidget::compose_sequence(Clip* nest, bool render_audio) {
textureID = -1;
}
- if (!texture_failed) {
- if (textureID == 0 && c->media_type != MEDIA_TYPE_SOLID) {
- dout << "[WARNING] Texture hasn't been created yet";
- texture_failed = true;
- } else if (playhead >= c->timeline_in) {
- glPushMatrix();
+ if (textureID == 0 && c->media_type != MEDIA_TYPE_SOLID) {
+ dout << "[WARNING] Texture hasn't been created yet";
+ texture_failed = true;
+ } else if (playhead >= c->timeline_in) {
+ glPushMatrix();
- // start preparing cache
- if (c->fbo == NULL) {
- c->fbo = new QOpenGLFramebufferObject* [2];
- c->fbo[0] = new QOpenGLFramebufferObject(video_width, video_height);
- c->fbo[1] = new QOpenGLFramebufferObject(video_width, video_height);
- }
-
- // clear fbos
- c->fbo[0]->bind();
- glClear(GL_COLOR_BUFFER_BIT);
- c->fbo[0]->release();
- c->fbo[1]->bind();
- glClear(GL_COLOR_BUFFER_BIT);
- c->fbo[1]->release();
-
- bool fbo_switcher = false;
-
- glViewport(0, 0, video_width, video_height);
-
- // for nested sequences
- if (c->media_type == MEDIA_TYPE_SEQUENCE) {
- textureID = compose_sequence(c, render_audio);
- fbo_switcher = true;
- }
-
- GLuint composite_texture;
- if (c->media_type == MEDIA_TYPE_SOLID) {
- composite_texture = c->fbo[fbo_switcher]->texture();
- } else {
- composite_texture = draw_clip(c->fbo[fbo_switcher], textureID);
- }
-
- fbo_switcher = !fbo_switcher;
-
- GLTextureCoords coords;
- coords.vertexTopLeftX = coords.vertexBottomLeftX = -video_width/2;
- coords.vertexTopLeftY = coords.vertexTopRightY = -video_height/2;
- coords.vertexTopRightX = coords.vertexBottomRightX = video_width/2;
- coords.vertexBottomLeftY = coords.vertexBottomRightY = video_height/2;
- coords.textureTopLeftY = coords.textureTopRightY = coords.textureTopLeftX = coords.textureBottomLeftX = 0;
- coords.textureBottomLeftY = coords.textureBottomRightY = coords.textureTopRightX = coords.textureBottomRightX = 1.0;
-
- if (c->autoscale && (video_width != s->width || video_height != s->height)) {
- double width_multiplier = (double) s->width / (double) video_width;
- double height_multiplier = (double) s->height / (double) video_height;
- double scale_multiplier = qMin(width_multiplier, height_multiplier);
- glScalef(scale_multiplier, scale_multiplier, 1);
- }
-
- // EFFECT CODE START
- for (int j=0;jeffects.size();j++) {
- Effect* e = c->effects.at(j);
- if (e->is_enabled()) {
- double timecode = ((double)(playhead-c->timeline_in+c->clip_in)/(double)c->sequence->frame_rate);
- if (e->enable_coords) {
- e->process_coords(timecode, coords);
- }
- if (e->enable_shader || e->enable_superimpose) {
- e->startEffect();
- if (e->enable_shader) {
- e->process_shader(timecode);
- }
- composite_texture = draw_clip(c->fbo[fbo_switcher], composite_texture);
- if (e->enable_superimpose) {
- GLuint superimpose_texture = e->process_superimpose(timecode);
- if (superimpose_texture != 0) draw_clip(c->fbo[fbo_switcher], superimpose_texture);
- }
- fbo_switcher = !fbo_switcher;
- }
- }
- }
-
- if (c->opening_transition != NULL) {
- int transition_progress = playhead - c->timeline_in;
- if (transition_progress < c->opening_transition->length) {
- c->opening_transition->process_transition((double)transition_progress/(double)c->opening_transition->length);
- }
- }
-
- if (c->closing_transition != NULL) {
- int transition_progress = c->closing_transition->length - (playhead - c->timeline_in - c->getLength() + c->closing_transition->length);
- if (transition_progress < c->closing_transition->length) {
- c->closing_transition->process_transition((double)transition_progress/(double)c->closing_transition->length);
- }
- }
-
- for (int j=0;jeffects.size();j++) {
- if ((c->effects.at(j)->enable_shader || c->effects.at(j)->enable_superimpose) && c->effects.at(j)->is_enabled()) {
- c->effects.at(j)->endEffect();
- }
- }
- // EFFECT CODE END
-
- if (nest != NULL) {
- nest->fbo[0]->bind();
- glViewport(0, 0, s->width, s->height);
- } else if (rendering) {
- glViewport(0, 0, s->width, s->height);
- } else {
- glViewport(0, 0, width(), height());
- }
-
- glBindTexture(GL_TEXTURE_2D, composite_texture);
-
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-
- 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();
-
- glBindTexture(GL_TEXTURE_2D, 0);
-
- if (nest != NULL) {
- nest->fbo[0]->release();
- if (default_fbo != NULL) default_fbo->bind();
- }
-
- glPopMatrix();
+ // start preparing cache
+ if (c->fbo == NULL) {
+ c->fbo = new QOpenGLFramebufferObject* [2];
+ c->fbo[0] = new QOpenGLFramebufferObject(video_width, video_height);
+ c->fbo[1] = new QOpenGLFramebufferObject(video_width, video_height);
}
+
+ // clear fbos
+ /*c->fbo[0]->bind();
+ glClear(GL_COLOR_BUFFER_BIT);
+ c->fbo[0]->release();
+ c->fbo[1]->bind();
+ glClear(GL_COLOR_BUFFER_BIT);
+ c->fbo[1]->release();*/
+
+ bool fbo_switcher = false;
+
+ glViewport(0, 0, video_width, video_height);
+
+ // for nested sequences
+ if (c->media_type == MEDIA_TYPE_SEQUENCE) {
+ textureID = compose_sequence(c, render_audio);
+ fbo_switcher = true;
+ }
+
+ GLuint composite_texture;
+ if (c->media_type == MEDIA_TYPE_SOLID) {
+ composite_texture = c->fbo[fbo_switcher]->texture();
+ } else {
+ composite_texture = draw_clip(c->fbo[fbo_switcher], textureID);
+ }
+
+ fbo_switcher = !fbo_switcher;
+
+ GLTextureCoords coords;
+ coords.vertexTopLeftX = coords.vertexBottomLeftX = -video_width/2;
+ coords.vertexTopLeftY = coords.vertexTopRightY = -video_height/2;
+ coords.vertexTopRightX = coords.vertexBottomRightX = video_width/2;
+ coords.vertexBottomLeftY = coords.vertexBottomRightY = video_height/2;
+ coords.textureTopLeftY = coords.textureTopRightY = coords.textureTopLeftX = coords.textureBottomLeftX = 0;
+ coords.textureBottomLeftY = coords.textureBottomRightY = coords.textureTopRightX = coords.textureBottomRightX = 1.0;
+
+ if (c->autoscale && (video_width != s->width || video_height != s->height)) {
+ double width_multiplier = (double) s->width / (double) video_width;
+ double height_multiplier = (double) s->height / (double) video_height;
+ double scale_multiplier = qMin(width_multiplier, height_multiplier);
+ glScalef(scale_multiplier, scale_multiplier, 1);
+ }
+
+ // EFFECT CODE START
+ for (int j=0;jeffects.size();j++) {
+ Effect* e = c->effects.at(j);
+ if (e->is_enabled()) {
+ double timecode = ((double)(playhead-c->timeline_in+c->clip_in)/(double)c->sequence->frame_rate);
+ if (e->enable_coords) {
+ e->process_coords(timecode, coords);
+ }
+ if (e->enable_shader || e->enable_superimpose) {
+ e->startEffect();
+ if (e->enable_shader) {
+ e->process_shader(timecode);
+ }
+ composite_texture = draw_clip(c->fbo[fbo_switcher], composite_texture);
+ if (e->enable_superimpose) {
+ GLuint superimpose_texture = e->process_superimpose(timecode);
+ if (superimpose_texture != 0) draw_clip(c->fbo[fbo_switcher], superimpose_texture);
+ }
+ fbo_switcher = !fbo_switcher;
+ }
+ }
+ }
+
+ if (c->opening_transition != NULL) {
+ int transition_progress = playhead - c->timeline_in;
+ if (transition_progress < c->opening_transition->length) {
+ c->opening_transition->process_transition((double)transition_progress/(double)c->opening_transition->length);
+ }
+ }
+
+ if (c->closing_transition != NULL) {
+ int transition_progress = c->closing_transition->length - (playhead - c->timeline_in - c->getLength() + c->closing_transition->length);
+ if (transition_progress < c->closing_transition->length) {
+ c->closing_transition->process_transition((double)transition_progress/(double)c->closing_transition->length);
+ }
+ }
+
+ for (int j=0;jeffects.size();j++) {
+ if ((c->effects.at(j)->enable_shader || c->effects.at(j)->enable_superimpose) && c->effects.at(j)->is_enabled()) {
+ c->effects.at(j)->endEffect();
+ }
+ }
+ // EFFECT CODE END
+
+ if (nest != NULL) {
+ nest->fbo[0]->bind();
+ glViewport(0, 0, s->width, s->height);
+ } else if (rendering) {
+ glViewport(0, 0, s->width, s->height);
+ } else {
+ glViewport(0, 0, width(), height());
+ }
+
+ glBindTexture(GL_TEXTURE_2D, composite_texture);
+
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ 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();
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ if (nest != NULL) {
+ nest->fbo[0]->release();
+ if (default_fbo != NULL) default_fbo->bind();
+ }
+
+ glPopMatrix();
}
} else {
if (render_audio || (config.enable_audio_scrubbing && audio_scrub)) {