implement blend mode selection in shader and fix alpha lock
This commit is contained in:
@@ -158,7 +158,7 @@
|
|||||||
</node>
|
</node>
|
||||||
<border dir="col" align="center" grow="1" width="1" flood-events="1">
|
<border dir="col" align="center" grow="1" width="1" flood-events="1">
|
||||||
<node height="30" pad="1" width="100%" dir="row">
|
<node height="30" pad="1" width="100%" dir="row">
|
||||||
<combobox id="btn-ok" text="Normal" width="100%" height="30"/>
|
<combobox id="blend-mode" text="Normal" width="100%" height="30"/>
|
||||||
</node>
|
</node>
|
||||||
<node height="20" pad="1" width="100%" dir="row">
|
<node height="20" pad="1" width="100%" dir="row">
|
||||||
<slider-h id="tip-size" width="1" grow="1" value=".25"/>
|
<slider-h id="tip-size" width="1" grow="1" value=".25"/>
|
||||||
|
|||||||
@@ -84,6 +84,7 @@ void App::initShaders()
|
|||||||
"uniform sampler2D tex_stencil;\n"
|
"uniform sampler2D tex_stencil;\n"
|
||||||
//"uniform image2D img_mixer;\n"
|
//"uniform image2D img_mixer;\n"
|
||||||
"uniform mediump float alpha;\n"
|
"uniform mediump float alpha;\n"
|
||||||
|
"uniform mediump int blend_mode;\n"
|
||||||
"uniform bool lock;\n"
|
"uniform bool lock;\n"
|
||||||
"uniform bool mask;\n"
|
"uniform bool mask;\n"
|
||||||
"in mediump vec3 uv;\n"
|
"in mediump vec3 uv;\n"
|
||||||
@@ -100,10 +101,16 @@ void App::initShaders()
|
|||||||
" sum += textureOffset(t, uv, ivec2( 1, 1));\n"
|
" sum += textureOffset(t, uv, ivec2( 1, 1));\n"
|
||||||
" return sum / vec4(9.0);\n"
|
" return sum / vec4(9.0);\n"
|
||||||
"}\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_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_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"
|
"void main(){\n"
|
||||||
" mediump vec2 uv2 = gl_FragCoord.st / vec2(2048) * 20.0;\n"
|
" mediump vec2 uv2 = gl_FragCoord.st / vec2(2048) * 20.0;\n"
|
||||||
" mediump vec4 base = texture(tex, uv.xy);\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"
|
" 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"
|
" 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 contribution = (1.0 - base.a) * stroke.a;\n"
|
||||||
" mediump float alpha_tot = base.a + contribution;"
|
" 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"
|
" frag = vec4(rgb, (lock ? base.a : alpha_tot));\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ public:
|
|||||||
float m_jitter_angle = 0;
|
float m_jitter_angle = 0;
|
||||||
float m_jitter_spread = 0;
|
float m_jitter_spread = 0;
|
||||||
float m_jitter_flow = 0;
|
float m_jitter_flow = 0;
|
||||||
|
int m_blend_mode = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct StrokeSample
|
struct StrokeSample
|
||||||
|
|||||||
@@ -506,7 +506,8 @@ void ui::Canvas::stroke_commit()
|
|||||||
ui::ShaderManager::u_int(kShaderUniform::TexMask, 2);
|
ui::ShaderManager::u_int(kShaderUniform::TexMask, 2);
|
||||||
ui::ShaderManager::u_float(kShaderUniform::Alpha, m_current_stroke->m_brush.m_tip_opacity);
|
ui::ShaderManager::u_float(kShaderUniform::Alpha, m_current_stroke->m_brush.m_tip_opacity);
|
||||||
ui::ShaderManager::u_int(kShaderUniform::Mask, m_smask_active);
|
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);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
m_tex2[i].bind();
|
m_tex2[i].bind();
|
||||||
|
|||||||
@@ -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_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::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::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);
|
ui::ShaderManager::u_mat4(kShaderUniform::MVP, plane_mvp_z);
|
||||||
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();
|
||||||
|
|||||||
@@ -28,12 +28,14 @@ void NodeComboBox::loaded()
|
|||||||
btn->m_text->set_text(labels[i].c_str());
|
btn->m_text->set_text(labels[i].c_str());
|
||||||
btn->m_border->SetWidthP(100.f);
|
btn->m_border->SetWidthP(100.f);
|
||||||
btn->m_border->SetHeight(30.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);
|
int index = popup->get_child_index(target);
|
||||||
m_current_index = index;
|
m_current_index = index;
|
||||||
m_text->set_text(labels[index].c_str());
|
m_text->set_text(labels[index].c_str());
|
||||||
popup->mouse_release();
|
popup->mouse_release();
|
||||||
popup->destroy();
|
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);
|
glm::vec2 pos = m_pos + glm::vec2(0, m_size.y - (m_current_index+1) * 30.f);
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
class NodeComboBox : public NodeButton
|
class NodeComboBox : public NodeButton
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
std::function<void(Node* target, int index)> on_select;
|
||||||
std::array<std::string, 4> labels{ "Normal", "Multiply", "Screen", "Color Dodge" };
|
std::array<std::string, 4> labels{ "Normal", "Multiply", "Screen", "Color Dodge" };
|
||||||
int m_current_index = 0;
|
int m_current_index = 0;
|
||||||
virtual Node* clone_instantiate() const override;
|
virtual Node* clone_instantiate() const override;
|
||||||
|
|||||||
@@ -43,6 +43,10 @@ void NodePanelStroke::update_controls()
|
|||||||
void NodePanelStroke::init_controls()
|
void NodePanelStroke::init_controls()
|
||||||
{
|
{
|
||||||
m_preview = find<NodeStrokePreview>("canvas");
|
m_preview = find<NodeStrokePreview>("canvas");
|
||||||
|
m_blend_mode = find<NodeComboBox>("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_size, "tip-size", &ui::Brush::m_tip_size);
|
||||||
init_slider(m_tip_spacing, "tip-spacing", &ui::Brush::m_tip_spacing);
|
init_slider(m_tip_spacing, "tip-spacing", &ui::Brush::m_tip_spacing);
|
||||||
|
|||||||
@@ -4,11 +4,13 @@
|
|||||||
#include "node_slider.h"
|
#include "node_slider.h"
|
||||||
#include "brush.h"
|
#include "brush.h"
|
||||||
#include "node_checkbox.h"
|
#include "node_checkbox.h"
|
||||||
|
#include "node_combobox.h"
|
||||||
|
|
||||||
class NodePanelStroke : public Node
|
class NodePanelStroke : public Node
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NodeStrokePreview* m_preview;
|
NodeStrokePreview* m_preview;
|
||||||
|
NodeComboBox* m_blend_mode;
|
||||||
NodeSliderH* m_tip_size;
|
NodeSliderH* m_tip_size;
|
||||||
NodeSliderH* m_tip_spacing;
|
NodeSliderH* m_tip_spacing;
|
||||||
NodeSliderH* m_tip_flow;
|
NodeSliderH* m_tip_flow;
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ enum class kShaderUniform : uint16_t
|
|||||||
Mask = const_hash("mask"),
|
Mask = const_hash("mask"),
|
||||||
Resolution = const_hash("resolution"),
|
Resolution = const_hash("resolution"),
|
||||||
Highlight = const_hash("highlight"),
|
Highlight = const_hash("highlight"),
|
||||||
|
BlendMode = const_hash("blend_mode"),
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class kShader : uint16_t
|
enum class kShader : uint16_t
|
||||||
|
|||||||
Reference in New Issue
Block a user