diff --git a/data/layout.xml b/data/layout.xml index 71fdbd0..873c8df 100644 --- a/data/layout.xml +++ b/data/layout.xml @@ -360,7 +360,7 @@ - + diff --git a/src/app_shaders.cpp b/src/app_shaders.cpp index 1b6b0e8..033776c 100644 --- a/src/app_shaders.cpp +++ b/src/app_shaders.cpp @@ -38,6 +38,16 @@ " else return vec4(1, 0, 0, 1);\n"\ "}\n" +#define SHADER_FUNCTION_BLEND_STROKE \ + "mediump float blend_stroke(mediump float base, mediump float stroke, int mode) {\n"\ + " if (mode == 0) return (base + stroke) * 0.5;\n"\ + " else if (mode == 1) return base * stroke;\n"\ + " else if (mode == 2) return 1.0-(1.0-base)*(1.0-stroke);\n"\ + " else if (mode == 3) return base/(1.0-stroke);\n"\ + " else if (mode == 4) return mix(2.0*base*stroke, 1.0-2.0*(1.0-base)*(1.0-stroke), floor(base*2.0));\n"\ + " else return 1;\n"\ + "}\n" + #define SHADER_FUNCTION_HSV \ "mediump vec3 rgb2hsv(mediump vec3 c) {\n"\ " mediump vec4 k = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);\n"\ @@ -223,13 +233,16 @@ void App::initShaders() "out mediump vec4 frag;\n" SHADER_FUNCTION_BLUR SHADER_FUNCTION_BLEND + SHADER_FUNCTION_BLEND_STROKE "void main() {\n" " mediump vec2 uv2 = fragUV2 ? (gl_FragCoord.st / resolution) : uv;\n" " mediump vec4 base = texture(tex, uv2);\n" " mediump vec4 stroke = texture(tex_stroke, uv);\n" - " mediump vec4 dual = texture(tex_dual, uv);\n" - " if (use_dual)\n" - " stroke.a = stroke.a * dual.a;\n" + " if (use_dual){\n" + " mediump vec4 dual = texture(tex_dual, uv);\n" + //" stroke.a = stroke.a * dual.a;\n" + " stroke.a = blend_stroke(stroke.a, dual.a, dual_blend_mode);\n" + " }\n" " stroke.a = mask ? stroke.a * stroke_alpha * blur(tex_mask, uv2).r : stroke.a * stroke_alpha;\n" " if (!lock && base.a == 0.0) { frag = stroke * vec4(1.0, 1.0, 1.0, alpha); return; }\n" " mediump vec4 blended = blend(base, stroke, blend_mode);\n" diff --git a/src/canvas.cpp b/src/canvas.cpp index f135153..39cbec4 100644 --- a/src/canvas.cpp +++ b/src/canvas.cpp @@ -562,8 +562,12 @@ void Canvas::stroke_draw() if (P.size() < 3) continue; m_tmp_dual[i].bindFramebuffer(); - stroke_draw_samples(i, P); + auto rect = stroke_draw_samples(i, P); m_tmp_dual[i].unbindFramebuffer(); + + // this mode overflows the main brush boundries + if (brush->m_dual_blend_mode == 0) + m_dirty_box[i] = glm::clamp(box_union(m_dirty_box[i], rect), glm::vec4(0), glm::vec4(m_width)); } } glActiveTexture(GL_TEXTURE2); @@ -791,8 +795,8 @@ void Canvas::stroke_commit() ShaderManager::u_int(kShaderUniform::BlendMode, m_current_stroke->m_brush->m_blend_mode); ShaderManager::u_mat4(kShaderUniform::MVP, glm::ortho(-.5f, .5f, -.5f, .5f, -1.f, 1.f)); ShaderManager::u_int(kShaderUniform::TexDual, 3); - ShaderManager::u_int(kShaderUniform::UseDual, true); - ShaderManager::u_int(kShaderUniform::DualBlendMode, 1); + ShaderManager::u_int(kShaderUniform::UseDual, m_current_stroke->m_brush->m_dual_enabled); + ShaderManager::u_int(kShaderUniform::DualBlendMode, m_current_stroke->m_brush->m_dual_blend_mode); glActiveTexture(GL_TEXTURE0); m_tex2[i].bind(); diff --git a/src/node_canvas.cpp b/src/node_canvas.cpp index 7fa473a..19b55b0 100644 --- a/src/node_canvas.cpp +++ b/src/node_canvas.cpp @@ -214,8 +214,8 @@ void NodeCanvas::draw() ShaderManager::u_int(kShaderUniform::BlendMode, m_canvas->m_current_stroke->m_brush->m_blend_mode); ShaderManager::u_mat4(kShaderUniform::MVP, plane_mvp_z); ShaderManager::u_int(kShaderUniform::TexDual, 3); - ShaderManager::u_int(kShaderUniform::UseDual, true); - ShaderManager::u_int(kShaderUniform::DualBlendMode, 1); + ShaderManager::u_int(kShaderUniform::UseDual, m_canvas->m_current_stroke->m_brush->m_dual_enabled); + ShaderManager::u_int(kShaderUniform::DualBlendMode, m_canvas->m_current_stroke->m_brush->m_dual_blend_mode); glActiveTexture(GL_TEXTURE0); m_canvas->m_layers[layer_index].m_rtt[plane_index].bindTexture(); diff --git a/src/node_panel_stroke.cpp b/src/node_panel_stroke.cpp index 5de6603..6a35108 100644 --- a/src/node_panel_stroke.cpp +++ b/src/node_panel_stroke.cpp @@ -146,11 +146,9 @@ void NodePanelStroke::init_controls() m_preview->draw_stroke(); m_preset_preview->draw_stroke(); m_brush_thumb->set_image(b->m_brush_thumb_path); + m_dual_brush_thumb->set_image(b->m_dual_thumb_path); m_preset_thumb->set_image(b->m_brush_thumb_path); update_controls(); - - //m_presets_popup->mouse_release(); - //m_presets_popup->parent->remove_child(m_presets_popup.get()); }; }; @@ -299,7 +297,7 @@ void NodePanelStroke::init_controls() on_stroke_change(this); }; - m_dual_blend_mode = find("blend-mode"); + m_dual_blend_mode = find("dual-blend-mode"); m_dual_blend_mode->on_select = [this](Node*, int index) { Canvas::I->m_current_brush->m_dual_blend_mode = index; m_preview->draw_stroke(); diff --git a/src/shader.h b/src/shader.h index 46210a5..6780a60 100644 --- a/src/shader.h +++ b/src/shader.h @@ -28,7 +28,7 @@ enum class kShaderUniform : uint16_t Resolution = const_hash("resolution"), Highlight = const_hash("highlight"), BlendMode = const_hash("blend_mode"), - DualBlendMode = const_hash("blend_mode"), + DualBlendMode = const_hash("dual_blend_mode"), Noise = const_hash("noise"), Direction = const_hash("dir"), UseFragCoordUV2 = const_hash("fragUV2"),