further progress on better blending
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
#version 110
|
||||
|
||||
const int BLEND_MODE_ADD = 0;
|
||||
const int BLEND_MODE_AVERAGE = 1;
|
||||
const int BLEND_MODE_COLORBURN = 2;
|
||||
const int BLEND_MODE_COLORDODGE = 3;
|
||||
const int BLEND_MODE_DARKEN = 4;
|
||||
const int BLEND_MODE_DIFFERENCE = 5;
|
||||
const int BLEND_MODE_EXCLUSION = 6;
|
||||
const int BLEND_MODE_GLOW = 7;
|
||||
const int BLEND_MODE_HARDLIGHT = 8;
|
||||
const int BLEND_MODE_HARDMIX = 9;
|
||||
const int BLEND_MODE_LIGHTEN = 10;
|
||||
const int BLEND_MODE_LINEARBURN = 11;
|
||||
const int BLEND_MODE_LINEARDODGE = 12;
|
||||
const int BLEND_MODE_LINEARLIGHT = 13;
|
||||
const int BLEND_MODE_MULTIPLY = 14;
|
||||
const int BLEND_MODE_NEGATION = 15;
|
||||
const int BLEND_MODE_NORMAL = 16;
|
||||
const int BLEND_MODE_OVERLAY = 17;
|
||||
const int BLEND_MODE_PHOENIX = 18;
|
||||
const int BLEND_MODE_PINLIGHT = 19;
|
||||
const int BLEND_MODE_REFLECT = 20;
|
||||
const int BLEND_MODE_SCREEN = 21;
|
||||
const int BLEND_MODE_SOFTLIGHT = 22;
|
||||
const int BLEND_MODE_SUBSTRACT = 23;
|
||||
const int BLEND_MODE_SUBTRACT = 24;
|
||||
const int BLEND_MODE_VIVIDLIGHT = 25;
|
||||
|
||||
uniform sampler2D background;
|
||||
uniform sampler2D texture;
|
||||
varying vec2 vTexCoord;
|
||||
|
||||
void main(void) {
|
||||
// gl_FragColor = texture2D(background, vTexCoord);
|
||||
gl_FragColor = texture2D(texture, vTexCoord);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
#version 110
|
||||
|
||||
varying vec2 vTexCoord;
|
||||
|
||||
void main() {
|
||||
vTexCoord = gl_MultiTexCoord0.xy;
|
||||
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
#version 130
|
||||
|
||||
uniform sampler2D tex;
|
||||
uniform bool perspective;
|
||||
|
||||
varying vec2 q;
|
||||
varying vec2 b1;
|
||||
varying vec2 b2;
|
||||
varying vec2 b3;
|
||||
varying vec2 vTexCoord;
|
||||
|
||||
float Wedge2D(vec2 v, vec2 w) {
|
||||
return (v.x*w.y) - (v.y*w.x);
|
||||
}
|
||||
|
||||
void main(void) {
|
||||
if (perspective) {
|
||||
gl_FragColor = texture2D(tex, vTexCoord);
|
||||
} else {
|
||||
float A = Wedge2D(b2, b3);
|
||||
float B = Wedge2D(b3, q) - Wedge2D(b1, b2);
|
||||
float C = Wedge2D(b1, q);
|
||||
|
||||
vec2 uv;
|
||||
|
||||
// solve for v
|
||||
if (abs(A) < 0.001) {
|
||||
uv.y = -C/B;
|
||||
} else {
|
||||
float discrim = B*B - 4.0*A*C;
|
||||
uv.y = 0.5 * (-B + sqrt(discrim)) / A;
|
||||
}
|
||||
|
||||
// solve for u
|
||||
vec2 denom = b1 + uv.y * b3;
|
||||
if (abs(denom.x) > abs(denom.y)) {
|
||||
uv.x = (q.x - b2.x * uv.y) / denom.x;
|
||||
} else {
|
||||
uv.x = (q.y - b2.y * uv.y) / denom.y;
|
||||
}
|
||||
|
||||
uv.y = 1.0 - uv.y;
|
||||
|
||||
gl_FragColor = texture2D(tex, uv);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
#version 130
|
||||
|
||||
uniform bool perspective;
|
||||
uniform vec2 p0;
|
||||
uniform vec2 p1;
|
||||
uniform vec2 p2;
|
||||
uniform vec2 p3;
|
||||
|
||||
varying vec2 q;
|
||||
varying vec2 b1;
|
||||
varying vec2 b2;
|
||||
varying vec2 b3;
|
||||
varying vec2 vTexCoord;
|
||||
|
||||
void main() {
|
||||
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
|
||||
|
||||
if (perspective) {
|
||||
float m1 = (p3.y - p0.y)/(p3.x - p0.x);
|
||||
float c1 = p0.y - m1 * p0.x;
|
||||
float m2 = (p1.y - p2.y)/(p1.x - p2.x);
|
||||
float c2 = p2.y - m2 * p2.x;
|
||||
float mid_x = (c2 - c1) / (m1 - m2);
|
||||
float mid_y = m1 * mid_x + c1;
|
||||
|
||||
float d0 = length(vec2(mid_x - p0.x, mid_y - p0.y));
|
||||
float d1 = length(vec2(p1.x - mid_x, mid_y - p1.y));
|
||||
float d2 = length(vec2(p3.x - mid_x, p3.y - mid_y));
|
||||
float d3 = length(vec2(mid_x - p2.x, p2.y - mid_y));
|
||||
|
||||
float q;
|
||||
|
||||
if (gl_VertexID == 0) {
|
||||
q = (d1+d3)/d3;
|
||||
} else if (gl_VertexID == 1) {
|
||||
q = (d0+d2)/d2;
|
||||
} else if (gl_VertexID == 2) {
|
||||
q = (d3+d1)/d1;
|
||||
} else {
|
||||
q = (d2+d0)/d0;
|
||||
}
|
||||
|
||||
gl_Position[0] *= q;
|
||||
gl_Position[1] *= q;
|
||||
gl_Position[3] = q;
|
||||
|
||||
vTexCoord = gl_MultiTexCoord0.xy;
|
||||
} else {
|
||||
vec2 pos;
|
||||
|
||||
if (gl_VertexID == 0) { // top left
|
||||
pos = p2;
|
||||
} else if (gl_VertexID == 1) { // top right
|
||||
pos = p3;
|
||||
} else if (gl_VertexID == 2) { // bottom right
|
||||
pos = p1;
|
||||
} else if (gl_VertexID == 3) { // bottom left
|
||||
pos = p0;
|
||||
}
|
||||
|
||||
q = pos - p0;
|
||||
b1 = p1 - p0;
|
||||
b2 = p2 - p0;
|
||||
b3 = p0 - p1 - p2 + p3;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
#version 110
|
||||
|
||||
uniform sampler2D image;
|
||||
|
||||
uniform vec2 resolution;
|
||||
|
||||
uniform int shadow;
|
||||
uniform vec3 shadowcolor;
|
||||
uniform float shadowsoftness;
|
||||
uniform float shadowopacity;
|
||||
uniform float shadowdistance;
|
||||
|
||||
varying vec2 vTexCoord;
|
||||
|
||||
void main(void) {
|
||||
/*
|
||||
vec4 master_px = texture2D(image, vTexCoord);
|
||||
if (shadow == 1) {
|
||||
vec2 shadow_dist = vec2(shadowdistance)/resolution;
|
||||
|
||||
float shadow_opacity = 0.01*shadowopacity;
|
||||
|
||||
vec4 shadowed_px = vec4(shadowcolor.r, shadowcolor.g, shadowcolor.b, shadow_opacity*texture2D(image, vTexCoord-shadow_dist).a);
|
||||
|
||||
float rad = floor(shadowsoftness);
|
||||
if (rad > 0.0) {
|
||||
shadowed_px.a = 0.0;
|
||||
float divider = (1.0 / pow(rad, 2.0))*shadow_opacity;
|
||||
for (float x=-rad+0.5;x<=rad;x+=2.0) {
|
||||
for (float y=-rad+0.5;y<=rad;y+=2.0) {
|
||||
shadowed_px.a += shadow_opacity*texture2D(image, vTexCoord-shadow_dist+(vec2(x, y)/resolution)).a*divider;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vec4 shadow_blend = (shadowed_px*(1.0-master_px.a));
|
||||
|
||||
vec4 composition = mix(shadow_blend, master_px, master_px.a);
|
||||
|
||||
gl_FragColor = composition;
|
||||
} else {
|
||||
gl_FragColor = master_px;
|
||||
}
|
||||
*/
|
||||
gl_FragColor = texture2D(image, vTexCoord);
|
||||
}
|
||||
@@ -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>
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user