diff --git a/engine/app_shaders.cpp b/engine/app_shaders.cpp index d01dd7d..bd6be42 100644 --- a/engine/app_shaders.cpp +++ b/engine/app_shaders.cpp @@ -37,12 +37,15 @@ void App::initShaders() static const char* shader_alpha_f = SHADER_VERSION "uniform sampler2D tex;\n" + "uniform sampler2D tex_alpha;\n" "uniform mediump float alpha;\n" "uniform bool highlight;\n" "in mediump vec3 uv;\n" "out mediump vec4 frag;\n" "void main(){\n" - " mediump vec4 c = texture(tex, uv.xy);\n" + " mediump vec3 rgb = texture(tex, uv.xy).rgb;\n" + " mediump float a = texture(tex_alpha, uv.xy).a;\n" + " mediump vec4 c = vec4(rgb, a);\n" " frag = highlight ? \n" " vec4(clamp(vec3(.3)+c.rgb, vec3(0), vec3(1)), c.a) : \n" " texture(tex, uv.xy) * vec4(1,1,1,alpha);\n" @@ -350,15 +353,15 @@ void App::initShaders() #endif " fg.a *= 1.0-rand(uv2+uv)*noise;\n" " if (fg.a == 0.0) discard;\n" - " mediump float contribution = (1.0 - bg.a) * fg.a;\n" - " mediump float alpha_tot = bg.a + contribution;" - " mediump vec3 rgb = mix(bg.rgb, fg.rgb, fg.a / alpha_tot);\n" " if (mix_alpha > 0.0){\n" " mediump vec2 uv_mix = uv_2 / q;\n" " if (uv_mix.x < 0.0 || uv_mix.x > 1.0 || uv_mix.y < 0.0 || uv_mix.y > 1.0) discard;\n" " mediump vec4 mbg = texture(tex_mix, uv_mix);\n" - " rgb.rgb = mix(rgb.rgb, mbg.rgb, mix_alpha * mbg.a);\n" + " fg.rgb = mix(fg.rgb, mbg.rgb, mix_alpha * mbg.a);\n" " }\n" + " mediump float contribution = (1.0 - bg.a) * fg.a;\n" + " mediump float alpha_tot = bg.a + contribution;" + " mediump vec3 rgb = mix(bg.rgb, fg.rgb, fg.a / alpha_tot);\n" " mediump vec4 frag_wet = vec4(rgb, max(bg.a, fg.a * 1.2));\n" " mediump vec4 frag_dry = vec4(rgb, alpha_tot);\n" " frag = mix(frag_dry, frag_wet, wet);\n" diff --git a/engine/canvas.cpp b/engine/canvas.cpp index 4d0a9e2..6d6095e 100644 --- a/engine/canvas.cpp +++ b/engine/canvas.cpp @@ -219,16 +219,19 @@ void ui::Canvas::stroke_cancel() m_current_stroke = nullptr; m_show_tmp = false; } -void ui::Canvas::stroke_draw_mix() +void ui::Canvas::stroke_draw_mix(const glm::vec2& bb_min, const glm::vec2& bb_sz) { m_mixer.bindFramebuffer(); - m_mixer.clear({ 1, 1, 1, 0 }); glViewport(0, 0, m_mixer.getWidth(), m_mixer.getHeight()); glDisable(GL_DEPTH_TEST); - glEnable(GL_BLEND); + glEnable(GL_SCISSOR_TEST); + glScissor(bb_min.x, bb_min.y, bb_sz.x, bb_sz.y); + + m_mixer.clear({ 1, 1, 1, 0 }); m_sampler.bind(0); + m_sampler_linear.bind(1); auto layer_index = m_current_layer_idx; for (int plane_index = 0; plane_index < 6; plane_index++) { @@ -244,28 +247,77 @@ void ui::Canvas::stroke_draw_mix() ui::ShaderManager::use(kShader::TextureAlpha); ui::ShaderManager::u_int(kShaderUniform::Tex, 0); + ui::ShaderManager::u_int(kShaderUniform::TexA, 1); ui::ShaderManager::u_float(kShaderUniform::Alpha, m_layers[layer_index].m_opacity); ui::ShaderManager::u_int(kShaderUniform::Highlight, false); ui::ShaderManager::u_mat4(kShaderUniform::MVP, plane_mvp_z); - glActiveTexture(GL_TEXTURE0); - //glDisable(GL_BLEND); + glEnable(GL_BLEND); + glActiveTexture(GL_TEXTURE0); + m_layers[layer_index].m_rtt[plane_index].bindTexture(); + glActiveTexture(GL_TEXTURE1); m_layers[layer_index].m_rtt[plane_index].bindTexture(); m_node->m_face_plane.draw_fill(); + glActiveTexture(GL_TEXTURE1); + m_layers[layer_index].m_rtt[plane_index].unbindTexture(); + glActiveTexture(GL_TEXTURE0); m_layers[layer_index].m_rtt[plane_index].unbindTexture(); + glEnable(GL_BLEND); +// glActiveTexture(GL_TEXTURE0); +// m_tmp[plane_index].bindTexture(); +// glActiveTexture(GL_TEXTURE1); +// m_tmp[plane_index].bindTexture(); +// m_node->m_face_plane.draw_fill(); +// glActiveTexture(GL_TEXTURE1); +// m_tmp[plane_index].unbindTexture(); +// glActiveTexture(GL_TEXTURE0); +// m_tmp[plane_index].unbindTexture(); + + m_sampler.bind(0); + m_sampler.bind(1); + m_sampler.bind(2); + auto& paper = TextureManager::get(const_hash("data/paper.jpg")); + ui::ShaderManager::use(kShader::CompDraw); + ui::ShaderManager::u_int(kShaderUniform::Tex, 0); + //ui::ShaderManager::u_int(kShaderUniform::TexA, 0); + ui::ShaderManager::u_int(kShaderUniform::TexStroke, 1); + ui::ShaderManager::u_int(kShaderUniform::TexMask, 2); + //ui::ShaderManager::u_int(kShaderUniform::TexStencil, 3); + ui::ShaderManager::u_float(kShaderUniform::Alpha, m_current_stroke->m_brush.m_tip_opacity); + ui::ShaderManager::u_int(kShaderUniform::Lock, m_layers[layer_index].m_alpha_locked); + ui::ShaderManager::u_int(kShaderUniform::Mask, m_smask_active); + ui::ShaderManager::u_int(kShaderUniform::BlendMode, m_current_stroke->m_brush.m_blend_mode); + ui::ShaderManager::u_mat4(kShaderUniform::MVP, plane_mvp_z); + glActiveTexture(GL_TEXTURE0); + m_layers[layer_index].m_rtt[plane_index].bindTexture(); + glActiveTexture(GL_TEXTURE1); m_tmp[plane_index].bindTexture(); + glActiveTexture(GL_TEXTURE2); + m_smask.m_rtt[plane_index].bindTexture(); + glActiveTexture(GL_TEXTURE3); + paper.bind(); m_node->m_face_plane.draw_fill(); + paper.unbind(); + glActiveTexture(GL_TEXTURE2); + m_smask.m_rtt[plane_index].unbindTexture(); + glActiveTexture(GL_TEXTURE1); m_tmp[plane_index].unbindTexture(); + glActiveTexture(GL_TEXTURE0); + m_layers[layer_index].m_rtt[plane_index].unbindTexture(); } m_sampler.unbind(); m_mixer.unbindFramebuffer(); + glDisable(GL_SCISSOR_TEST); } void ui::Canvas::stroke_draw() { if (!(m_current_stroke && m_current_stroke->has_sample())) + { + //stroke_draw_mix({ 0,0 }, { m_mixer.getWidth(), m_mixer.getHeight() }); return; + } m_dirty = true; @@ -288,8 +340,31 @@ void ui::Canvas::stroke_draw() m_mixer_idle = false; } - if (m_brush.m_tip_mix > 0.f) - stroke_draw_mix(); + static glm::vec2 UV2[4]; + { + glm::vec2 dx(m_mixer_sample.size * 0.5f, 0), dy(0, m_mixer_sample.size * 0.5f); + glm::vec2 off[4] = { + -dx - dy, // A - bottom-left + -dx + dy, // B - top-left + +dx + dy, // C - top-right + +dx - dy, // D - bottom-right + }; + auto sz = glm::vec2(m_mixer.getWidth(), m_mixer.getHeight()) * m_mixer_scale; + glm::vec2 bb_min(sz); + glm::vec2 bb_max(0, 0); + for (int j = 0; j < 4; j++) + { + auto p = (m_mixer_sample.pos + off[j] + glm::vec2(0, 1)); + UV2[j] = p / sz; + //UV2[j].y = 1.f - UV2[j].y; + bb_min = glm::max({ 0, 0 }, glm::min(bb_min, p)); + bb_max = glm::min(sz, glm::max(bb_max, p)); + } + auto bb_sz = bb_max - bb_min; + + if (m_brush.m_tip_mix > 0.f) + stroke_draw_mix(bb_min, bb_sz); + } glViewport(0, 0, m_width, m_height); @@ -298,7 +373,8 @@ void ui::Canvas::stroke_draw() m_sampler_brush.bind(0); m_sampler_bg.bind(1); m_sampler_stencil.bind(2); - m_sampler_mix.bind(3); + m_sampler.bind(3); + //m_sampler_linear.bind(5); glActiveTexture(GL_TEXTURE2); stencil.bind(); @@ -313,6 +389,7 @@ void ui::Canvas::stroke_draw() #endif ShaderManager::u_int(kShaderUniform::TexStencil, 2); // stencil ShaderManager::u_int(kShaderUniform::TexMix, 3); // mixer + //ShaderManager::u_int(kShaderUniform::TexMixA, 4); // mixer ShaderManager::u_vec2(kShaderUniform::Resolution, { m_width, m_height }); ShaderManager::u_vec2(kShaderUniform::StencilOffset, stencil_offset); ShaderManager::u_float(kShaderUniform::StencilAlpha, m_brush.m_tip_stencil); @@ -320,20 +397,6 @@ void ui::Canvas::stroke_draw() ShaderManager::u_float(kShaderUniform::Wet, m_brush.m_tip_wet); ShaderManager::u_float(kShaderUniform::Noise, m_brush.m_tip_noise); - static glm::vec2 UV2[4]; - for (int j = 0; j < 4; j++) - { - glm::vec2 dx(m_mixer_sample.size * 0.5f, 0), dy(0, m_mixer_sample.size * 0.5f); - glm::vec2 off[4] = { - -dx - dy, // A - bottom-left - -dx + dy, // B - top-left - +dx + dy, // C - top-right - +dx - dy, // D - bottom-right - }; - UV2[j] = (m_mixer_sample.pos + off[j] + glm::vec2(0,1)) / glm::vec2(m_mixer.getWidth(), m_mixer.getHeight()) * m_mixer_scale; - //UV2[j].y = 1.f - UV2[j].y; - } - for (int i = 0; i < 6; i++) { // check if plane is even visible @@ -863,6 +926,7 @@ bool ui::Canvas::create(int width, int height) m_tex2[i].create(width, height, GL_RGBA8); // TODO: destroy before recreating } m_sampler.create(GL_NEAREST); + m_sampler.create(GL_LINEAR); m_sampler_brush.create(); m_sampler_brush.set_filter(GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR); m_sampler_bg.create(GL_NEAREST); @@ -878,7 +942,7 @@ bool ui::Canvas::create(int width, int height) l.create(width, height, ""); } m_smask.create(width*2, height*2, "mask"); - m_smask.clear({1, 1, 1, 1}); + //m_smask.clear({1, 1, 1, 1}); m_unsaved = true; return true; } diff --git a/engine/canvas.h b/engine/canvas.h index 8da6ea6..886bc3c 100644 --- a/engine/canvas.h +++ b/engine/canvas.h @@ -90,6 +90,7 @@ public: static glm::mat4 m_plane_transform[6]; glm::vec2 stencil_offset; Sampler m_sampler; + Sampler m_sampler_linear; Sampler m_sampler_brush; Sampler m_sampler_bg; Sampler m_sampler_mask; @@ -131,7 +132,7 @@ public: void layer_merge(int source_idx, int dest_idx); void stroke_start(glm::vec2 point, float pressure, const ui::Brush& brush); void stroke_update(glm::vec2 point, float pressure); - void stroke_draw_mix(); + void stroke_draw_mix(const glm::vec2& bb_min, const glm::vec2& bb_sz); void stroke_draw(); void stroke_end(); void stroke_cancel(); diff --git a/engine/canvas_modes.cpp b/engine/canvas_modes.cpp index 58c9c32..2fc27f6 100644 --- a/engine/canvas_modes.cpp +++ b/engine/canvas_modes.cpp @@ -160,7 +160,7 @@ void CanvasModePen::on_MouseEvent(MouseEvent* me, glm::vec2& loc) void CanvasModePen::on_Draw(const glm::mat4& ortho, const glm::mat4& proj, const glm::mat4& camera) { #ifndef __IOS__ - if (1) + if (!m_dragging) { auto pos = m_resizing ? m_size_pos_start : m_cur_pos; if (App::I.keys[(int)kKey::KeyAlt]) diff --git a/engine/node_canvas.cpp b/engine/node_canvas.cpp index 0ab34cd..39ad660 100644 --- a/engine/node_canvas.cpp +++ b/engine/node_canvas.cpp @@ -179,15 +179,25 @@ void NodeCanvas::draw() } else { - m_sampler_linear.bind(0); + m_sampler.bind(0); + m_sampler_linear.bind(1); ui::ShaderManager::use(kShader::TextureAlpha); ui::ShaderManager::u_int(kShaderUniform::Tex, 0); + ui::ShaderManager::u_int(kShaderUniform::TexA, 1); ui::ShaderManager::u_float(kShaderUniform::Alpha, m_canvas->m_layers[layer_index].m_opacity); ui::ShaderManager::u_int(kShaderUniform::Highlight, m_canvas->m_layers[layer_index].m_hightlight); ui::ShaderManager::u_mat4(kShaderUniform::MVP, plane_mvp_z); + glActiveTexture(GL_TEXTURE0); m_canvas->m_layers[layer_index].m_rtt[plane_index].bindTexture(); + glActiveTexture(GL_TEXTURE1); + m_canvas->m_layers[layer_index].m_rtt[plane_index].bindTexture(); + m_face_plane.draw_fill(); + + glActiveTexture(GL_TEXTURE1); + m_canvas->m_layers[layer_index].m_rtt[plane_index].unbindTexture(); + glActiveTexture(GL_TEXTURE0); m_canvas->m_layers[layer_index].m_rtt[plane_index].unbindTexture(); } diff --git a/engine/shader.h b/engine/shader.h index 5557c14..7bbc91d 100644 --- a/engine/shader.h +++ b/engine/shader.h @@ -7,9 +7,11 @@ enum class kShaderUniform : uint16_t { MVP = const_hash("mvp"), Tex = const_hash("tex"), + TexA = const_hash("tex_alpha"), TexFG = const_hash("tex_fg"), TexBG = const_hash("tex_bg"), TexMix = const_hash("tex_mix"), + TexMixA = const_hash("tex_mix_alpha"), TexMask = const_hash("tex_mask"), TexStroke = const_hash("tex_stroke"), TexStencil = const_hash("tex_stencil"),