dual-brush blend modes

This commit is contained in:
2019-02-15 02:17:04 +01:00
parent 6aca330db3
commit 945c51aa25
6 changed files with 29 additions and 14 deletions

View File

@@ -360,7 +360,7 @@
</node> </node>
</node> </node>
<node height="30" width="100%" pad="1" dir="row" margin="0 0 5 0"> <node height="30" width="100%" pad="1" dir="row" margin="0 0 5 0">
<combobox id="db-blend" width="100%" height="28" combo-list="Normal,-,Multiply,Screen,-,Color Dodge,Overlay" default="0"/> <combobox id="dual-blend-mode" width="100%" height="28" combo-list="Normal,-,Multiply,Screen,-,Color Dodge,Overlay" default="0"/>
</node> </node>
<node align="center" dir="row"> <node align="center" dir="row">
<checkbox id="dual-randflip" height="20" width="20"/> <checkbox id="dual-randflip" height="20" width="20"/>

View File

@@ -38,6 +38,16 @@
" else return vec4(1, 0, 0, 1);\n"\ " else return vec4(1, 0, 0, 1);\n"\
"}\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 \ #define SHADER_FUNCTION_HSV \
"mediump vec3 rgb2hsv(mediump vec3 c) {\n"\ "mediump vec3 rgb2hsv(mediump vec3 c) {\n"\
" mediump vec4 k = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);\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" "out mediump vec4 frag;\n"
SHADER_FUNCTION_BLUR SHADER_FUNCTION_BLUR
SHADER_FUNCTION_BLEND SHADER_FUNCTION_BLEND
SHADER_FUNCTION_BLEND_STROKE
"void main() {\n" "void main() {\n"
" mediump vec2 uv2 = fragUV2 ? (gl_FragCoord.st / resolution) : uv;\n" " mediump vec2 uv2 = fragUV2 ? (gl_FragCoord.st / resolution) : uv;\n"
" mediump vec4 base = texture(tex, uv2);\n" " mediump vec4 base = texture(tex, uv2);\n"
" mediump vec4 stroke = texture(tex_stroke, uv);\n" " mediump vec4 stroke = texture(tex_stroke, uv);\n"
" if (use_dual){\n"
" mediump vec4 dual = texture(tex_dual, uv);\n" " mediump vec4 dual = texture(tex_dual, uv);\n"
" if (use_dual)\n" //" stroke.a = stroke.a * dual.a;\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" " 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" " 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" " mediump vec4 blended = blend(base, stroke, blend_mode);\n"

View File

@@ -562,8 +562,12 @@ void Canvas::stroke_draw()
if (P.size() < 3) if (P.size() < 3)
continue; continue;
m_tmp_dual[i].bindFramebuffer(); m_tmp_dual[i].bindFramebuffer();
stroke_draw_samples(i, P); auto rect = stroke_draw_samples(i, P);
m_tmp_dual[i].unbindFramebuffer(); 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); 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_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_mat4(kShaderUniform::MVP, glm::ortho(-.5f, .5f, -.5f, .5f, -1.f, 1.f));
ShaderManager::u_int(kShaderUniform::TexDual, 3); ShaderManager::u_int(kShaderUniform::TexDual, 3);
ShaderManager::u_int(kShaderUniform::UseDual, true); ShaderManager::u_int(kShaderUniform::UseDual, m_current_stroke->m_brush->m_dual_enabled);
ShaderManager::u_int(kShaderUniform::DualBlendMode, 1); ShaderManager::u_int(kShaderUniform::DualBlendMode, m_current_stroke->m_brush->m_dual_blend_mode);
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
m_tex2[i].bind(); m_tex2[i].bind();

View File

@@ -214,8 +214,8 @@ void NodeCanvas::draw()
ShaderManager::u_int(kShaderUniform::BlendMode, m_canvas->m_current_stroke->m_brush->m_blend_mode); 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_mat4(kShaderUniform::MVP, plane_mvp_z);
ShaderManager::u_int(kShaderUniform::TexDual, 3); ShaderManager::u_int(kShaderUniform::TexDual, 3);
ShaderManager::u_int(kShaderUniform::UseDual, true); ShaderManager::u_int(kShaderUniform::UseDual, m_canvas->m_current_stroke->m_brush->m_dual_enabled);
ShaderManager::u_int(kShaderUniform::DualBlendMode, 1); ShaderManager::u_int(kShaderUniform::DualBlendMode, m_canvas->m_current_stroke->m_brush->m_dual_blend_mode);
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
m_canvas->m_layers[layer_index].m_rtt[plane_index].bindTexture(); m_canvas->m_layers[layer_index].m_rtt[plane_index].bindTexture();

View File

@@ -146,11 +146,9 @@ void NodePanelStroke::init_controls()
m_preview->draw_stroke(); m_preview->draw_stroke();
m_preset_preview->draw_stroke(); m_preset_preview->draw_stroke();
m_brush_thumb->set_image(b->m_brush_thumb_path); 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); m_preset_thumb->set_image(b->m_brush_thumb_path);
update_controls(); 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); on_stroke_change(this);
}; };
m_dual_blend_mode = find<NodeComboBox>("blend-mode"); m_dual_blend_mode = find<NodeComboBox>("dual-blend-mode");
m_dual_blend_mode->on_select = [this](Node*, int index) { m_dual_blend_mode->on_select = [this](Node*, int index) {
Canvas::I->m_current_brush->m_dual_blend_mode = index; Canvas::I->m_current_brush->m_dual_blend_mode = index;
m_preview->draw_stroke(); m_preview->draw_stroke();

View File

@@ -28,7 +28,7 @@ enum class kShaderUniform : uint16_t
Resolution = const_hash("resolution"), Resolution = const_hash("resolution"),
Highlight = const_hash("highlight"), Highlight = const_hash("highlight"),
BlendMode = const_hash("blend_mode"), BlendMode = const_hash("blend_mode"),
DualBlendMode = const_hash("blend_mode"), DualBlendMode = const_hash("dual_blend_mode"),
Noise = const_hash("noise"), Noise = const_hash("noise"),
Direction = const_hash("dir"), Direction = const_hash("dir"),
UseFragCoordUV2 = const_hash("fragUV2"), UseFragCoordUV2 = const_hash("fragUV2"),