diff --git a/effects/add.blend b/effects/add.blend new file mode 100644 index 000000000..2615a387f --- /dev/null +++ b/effects/add.blend @@ -0,0 +1,13 @@ +float blendAdd(float base, float blend) { + return min(base+blend,1.0); +} + +vec3 blendAdd(vec3 base, vec3 blend) { + return min(base+blend,vec3(1.0)); +} + +vec3 blendAdd(vec3 base, vec3 blend, float opacity) { + return (blendAdd(base, blend) * opacity + base * (1.0 - opacity)); +} + +#pragma glslify: export(blendAdd) \ No newline at end of file diff --git a/effects/average.blend b/effects/average.blend new file mode 100644 index 000000000..b838757bd --- /dev/null +++ b/effects/average.blend @@ -0,0 +1,9 @@ +vec3 blendAverage(vec3 base, vec3 blend) { + return (base+blend)/2.0; +} + +vec3 blendAverage(vec3 base, vec3 blend, float opacity) { + return (blendAverage(base, blend) * opacity + base * (1.0 - opacity)); +} + +#pragma glslify: export(blendAverage) \ No newline at end of file diff --git a/effects/color-burn.blend b/effects/color-burn.blend new file mode 100644 index 000000000..e524511b5 --- /dev/null +++ b/effects/color-burn.blend @@ -0,0 +1,13 @@ +float blendColorBurn(float base, float blend) { + return (blend==0.0)?blend:max((1.0-((1.0-base)/blend)),0.0); +} + +vec3 blendColorBurn(vec3 base, vec3 blend) { + return vec3(blendColorBurn(base.r,blend.r),blendColorBurn(base.g,blend.g),blendColorBurn(base.b,blend.b)); +} + +vec3 blendColorBurn(vec3 base, vec3 blend, float opacity) { + return (blendColorBurn(base, blend) * opacity + base * (1.0 - opacity)); +} + +#pragma glslify: export(blendColorBurn) \ No newline at end of file diff --git a/effects/color-dodge.blend b/effects/color-dodge.blend new file mode 100644 index 000000000..38f9fc033 --- /dev/null +++ b/effects/color-dodge.blend @@ -0,0 +1,13 @@ +float blendColorDodge(float base, float blend) { + return (blend==1.0)?blend:min(base/(1.0-blend),1.0); +} + +vec3 blendColorDodge(vec3 base, vec3 blend) { + return vec3(blendColorDodge(base.r,blend.r),blendColorDodge(base.g,blend.g),blendColorDodge(base.b,blend.b)); +} + +vec3 blendColorDodge(vec3 base, vec3 blend, float opacity) { + return (blendColorDodge(base, blend) * opacity + base * (1.0 - opacity)); +} + +#pragma glslify: export(blendColorDodge) \ No newline at end of file diff --git a/effects/darken.blend b/effects/darken.blend new file mode 100644 index 000000000..2c74f2911 --- /dev/null +++ b/effects/darken.blend @@ -0,0 +1,13 @@ +float blendDarken(float base, float blend) { + return min(blend,base); +} + +vec3 blendDarken(vec3 base, vec3 blend) { + return vec3(blendDarken(base.r,blend.r),blendDarken(base.g,blend.g),blendDarken(base.b,blend.b)); +} + +vec3 blendDarken(vec3 base, vec3 blend, float opacity) { + return (blendDarken(base, blend) * opacity + base * (1.0 - opacity)); +} + +#pragma glslify: export(blendDarken) \ No newline at end of file diff --git a/effects/difference.blend b/effects/difference.blend new file mode 100644 index 000000000..88810665b --- /dev/null +++ b/effects/difference.blend @@ -0,0 +1,9 @@ +vec3 blendDifference(vec3 base, vec3 blend) { + return abs(base-blend); +} + +vec3 blendDifference(vec3 base, vec3 blend, float opacity) { + return (blendDifference(base, blend) * opacity + base * (1.0 - opacity)); +} + +#pragma glslify: export(blendDifference) \ No newline at end of file diff --git a/effects/exclusion.blend b/effects/exclusion.blend new file mode 100644 index 000000000..3eb0b9dfc --- /dev/null +++ b/effects/exclusion.blend @@ -0,0 +1,9 @@ +vec3 blendExclusion(vec3 base, vec3 blend) { + return base+blend-2.0*base*blend; +} + +vec3 blendExclusion(vec3 base, vec3 blend, float opacity) { + return (blendExclusion(base, blend) * opacity + base * (1.0 - opacity)); +} + +#pragma glslify: export(blendExclusion) \ No newline at end of file diff --git a/effects/glow.blend b/effects/glow.blend new file mode 100644 index 000000000..ec087790d --- /dev/null +++ b/effects/glow.blend @@ -0,0 +1,11 @@ +#pragma glslify: blendReflect = require(./reflect) + +vec3 blendGlow(vec3 base, vec3 blend) { + return blendReflect(blend,base); +} + +vec3 blendGlow(vec3 base, vec3 blend, float opacity) { + return (blendGlow(base, blend) * opacity + base * (1.0 - opacity)); +} + +#pragma glslify: export(blendGlow) \ No newline at end of file diff --git a/effects/hard-light.blend b/effects/hard-light.blend new file mode 100644 index 000000000..4a376d2ec --- /dev/null +++ b/effects/hard-light.blend @@ -0,0 +1,11 @@ +#pragma glslify: blendOverlay = require(./overlay) + +vec3 blendHardLight(vec3 base, vec3 blend) { + return blendOverlay(blend,base); +} + +vec3 blendHardLight(vec3 base, vec3 blend, float opacity) { + return (blendHardLight(base, blend) * opacity + base * (1.0 - opacity)); +} + +#pragma glslify: export(blendHardLight) \ No newline at end of file diff --git a/effects/hard-mix.blend b/effects/hard-mix.blend new file mode 100644 index 000000000..3ce420ef9 --- /dev/null +++ b/effects/hard-mix.blend @@ -0,0 +1,15 @@ +#pragma glslify: blendVividLight = require(./vivid-light) + +float blendHardMix(float base, float blend) { + return (blendVividLight(base,blend)<0.5)?0.0:1.0; +} + +vec3 blendHardMix(vec3 base, vec3 blend) { + return vec3(blendHardMix(base.r,blend.r),blendHardMix(base.g,blend.g),blendHardMix(base.b,blend.b)); +} + +vec3 blendHardMix(vec3 base, vec3 blend, float opacity) { + return (blendHardMix(base, blend) * opacity + base * (1.0 - opacity)); +} + +#pragma glslify: export(blendHardMix) \ No newline at end of file diff --git a/effects/internal/transformeffect.cpp b/effects/internal/transformeffect.cpp index f4065ba1e..84216f2ab 100644 --- a/effects/internal/transformeffect.cpp +++ b/effects/internal/transformeffect.cpp @@ -36,6 +36,7 @@ #include "io/math.h" #include "ui/labelslider.h" #include "ui/comboboxex.h" +#include "project/effectloaders.h" #include "panels/project.h" #include "debug.h" @@ -78,9 +79,11 @@ TransformEffect::TransformEffect(Clip* c, const EffectMeta* em) : Effect(c, em) blend_mode_box->add_combo_item(tr("Normal"), -1); // add loaded blending modes + olive::effects_loaded.lock(); for (int i=0;iadd_combo_item(olive::blend_modes.at(i).name, i); } + olive::effects_loaded.unlock(); // set up gizmos top_left_gizmo = add_gizmo(GIZMO_TYPE_DOT); diff --git a/effects/lighten.blend b/effects/lighten.blend new file mode 100644 index 000000000..2ffaf9616 --- /dev/null +++ b/effects/lighten.blend @@ -0,0 +1,13 @@ +float blendLighten(float base, float blend) { + return max(blend,base); +} + +vec3 blendLighten(vec3 base, vec3 blend) { + return vec3(blendLighten(base.r,blend.r),blendLighten(base.g,blend.g),blendLighten(base.b,blend.b)); +} + +vec3 blendLighten(vec3 base, vec3 blend, float opacity) { + return (blendLighten(base, blend) * opacity + base * (1.0 - opacity)); +} + +#pragma glslify: export(blendLighten) \ No newline at end of file diff --git a/effects/linear-burn.blend b/effects/linear-burn.blend new file mode 100644 index 000000000..9c9ec26c1 --- /dev/null +++ b/effects/linear-burn.blend @@ -0,0 +1,15 @@ +float blendLinearBurn(float base, float blend) { + // Note : Same implementation as BlendSubtractf + return max(base+blend-1.0,0.0); +} + +vec3 blendLinearBurn(vec3 base, vec3 blend) { + // Note : Same implementation as BlendSubtract + return max(base+blend-vec3(1.0),vec3(0.0)); +} + +vec3 blendLinearBurn(vec3 base, vec3 blend, float opacity) { + return (blendLinearBurn(base, blend) * opacity + base * (1.0 - opacity)); +} + +#pragma glslify: export(blendLinearBurn) \ No newline at end of file diff --git a/effects/linear-dodge.blend b/effects/linear-dodge.blend new file mode 100644 index 000000000..147418f58 --- /dev/null +++ b/effects/linear-dodge.blend @@ -0,0 +1,15 @@ +float blendLinearDodge(float base, float blend) { + // Note : Same implementation as BlendAddf + return min(base+blend,1.0); +} + +vec3 blendLinearDodge(vec3 base, vec3 blend) { + // Note : Same implementation as BlendAdd + return min(base+blend,vec3(1.0)); +} + +vec3 blendLinearDodge(vec3 base, vec3 blend, float opacity) { + return (blendLinearDodge(base, blend) * opacity + base * (1.0 - opacity)); +} + +#pragma glslify: export(blendLinearDodge) \ No newline at end of file diff --git a/effects/linear-light.blend b/effects/linear-light.blend new file mode 100644 index 000000000..a66b56c65 --- /dev/null +++ b/effects/linear-light.blend @@ -0,0 +1,16 @@ +#pragma glslify: blendLinearDodge = require(./linear-dodge) +#pragma glslify: blendLinearBurn = require(./linear-burn) + +float blendLinearLight(float base, float blend) { + return blend<0.5?blendLinearBurn(base,(2.0*blend)):blendLinearDodge(base,(2.0*(blend-0.5))); +} + +vec3 blendLinearLight(vec3 base, vec3 blend) { + return vec3(blendLinearLight(base.r,blend.r),blendLinearLight(base.g,blend.g),blendLinearLight(base.b,blend.b)); +} + +vec3 blendLinearLight(vec3 base, vec3 blend, float opacity) { + return (blendLinearLight(base, blend) * opacity + base * (1.0 - opacity)); +} + +#pragma glslify: export(blendLinearLight) \ No newline at end of file diff --git a/effects/negation.blend b/effects/negation.blend new file mode 100644 index 000000000..03d5e478b --- /dev/null +++ b/effects/negation.blend @@ -0,0 +1,9 @@ +vec3 blendNegation(vec3 base, vec3 blend) { + return vec3(1.0)-abs(vec3(1.0)-base-blend); +} + +vec3 blendNegation(vec3 base, vec3 blend, float opacity) { + return (blendNegation(base, blend) * opacity + base * (1.0 - opacity)); +} + +#pragma glslify: export(blendNegation) \ No newline at end of file diff --git a/effects/normal.blend b/effects/normal.blend new file mode 100644 index 000000000..f66aa9b13 --- /dev/null +++ b/effects/normal.blend @@ -0,0 +1,9 @@ +vec3 blendNormal(vec3 base, vec3 blend) { + return blend; +} + +vec3 blendNormal(vec3 base, vec3 blend, float opacity) { + return (blendNormal(base, blend) * opacity + base * (1.0 - opacity)); +} + +#pragma glslify: export(blendNormal) \ No newline at end of file diff --git a/effects/overlay.blend b/effects/overlay.blend new file mode 100644 index 000000000..a5d0aba85 --- /dev/null +++ b/effects/overlay.blend @@ -0,0 +1,13 @@ +float blendOverlay(float base, float blend) { + return base<0.5?(2.0*base*blend):(1.0-2.0*(1.0-base)*(1.0-blend)); +} + +vec3 blendOverlay(vec3 base, vec3 blend) { + return vec3(blendOverlay(base.r,blend.r),blendOverlay(base.g,blend.g),blendOverlay(base.b,blend.b)); +} + +vec3 blendOverlay(vec3 base, vec3 blend, float opacity) { + return (blendOverlay(base, blend) * opacity + base * (1.0 - opacity)); +} + +#pragma glslify: export(blendOverlay) \ No newline at end of file diff --git a/effects/phoenix.blend b/effects/phoenix.blend new file mode 100644 index 000000000..eb16f2c4e --- /dev/null +++ b/effects/phoenix.blend @@ -0,0 +1,9 @@ +vec3 blendPhoenix(vec3 base, vec3 blend) { + return min(base,blend)-max(base,blend)+vec3(1.0); +} + +vec3 blendPhoenix(vec3 base, vec3 blend, float opacity) { + return (blendPhoenix(base, blend) * opacity + base * (1.0 - opacity)); +} + +#pragma glslify: export(blendPhoenix) \ No newline at end of file diff --git a/effects/pin-light.blend b/effects/pin-light.blend new file mode 100644 index 000000000..04e4ae7c6 --- /dev/null +++ b/effects/pin-light.blend @@ -0,0 +1,16 @@ +#pragma glslify: blendLighten = require(./lighten) +#pragma glslify: blendDarken = require(./darken) + +float blendPinLight(float base, float blend) { + return (blend<0.5)?blendDarken(base,(2.0*blend)):blendLighten(base,(2.0*(blend-0.5))); +} + +vec3 blendPinLight(vec3 base, vec3 blend) { + return vec3(blendPinLight(base.r,blend.r),blendPinLight(base.g,blend.g),blendPinLight(base.b,blend.b)); +} + +vec3 blendPinLight(vec3 base, vec3 blend, float opacity) { + return (blendPinLight(base, blend) * opacity + base * (1.0 - opacity)); +} + +#pragma glslify: export(blendPinLight) \ No newline at end of file diff --git a/effects/reflect.blend b/effects/reflect.blend new file mode 100644 index 000000000..a7b7766aa --- /dev/null +++ b/effects/reflect.blend @@ -0,0 +1,13 @@ +float blendReflect(float base, float blend) { + return (blend==1.0)?blend:min(base*base/(1.0-blend),1.0); +} + +vec3 blendReflect(vec3 base, vec3 blend) { + return vec3(blendReflect(base.r,blend.r),blendReflect(base.g,blend.g),blendReflect(base.b,blend.b)); +} + +vec3 blendReflect(vec3 base, vec3 blend, float opacity) { + return (blendReflect(base, blend) * opacity + base * (1.0 - opacity)); +} + +#pragma glslify: export(blendReflect) \ No newline at end of file diff --git a/effects/screen.blend b/effects/screen.blend new file mode 100644 index 000000000..24f345738 --- /dev/null +++ b/effects/screen.blend @@ -0,0 +1,13 @@ +float blendScreen(float base, float blend) { + return 1.0-((1.0-base)*(1.0-blend)); +} + +vec3 blendScreen(vec3 base, vec3 blend) { + return vec3(blendScreen(base.r,blend.r),blendScreen(base.g,blend.g),blendScreen(base.b,blend.b)); +} + +vec3 blendScreen(vec3 base, vec3 blend, float opacity) { + return (blendScreen(base, blend) * opacity + base * (1.0 - opacity)); +} + +#pragma glslify: export(blendScreen) \ No newline at end of file diff --git a/effects/soft-light.blend b/effects/soft-light.blend new file mode 100644 index 000000000..c9558d1d2 --- /dev/null +++ b/effects/soft-light.blend @@ -0,0 +1,13 @@ +float blendSoftLight(float base, float blend) { + return (blend<0.5)?(2.0*base*blend+base*base*(1.0-2.0*blend)):(sqrt(base)*(2.0*blend-1.0)+2.0*base*(1.0-blend)); +} + +vec3 blendSoftLight(vec3 base, vec3 blend) { + return vec3(blendSoftLight(base.r,blend.r),blendSoftLight(base.g,blend.g),blendSoftLight(base.b,blend.b)); +} + +vec3 blendSoftLight(vec3 base, vec3 blend, float opacity) { + return (blendSoftLight(base, blend) * opacity + base * (1.0 - opacity)); +} + +#pragma glslify: export(blendSoftLight) \ No newline at end of file diff --git a/effects/substract.blend b/effects/substract.blend new file mode 100644 index 000000000..bdc1c65a3 --- /dev/null +++ b/effects/substract.blend @@ -0,0 +1,13 @@ +float blendSubstract(float base, float blend) { + return max(base+blend-1.0,0.0); +} + +vec3 blendSubstract(vec3 base, vec3 blend) { + return max(base+blend-vec3(1.0),vec3(0.0)); +} + +vec3 blendSubstract(vec3 base, vec3 blend, float opacity) { + return (blendSubstract(base, blend) * opacity + blend * (1.0 - opacity)); +} + +#pragma glslify: export(blendSubstract) \ No newline at end of file diff --git a/effects/subtract.blend b/effects/subtract.blend new file mode 100644 index 000000000..2a8f50a31 --- /dev/null +++ b/effects/subtract.blend @@ -0,0 +1,13 @@ +float blendSubtract(float base, float blend) { + return max(base+blend-1.0,0.0); +} + +vec3 blendSubtract(vec3 base, vec3 blend) { + return max(base+blend-vec3(1.0),vec3(0.0)); +} + +vec3 blendSubtract(vec3 base, vec3 blend, float opacity) { + return (blendSubtract(base, blend) * opacity + base * (1.0 - opacity)); +} + +#pragma glslify: export(blendSubtract) \ No newline at end of file diff --git a/effects/vivid-light.blend b/effects/vivid-light.blend new file mode 100644 index 000000000..f86ca4922 --- /dev/null +++ b/effects/vivid-light.blend @@ -0,0 +1,16 @@ +#pragma glslify: blendColorDodge = require(./color-dodge) +#pragma glslify: blendColorBurn = require(./color-burn) + +float blendVividLight(float base, float blend) { + return (blend<0.5)?blendColorBurn(base,(2.0*blend)):blendColorDodge(base,(2.0*(blend-0.5))); +} + +vec3 blendVividLight(vec3 base, vec3 blend) { + return vec3(blendVividLight(base.r,blend.r),blendVividLight(base.g,blend.g),blendVividLight(base.b,blend.b)); +} + +vec3 blendVividLight(vec3 base, vec3 blend, float opacity) { + return (blendVividLight(base, blend) * opacity + base * (1.0 - opacity)); +} + +#pragma glslify: export(blendVividLight) \ No newline at end of file diff --git a/io/loadthread.cpp b/io/loadthread.cpp index 6b2dc103b..d33a6c2a7 100644 --- a/io/loadthread.cpp +++ b/io/loadthread.cpp @@ -32,6 +32,7 @@ #include "rendering/renderfunctions.h" #include "io/previewgenerator.h" #include "effects/internal/voideffect.h" +#include "project/effectloaders.h" #include "debug.h" #include @@ -115,7 +116,7 @@ void LoadThread::load_effect(QXmlStreamReader& stream, Clip* c) { // Effect loading occurs in another thread, and while it's usually very quick, just for safety we wait here // for all the effects to finish loading - panel_effect_controls->effects_loaded.lock(); + olive::effects_loaded.lock(); const EffectMeta* meta = nullptr; @@ -124,7 +125,7 @@ void LoadThread::load_effect(QXmlStreamReader& stream, Clip* c) { meta = get_meta_from_name(effect_name); } - panel_effect_controls->effects_loaded.unlock(); + olive::effects_loaded.unlock(); int type; if (tag == "opening") { diff --git a/panels/effectcontrols.cpp b/panels/effectcontrols.cpp index 1f0088ed1..d93849d24 100644 --- a/panels/effectcontrols.cpp +++ b/panels/effectcontrols.cpp @@ -39,6 +39,7 @@ #include "ui/collapsiblewidget.h" #include "project/sequence.h" #include "project/undo.h" +#include "project/effectloaders.h" #include "panels/project.h" #include "panels/timeline.h" #include "panels/viewer.h" @@ -194,7 +195,7 @@ void EffectControls::show_effect_menu(int type, int subtype) { effect_menu_type = type; effect_menu_subtype = subtype; - effects_loaded.lock(); + olive::effects_loaded.lock(); QMenu effects_menu(this); effects_menu.setToolTipsVisible(true); @@ -254,7 +255,7 @@ void EffectControls::show_effect_menu(int type, int subtype) { } } - effects_loaded.unlock(); + olive::effects_loaded.unlock(); connect(&effects_menu, SIGNAL(triggered(QAction*)), this, SLOT(menu_select(QAction*))); effects_menu.exec(QCursor::pos()); diff --git a/panels/effectcontrols.h b/panels/effectcontrols.h index 4cc3a9116..a204a65d0 100644 --- a/panels/effectcontrols.h +++ b/panels/effectcontrols.h @@ -74,8 +74,6 @@ public: ResizableScrollBar* horizontalScrollBar; QScrollBar* verticalScrollBar; - QMutex effects_loaded; - void add_effect_paste_action(QMenu* menu); virtual void Retranslate() override; diff --git a/project/effectloaders.cpp b/project/effectloaders.cpp index 0dd3863d1..8c96494c0 100644 --- a/project/effectloaders.cpp +++ b/project/effectloaders.cpp @@ -33,6 +33,8 @@ #include +QMutex olive::effects_loaded; + #ifndef NOFREI0R #include typedef void (*f0rGetPluginInfo)(f0r_plugin_info_t* info); @@ -287,15 +289,27 @@ void GenerateBlendingShader() while (!stream.atEnd()) { QString line = stream.readLine(); - if (line.startsWith("#olive name ")) { + if (line.length() > 0 && line.at(0) == '#') { - // The blending mode can specify its own name - olive::blend_modes[i].name = line.mid(12); + if (line.startsWith("#olive name ")) { - } else if (line.startsWith("#pragma glslify: export(")) { + // The blending mode can specify its own name + olive::blend_modes[i].name = line.mid(12); - // Get function name - olive::blend_modes[i].function_name = line.mid(24, line.length()-25); + } else if (line.startsWith("#pragma glslify: export(")) { + + // Get function name + olive::blend_modes[i].function_name = line.mid(24, line.length()-25); + + } else if (line.contains("require")) { + + // This function wanted to include an external shader + + int index_of_last_bracked = line.lastIndexOf('(') + 1; + + qDebug() << "this blend mode wanted:" << line.mid(index_of_last_bracked, line.length() - index_of_last_bracked - 1); + + } } else { @@ -324,7 +338,7 @@ void GenerateBlendingShader() olive::generated_blending_shader.append(QString(" else if (blendmode == %1) {\n").arg(i)); } - olive::generated_blending_shader.append(QString(" return %1(base, blend)\n").arg(olive::blend_modes.at(i).function_name)); + olive::generated_blending_shader.append(QString(" return %1(base, blend);\n").arg(olive::blend_modes.at(i).function_name)); olive::generated_blending_shader.append(" }"); } @@ -344,7 +358,7 @@ void GenerateBlendingShader() } EffectInit::EffectInit() { - panel_effect_controls->effects_loaded.lock(); + olive::effects_loaded.lock(); } void EffectInit::run() { @@ -355,6 +369,6 @@ void EffectInit::run() { load_frei0r_effects(); #endif GenerateBlendingShader(); - panel_effect_controls->effects_loaded.unlock(); + olive::effects_loaded.unlock(); qInfo() << "Finished initializing effects"; } diff --git a/project/effectloaders.h b/project/effectloaders.h index a5370df41..1c09268d4 100644 --- a/project/effectloaders.h +++ b/project/effectloaders.h @@ -23,6 +23,11 @@ #include #include +#include + +namespace olive { + extern QMutex effects_loaded; +} void init_effects(); diff --git a/rendering/renderthread.cpp b/rendering/renderthread.cpp index 2bfc54006..402059288 100644 --- a/rendering/renderthread.cpp +++ b/rendering/renderthread.cpp @@ -32,6 +32,7 @@ namespace OCIO = OCIO_NAMESPACE; #include "rendering/renderfunctions.h" #include "project/sequence.h" +#include "project/effectloaders.h" RenderThread::RenderThread() : gizmos(nullptr), @@ -99,7 +100,9 @@ void RenderThread::run() { blend_mode_program = new QOpenGLShaderProgram(); blend_mode_program->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/internalshaders/common.vert"); + olive::effects_loaded.lock(); blend_mode_program->addShaderFromSourceCode(QOpenGLShader::Fragment, olive::generated_blending_shader); + olive::effects_loaded.unlock(); blend_mode_program->link(); premultiply_program = new QOpenGLShaderProgram();