further progress on better blending

This commit is contained in:
itsmattkc
2019-01-26 23:34:58 +11:00
parent 97a28ab54a
commit 7a436ef51f
20 changed files with 271 additions and 189 deletions
+5 -1
View File
@@ -47,11 +47,15 @@ void main(void) {
float mask = colorclose(cb, cr, cb_key, cr_key, (tola/100.0), (tolb/100.0));
if (mode == 0) { // composite
float submask = 1.0-mask;
//float submask = 1.0-mask;
float submask = 0.0;
texture_color.r = max(texture_color.r - submask*key_color.r, 0.0) + submask;
texture_color.g = max(texture_color.g - submask*key_color.g, 0.0) + submask;
texture_color.b = max(texture_color.b - submask*key_color.b, 0.0) + submask;
texture_color.a *= mask;
// premultiply
texture_color.rgb *= texture_color.a;
} else if (mode == 1) { // alpha
texture_color.rgb = vec3(mask);
} else if (mode == 2) { // original
@@ -32,6 +32,6 @@ uniform sampler2D texture;
varying vec2 vTexCoord;
void main(void) {
gl_FragColor = texture2D(background, vTexCoord);
// gl_FragColor = texture2D(texture, vTexCoord)*2.0;
// gl_FragColor = texture2D(background, vTexCoord);
gl_FragColor = texture2D(texture, vTexCoord);
}
+8
View File
@@ -0,0 +1,8 @@
#version 110
varying vec2 vTexCoord;
void main() {
vTexCoord = gl_MultiTexCoord0.xy;
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
+5 -5
View File
@@ -8,23 +8,23 @@ CornerPinEffect::CornerPinEffect(Clip *c, const EffectMeta *em) : Effect(c, em)
enable_coords = true;
enable_shader = true;
EffectRow* top_left = add_row(tr("Top Left"));
EffectRow* top_left = add_row(tr("Top Left"));
top_left_x = top_left->add_field(EFFECT_FIELD_DOUBLE, "topleftx");
top_left_y = top_left->add_field(EFFECT_FIELD_DOUBLE, "toplefty");
EffectRow* top_right = add_row(tr("Top Right"));
EffectRow* top_right = add_row(tr("Top Right"));
top_right_x = top_right->add_field(EFFECT_FIELD_DOUBLE, "toprightx");
top_right_y = top_right->add_field(EFFECT_FIELD_DOUBLE, "toprighty");
EffectRow* bottom_left = add_row(tr("Bottom Left"));
EffectRow* bottom_left = add_row(tr("Bottom Left"));
bottom_left_x = bottom_left->add_field(EFFECT_FIELD_DOUBLE, "bottomleftx");
bottom_left_y = bottom_left->add_field(EFFECT_FIELD_DOUBLE, "bottomlefty");
EffectRow* bottom_right = add_row(tr("Bottom Right"));
EffectRow* bottom_right = add_row(tr("Bottom Right"));
bottom_right_x = bottom_right->add_field(EFFECT_FIELD_DOUBLE, "bottomrightx");
bottom_right_y = bottom_right->add_field(EFFECT_FIELD_DOUBLE, "bottomrighty");
perspective = add_row(tr("Perspective"))->add_field(EFFECT_FIELD_BOOL, "perspective");
perspective = add_row(tr("Perspective"))->add_field(EFFECT_FIELD_BOOL, "perspective");
perspective->set_bool_value(true);
top_left_gizmo = add_gizmo(GIZMO_TYPE_DOT);
@@ -13,6 +13,7 @@ uniform float shadowdistance;
varying vec2 vTexCoord;
void main(void) {
/*
vec4 master_px = texture2D(image, vTexCoord);
if (shadow == 1) {
vec2 shadow_dist = vec2(shadowdistance)/resolution;
@@ -39,5 +40,7 @@ void main(void) {
gl_FragColor = composition;
} else {
gl_FragColor = master_px;
}
}
*/
gl_FragColor = texture2D(image, vTexCoord);
}
+10
View File
@@ -0,0 +1,10 @@
<RCC>
<qresource prefix="/internalshaders">
<file>blending.frag</file>
<file>common.vert</file>
<file>cornerpin.frag</file>
<file>cornerpin.vert</file>
<file>premultiply.frag</file>
<file>dropshadow.frag</file>
</qresource>
</RCC>
+10
View File
@@ -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;
}
+66 -65
View File
@@ -94,67 +94,67 @@ TextEffect::TextEffect(Clip *c, const EffectMeta* em) :
}
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 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 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 bpl = result.bytesPerLine();
int rgba[4];
unsigned char* p;
int i1 = 0;
int i2 = 3;
int i1 = 0;
int i2 = 3;
if (alphaOnly)
i1 = i2 = (QSysInfo::ByteOrder == QSysInfo::BigEndian ? 0 : 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;
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;
}
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;
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;
}
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;
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;
}
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;
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;
}
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) {
@@ -254,25 +254,25 @@ void TextEffect::redraw(double timecode) {
path.addText(text_x, text_y, font, lines.at(i));
}
// draw software shadow
if (!enable_shader && shadow_bool->get_bool_value(timecode)) {
p.setPen(Qt::NoPen);
int shadow_offset = shadow_distance->get_double_value(timecode);
// draw software shadow
if (shadow_bool->get_bool_value(timecode)) {
p.setPen(Qt::NoPen);
int shadow_offset = shadow_distance->get_double_value(timecode);
QPainterPath shadow_path(path);
shadow_path.translate(shadow_offset, shadow_offset);
QPainterPath shadow_path(path);
shadow_path.translate(shadow_offset, shadow_offset);
QColor col = shadow_color->get_color_value(timecode);
col.setAlpha(0);
img.fill(col);
QColor col = shadow_color->get_color_value(timecode);
col.setAlpha(0);
img.fill(col);
col.setAlphaF(shadow_opacity->get_double_value(timecode)*0.01);
p.setBrush(col);
p.drawPath(shadow_path);
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);
}
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);
@@ -288,10 +288,11 @@ void TextEffect::redraw(double timecode) {
p.setPen(Qt::NoPen);
p.setBrush(set_color_button->get_color_value(timecode));
p.drawPath(path);
p.end();
}
void TextEffect::shadow_enable(bool e) {
enable_shader = (e && !config.use_software_fallback);
close();
shadow_color->set_enabled(e);
+2 -1
View File
@@ -256,7 +256,8 @@ unix:!mac {
}
RESOURCES += \
icons/icons.qrc
icons/icons.qrc \
effects/internal/internalshaders.qrc
unix:!mac:isEmpty(PREFIX) {
PREFIX = /usr/local
+4 -7
View File
@@ -777,6 +777,8 @@ void open_clip_worker(Clip* clip) {
last_filter = yadif_filter;
}
// ffmpeg premultiplier
/*
if (!clip->media->to_footage()->alpha_is_premultiplied) {
AVFilterContext* premultiply_filter;
snprintf(filter_args, sizeof(filter_args), "inplace=1");
@@ -785,6 +787,7 @@ void open_clip_worker(Clip* clip) {
avfilter_link(last_filter, 0, premultiply_filter, 0);
last_filter = premultiply_filter;
}
*/
/* stabilization code */
/*bool stabilize = false;
@@ -801,13 +804,7 @@ void open_clip_worker(Clip* clip) {
}
}*/
enum AVPixelFormat valid_pix_fmts[] = {
// AV_PIX_FMT_RGB24,
AV_PIX_FMT_RGBA,
AV_PIX_FMT_NONE
};
clip->pix_fmt = avcodec_find_best_pix_fmt_of_list(valid_pix_fmts, static_cast<enum AVPixelFormat>(clip->stream->codecpar->format), 1, nullptr);
clip->pix_fmt = AV_PIX_FMT_RGBA;
const char* chosen_format = av_get_pix_fmt_name(static_cast<enum AVPixelFormat>(clip->pix_fmt));
snprintf(filter_args, sizeof(filter_args), "pix_fmts=%s", chosen_format);
+8 -2
View File
@@ -370,9 +370,15 @@ int retrieve_next_frame(Clip* c, AVFrame* f) {
}
bool is_clip_active(Clip* c, long playhead) {
// these buffers allow clips to be opened and prepared well before they're displayed
// as well as closed a little after they're not needed anymore
int open_buffer = qCeil(c->sequence->frame_rate*2);
int close_buffer = qCeil(c->sequence->frame_rate);
return c->enabled
&& c->get_timeline_in_with_transition() < playhead + ceil(c->sequence->frame_rate*2)
&& c->get_timeline_out_with_transition() > playhead
&& c->get_timeline_in_with_transition() < playhead + open_buffer
&& c->get_timeline_out_with_transition() > playhead - close_buffer
&& playhead - c->get_timeline_in_with_transition() + c->get_clip_in_with_transition() < c->getMaximumLength();
}
+23 -17
View File
@@ -660,10 +660,6 @@ void Effect::open() {
} else {
isOpen = true;
}
if (enable_superimpose) {
texture = new QOpenGLTexture(QOpenGLTexture::Target2D);
}
}
void Effect::close() {
@@ -747,30 +743,40 @@ void Effect::process_shader(double timecode, GLTextureCoords&) {
void Effect::process_coords(double, GLTextureCoords&, int) {}
GLuint Effect::process_superimpose(double timecode) {
bool recreate_texture = false;
bool dimensions_changed = false;
bool redrew_image = 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_Premultiplied);
recreate_texture = true;
dimensions_changed = true;
}
if (valueHasChanged(timecode) || recreate_texture || enable_always_update) {
if (valueHasChanged(timecode) || dimensions_changed || enable_always_update) {
redraw(timecode);
redrew_image = true;
}
if (texture != nullptr) {
if (recreate_texture || texture->width() != img.width() || texture->height() != img.height()) {
delete_texture();
texture = new QOpenGLTexture(QOpenGLTexture::Target2D);
texture->setData(img);
} else {
texture->setData(0, QOpenGLTexture::RGBA, QOpenGLTexture::UInt8, img.constBits());
}
return texture->textureId();
if (texture == nullptr || texture->width() != img.width() || texture->height() != img.height()) {
delete_texture();
texture = new QOpenGLTexture(QOpenGLTexture::Target2D);
texture->setSize(img.width(), img.height());
texture->setFormat(QOpenGLTexture::RGBA8_UNorm);
texture->setMipLevels(texture->maximumMipLevels());
texture->setMinMagFilters(QOpenGLTexture::Linear, QOpenGLTexture::Linear);
texture->allocateStorage(QOpenGLTexture::RGBA, QOpenGLTexture::UInt8);
redrew_image = true;
}
return 0;
if (redrew_image) {
texture->setData(0, QOpenGLTexture::RGBA, QOpenGLTexture::UInt8, img.constBits());
}
return texture->textureId();
}
void Effect::process_audio(double, double, quint8*, int, int) {}
+3 -1
View File
@@ -22,7 +22,9 @@ void load_internal_effects() {
EffectMeta em;
// internal effects
// load internal effects
em.path = ":/internalshaders";
em.type = EFFECT_TYPE_EFFECT;
em.subtype = EFFECT_TYPE_AUDIO;
+5 -3
View File
@@ -9,9 +9,11 @@
#include <QPixmap>
#include <QIcon>
#define VIDEO_PROGRESSIVE 0
#define VIDEO_TOP_FIELD_FIRST 1
#define VIDEO_BOTTOM_FIELD_FIRST 2
enum VideoInterlacingMode {
VIDEO_PROGRESSIVE,
VIDEO_TOP_FIELD_FIRST,
VIDEO_BOTTOM_FIELD_FIRST
};
struct Sequence;
struct Clip;
+102 -82
View File
@@ -78,22 +78,26 @@ 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...";
texture_failed = true;
} else if (composite_texture == 0) {
// 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 (composite_texture == 0) {
// if there is no previous texture, just return the superimposes texture
composite_texture = superimpose_texture;
} else {
// if the source texture is not already a framebuffer texture,
// we'll need to make it one before drawing a superimpose effect on it
if (composite_texture != c->fbo[0]->texture() && composite_texture != c->fbo[1]->texture()) {
draw_clip(c->fbo[!fbo_switcher], composite_texture, true);
}
composite_texture = draw_clip(c->fbo[!fbo_switcher], superimpose_texture, false);
// if the source texture is not already a framebuffer texture,
// we'll need to make it one before drawing a superimpose effect on it
if (composite_texture != c->fbo[0]->texture() && composite_texture != c->fbo[1]->texture()) {
draw_clip(c->fbo[!fbo_switcher], composite_texture, true);
}
composite_texture = draw_clip(c->fbo[!fbo_switcher], superimpose_texture, false);
}
}
e->endEffect();
@@ -279,7 +283,8 @@ GLuint compose_sequence(ComposeSequenceParams &params) {
}
// if clip should actually be shown on screen in this frame
if (playhead >= c->get_timeline_in_with_transition()) {
if (playhead >= c->get_timeline_in_with_transition()
&& playhead < c->get_timeline_out_with_transition()) {
glPushMatrix();
// simple bool for switching between the two framebuffers
@@ -287,20 +292,31 @@ GLuint compose_sequence(ComposeSequenceParams &params) {
glViewport(0, 0, video_width, video_height);
if (c->media != nullptr && c->media->get_type()== MEDIA_TYPE_SEQUENCE) {
// for a nested sequence, run this function again on that sequence and retrieve the texture
if (c->media != nullptr) {
if (c->media->get_type() == MEDIA_TYPE_SEQUENCE) {
// for a nested sequence, run this function again on that sequence and retrieve the texture
// add nested sequence to nest list
params.nests.append(c);
// add nested sequence to nest list
params.nests.append(c);
// compose sequence
textureID = compose_sequence(params);
// compose sequence
textureID = compose_sequence(params);
// remove sequence from nest list
params.nests.removeLast();
// remove sequence from nest list
params.nests.removeLast();
// compose_sequence() would have written to this clip's fbo[0], so we switch to fbo[1]
fbo_switcher = true;
// compose_sequence() would have written to this clip's fbo[0], so we switch to fbo[1]
fbo_switcher = true;
} else if (c->media->get_type() == MEDIA_TYPE_FOOTAGE && !c->media->to_footage()->alpha_is_premultiplied) {
// alpha is not premultiplied, we'll need to premultiply it for the rest of the pipeline
params.premultiply_program->bind();
textureID = draw_clip(c->fbo[0], textureID, true);
params.premultiply_program->release();
fbo_switcher = true;
}
}
// set up default coordinates for drawing the clip
@@ -345,6 +361,7 @@ GLuint compose_sequence(ComposeSequenceParams &params) {
if (e->container->selected) selected_effect = e;
}
}
qDebug() << "texture ID:" << textureID;
// using gizmo data, set definitive gizmo
if (selected_effect != nullptr) {
@@ -373,80 +390,83 @@ GLuint compose_sequence(ComposeSequenceParams &params) {
// == START FINAL DRAW ON SEQUENCE BUFFER ==
// bind framebuffer
params.ctx->functions()->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, final_fbo);
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);
// set viewport to sequence size
glViewport(0, 0, s->width, s->height);
// bind final texture
glBindTexture(GL_TEXTURE_2D, textureID);
// bind final 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);
// 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);
// 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("opacity", coords.opacity);
// 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("opacity", coords.opacity);
// draw clip on screen
glBegin(GL_QUADS);
// draw clip on screen
glBegin(GL_QUADS);
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;
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;k<rows;k++) {
float row_prog = float(k)/rows;
float next_row_prog = float(k+1)/rows;
for (int j=0;j<cols;j++) {
float col_prog = float(j)/cols;
float next_col_prog = float(j+1)/cols;
for (int k=0;k<rows;k++) {
float row_prog = float(k)/rows;
float next_row_prog = float(k+1)/rows;
for (int j=0;j<cols;j++) {
float col_prog = float(j)/cols;
float next_col_prog = float(j+1)/cols;
float vertexTLX = float_lerp(coords.vertexTopLeftX, coords.vertexBottomLeftX, row_prog);
float vertexTRX = float_lerp(coords.vertexTopRightX, coords.vertexBottomRightX, row_prog);
float vertexBLX = float_lerp(coords.vertexTopLeftX, coords.vertexBottomLeftX, next_row_prog);
float vertexBRX = float_lerp(coords.vertexTopRightX, coords.vertexBottomRightX, next_row_prog);
float vertexTLX = float_lerp(coords.vertexTopLeftX, coords.vertexBottomLeftX, row_prog);
float vertexTRX = float_lerp(coords.vertexTopRightX, coords.vertexBottomRightX, row_prog);
float vertexBLX = float_lerp(coords.vertexTopLeftX, coords.vertexBottomLeftX, next_row_prog);
float vertexBRX = float_lerp(coords.vertexTopRightX, coords.vertexBottomRightX, next_row_prog);
float vertexTLY = float_lerp(coords.vertexTopLeftY, coords.vertexTopRightY, col_prog);
float vertexTRY = float_lerp(coords.vertexTopLeftY, coords.vertexTopRightY, next_col_prog);
float vertexBLY = float_lerp(coords.vertexBottomLeftY, coords.vertexBottomRightY, col_prog);
float vertexBRY = float_lerp(coords.vertexBottomLeftY, coords.vertexBottomRightY, next_col_prog);
float vertexTLY = float_lerp(coords.vertexTopLeftY, coords.vertexTopRightY, col_prog);
float vertexTRY = float_lerp(coords.vertexTopLeftY, coords.vertexTopRightY, next_col_prog);
float vertexBLY = float_lerp(coords.vertexBottomLeftY, coords.vertexBottomRightY, col_prog);
float vertexBRY = float_lerp(coords.vertexBottomLeftY, coords.vertexBottomRightY, next_col_prog);
glTexCoord2f(float_lerp(coords.textureTopLeftX, coords.textureTopRightX, col_prog), float_lerp(coords.textureTopLeftY, coords.textureBottomLeftY, row_prog)); // top left
glVertex2f(float_lerp(vertexTLX, vertexTRX, col_prog), float_lerp(vertexTLY, vertexBLY, row_prog)); // top left
glTexCoord2f(float_lerp(coords.textureTopLeftX, coords.textureTopRightX, next_col_prog), float_lerp(coords.textureTopRightY, coords.textureBottomRightY, row_prog)); // top right
glVertex2f(float_lerp(vertexTLX, vertexTRX, next_col_prog), float_lerp(vertexTRY, vertexBRY, row_prog)); // top right
glTexCoord2f(float_lerp(coords.textureBottomLeftX, coords.textureBottomRightX, next_col_prog), float_lerp(coords.textureTopRightY, coords.textureBottomRightY, next_row_prog)); // bottom right
glVertex2f(float_lerp(vertexBLX, vertexBRX, next_col_prog), float_lerp(vertexTRY, vertexBRY, next_row_prog)); // bottom right
glTexCoord2f(float_lerp(coords.textureBottomLeftX, coords.textureBottomRightX, col_prog), float_lerp(coords.textureTopLeftY, coords.textureBottomLeftY, next_row_prog)); // bottom left
glVertex2f(float_lerp(vertexBLX, vertexBRX, col_prog), float_lerp(vertexTLY, vertexBLY, next_row_prog)); // bottom left
glTexCoord2f(float_lerp(coords.textureTopLeftX, coords.textureTopRightX, col_prog), float_lerp(coords.textureTopLeftY, coords.textureBottomLeftY, row_prog)); // top left
glVertex2f(float_lerp(vertexTLX, vertexTRX, col_prog), float_lerp(vertexTLY, vertexBLY, row_prog)); // top left
glTexCoord2f(float_lerp(coords.textureTopLeftX, coords.textureTopRightX, next_col_prog), float_lerp(coords.textureTopRightY, coords.textureBottomRightY, row_prog)); // top right
glVertex2f(float_lerp(vertexTLX, vertexTRX, next_col_prog), float_lerp(vertexTRY, vertexBRY, row_prog)); // top right
glTexCoord2f(float_lerp(coords.textureBottomLeftX, coords.textureBottomRightX, next_col_prog), float_lerp(coords.textureTopRightY, coords.textureBottomRightY, next_row_prog)); // bottom right
glVertex2f(float_lerp(vertexBLX, vertexBRX, next_col_prog), float_lerp(vertexTRY, vertexBRY, next_row_prog)); // bottom right
glTexCoord2f(float_lerp(coords.textureBottomLeftX, coords.textureBottomRightX, col_prog), float_lerp(coords.textureTopLeftY, coords.textureBottomLeftY, next_row_prog)); // bottom left
glVertex2f(float_lerp(vertexBLX, vertexBRX, col_prog), float_lerp(vertexTLY, vertexBLY, next_row_prog)); // bottom left
}
}
}
glEnd();
// release blend mode shader
params.blend_mode_program->release();
// unbind texture
glBindTexture(GL_TEXTURE_2D, 0);
// unbind framebuffer
params.ctx->functions()->glBindFramebuffer(GL_TEXTURE_2D, 0);
}
glEnd();
// release blend mode shader
params.blend_mode_program->release();
// unbind texture
glBindTexture(GL_TEXTURE_2D, 0);
// unbind framebuffer
params.ctx->functions()->glBindFramebuffer(GL_TEXTURE_2D, 0);
// == END FINAL DRAW ON SEQUENCE BUFFER ==
// prepare gizmos
+1
View File
@@ -22,6 +22,7 @@ struct ComposeSequenceParams {
bool rendering;
int playback_speed;
QOpenGLShaderProgram* blend_mode_program;
QOpenGLShaderProgram* premultiply_program;
GLuint main_buffer;
GLuint backend_buffer1;
GLuint backend_attachment1;
+12 -2
View File
@@ -16,6 +16,7 @@ RenderThread::RenderThread() :
share_ctx(nullptr),
ctx(nullptr),
blend_mode_program(nullptr),
premultiply_program(nullptr),
seq(nullptr),
tex_width(-1),
tex_height(-1),
@@ -107,10 +108,16 @@ void RenderThread::run() {
if (blend_mode_program == nullptr) {
// create shader program to make blending modes work
delete_shader_program();
blend_mode_program = new QOpenGLShaderProgram();
blend_mode_program->addShaderFromSourceFile(QOpenGLShader::Vertex, "C:/msys64/home/Matt/olive/effects/common.vert");
blend_mode_program->addShaderFromSourceFile(QOpenGLShader::Fragment, "C:/msys64/home/Matt/olive/effects/blending.frag");
blend_mode_program->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/internalshaders/common.vert");
blend_mode_program->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/internalshaders/blending.frag");
blend_mode_program->link();
premultiply_program = new QOpenGLShaderProgram();
premultiply_program->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/internalshaders/common.vert");
premultiply_program->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/internalshaders/premultiply.frag");
premultiply_program->link();
}
// bind framebuffer for drawing
@@ -161,6 +168,7 @@ void RenderThread::paint() {
params.rendering = false;
params.playback_speed = 1;
params.blend_mode_program = blend_mode_program;
params.premultiply_program = premultiply_program;
params.backend_buffer1 = back_buffer_1;
params.backend_buffer2 = back_buffer_2;
params.backend_attachment1 = back_texture_1;
@@ -253,8 +261,10 @@ void RenderThread::delete_fbo() {
void RenderThread::delete_shader_program() {
if (blend_mode_program != nullptr) {
delete blend_mode_program;
delete premultiply_program;
}
blend_mode_program = nullptr;
premultiply_program = nullptr;
}
void RenderThread::delete_ctx() {
+1
View File
@@ -43,6 +43,7 @@ private:
QOpenGLContext* share_ctx;
QOpenGLContext* ctx;
QOpenGLShaderProgram* blend_mode_program;
QOpenGLShaderProgram* premultiply_program;
GLuint back_buffer_1;
GLuint back_buffer_2;