From 5dccd611604d02913710c4471a684c2b50867b7f Mon Sep 17 00:00:00 2001 From: omigamedev Date: Sun, 12 Nov 2017 03:27:28 +0000 Subject: [PATCH] implement blend mode selection in shader and fix alpha lock --- data/layout.xml | 2 +- engine/app_shaders.cpp | 15 +++++++++++---- engine/brush.h | 1 + engine/canvas.cpp | 3 ++- engine/node_canvas.cpp | 1 + engine/node_combobox.cpp | 4 +++- engine/node_combobox.h | 1 + engine/node_panel_stroke.cpp | 4 ++++ engine/node_panel_stroke.h | 2 ++ engine/shader.h | 1 + 10 files changed, 27 insertions(+), 7 deletions(-) diff --git a/data/layout.xml b/data/layout.xml index 7836204..c062683 100644 --- a/data/layout.xml +++ b/data/layout.xml @@ -158,7 +158,7 @@ - + diff --git a/engine/app_shaders.cpp b/engine/app_shaders.cpp index 92bd65c..b2a3d73 100644 --- a/engine/app_shaders.cpp +++ b/engine/app_shaders.cpp @@ -84,6 +84,7 @@ void App::initShaders() "uniform sampler2D tex_stencil;\n" //"uniform image2D img_mixer;\n" "uniform mediump float alpha;\n" + "uniform mediump int blend_mode;\n" "uniform bool lock;\n" "uniform bool mask;\n" "in mediump vec3 uv;\n" @@ -100,10 +101,16 @@ void App::initShaders() " sum += textureOffset(t, uv, ivec2( 1, 1));\n" " return sum / vec4(9.0);\n" "}\n" - "vec3 blend_colorDodge(vec4 base, vec4 stroke, float alpha_tot) { return mix(stroke.rgb, mix(base.rgb, base.rgb/(1.0-stroke.rgb), stroke.a/alpha_tot), base.a/alpha_tot); }\n" + "vec3 blend_normal(vec4 base, vec4 stroke, float alpha_tot) { return mix(base.rgb, stroke.rgb, stroke.a/alpha_tot); }\n" "vec3 blend_multiply(vec4 base, vec4 stroke, float alpha_tot) { return mix(stroke.rgb, mix(base.rgb, base.rgb*stroke.rgb, stroke.a/alpha_tot), base.a/alpha_tot); }\n" "vec3 blend_screen(vec4 base, vec4 stroke, float alpha_tot) { return mix(stroke.rgb, mix(base.rgb, 1.0-(1.0-base.rgb)*(1.0-stroke.rgb), stroke.a/alpha_tot), base.a/alpha_tot); }\n" - "vec3 blend_normal(vec4 base, vec4 stroke, float alpha_tot) { return mix(base.rgb, stroke.rgb, stroke.a/alpha_tot); }\n" + "vec3 blend_colorDodge(vec4 base, vec4 stroke, float alpha_tot) { return mix(stroke.rgb, mix(base.rgb, base.rgb/(1.0-stroke.rgb), stroke.a/alpha_tot), base.a/alpha_tot); }\n" + "vec3 blend(vec4 base, vec4 stroke, float alpha_tot, int mode) { switch(mode){\n" + " case 0: return blend_normal(base, stroke, alpha_tot);" + " case 1: return blend_multiply(base, stroke, alpha_tot);" + " case 2: return blend_screen(base, stroke, alpha_tot);" + " case 3: return blend_colorDodge(base, stroke, alpha_tot);" + "}}\n" "void main(){\n" " mediump vec2 uv2 = gl_FragCoord.st / vec2(2048) * 20.0;\n" " mediump vec4 base = texture(tex, uv.xy);\n" @@ -111,10 +118,10 @@ void App::initShaders() " mediump float stencil = pow(texture(tex_stencil, uv2).r, 8.0);\n" " stroke.a = mask ? stroke.a * alpha * blur(tex_mask, uv.xy).r : stroke.a * alpha;\n" - " if (base.a == 0.0) { frag = stroke; return; }\n" + " if (!lock && base.a == 0.0) { frag = stroke; return; }\n" " mediump float contribution = (1.0 - base.a) * stroke.a;\n" " mediump float alpha_tot = base.a + contribution;" - " mediump vec3 rgb = blend_screen(base, stroke, alpha_tot);\n" + " mediump vec3 rgb = blend(base, stroke, alpha_tot, blend_mode);\n" " frag = vec4(rgb, (lock ? base.a : alpha_tot));\n" "}\n"; diff --git a/engine/brush.h b/engine/brush.h index 4e391f2..7cb0868 100644 --- a/engine/brush.h +++ b/engine/brush.h @@ -25,6 +25,7 @@ public: float m_jitter_angle = 0; float m_jitter_spread = 0; float m_jitter_flow = 0; + int m_blend_mode = 0; }; struct StrokeSample diff --git a/engine/canvas.cpp b/engine/canvas.cpp index 20e693a..d6c0740 100644 --- a/engine/canvas.cpp +++ b/engine/canvas.cpp @@ -506,7 +506,8 @@ void ui::Canvas::stroke_commit() ui::ShaderManager::u_int(kShaderUniform::TexMask, 2); ui::ShaderManager::u_float(kShaderUniform::Alpha, m_current_stroke->m_brush.m_tip_opacity); ui::ShaderManager::u_int(kShaderUniform::Mask, m_smask_active); - ShaderManager::u_mat4(kShaderUniform::MVP, glm::ortho(-.5f, .5f, -.5f, .5f, -1.f, 1.f)); + ui::ShaderManager::u_int(kShaderUniform::BlendMode, m_current_stroke->m_brush.m_blend_mode); + ui::ShaderManager::u_mat4(kShaderUniform::MVP, glm::ortho(-.5f, .5f, -.5f, .5f, -1.f, 1.f)); glActiveTexture(GL_TEXTURE0); m_tex2[i].bind(); diff --git a/engine/node_canvas.cpp b/engine/node_canvas.cpp index 8ae512a..2d0697d 100644 --- a/engine/node_canvas.cpp +++ b/engine/node_canvas.cpp @@ -153,6 +153,7 @@ void NodeCanvas::draw() ui::ShaderManager::u_float(kShaderUniform::Alpha, m_canvas->m_current_stroke->m_brush.m_tip_opacity); ui::ShaderManager::u_int(kShaderUniform::Lock, m_canvas->m_layers[m_canvas->m_current_layer_idx].m_alpha_locked); ui::ShaderManager::u_int(kShaderUniform::Mask, m_canvas->m_smask_active); + ui::ShaderManager::u_int(kShaderUniform::BlendMode, m_canvas->m_current_stroke->m_brush.m_blend_mode); ui::ShaderManager::u_mat4(kShaderUniform::MVP, plane_mvp_z); glActiveTexture(GL_TEXTURE0); m_canvas->m_layers[layer_index].m_rtt[plane_index].bindTexture(); diff --git a/engine/node_combobox.cpp b/engine/node_combobox.cpp index ab0010c..50f9159 100644 --- a/engine/node_combobox.cpp +++ b/engine/node_combobox.cpp @@ -28,12 +28,14 @@ void NodeComboBox::loaded() btn->m_text->set_text(labels[i].c_str()); btn->m_border->SetWidthP(100.f); btn->m_border->SetHeight(30.f); - btn->on_click = [this,popup](Node* target) { + btn->on_click = [this,popup,btn](Node* target) { int index = popup->get_child_index(target); m_current_index = index; m_text->set_text(labels[index].c_str()); popup->mouse_release(); popup->destroy(); + if (on_select) + on_select(btn, index); }; } glm::vec2 pos = m_pos + glm::vec2(0, m_size.y - (m_current_index+1) * 30.f); diff --git a/engine/node_combobox.h b/engine/node_combobox.h index c699e07..2cf8eb3 100644 --- a/engine/node_combobox.h +++ b/engine/node_combobox.h @@ -4,6 +4,7 @@ class NodeComboBox : public NodeButton { public: + std::function on_select; std::array labels{ "Normal", "Multiply", "Screen", "Color Dodge" }; int m_current_index = 0; virtual Node* clone_instantiate() const override; diff --git a/engine/node_panel_stroke.cpp b/engine/node_panel_stroke.cpp index 4c8cde9..0317f01 100644 --- a/engine/node_panel_stroke.cpp +++ b/engine/node_panel_stroke.cpp @@ -43,6 +43,10 @@ void NodePanelStroke::update_controls() void NodePanelStroke::init_controls() { m_preview = find("canvas"); + m_blend_mode = find("blend-mode"); + m_blend_mode->on_select = [](Node*, int index) { + ui::Canvas::I->m_current_brush.m_blend_mode = index; + }; init_slider(m_tip_size, "tip-size", &ui::Brush::m_tip_size); init_slider(m_tip_spacing, "tip-spacing", &ui::Brush::m_tip_spacing); diff --git a/engine/node_panel_stroke.h b/engine/node_panel_stroke.h index 7f12a7c..8e4c912 100644 --- a/engine/node_panel_stroke.h +++ b/engine/node_panel_stroke.h @@ -4,11 +4,13 @@ #include "node_slider.h" #include "brush.h" #include "node_checkbox.h" +#include "node_combobox.h" class NodePanelStroke : public Node { public: NodeStrokePreview* m_preview; + NodeComboBox* m_blend_mode; NodeSliderH* m_tip_size; NodeSliderH* m_tip_spacing; NodeSliderH* m_tip_flow; diff --git a/engine/shader.h b/engine/shader.h index 7d849fd..8582d60 100644 --- a/engine/shader.h +++ b/engine/shader.h @@ -23,6 +23,7 @@ enum class kShaderUniform : uint16_t Mask = const_hash("mask"), Resolution = const_hash("resolution"), Highlight = const_hash("highlight"), + BlendMode = const_hash("blend_mode"), }; enum class kShader : uint16_t