From 8019f4ea25c4267d5e524837758bf1434261c729 Mon Sep 17 00:00:00 2001 From: brunoherbelin Date: Sun, 21 Feb 2021 22:02:04 +0100 Subject: [PATCH] Cleanup blending update --- CMakeLists.txt | 1 + ImGuiVisitor.cpp | 6 +++--- ImageShader.cpp | 24 +++++++++++++++++------- ImageShader.h | 8 ++++++++ SessionSource.cpp | 5 ++--- Shader.cpp | 29 +++-------------------------- Shader.h | 4 +--- Source.cpp | 18 +++++++++--------- View.cpp | 2 ++ rsc/shaders/image.fs | 10 ++++------ rsc/shaders/imageblending.fs | 23 ++++++++++++----------- rsc/shaders/imageprocessing.fs | 6 +++--- rsc/shaders/simple.fs | 3 +-- 13 files changed, 66 insertions(+), 73 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7f0876d..580999d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -303,6 +303,7 @@ set(VMIX_RSC_FILES ./rsc/shaders/mask_draw.fs ./rsc/shaders/image.vs ./rsc/shaders/imageprocessing.fs + ./rsc/shaders/imageblending.fs ./rsc/fonts/Hack-Regular.ttf ./rsc/fonts/Roboto-Regular.ttf ./rsc/fonts/Roboto-Bold.ttf diff --git a/ImGuiVisitor.cpp b/ImGuiVisitor.cpp index 3e03a27..fed9800 100644 --- a/ImGuiVisitor.cpp +++ b/ImGuiVisitor.cpp @@ -171,7 +171,7 @@ void ImGuiVisitor::visit(Shader &n) // ImGui::SameLine(0, 5); ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN); int mode = n.blending; - if (ImGui::Combo("Blending", &mode, "Normal\0Screen\0Subtract\0Multiply\0Soft light\0Soft subtract\0Lighten only\0") ) { + if (ImGui::Combo("Blending", &mode, "Normal\0Screen\0Subtract\0Multiply\0Soft light\0Soft subtract\0Lighten only\0None\0") ) { n.blending = Shader::BlendMode(mode); std::ostringstream oss; @@ -198,8 +198,8 @@ void ImGuiVisitor::visit(Shader &n) case Shader::BLEND_LIGHTEN_ONLY: oss<<"Lighten only"; break; - case Shader::BLEND_CUSTOM: - oss<<"Custom"; + case Shader::BLEND_NONE: + oss<<"None"; break; } Action::manager().store(oss.str(), n.id()); diff --git a/ImageShader.cpp b/ImageShader.cpp index 0850f08..5d140ea 100644 --- a/ImageShader.cpp +++ b/ImageShader.cpp @@ -2,14 +2,15 @@ #include "defines.h" #include "Visitor.h" -#include "ImageShader.h" #include "Resource.h" #include "rsc/fonts/IconsFontAwesome5.h" -//#include -static ShadingProgram imageShadingProgram("shaders/image.vs", "shaders/image.fs"); +#include "ImageShader.h" -const char* MaskShader::mask_names[3] = { ICON_FA_EXPAND, ICON_FA_EDIT, ICON_FA_SHAPES }; +ShadingProgram imageShadingProgram("shaders/image.vs", "shaders/image.fs"); +ShadingProgram inverseAlphaProgram("shaders/image.vs", "shaders/imageblending.fs"); + +const char* MaskShader::mask_names[3] = { ICON_FA_EXPAND, ICON_FA_EDIT, ICON_FA_SHAPES }; const char* MaskShader::mask_shapes[5] = { "Elipse", "Oblong", "Rectangle", "Horizontal", "Vertical" }; std::vector< ShadingProgram* > MaskShader::mask_programs; @@ -25,15 +26,15 @@ void ImageShader::use() { Shader::use(); + // set stippling program_->setUniform("stipple", stipple); + // setup mask texture glActiveTexture(GL_TEXTURE1); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glBindTexture(GL_TEXTURE_2D, mask_texture); - + glBindTexture (GL_TEXTURE_2D, mask_texture); glActiveTexture(GL_TEXTURE0); - } void ImageShader::reset() @@ -61,6 +62,15 @@ void ImageShader::accept(Visitor& v) { } +DivideAlphaShader::DivideAlphaShader(): ImageShader() +{ + // to inverse alpha mode, use dedicated shading program + program_ = &inverseAlphaProgram; + // reset instance + reset(); + + blending = Shader::BLEND_NONE; +} MaskShader::MaskShader(): Shader(), mode(0) diff --git a/ImageShader.h b/ImageShader.h index 0005eaa..f2d3f7c 100644 --- a/ImageShader.h +++ b/ImageShader.h @@ -27,6 +27,14 @@ public: float stipple; }; +class DivideAlphaShader : public ImageShader +{ + +public: + DivideAlphaShader(); + +}; + class MaskShader : public Shader { diff --git a/SessionSource.cpp b/SessionSource.cpp index 5690a1e..919a671 100644 --- a/SessionSource.cpp +++ b/SessionSource.cpp @@ -264,7 +264,6 @@ SessionGroupSource::SessionGroupSource() : SessionSource(), resolution_(glm::vec group->attach(persp); frames_[View::LAYER]->attach(group); - // set symbol symbol_ = new Symbol(Symbol::GROUP, glm::vec3(0.75f, 0.75f, 0.01f)); symbol_->scale_.y = 1.5f; @@ -274,7 +273,7 @@ void SessionGroupSource::init() { if ( resolution_.x > 0.f && resolution_.y > 0.f ) { - session_->setResolution( resolution_, true ); + session_->setResolution( resolution_ ); // update to draw framebuffer session_->update( dt_ ); @@ -283,7 +282,7 @@ void SessionGroupSource::init() texturesurface_->setTextureIndex( session_->frame()->texture() ); // create Frame buffer matching size of session - FrameBuffer *renderbuffer = new FrameBuffer( session_->frame()->resolution(), true ); + FrameBuffer *renderbuffer = new FrameBuffer( session_->frame()->resolution() ); // set the renderbuffer of the source and attach rendering nodes attach(renderbuffer); diff --git a/Shader.cpp b/Shader.cpp index 8107422..aac55b0 100644 --- a/Shader.cpp +++ b/Shader.cpp @@ -47,12 +47,7 @@ GLenum blending_destination_function[8] = {GL_ONE_MINUS_SRC_ALPHA,// normal GL_ONE, // soft light GL_ONE, // soft subtract GL_ONE, // lighten only - GL_ONE_MINUS_SRC_ALPHA}; - -//GLenum blending_equation[6] = { GL_FUNC_ADD, GL_FUNC_ADD, GL_FUNC_REVERSE_SUBTRACT, GL_FUNC_ADD, GL_FUNC_REVERSE_SUBTRACT, GL_FUNC_ADD}; -//GLenum blending_source_function[6] = { GL_SRC_ALPHA,GL_SRC_ALPHA,GL_SRC_ALPHA,GL_SRC_ALPHA,GL_SRC_ALPHA,GL_SRC_ALPHA}; -//GLenum blending_destination_function[6] = {GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE, GL_DST_COLOR, GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA}; - + GL_ZERO}; ShadingProgram::ShadingProgram(const std::string& vertex_file, const std::string& fragment_file) : vertex_id_(0), fragment_id_(0), id_(0) { @@ -202,7 +197,6 @@ void ShadingProgram::checkLinkingErr() bool Shader::force_blending_opacity = false; -bool Shader::force_blending_overwrite = false; Shader::Shader() : blending(BLEND_OPACITY) { @@ -231,7 +225,7 @@ void Shader::use() if (!program_->initialized()) program_->init(); - // Use program and set uniforms + // Use program program_->use(); // set uniforms @@ -248,25 +242,8 @@ void Shader::use() glEnable(GL_BLEND); glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD); glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - } - else if (force_blending_overwrite) { - glDisable(GL_BLEND); -// glEnable(GL_BLEND); -// glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD); -// glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - - -// glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD); -// glBlendColor(1.f, 1.f, 1.f, 1.f); -// glBlendFuncSeparate(GL_CONSTANT_COLOR, GL_CONSTANT_COLOR, GL_CONSTANT_COLOR, GL_CONSTANT_ALPHA); -// glBlendEquationSeparate(blending_equation[blending], GL_FUNC_ADD); -// glBlendFuncSeparate(blending_source_function[blending], blending_destination_function[blending], GL_ONE, GL_ONE); - -// Log::Info("force_blending_overwrite"); - - } - else if ( blending != BLEND_CUSTOM ) { + else if ( blending < BLEND_NONE ) { glEnable(GL_BLEND); glBlendEquationSeparate(blending_equation[blending], GL_FUNC_ADD); glBlendFuncSeparate(blending_source_function[blending], blending_destination_function[blending], GL_ONE, GL_ONE_MINUS_SRC_ALPHA); diff --git a/Shader.h b/Shader.h index f06b556..ee8e551 100644 --- a/Shader.h +++ b/Shader.h @@ -66,16 +66,14 @@ public: BLEND_SOFT_LIGHT, BLEND_SOFT_SUBTRACT, BLEND_LIGHTEN_ONLY, - BLEND_CUSTOM + BLEND_NONE } BlendMode; BlendMode blending; static bool force_blending_opacity; - static bool force_blending_overwrite; protected: ShadingProgram *program_; - }; diff --git a/Source.cpp b/Source.cpp index e995da8..36ea338 100644 --- a/Source.cpp +++ b/Source.cpp @@ -353,12 +353,12 @@ void Source::render() void Source::attach(FrameBuffer *renderbuffer) { // invalid argument -// if (renderbuffer == nullptr) -// return; + if (renderbuffer == nullptr) + return; -// // replace renderbuffer_ -// if (renderbuffer_) -// delete renderbuffer_; + // replace renderbuffer_ + if (renderbuffer_) + delete renderbuffer_; renderbuffer_ = renderbuffer; // if a symbol is available, add it to overlay @@ -488,10 +488,10 @@ void Source::setAlpha(float a) step = glm::vec2(0.01f, 0.01f); // converge linearly to reduce the difference of alpha - float delta = sin_quad(dist.x, dist.y) - a; - while ( glm::abs(delta) > 0.01 ){ + float delta = sin_quad(dist.x, dist.y) - CLAMP(a, 0.f, 1.f); + while ( glm::abs(delta) > 0.01f ){ dist += step * glm::sign(delta); - delta = sin_quad(dist.x, dist.y) - a; + delta = sin_quad(dist.x, dist.y) - CLAMP(a, 0.f, 1.f); } // apply new mixing coordinates @@ -512,7 +512,7 @@ void Source::update(float dt) // read position of the mixing node and interpret this as transparency of render output glm::vec2 dist = glm::vec2(groups_[View::MIXING]->translation_); // use the sinusoidal transfer function - blendingshader_->color = glm::vec4(1.0, 1.0, 1.0, sin_quad( dist.x, dist.y )); + blendingshader_->color = glm::vec4(1.f, 1.f, 1.f, sin_quad( dist.x, dist.y )); mixingshader_->color = blendingshader_->color; // CHANGE update status based on limbo diff --git a/View.cpp b/View.cpp index 5a06e6d..a364457 100644 --- a/View.cpp +++ b/View.cpp @@ -709,6 +709,8 @@ void RenderView::draw() if (frame_buffer_) { // draw in frame buffer glm::mat4 P = glm::scale( projection, glm::vec3(1.f / frame_buffer_->aspectRatio(), 1.f, 1.f)); + + // render the scene normally (pre-multiplied alpha in RGB) frame_buffer_->begin(); scene.root()->draw(glm::identity(), P); fading_overlay_->draw(glm::identity(), projection); diff --git a/rsc/shaders/image.fs b/rsc/shaders/image.fs index 4cafe1d..1de3ae1 100644 --- a/rsc/shaders/image.fs +++ b/rsc/shaders/image.fs @@ -9,11 +9,10 @@ in vec2 vertexUV; uniform vec3 iResolution; // viewport image resolution (in pixels) uniform mat4 iTransform; // image transformation uniform vec4 color; -uniform vec4 uv; // Image Shader -uniform sampler2D iChannel0; // input channel (texture id). -uniform sampler2D iChannel1; // input mask +uniform sampler2D iChannel0; // input channel (texture id). +uniform sampler2D iChannel1; // input mask uniform float stipple; void main() @@ -28,12 +27,11 @@ void main() // read mask intensity as average of RGB float maskIntensity = dot(texture(iChannel1, vertexUV).rgb, vec3(1.0/3.0)); - // alpha is a mix of texture alpha, vertex alpha, and uniform alpha affected by stippling + // alpha is a mix of texture, vertex, uniform and mask alpha, affected by stippling float A = textureColor.a * vertexColor.a * color.a * maskIntensity; A += textureColor.a * stipple * ( int(gl_FragCoord.x + gl_FragCoord.y) % 2 ); A = clamp(A, 0.0, 1.0); - // output RGBA + // output RGB with Alpha pre-multiplied FragColor = vec4(RGB * A, A); -// FragColor = texture(iChannel1, vertexUV); } diff --git a/rsc/shaders/imageblending.fs b/rsc/shaders/imageblending.fs index 292fb2a..c5534d2 100644 --- a/rsc/shaders/imageblending.fs +++ b/rsc/shaders/imageblending.fs @@ -6,9 +6,9 @@ in vec4 vertexColor; in vec2 vertexUV; // from General Shader -uniform vec3 iResolution; // viewport resolution (in pixels) +uniform vec3 iResolution; // viewport image resolution (in pixels) +uniform mat4 iTransform; // image transformation uniform vec4 color; -uniform vec4 uv; // Image Shader uniform sampler2D iChannel0; // input channel (texture id). @@ -18,18 +18,19 @@ uniform float stipple; void main() { // adjust UV - vec2 texcoord = vec2(uv.x, uv.y) + vertexUV * vec2(uv.z - uv.x, uv.w - uv.y); + vec4 texcoord = iTransform * vec4(vertexUV.x, vertexUV.y, 0.0, 1.0); - // color is a mix of texture (manipulated with brightness & contrast), vertex and uniform colors - vec4 textureColor = texture(iChannel0, texcoord); + // color texture + vec4 textureColor = texture(iChannel0, texcoord.xy); vec3 RGB = textureColor.rgb * vertexColor.rgb * color.rgb; - // alpha is a mix of texture alpha, vertex alpha, and uniform alpha affected by stippling - float maskIntensity = dot(texture(iChannel1, vertexUV).rgb, vec3(1.0/3.0)); + // alpha is a mix of texture, vertex, uniform and mask alpha + float A = textureColor.a * vertexColor.a * color.a; - float A = textureColor.a * vertexColor.a * color.a * maskIntensity; - A -= stipple * ( int(gl_FragCoord.x + gl_FragCoord.y) % 2 > 0 ? 0.05 : 0.95 ); + // post-reversing premultiplication of alpha + float invA = 1.0 / clamp( A , 0.000001, 10.0); +// float invA = 1.0 / (A*A); - // output RGBA - FragColor = vec4(RGB, clamp(A, 0.0, 1.0) ); + // output + FragColor = vec4( RGB * invA, A); } diff --git a/rsc/shaders/imageprocessing.fs b/rsc/shaders/imageprocessing.fs index 17e6b4a..283f24a 100644 --- a/rsc/shaders/imageprocessing.fs +++ b/rsc/shaders/imageprocessing.fs @@ -326,8 +326,7 @@ void main(void) float alpha = clamp(ma * color.a, 0.0, 1.0); // read color & apply basic filterid - vec3 transformedRGB; - transformedRGB = apply_filter(); + vec3 transformedRGB = apply_filter(); // chromakey alpha -= mix( 0.0, 1.0 - alphachromakey( transformedRGB, chromakey.rgb, chromadelta), float(chromadelta > 0.0001) ); @@ -355,6 +354,7 @@ void main(void) // luma key alpha -= mix( 0.0, step( transformedHSL.z, lumakey ), float(lumakey > EPSILON)); + alpha = clamp(alpha, 0.0, 1.0); // level threshold transformedHSL = mix( transformedHSL, vec3(0.0, 0.0, 0.95 - step( transformedHSL.z, threshold )), float(threshold > EPSILON)); @@ -366,7 +366,7 @@ void main(void) transformedRGB = LevelsControl(transformedRGB, levels.x, gamma.rgb * gamma.a, levels.y, levels.z, levels.w); // apply base color and alpha for final fragment color - FragColor = vec4(transformedRGB * vertexColor.rgb * color.rgb * alpha, clamp(alpha, 0.0, 1.0) ); + FragColor = vec4(transformedRGB * vertexColor.rgb * color.rgb * alpha, alpha); } diff --git a/rsc/shaders/simple.fs b/rsc/shaders/simple.fs index 4d890aa..14bbccd 100644 --- a/rsc/shaders/simple.fs +++ b/rsc/shaders/simple.fs @@ -7,12 +7,11 @@ in vec4 vertexColor; uniform vec3 iResolution; // viewport resolution (in pixels) uniform vec4 color; // drawing color -uniform vec4 uv; void main() { vec4 c = color * vertexColor; - FragColor = vec4( vec3(c) * c.a, c.a); + FragColor = vec4( c.r * c.a, c.g * c.a, c.b * c.a, c.a); } // RGBA 2 YUVA converter