ported ALL effects to opengl
This commit is contained in:
+83
-4
@@ -95,8 +95,9 @@ Effect::Effect(Clip* c, int t, int i) :
|
||||
parent_clip(c),
|
||||
type(t),
|
||||
id(i),
|
||||
enable_image(false),
|
||||
enable_opengl(false),
|
||||
enable_shader(false),
|
||||
enable_coords(false),
|
||||
enable_superimpose(false),
|
||||
iterations(1),
|
||||
isOpen(false),
|
||||
glslProgram(NULL),
|
||||
@@ -355,10 +356,88 @@ Effect* Effect::copy(Clip* c) {
|
||||
return copy;
|
||||
}
|
||||
|
||||
void Effect::process_image(double, uint8_t*, int, int) {}
|
||||
void Effect::process_gl(double, GLTextureCoords&) {}
|
||||
void Effect::process_shader(double) {}
|
||||
void Effect::process_coords(double, GLTextureCoords&) {}
|
||||
const GLuint Effect::process_superimpose(double) {return 0;}
|
||||
void Effect::process_audio(double, double, quint8*, int, int) {}
|
||||
|
||||
SuperimposeEffect::SuperimposeEffect(Clip* c, int t, int i) : Effect(c, t, i), texture(NULL) {
|
||||
enable_superimpose = true;
|
||||
}
|
||||
|
||||
void SuperimposeEffect::open() {
|
||||
Effect::open();
|
||||
texture = new QOpenGLTexture(QOpenGLTexture::Target2D);
|
||||
}
|
||||
|
||||
void SuperimposeEffect::close() {
|
||||
Effect::close();
|
||||
deleteTexture();
|
||||
}
|
||||
|
||||
const GLuint SuperimposeEffect::process_superimpose(double timecode) {
|
||||
bool recreate_texture = false;
|
||||
int width = parent_clip->getWidth();
|
||||
int height = parent_clip->getHeight();
|
||||
|
||||
if (width != img.width() || height != img.height()) {
|
||||
img = QImage(width, height, QImage::Format_RGBA8888);
|
||||
recreate_texture = true;
|
||||
}
|
||||
|
||||
if (valueHasChanged(timecode) || recreate_texture) {
|
||||
redraw(timecode);
|
||||
}
|
||||
|
||||
if (texture != NULL) {
|
||||
if (recreate_texture || texture->width() != img.width() || texture->height() != img.height()) {
|
||||
deleteTexture();
|
||||
texture = new QOpenGLTexture(QOpenGLTexture::Target2D);
|
||||
texture->setData(img);
|
||||
} else {
|
||||
texture->setData(0, QOpenGLTexture::RGBA, QOpenGLTexture::UInt8, img.constBits());
|
||||
}
|
||||
return texture->textureId();
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
void SuperimposeEffect::redraw(double) {}
|
||||
|
||||
void SuperimposeEffect::deleteTexture() {
|
||||
delete texture;
|
||||
texture = NULL;
|
||||
}
|
||||
|
||||
bool SuperimposeEffect::valueHasChanged(double timecode) {
|
||||
if (cachedValues.size() == 0) {
|
||||
for (int i=0;i<row_count();i++) {
|
||||
EffectRow* crow = row(i);
|
||||
for (int j=0;j<crow->fieldCount();j++) {
|
||||
cachedValues.append(crow->field(j)->get_current_data());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
bool changed = false;
|
||||
int index = 0;
|
||||
for (int i=0;i<row_count();i++) {
|
||||
EffectRow* crow = row(i);
|
||||
for (int j=0;j<crow->fieldCount();j++) {
|
||||
EffectField* field = crow->field(j);
|
||||
field->validate_keyframe_data(timecode);
|
||||
if (cachedValues.at(index) != field->get_current_data()) {
|
||||
changed = true;
|
||||
}
|
||||
cachedValues[index] = field->get_current_data();
|
||||
index++;
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
}
|
||||
|
||||
/* Effect Row Definitions */
|
||||
|
||||
EffectRow::EffectRow(Effect *parent, QGridLayout *uilayout, const QString &n, int row) :
|
||||
|
||||
+28
-8
@@ -5,7 +5,9 @@
|
||||
#include <QString>
|
||||
#include <QVector>
|
||||
#include <QColor>
|
||||
#include <QOpenGLFunctions>
|
||||
#include <QOpenGLShaderProgram>
|
||||
#include <QOpenGLTexture>
|
||||
class QLabel;
|
||||
class QWidget;
|
||||
class CollapsibleWidget;
|
||||
@@ -193,21 +195,23 @@ public:
|
||||
void save(QXmlStreamWriter& stream);
|
||||
|
||||
// glsl handling
|
||||
void open();
|
||||
void close();
|
||||
void startEffect();
|
||||
void endEffect();
|
||||
virtual void open();
|
||||
virtual void close();
|
||||
virtual void startEffect();
|
||||
virtual void endEffect();
|
||||
|
||||
bool enable_image;
|
||||
bool enable_opengl;
|
||||
bool enable_shader;
|
||||
bool enable_coords;
|
||||
bool enable_superimpose;
|
||||
|
||||
int getIterations();
|
||||
void setIterations(int i);
|
||||
|
||||
const char* ffmpeg_filter;
|
||||
|
||||
virtual void process_image(double timecode, uint8_t* data, int width, int height);
|
||||
virtual void process_gl(double timecode, GLTextureCoords& coords);
|
||||
virtual void process_shader(double timecode);
|
||||
virtual void process_coords(double timecode, GLTextureCoords& coords);
|
||||
virtual const GLuint process_superimpose(double timecode);
|
||||
virtual void process_audio(double timecode_start, double timecode_end, quint8* samples, int nb_bytes, int channel_count);
|
||||
public slots:
|
||||
void field_changed();
|
||||
@@ -224,4 +228,20 @@ private:
|
||||
bool bound;
|
||||
};
|
||||
|
||||
class SuperimposeEffect : public Effect {
|
||||
public:
|
||||
SuperimposeEffect(Clip* c, int t, int i);
|
||||
virtual void open();
|
||||
virtual void close();
|
||||
virtual const GLuint process_superimpose(double timecode);
|
||||
virtual void redraw(double timecode);
|
||||
protected:
|
||||
QImage img;
|
||||
QOpenGLTexture* texture;
|
||||
void deleteTexture();
|
||||
bool valueHasChanged(double timecode);
|
||||
private:
|
||||
QVector<QVariant> cachedValues;
|
||||
};
|
||||
|
||||
#endif // EFFECT_H
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#include "project/clip.h"
|
||||
|
||||
BoxBlurEffect::BoxBlurEffect(Clip *c) : Effect(c, EFFECT_TYPE_VIDEO, VIDEO_BOXBLUR_EFFECT) {
|
||||
enable_opengl = true;
|
||||
enable_shader = true;
|
||||
|
||||
radius_val = add_row("Radius:")->add_field(EFFECT_FIELD_DOUBLE);
|
||||
// iteration_val = add_row("Iterations:")->add_field(EFFECT_FIELD_DOUBLE);
|
||||
@@ -33,7 +33,7 @@ BoxBlurEffect::BoxBlurEffect(Clip *c) : Effect(c, EFFECT_TYPE_VIDEO, VIDEO_BOXBL
|
||||
connect(vert_val, SIGNAL(changed()), this, SLOT(field_changed()));
|
||||
}
|
||||
|
||||
void BoxBlurEffect::process_gl(double timecode, GLTextureCoords&) {
|
||||
void BoxBlurEffect::process_shader(double timecode) {
|
||||
glslProgram->setUniformValue("resolution", parent_clip->getWidth(), parent_clip->getHeight());
|
||||
glslProgram->setUniformValue("radius", (GLfloat) radius_val->get_double_value(timecode));
|
||||
glslProgram->setUniformValue("horiz_blur", horiz_val->get_bool_value(timecode));
|
||||
|
||||
@@ -7,8 +7,7 @@ class BoxBlurEffect : public Effect
|
||||
{
|
||||
public:
|
||||
BoxBlurEffect(Clip* c);
|
||||
|
||||
void process_gl(double timecode, GLTextureCoords &coords);
|
||||
void process_shader(double timecode);
|
||||
private:
|
||||
EffectField* radius_val;
|
||||
EffectField* iteration_val;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "chromakeyeffect.h"
|
||||
|
||||
ChromaKeyEffect::ChromaKeyEffect(Clip* c) : Effect(c, EFFECT_TYPE_VIDEO, VIDEO_CHROMAKEY_EFFECT) {
|
||||
enable_opengl = true;
|
||||
enable_shader = true;
|
||||
|
||||
color_field = add_row("Color:")->add_field(EFFECT_FIELD_COLOR);
|
||||
tolerance_field = add_row("Tolerance:")->add_field(EFFECT_FIELD_DOUBLE);
|
||||
@@ -19,7 +19,7 @@ ChromaKeyEffect::ChromaKeyEffect(Clip* c) : Effect(c, EFFECT_TYPE_VIDEO, VIDEO_C
|
||||
connect(tolerance_field, SIGNAL(changed()), this, SLOT(field_changed()));
|
||||
}
|
||||
|
||||
void ChromaKeyEffect::process_gl(double timecode, GLTextureCoords&) {
|
||||
void ChromaKeyEffect::process_shader(double timecode) {
|
||||
glslProgram->setUniformValue("keyColor", color_field->get_color_value(timecode));
|
||||
glslProgram->setUniformValue("threshold", (GLfloat) (tolerance_field->get_double_value(timecode)*0.01));
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
class ChromaKeyEffect : public Effect {
|
||||
public:
|
||||
ChromaKeyEffect(Clip* c);
|
||||
void process_gl(double timecode, GLTextureCoords &coords);
|
||||
void process_shader(double timecode);
|
||||
private:
|
||||
EffectField* color_field;
|
||||
EffectField* tolerance_field;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "cropeffect.h"
|
||||
|
||||
CropEffect::CropEffect(Clip *c) : Effect(c, EFFECT_TYPE_VIDEO, VIDEO_CROP_EFFECT) {
|
||||
enable_opengl = true;
|
||||
enable_coords = true;
|
||||
|
||||
left_field = add_row("Left:")->add_field(EFFECT_FIELD_DOUBLE);
|
||||
top_field = add_row("Top:")->add_field(EFFECT_FIELD_DOUBLE);
|
||||
@@ -23,7 +23,7 @@ CropEffect::CropEffect(Clip *c) : Effect(c, EFFECT_TYPE_VIDEO, VIDEO_CROP_EFFECT
|
||||
connect(bottom_field, SIGNAL(changed()), this, SLOT(field_changed()));
|
||||
}
|
||||
|
||||
void CropEffect::process_gl(double timecode, GLTextureCoords &coords) {
|
||||
void CropEffect::process_coords(double timecode, GLTextureCoords &coords) {
|
||||
// store initial coord data
|
||||
int left = coords.vertexTopLeftX;
|
||||
int top = coords.vertexTopLeftY;
|
||||
|
||||
@@ -7,7 +7,7 @@ class CropEffect : public Effect
|
||||
{
|
||||
public:
|
||||
CropEffect(Clip* c);
|
||||
void process_gl(double timecode, GLTextureCoords &coords);
|
||||
void process_coords(double timecode, GLTextureCoords &coords);
|
||||
private:
|
||||
EffectField* left_field;
|
||||
EffectField* top_field;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "flipeffect.h"
|
||||
|
||||
FlipEffect::FlipEffect(Clip *c) : Effect(c, EFFECT_TYPE_VIDEO, VIDEO_FLIP_EFFECT) {
|
||||
enable_opengl = true;
|
||||
enable_coords = true;
|
||||
|
||||
horizontal_field = add_row("Horizontal:")->add_field(EFFECT_FIELD_BOOL);
|
||||
vertical_field = add_row("Vertical:")->add_field(EFFECT_FIELD_BOOL);
|
||||
@@ -10,7 +10,7 @@ FlipEffect::FlipEffect(Clip *c) : Effect(c, EFFECT_TYPE_VIDEO, VIDEO_FLIP_EFFECT
|
||||
connect(vertical_field, SIGNAL(changed()), this, SLOT(field_changed()));
|
||||
}
|
||||
|
||||
void FlipEffect::process_gl(double timecode, GLTextureCoords &coords) {
|
||||
void FlipEffect::process_coords(double timecode, GLTextureCoords &coords) {
|
||||
if (horizontal_field->get_bool_value(timecode)) {
|
||||
double tlX = coords.textureTopLeftX;
|
||||
double blX = coords.textureBottomLeftX;
|
||||
|
||||
@@ -7,7 +7,7 @@ class FlipEffect : public Effect
|
||||
{
|
||||
public:
|
||||
FlipEffect(Clip* c);
|
||||
void process_gl(double timecode, GLTextureCoords &coords);
|
||||
void process_coords(double timecode, GLTextureCoords &coords);
|
||||
private:
|
||||
EffectField* horizontal_field;
|
||||
EffectField* vertical_field;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#include <QImage>
|
||||
|
||||
GaussianBlurEffect::GaussianBlurEffect(Clip *c) : Effect(c, EFFECT_TYPE_VIDEO, VIDEO_GAUSSIANBLUR_EFFECT) {
|
||||
enable_opengl = true;
|
||||
enable_shader = true;
|
||||
|
||||
radius_val = add_row("Radius:")->add_field(EFFECT_FIELD_DOUBLE);
|
||||
sigma_val = add_row("Sigma:")->add_field(EFFECT_FIELD_DOUBLE);
|
||||
@@ -30,7 +30,7 @@ GaussianBlurEffect::GaussianBlurEffect(Clip *c) : Effect(c, EFFECT_TYPE_VIDEO, V
|
||||
connect(vert_val, SIGNAL(changed()), this, SLOT(field_changed()));
|
||||
}
|
||||
|
||||
void GaussianBlurEffect::process_gl(double timecode, GLTextureCoords &coords) {
|
||||
void GaussianBlurEffect::process_shader(double timecode) {
|
||||
glslProgram->setUniformValue("resolution", parent_clip->getWidth(), parent_clip->getHeight());
|
||||
glslProgram->setUniformValue("radius", (GLfloat) radius_val->get_double_value(timecode));
|
||||
glslProgram->setUniformValue("sigma", (GLfloat) sigma_val->get_double_value(timecode));
|
||||
|
||||
@@ -7,7 +7,7 @@ class GaussianBlurEffect : public Effect
|
||||
{
|
||||
public:
|
||||
GaussianBlurEffect(Clip* c);
|
||||
void process_gl(double timecode, GLTextureCoords &coords);
|
||||
void process_shader(double timecode);
|
||||
private:
|
||||
EffectField* radius_val;
|
||||
EffectField* sigma_val;
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include <QXmlStreamAttributes>
|
||||
|
||||
InvertEffect::InvertEffect(Clip* c) : Effect(c, EFFECT_TYPE_VIDEO, VIDEO_INVERT_EFFECT) {
|
||||
enable_opengl = true;
|
||||
enable_shader = true;
|
||||
|
||||
EffectRow* amount_row = add_row("Amount:");
|
||||
amount_val = amount_row->add_field(EFFECT_FIELD_DOUBLE);
|
||||
@@ -26,6 +26,6 @@ InvertEffect::InvertEffect(Clip* c) : Effect(c, EFFECT_TYPE_VIDEO, VIDEO_INVERT_
|
||||
fragPath = ":/shaders/inverteffect.frag";
|
||||
}
|
||||
|
||||
void InvertEffect::process_gl(double timecode, GLTextureCoords&) {
|
||||
void InvertEffect::process_shader(double timecode) {
|
||||
glslProgram->setUniformValue("amount_val", (GLfloat) (amount_val->get_double_value(timecode)*0.01));
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ class InvertEffect : public Effect {
|
||||
Q_OBJECT
|
||||
public:
|
||||
InvertEffect(Clip* c);
|
||||
void process_gl(double timecode, GLTextureCoords& coords);
|
||||
void process_shader(double timecode);
|
||||
private:
|
||||
EffectField* amount_val;
|
||||
};
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#include "panels/timeline.h"
|
||||
|
||||
ShakeEffect::ShakeEffect(Clip *c) : Effect(c, EFFECT_TYPE_VIDEO, VIDEO_SHAKE_EFFECT), inside(false) {
|
||||
enable_opengl = true;
|
||||
enable_coords = true;
|
||||
|
||||
EffectRow* intensity_row = add_row("Intensity:");
|
||||
intensity_val = intensity_row->add_field(EFFECT_FIELD_DOUBLE);
|
||||
@@ -49,7 +49,7 @@ void ShakeEffect::refresh() {
|
||||
}
|
||||
}
|
||||
|
||||
void ShakeEffect::process_gl(double timecode, GLTextureCoords&) {
|
||||
void ShakeEffect::process_coords(double timecode, GLTextureCoords&) {
|
||||
if (shake_progress > shake_limit) {
|
||||
double ival = intensity_val->get_double_value(timecode);
|
||||
if ((int)ival > 0) {
|
||||
|
||||
@@ -7,7 +7,7 @@ class ShakeEffect : public Effect {
|
||||
Q_OBJECT
|
||||
public:
|
||||
ShakeEffect(Clip* c);
|
||||
void process_gl(double timecode, GLTextureCoords& coords);
|
||||
void process_coords(double timecode, GLTextureCoords& coords);
|
||||
|
||||
EffectField* intensity_val;
|
||||
EffectField* rotation_val;
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <QPainter>
|
||||
#include <QtMath>
|
||||
#include <QVariant>
|
||||
#include <QImage>
|
||||
|
||||
#include "project/clip.h"
|
||||
#include "project/sequence.h"
|
||||
@@ -15,9 +16,7 @@
|
||||
#define SMPTE_STRIP_COUNT 3
|
||||
#define SMPTE_LOWER_BARS 4
|
||||
|
||||
SolidEffect::SolidEffect(Clip* c) : Effect(c, EFFECT_TYPE_VIDEO, VIDEO_SOLID_EFFECT) {
|
||||
enable_opengl = true;
|
||||
|
||||
SolidEffect::SolidEffect(Clip* c) : SuperimposeEffect(c, EFFECT_TYPE_VIDEO, VIDEO_SOLID_EFFECT) {
|
||||
solid_type = add_row("Type:")->add_field(EFFECT_FIELD_COMBO);
|
||||
solid_type->add_combo_item("Solid Color", SOLID_TYPE_COLOR);
|
||||
solid_type->add_combo_item("SMPTE Bars", SOLID_TYPE_BARS);
|
||||
@@ -38,14 +37,113 @@ SolidEffect::SolidEffect(Clip* c) : Effect(c, EFFECT_TYPE_VIDEO, VIDEO_SOLID_EFF
|
||||
fragPath = ":/shaders/solideffect.frag";
|
||||
}
|
||||
|
||||
void SolidEffect::process_gl(double timecode, GLTextureCoords&) {
|
||||
solid_color_field->set_enabled(solid_type->get_combo_data(timecode) == SOLID_TYPE_COLOR);
|
||||
/*void SolidEffect::process_gl(double timecode, GLTextureCoords&) {
|
||||
|
||||
|
||||
glslProgram->setUniformValue("solidColor", solid_color_field->get_color_value(timecode));
|
||||
glslProgram->setUniformValue("amount_val", (GLfloat) (opacity_field->get_double_value(timecode)*0.01));
|
||||
}*/
|
||||
|
||||
void SolidEffect::redraw(double timecode) {
|
||||
int w = img.width();
|
||||
int h = img.height();
|
||||
int alpha = (opacity_field->get_double_value(timecode)*2.55);
|
||||
switch (solid_type->get_combo_data(timecode).toInt()) {
|
||||
case SOLID_TYPE_COLOR:
|
||||
{
|
||||
QColor solidColor = solid_color_field->get_color_value(timecode);
|
||||
solidColor.setAlpha(alpha);
|
||||
img.fill(solidColor);
|
||||
}
|
||||
break;
|
||||
case SOLID_TYPE_BARS:
|
||||
{
|
||||
// draw smpte bars
|
||||
QPainter p(&img);
|
||||
img.fill(Qt::transparent);
|
||||
int bar_width = qCeil((double) w / 7.0);
|
||||
int first_bar_height = qCeil((double) h / 3.0 * 2.0);
|
||||
int second_bar_height = qCeil((double) h / 12.5);
|
||||
int third_bar_y = first_bar_height + second_bar_height;
|
||||
int third_bar_height = h - third_bar_y;
|
||||
int third_bar_width = 0;
|
||||
int bar_x, strip_width;
|
||||
QColor first_color, second_color, third_color;
|
||||
for (int i=0;i<SMPTE_BARS;i++) {
|
||||
bar_x = bar_width*i;
|
||||
switch (i) {
|
||||
case 0:
|
||||
first_color = QColor(192, 192, 192);
|
||||
second_color = QColor(0, 0, 192);
|
||||
break;
|
||||
case 1:
|
||||
first_color = QColor(192, 192, 0);
|
||||
second_color = QColor(19, 19, 19);
|
||||
break;
|
||||
case 2:
|
||||
first_color = QColor(0, 192, 192);
|
||||
second_color = QColor(192, 0, 192);
|
||||
break;
|
||||
case 3:
|
||||
first_color = QColor(0, 192, 0);
|
||||
second_color = QColor(19, 19, 19);
|
||||
break;
|
||||
case 4:
|
||||
first_color = QColor(192, 0, 192);
|
||||
second_color = QColor(0, 192, 192);
|
||||
break;
|
||||
case 5:
|
||||
third_bar_width = qRound((double) bar_x / (double) SMPTE_LOWER_BARS);
|
||||
|
||||
first_color = QColor(192, 0, 0);
|
||||
second_color = QColor(19, 19, 19);
|
||||
|
||||
strip_width = qCeil(bar_width/SMPTE_STRIP_COUNT);
|
||||
for (int j=0;j<SMPTE_STRIP_COUNT;j++) {
|
||||
switch (j) {
|
||||
case 0:
|
||||
third_color = QColor(29, 29, 29, alpha);
|
||||
p.fillRect(QRect(bar_x, third_bar_y, bar_width, third_bar_height), third_color);
|
||||
break;
|
||||
case 1:
|
||||
third_color = QColor(19, 19, 19, alpha);
|
||||
p.fillRect(QRect(bar_x + strip_width, third_bar_y, strip_width, third_bar_height), third_color);
|
||||
break;
|
||||
case 2:
|
||||
third_color = QColor(9, 9, 9, alpha);
|
||||
p.fillRect(QRect(bar_x, third_bar_y, strip_width, third_bar_height), third_color);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
first_color = QColor(0, 0, 192);
|
||||
second_color = QColor(192, 192, 192);
|
||||
p.fillRect(QRect(bar_x, third_bar_y, bar_width, third_bar_height), QColor(19, 19, 19, alpha));
|
||||
break;
|
||||
}
|
||||
first_color.setAlpha(alpha);
|
||||
second_color.setAlpha(alpha);
|
||||
p.fillRect(QRect(bar_x, 0, bar_width, first_bar_height), first_color);
|
||||
p.fillRect(QRect(bar_x, first_bar_height, bar_width, second_bar_height), second_color);
|
||||
}
|
||||
for (int i=0;i<SMPTE_LOWER_BARS;i++) {
|
||||
bar_x = third_bar_width*i;
|
||||
switch (i) {
|
||||
case 0: third_color = QColor(0, 33, 76); break;
|
||||
case 1: third_color = QColor(255, 255, 255); break;
|
||||
case 2: third_color = QColor(50, 0, 106); break;
|
||||
case 3: third_color = QColor(19, 19, 19); break;
|
||||
}
|
||||
third_color.setAlpha(alpha);
|
||||
p.fillRect(QRect(bar_x, third_bar_y, third_bar_width, third_bar_height), third_color);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void SolidEffect::process_image(long frame, uint8_t* data, int w, int h) {
|
||||
/*void SolidEffect::process_image(long frame, uint8_t* data, int w, int h) {
|
||||
QImage img(data, w, h, QImage::Format_RGBA8888); // create QImage wrapper
|
||||
QPainter p(&img);
|
||||
int width = img.width();
|
||||
@@ -136,4 +234,4 @@ void SolidEffect::process_image(long frame, uint8_t* data, int w, int h) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
@@ -3,15 +3,17 @@
|
||||
|
||||
#include "../effect.h"
|
||||
|
||||
class SolidEffect : public Effect {
|
||||
class QOpenGLTexture;
|
||||
#include <QImage>
|
||||
|
||||
class SolidEffect : public SuperimposeEffect {
|
||||
Q_OBJECT
|
||||
public:
|
||||
SolidEffect(Clip* c);
|
||||
EffectField* solid_type;
|
||||
EffectField* solid_color_field;
|
||||
EffectField* opacity_field;
|
||||
void process_gl(double timecode, GLTextureCoords& coords);
|
||||
void process_image(long p, uint8_t* data, int width, int height);
|
||||
void redraw(double timecode);
|
||||
};
|
||||
|
||||
#endif // SOLIDEFFECT_H
|
||||
|
||||
+186
-70
@@ -21,9 +21,9 @@
|
||||
#include "ui/fontcombobox.h"
|
||||
|
||||
TextEffect::TextEffect(Clip *c) :
|
||||
Effect(c, EFFECT_TYPE_VIDEO, VIDEO_TEXT_EFFECT)
|
||||
SuperimposeEffect(c, EFFECT_TYPE_VIDEO, VIDEO_TEXT_EFFECT)
|
||||
{
|
||||
enable_image = true;
|
||||
enable_superimpose = true;
|
||||
|
||||
text_val = add_row("Text:")->add_field(EFFECT_FIELD_STRING, 2);
|
||||
|
||||
@@ -98,6 +98,186 @@ TextEffect::TextEffect(Clip *c) :
|
||||
connect(outline_bool, SIGNAL(toggled(bool)), this, SLOT(outline_enable(bool)));
|
||||
}
|
||||
|
||||
void blurred2(QImage& result, const QRect& rect, int radius, bool alphaOnly = false) {
|
||||
int tab[] = { 14, 10, 8, 6, 5, 5, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2 };
|
||||
int alpha = (radius < 1) ? 16 : (radius > 17) ? 1 : tab[radius-1];
|
||||
|
||||
int r1 = rect.top();
|
||||
int r2 = rect.bottom();
|
||||
int c1 = rect.left();
|
||||
int c2 = rect.right();
|
||||
|
||||
int bpl = result.bytesPerLine();
|
||||
int rgba[4];
|
||||
unsigned char* p;
|
||||
|
||||
int i1 = 0;
|
||||
int i2 = 3;
|
||||
|
||||
if (alphaOnly)
|
||||
i1 = i2 = (QSysInfo::ByteOrder == QSysInfo::BigEndian ? 0 : 3);
|
||||
|
||||
for (int col = c1; col <= c2; col++) {
|
||||
p = result.scanLine(r1) + col * 4;
|
||||
for (int i = i1; i <= i2; i++)
|
||||
rgba[i] = p[i] << 4;
|
||||
|
||||
p += bpl;
|
||||
for (int j = r1; j < r2; j++, p += bpl)
|
||||
for (int i = i1; i <= i2; i++)
|
||||
p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4;
|
||||
}
|
||||
|
||||
for (int row = r1; row <= r2; row++) {
|
||||
p = result.scanLine(row) + c1 * 4;
|
||||
for (int i = i1; i <= i2; i++)
|
||||
rgba[i] = p[i] << 4;
|
||||
|
||||
p += 4;
|
||||
for (int j = c1; j < c2; j++, p += 4)
|
||||
for (int i = i1; i <= i2; i++)
|
||||
p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4;
|
||||
}
|
||||
|
||||
for (int col = c1; col <= c2; col++) {
|
||||
p = result.scanLine(r2) + col * 4;
|
||||
for (int i = i1; i <= i2; i++)
|
||||
rgba[i] = p[i] << 4;
|
||||
|
||||
p -= bpl;
|
||||
for (int j = r1; j < r2; j++, p -= bpl)
|
||||
for (int i = i1; i <= i2; i++)
|
||||
p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4;
|
||||
}
|
||||
|
||||
for (int row = r1; row <= r2; row++) {
|
||||
p = result.scanLine(row) + c2 * 4;
|
||||
for (int i = i1; i <= i2; i++)
|
||||
rgba[i] = p[i] << 4;
|
||||
|
||||
p -= 4;
|
||||
for (int j = c1; j < c2; j++, p -= 4)
|
||||
for (int i = i1; i <= i2; i++)
|
||||
p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4;
|
||||
}
|
||||
}
|
||||
|
||||
void TextEffect::redraw(double timecode) {
|
||||
img.fill(Qt::transparent);
|
||||
|
||||
QPainter p(&img);
|
||||
p.setRenderHint(QPainter::Antialiasing);
|
||||
int width = img.width();
|
||||
int height = img.height();
|
||||
|
||||
// set font
|
||||
font.setStyleHint(QFont::Helvetica, QFont::PreferAntialias);
|
||||
font.setFamily(set_font_combobox->get_font_name(timecode));
|
||||
font.setPointSize(size_val->get_double_value(timecode));
|
||||
p.setFont(font);
|
||||
QFontMetrics fm(font);
|
||||
|
||||
QStringList lines = text_val->get_string_value(timecode).split('\n');
|
||||
|
||||
// word wrap function
|
||||
if (word_wrap_field->get_bool_value(timecode)) {
|
||||
for (int i=0;i<lines.size();i++) {
|
||||
QString s(lines.at(i));
|
||||
if (fm.width(s) > width) {
|
||||
int last_space_index = 0;
|
||||
for (int j=0;j<s.length();j++) {
|
||||
if (s.at(j) == ' ') {
|
||||
if (fm.width(s.left(j)) > width) {
|
||||
break;
|
||||
} else {
|
||||
last_space_index = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (last_space_index > 0) {
|
||||
lines.insert(i+1, s.mid(last_space_index + 1));
|
||||
lines[i] = s.left(last_space_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QPainterPath path;
|
||||
|
||||
int text_height = fm.height()*lines.size();
|
||||
|
||||
for (int i=0;i<lines.size();i++) {
|
||||
int text_x, text_y;
|
||||
|
||||
switch (halign_field->get_combo_data(timecode).toInt()) {
|
||||
case Qt::AlignLeft: text_x = 0; break;
|
||||
case Qt::AlignHCenter: text_x = (width/2) - (fm.width(lines.at(i))/2); break;
|
||||
case Qt::AlignRight: text_x = width - fm.width(lines.at(i)); break;
|
||||
case Qt::AlignJustify:
|
||||
// add spaces until the string is too big
|
||||
text_x = 0;
|
||||
while (fm.width(lines.at(i) < width)) {
|
||||
bool space = false;
|
||||
QString spaced(lines.at(i));
|
||||
for (int i=0;i<spaced.length();i++) {
|
||||
if (spaced.at(i) == ' ') {
|
||||
// insert a space
|
||||
spaced.insert(i, ' ');
|
||||
space = true;
|
||||
|
||||
// scan to next non-space
|
||||
while (i < spaced.length() && spaced.at(i) == ' ') i++;
|
||||
}
|
||||
}
|
||||
if (fm.width(spaced) > width || !space) {
|
||||
break;
|
||||
} else {
|
||||
lines[i] = spaced;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
switch (valign_field->get_combo_data(timecode).toInt()) {
|
||||
case Qt::AlignTop: text_y = (fm.height()*i)+fm.ascent(); break;
|
||||
case Qt::AlignVCenter: text_y = ((height/2) - (text_height/2) - fm.descent()) + (fm.height()*(i+1)); break;
|
||||
case Qt::AlignBottom: text_y = (height - text_height - fm.descent()) + (fm.height()*(i+1)); break;
|
||||
}
|
||||
|
||||
path.addText(text_x, text_y, font, lines.at(i));
|
||||
}
|
||||
|
||||
p.setPen(Qt::NoPen);
|
||||
|
||||
// draw shadow
|
||||
if (shadow_bool->get_bool_value(timecode)) {
|
||||
int shadow_offset = shadow_distance->get_double_value(timecode);
|
||||
|
||||
QPainterPath shadow_path(path);
|
||||
shadow_path.translate(shadow_offset, shadow_offset);
|
||||
|
||||
QColor col = shadow_color->get_color_value(timecode);
|
||||
col.setAlphaF(shadow_opacity->get_double_value(timecode)*0.01);
|
||||
p.setBrush(col);
|
||||
p.drawPath(shadow_path);
|
||||
|
||||
int blurSoftness = shadow_softness->get_double_value(timecode);
|
||||
if (blurSoftness > 0) blurred2(img, img.rect(), blurSoftness, false);
|
||||
}
|
||||
|
||||
// draw outline
|
||||
int outline_width_val = outline_width->get_double_value(timecode);
|
||||
if (outline_bool->get_bool_value(timecode) && outline_width_val > 0) {
|
||||
QPen outline(outline_color->get_color_value(timecode));
|
||||
outline.setWidth(outline_width_val);
|
||||
p.setPen(outline);
|
||||
}
|
||||
|
||||
// draw "master" text
|
||||
p.setBrush(set_color_button->get_color_value(timecode));
|
||||
p.drawPath(path);
|
||||
}
|
||||
|
||||
void TextEffect::shadow_enable(bool e) {
|
||||
shadow_color->set_enabled(e);
|
||||
shadow_distance->set_enabled(e);
|
||||
@@ -110,7 +290,7 @@ void TextEffect::outline_enable(bool e) {
|
||||
outline_width->set_enabled(e);
|
||||
}
|
||||
|
||||
QImage blurred(const QImage& image, const QRect& rect, int radius, bool alphaOnly = false)
|
||||
/*QImage blurred(const QImage& image, const QRect& rect, int radius, bool alphaOnly = false)
|
||||
{
|
||||
int tab[] = { 14, 10, 8, 6, 5, 5, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2 };
|
||||
int alpha = (radius < 1) ? 16 : (radius > 17) ? 1 : tab[radius-1];
|
||||
@@ -176,73 +356,9 @@ QImage blurred(const QImage& image, const QRect& rect, int radius, bool alphaOnl
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}*/
|
||||
|
||||
void blurred2(QImage& result, const QRect& rect, int radius, bool alphaOnly = false) {
|
||||
int tab[] = { 14, 10, 8, 6, 5, 5, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2 };
|
||||
int alpha = (radius < 1) ? 16 : (radius > 17) ? 1 : tab[radius-1];
|
||||
|
||||
int r1 = rect.top();
|
||||
int r2 = rect.bottom();
|
||||
int c1 = rect.left();
|
||||
int c2 = rect.right();
|
||||
|
||||
int bpl = result.bytesPerLine();
|
||||
int rgba[4];
|
||||
unsigned char* p;
|
||||
|
||||
int i1 = 0;
|
||||
int i2 = 3;
|
||||
|
||||
if (alphaOnly)
|
||||
i1 = i2 = (QSysInfo::ByteOrder == QSysInfo::BigEndian ? 0 : 3);
|
||||
|
||||
for (int col = c1; col <= c2; col++) {
|
||||
p = result.scanLine(r1) + col * 4;
|
||||
for (int i = i1; i <= i2; i++)
|
||||
rgba[i] = p[i] << 4;
|
||||
|
||||
p += bpl;
|
||||
for (int j = r1; j < r2; j++, p += bpl)
|
||||
for (int i = i1; i <= i2; i++)
|
||||
p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4;
|
||||
}
|
||||
|
||||
for (int row = r1; row <= r2; row++) {
|
||||
p = result.scanLine(row) + c1 * 4;
|
||||
for (int i = i1; i <= i2; i++)
|
||||
rgba[i] = p[i] << 4;
|
||||
|
||||
p += 4;
|
||||
for (int j = c1; j < c2; j++, p += 4)
|
||||
for (int i = i1; i <= i2; i++)
|
||||
p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4;
|
||||
}
|
||||
|
||||
for (int col = c1; col <= c2; col++) {
|
||||
p = result.scanLine(r2) + col * 4;
|
||||
for (int i = i1; i <= i2; i++)
|
||||
rgba[i] = p[i] << 4;
|
||||
|
||||
p -= bpl;
|
||||
for (int j = r1; j < r2; j++, p -= bpl)
|
||||
for (int i = i1; i <= i2; i++)
|
||||
p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4;
|
||||
}
|
||||
|
||||
for (int row = r1; row <= r2; row++) {
|
||||
p = result.scanLine(row) + c2 * 4;
|
||||
for (int i = i1; i <= i2; i++)
|
||||
rgba[i] = p[i] << 4;
|
||||
|
||||
p -= 4;
|
||||
for (int j = c1; j < c2; j++, p -= 4)
|
||||
for (int i = i1; i <= i2; i++)
|
||||
p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4;
|
||||
}
|
||||
}
|
||||
|
||||
void TextEffect::process_image(double timecode, uint8_t* data, int w, int h) {
|
||||
/*void TextEffect::process_image(double timecode, uint8_t* data, int w, int h) {
|
||||
QImage img(data, w, h, QImage::Format_RGBA8888);
|
||||
QPainter p(&img);
|
||||
p.setRenderHint(QPainter::Antialiasing);
|
||||
@@ -357,4 +473,4 @@ void TextEffect::process_image(double timecode, uint8_t* data, int w, int h) {
|
||||
// draw "master" text
|
||||
p.setBrush(set_color_button->get_color_value(timecode));
|
||||
p.drawPath(path);
|
||||
}
|
||||
}*/
|
||||
|
||||
@@ -4,12 +4,14 @@
|
||||
#include "../effect.h"
|
||||
|
||||
#include <QFont>
|
||||
#include <QImage>
|
||||
class QOpenGLTexture;
|
||||
|
||||
class TextEffect : public Effect {
|
||||
class TextEffect : public SuperimposeEffect {
|
||||
Q_OBJECT
|
||||
public:
|
||||
TextEffect(Clip* c);
|
||||
void process_image(double timecode, uint8_t* data, int width, int height);
|
||||
void redraw(double timecode);
|
||||
|
||||
EffectField* text_val;
|
||||
EffectField* size_val;
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#define BLEND_MODE_OVERLAY 3
|
||||
|
||||
TransformEffect::TransformEffect(Clip* c) : Effect(c, EFFECT_TYPE_VIDEO, VIDEO_TRANSFORM_EFFECT) {
|
||||
enable_opengl = true;
|
||||
enable_coords = true;
|
||||
|
||||
EffectRow* position_row = add_row("Position:");
|
||||
position_x = position_row->add_field(EFFECT_FIELD_DOUBLE); // position X
|
||||
@@ -104,7 +104,7 @@ void TransformEffect::toggle_uniform_scale(bool enabled) {
|
||||
scale_y->set_enabled(!enabled);
|
||||
}
|
||||
|
||||
void TransformEffect::process_gl(double timecode, GLTextureCoords& coords) {
|
||||
void TransformEffect::process_coords(double timecode, GLTextureCoords& coords) {
|
||||
// position
|
||||
glTranslatef(position_x->get_double_value(timecode)-(parent_clip->sequence->width/2), position_y->get_double_value(timecode)-(parent_clip->sequence->height/2), 0);
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ class TransformEffect : public Effect {
|
||||
public:
|
||||
TransformEffect(Clip* c);
|
||||
void refresh();
|
||||
void process_gl(double timecode, GLTextureCoords& coords);
|
||||
void process_coords(double timecode, GLTextureCoords& coords);
|
||||
|
||||
EffectField* position_x;
|
||||
EffectField* position_y;
|
||||
|
||||
+2
-2
@@ -321,7 +321,7 @@ void ExportThread::run() {
|
||||
fbo.bind();
|
||||
|
||||
panel_viewer->viewer_widget->rendering = true;
|
||||
panel_viewer->viewer_widget->fbo = &fbo;
|
||||
panel_viewer->viewer_widget->default_fbo = &fbo;
|
||||
|
||||
long file_audio_samples = 0;
|
||||
|
||||
@@ -371,7 +371,7 @@ void ExportThread::run() {
|
||||
panel_timeline->playhead++;
|
||||
}
|
||||
|
||||
panel_viewer->viewer_widget->fbo = NULL;
|
||||
panel_viewer->viewer_widget->default_fbo = NULL;
|
||||
panel_viewer->viewer_widget->rendering = false;
|
||||
|
||||
fbo.release();
|
||||
|
||||
+1
-1
@@ -85,7 +85,7 @@ MainWindow::MainWindow(QWidget *parent) :
|
||||
updateTitle("");
|
||||
setWindowState(Qt::WindowMaximized);
|
||||
|
||||
statusBar()->showMessage("Welcome to Olive");
|
||||
statusBar()->showMessage("Welcome to " + appName);
|
||||
|
||||
setDockNestingEnabled(true);
|
||||
|
||||
|
||||
+1
-1
@@ -1281,7 +1281,7 @@ void MediaThrobber::stop(int icon_type, bool replace) {
|
||||
}
|
||||
|
||||
// redraw clips
|
||||
// panel_timeline->redraw_all_clips(replace);
|
||||
panel_timeline->redraw_all_clips(replace);
|
||||
|
||||
panel_project->source_table->viewport()->update();
|
||||
deleteLater();
|
||||
|
||||
@@ -347,9 +347,6 @@ void open_clip_worker(Clip* clip) {
|
||||
}
|
||||
clip->cache_B.frames[i]->linesize[0] = dstW*4;
|
||||
}
|
||||
|
||||
clip->comp_frame_size = dstW * dstH * 4;
|
||||
clip->comp_frame = new uchar[clip->comp_frame_size];
|
||||
} else if (clip->stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
|
||||
// if FFmpeg can't pick up the channel layout (usually WAV), assume
|
||||
// based on channel count (doesn't support surround sound sources yet)
|
||||
@@ -418,16 +415,10 @@ void cache_clip_worker(Clip* clip, long playhead, bool write_A, bool write_B, bo
|
||||
}
|
||||
|
||||
void close_clip_worker(Clip* clip) {
|
||||
for (int i=0;i<clip->effects.size();i++) {
|
||||
clip->effects.at(i)->close();
|
||||
}
|
||||
|
||||
// closes ffmpeg file handle and frees any memory used for caching
|
||||
MediaStream* ms = static_cast<Media*>(clip->media)->get_stream_from_file_index(clip->track < 0, clip->media_stream);
|
||||
if (clip->track < 0) {
|
||||
sws_freeContext(clip->sws_ctx);
|
||||
|
||||
delete [] clip->comp_frame;
|
||||
} else {
|
||||
swr_free(&clip->swr_ctx);
|
||||
}
|
||||
|
||||
@@ -55,8 +55,14 @@ void close_clip(Clip* clip) {
|
||||
clip->texture = NULL;
|
||||
}
|
||||
|
||||
for (int i=0;i<clip->effects.size();i++) {
|
||||
clip->effects.at(i)->close();
|
||||
}
|
||||
|
||||
if (clip->fbo != NULL) {
|
||||
delete clip->fbo;
|
||||
delete clip->fbo[0];
|
||||
delete clip->fbo[1];
|
||||
delete [] clip->fbo;
|
||||
clip->fbo = NULL;
|
||||
}
|
||||
|
||||
@@ -178,14 +184,7 @@ bool get_clip_frame(Clip* c, long playhead) {
|
||||
c->texture->allocateStorage(QOpenGLTexture::RGBA, QOpenGLTexture::UInt8);
|
||||
}
|
||||
|
||||
memcpy(c->comp_frame, current_frame->data[0], c->comp_frame_size);
|
||||
for (int i=0;i<c->effects.size();i++) {
|
||||
if (c->effects.at(i)->is_enabled() && c->effects.at(i)->enable_image) {
|
||||
c->effects.at(i)->process_image(sequence_clip_time, c->comp_frame, current_frame->width, current_frame->height);
|
||||
}
|
||||
}
|
||||
|
||||
c->texture->setData(0, QOpenGLTexture::RGBA, QOpenGLTexture::UInt8, c->comp_frame);
|
||||
c->texture->setData(0, QOpenGLTexture::RGBA, QOpenGLTexture::UInt8, current_frame->data[0]);
|
||||
c->texture_frame = clip_time;
|
||||
|
||||
return true;
|
||||
|
||||
+1
-3
@@ -81,8 +81,6 @@ struct Clip
|
||||
AVCodecContext* codecCtx;
|
||||
AVPacket* pkt;
|
||||
AVFrame* frame;
|
||||
uchar* comp_frame;
|
||||
int comp_frame_size;
|
||||
|
||||
bool pkt_written;
|
||||
bool reached_end;
|
||||
@@ -102,7 +100,7 @@ struct Clip
|
||||
|
||||
// video playback variables
|
||||
SwsContext* sws_ctx;
|
||||
QOpenGLFramebufferObject* fbo;
|
||||
QOpenGLFramebufferObject** fbo;
|
||||
QOpenGLTexture* texture;
|
||||
long texture_frame;
|
||||
|
||||
|
||||
+35
-22
@@ -28,7 +28,7 @@ extern "C" {
|
||||
ViewerWidget::ViewerWidget(QWidget *parent) :
|
||||
QOpenGLWidget(parent),
|
||||
rendering(false),
|
||||
fbo(NULL)
|
||||
default_fbo(NULL)
|
||||
{
|
||||
QSurfaceFormat format;
|
||||
format.setDepthBufferSize(24);
|
||||
@@ -67,12 +67,12 @@ void ViewerWidget::paintEvent(QPaintEvent *e) {
|
||||
}
|
||||
}
|
||||
|
||||
GLuint ViewerWidget::draw_clip(Clip* clip, GLuint texture) {
|
||||
GLuint ViewerWidget::draw_clip(QOpenGLFramebufferObject* fbo, GLuint texture) {
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
glOrtho(0, 1, 0, 1, -1, 1);
|
||||
|
||||
clip->fbo->bind();
|
||||
fbo->bind();
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
glBegin(GL_QUADS);
|
||||
@@ -87,11 +87,11 @@ GLuint ViewerWidget::draw_clip(Clip* clip, GLuint texture) {
|
||||
glEnd();
|
||||
glBindTexture(GL_TEXTURE_2D, NULL);
|
||||
|
||||
clip->fbo->release();
|
||||
if (fbo != NULL) fbo->bind();
|
||||
fbo->release();
|
||||
if (default_fbo != NULL) default_fbo->bind();
|
||||
|
||||
glPopMatrix();
|
||||
return clip->fbo->takeTexture();
|
||||
return fbo->texture();
|
||||
}
|
||||
|
||||
GLuint ViewerWidget::compose_sequence(Clip* nest, bool render_audio) {
|
||||
@@ -198,12 +198,15 @@ GLuint ViewerWidget::compose_sequence(Clip* nest, bool render_audio) {
|
||||
} else if (playhead >= c->timeline_in) {
|
||||
// start preparing cache
|
||||
if (c->fbo == NULL) {
|
||||
c->fbo = new QOpenGLFramebufferObject(video_width, video_height);
|
||||
c->fbo = new QOpenGLFramebufferObject* [2];
|
||||
c->fbo[0] = new QOpenGLFramebufferObject(video_width, video_height);
|
||||
c->fbo[1] = new QOpenGLFramebufferObject(video_width, video_height);
|
||||
}
|
||||
|
||||
glViewport(0, 0, video_width, video_height);
|
||||
|
||||
GLuint composite_texture = draw_clip(c, textureID);
|
||||
GLuint composite_texture = draw_clip(c->fbo[0], textureID);
|
||||
bool fbo_switcher = true;
|
||||
|
||||
GLTextureCoords coords;
|
||||
coords.vertexTopLeftX = coords.vertexBottomLeftX = -video_width/2;
|
||||
@@ -215,11 +218,23 @@ 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)->startEffect();
|
||||
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);
|
||||
Effect* e = c->effects.at(j);
|
||||
if (e->is_enabled()) {
|
||||
double timecode = ((double)(panel_timeline->playhead-c->timeline_in+c->clip_in)/(double)sequence->frame_rate);
|
||||
if (e->enable_coords) {
|
||||
e->process_coords(timecode, coords);
|
||||
}
|
||||
if (e->enable_shader || e->enable_superimpose) {
|
||||
e->startEffect();
|
||||
for (int k=0;k<e->getIterations();k++) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -237,17 +252,17 @@ GLuint ViewerWidget::compose_sequence(Clip* nest, bool render_audio) {
|
||||
c->closing_transition->process_transition((double)transition_progress/(double)c->closing_transition->length);
|
||||
}
|
||||
}
|
||||
// EFFECT CODE END
|
||||
|
||||
for (int j=0;j<c->effects.size();j++) {
|
||||
if (c->effects.at(j)->enable_opengl && c->effects.at(j)->is_enabled()) {
|
||||
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) {
|
||||
if (nest->fbo == NULL) nest->fbo = new QOpenGLFramebufferObject(s->width, s->height);
|
||||
nest->fbo->bind();
|
||||
// if (nest->fbo == NULL) nest->fbo = new QOpenGLFramebufferObject(s->width, s->height);
|
||||
nest->fbo[0]->bind();
|
||||
glViewport(0, 0, s->width, s->height);
|
||||
} else if (rendering) {
|
||||
glViewport(0, 0, s->width, s->height);
|
||||
@@ -271,11 +286,9 @@ GLuint ViewerWidget::compose_sequence(Clip* nest, bool render_audio) {
|
||||
glVertex2f(coords.vertexBottomLeftX, coords.vertexBottomLeftY); // bottom left
|
||||
glEnd();
|
||||
|
||||
glDeleteTextures(1, &composite_texture);
|
||||
|
||||
if (nest != NULL) {
|
||||
nest->fbo->release();
|
||||
if (fbo != NULL) fbo->bind();
|
||||
nest->fbo[0]->release();
|
||||
if (default_fbo != NULL) default_fbo->bind();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -292,7 +305,7 @@ GLuint ViewerWidget::compose_sequence(Clip* nest, bool render_audio) {
|
||||
}
|
||||
}
|
||||
|
||||
return (nest != NULL && nest->fbo != NULL) ? nest->fbo->takeTexture() : 0;
|
||||
return (nest != NULL && nest->fbo != NULL) ? nest->fbo[0]->texture() : 0;
|
||||
}
|
||||
|
||||
void ViewerWidget::paintGL() {
|
||||
|
||||
+2
-2
@@ -23,7 +23,7 @@ public:
|
||||
void paintGL();
|
||||
void initializeGL();
|
||||
|
||||
QOpenGLFramebufferObject* fbo;
|
||||
QOpenGLFramebufferObject* default_fbo;
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *e);
|
||||
// void resizeGL(int w, int h);
|
||||
@@ -33,7 +33,7 @@ private slots:
|
||||
void retry();
|
||||
void deleteFunction();
|
||||
GLuint compose_sequence(Clip *nest, bool render_audio);
|
||||
GLuint draw_clip(Clip *clip, GLuint texture);
|
||||
GLuint draw_clip(QOpenGLFramebufferObject *clip, GLuint texture);
|
||||
};
|
||||
|
||||
#endif // VIEWERWIDGET_H
|
||||
|
||||
Reference in New Issue
Block a user