mixer brush wip

This commit is contained in:
2018-08-01 10:48:04 +02:00
parent 5c2264ba8b
commit 57e2fa1abd
9 changed files with 84 additions and 14 deletions

View File

@@ -801,6 +801,7 @@
<text text="#opengl #fromscratch #c++" font-face="arial" font-size="11" margin="0 0 0 10" color=".2 .5 1 1"/> <text text="#opengl #fromscratch #c++" font-face="arial" font-size="11" margin="0 0 0 10" color=".2 .5 1 1"/>
</border>--> </border>-->
</node> </node>
<image-texture id="tex-debug" positioning="absolute" position="0 0" width="100" height="100"></image-texture>
<!--<color-picker/>--> <!--<color-picker/>-->
</layout> </layout>
</root> </root>

View File

@@ -307,13 +307,14 @@ void App::initShaders()
"uniform mediump sampler2D tex;\n" "uniform mediump sampler2D tex;\n"
"uniform mediump sampler2D tex_bg;\n" "uniform mediump sampler2D tex_bg;\n"
"uniform mediump sampler2D tex_stencil;\n" "uniform mediump sampler2D tex_stencil;\n"
//"layout (binding=3, rgba8) uniform image2D tex_mix;\n" "uniform mediump sampler2D tex_mix;\n"
"uniform mediump vec4 col;\n" "uniform mediump vec4 col;\n"
"uniform mediump vec2 resolution;\n" "uniform mediump vec2 resolution;\n"
"uniform mediump float alpha;\n" "uniform mediump float alpha;\n"
"uniform mediump float noise;\n" "uniform mediump float noise;\n"
"uniform mediump vec2 stencil_offset;\n" "uniform mediump vec2 stencil_offset;\n"
"uniform mediump float stencil_alpha;\n" "uniform mediump float stencil_alpha;\n"
"uniform mediump float mix_alpha;\n"
"uniform mediump float wet;\n" "uniform mediump float wet;\n"
"in mediump vec2 uv;\n" "in mediump vec2 uv;\n"
"in mediump float q;\n" "in mediump float q;\n"
@@ -343,6 +344,7 @@ void App::initShaders()
#else #else
" mediump vec4 bg = texture(tex_bg, uv2);\n" " mediump vec4 bg = texture(tex_bg, uv2);\n"
#endif #endif
" mediump vec4 mbg = texture(tex_mix, uv/q);\n"
" fg.a *= 1.0-rand(uv2+uv)*noise;\n" " fg.a *= 1.0-rand(uv2+uv)*noise;\n"
" if (fg.a == 0.0) discard;\n" " if (fg.a == 0.0) discard;\n"
" mediump float contribution = (1.0 - bg.a) * fg.a;\n" " mediump float contribution = (1.0 - bg.a) * fg.a;\n"
@@ -350,7 +352,7 @@ void App::initShaders()
" mediump vec3 rgb = mix(bg.rgb, fg.rgb, fg.a / alpha_tot);\n" " 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_wet = vec4(rgb, max(bg.a, fg.a * 1.2));\n"
" mediump vec4 frag_dry = vec4(rgb, alpha_tot);\n" " mediump vec4 frag_dry = vec4(rgb, alpha_tot);\n"
" frag = mix(frag_dry, frag_wet, wet);\n" " frag = mix(mix(frag_dry, frag_wet, wet), mbg, mix_alpha);\n"
"}\n"; "}\n";
static const char* shader_checkerboard_v = static const char* shader_checkerboard_v =

View File

@@ -16,6 +16,7 @@ public:
float m_tip_flow = 0; float m_tip_flow = 0;
float m_tip_opacity = 0; float m_tip_opacity = 0;
float m_tip_angle = 0; float m_tip_angle = 0;
float m_tip_mix = 0;
float m_tip_stencil = 0; float m_tip_stencil = 0;
float m_tip_wet = 0; float m_tip_wet = 0;
float m_tip_noise = 0; float m_tip_noise = 0;

View File

@@ -219,6 +219,46 @@ void ui::Canvas::stroke_cancel()
m_current_stroke = nullptr; m_current_stroke = nullptr;
m_show_tmp = false; m_show_tmp = false;
} }
void ui::Canvas::stroke_draw_mix()
{
m_mixer.bindFramebuffer();
m_mixer.clear({ 0, 1, 1, 1 });
glViewport(m_vp.x, m_vp.y, m_vp.z, m_vp.w);
glDisable(GL_BLEND);
glDisable(GL_DEPTH_TEST);
m_sampler_bg.bind(0);
auto layer_index = m_current_layer_idx;
for (int plane_index = 0; plane_index < 6; plane_index++)
{
if (m_layers[layer_index].m_opacity == .0f)
continue;
auto plane_mvp_z = m_proj * m_mv *
m_plane_transform[plane_index] *
glm::translate(glm::vec3(0, 0, -1));
{
ui::ShaderManager::use(kShader::TextureAlpha);
ui::ShaderManager::u_int(kShaderUniform::Tex, 0);
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);
// m_layers[layer_index].m_rtt[plane_index].bindTexture();
// m_node->m_face_plane.draw_fill();
// m_layers[layer_index].m_rtt[plane_index].unbindTexture();
m_tmp[plane_index].bindTexture();
m_node->m_face_plane.draw_fill();
m_tmp[plane_index].unbindTexture();
}
}
m_sampler_bg.unbind();
m_mixer.unbindFramebuffer();
}
void ui::Canvas::stroke_draw() void ui::Canvas::stroke_draw()
{ {
if (!(m_current_stroke && m_current_stroke->has_sample())) if (!(m_current_stroke && m_current_stroke->has_sample()))
@@ -231,6 +271,8 @@ void ui::Canvas::stroke_draw()
glGetIntegerv(GL_VIEWPORT, vp); glGetIntegerv(GL_VIEWPORT, vp);
glGetFloatv(GL_COLOR_CLEAR_VALUE, cc); glGetFloatv(GL_COLOR_CLEAR_VALUE, cc);
stroke_draw_mix();
glViewport(0, 0, m_width, m_height); glViewport(0, 0, m_width, m_height);
auto ortho_proj = glm::ortho(0.f, (float)m_width, 0.f, (float)m_height, -1.f, 1.f); auto ortho_proj = glm::ortho(0.f, (float)m_width, 0.f, (float)m_height, -1.f, 1.f);
@@ -243,11 +285,13 @@ void ui::Canvas::stroke_draw()
tex.bind(); tex.bind();
m_sampler_brush.bind(0); m_sampler_brush.bind(0);
m_sampler_bg.bind(1); m_sampler_bg.bind(1);
m_sampler_mask.bind(2); m_sampler_stencil.bind(2);
m_sampler_stencil.bind(3); m_sampler_mix.bind(3);
glActiveTexture(GL_TEXTURE3); glActiveTexture(GL_TEXTURE2);
stencil.bind(); stencil.bind();
glActiveTexture(GL_TEXTURE3);
m_mixer.bindTexture();
for (int i = 0; i < 6; i++) for (int i = 0; i < 6; i++)
{ {
@@ -280,10 +324,12 @@ void ui::Canvas::stroke_draw()
#ifndef __IOS__ #ifndef __IOS__
ShaderManager::u_int(kShaderUniform::TexBG, 1); // bg ShaderManager::u_int(kShaderUniform::TexBG, 1); // bg
#endif #endif
ShaderManager::u_int(kShaderUniform::TexStencil, 3); // stencil ShaderManager::u_int(kShaderUniform::TexStencil, 2); // stencil
ShaderManager::u_int(kShaderUniform::TexMix, 3); // mixer
ShaderManager::u_vec2(kShaderUniform::Resolution, { m_width, m_height }); ShaderManager::u_vec2(kShaderUniform::Resolution, { m_width, m_height });
ShaderManager::u_vec2(kShaderUniform::StencilOffset, stencil_offset); ShaderManager::u_vec2(kShaderUniform::StencilOffset, stencil_offset);
ShaderManager::u_float(kShaderUniform::StencilAlpha, m_brush.m_tip_stencil); ShaderManager::u_float(kShaderUniform::StencilAlpha, m_brush.m_tip_stencil);
ShaderManager::u_float(kShaderUniform::MixAlpha, m_brush.m_tip_mix);
ShaderManager::u_float(kShaderUniform::Wet, m_brush.m_tip_wet); ShaderManager::u_float(kShaderUniform::Wet, m_brush.m_tip_wet);
ShaderManager::u_float(kShaderUniform::Noise, m_brush.m_tip_noise); ShaderManager::u_float(kShaderUniform::Noise, m_brush.m_tip_noise);
for (const auto& s : samples) for (const auto& s : samples)
@@ -360,11 +406,11 @@ void ui::Canvas::stroke_draw()
} }
} }
if (m_alpha_lock) // if (m_alpha_lock)
{ // {
glActiveTexture(GL_TEXTURE2); // glActiveTexture(GL_TEXTURE2);
m_layers[m_current_layer_idx].m_rtt[i].unbindTexture(); // m_layers[m_current_layer_idx].m_rtt[i].unbindTexture();
} // }
glActiveTexture(GL_TEXTURE1); glActiveTexture(GL_TEXTURE1);
m_tex[i].unbind(); m_tex[i].unbind();
@@ -374,10 +420,15 @@ void ui::Canvas::stroke_draw()
glDisable(GL_BLEND); glDisable(GL_BLEND);
glActiveTexture(GL_TEXTURE2);
stencil.unbind();
glActiveTexture(GL_TEXTURE3);
m_mixer.unbindTexture();
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
m_sampler_brush.unbind(); m_sampler_brush.unbind();
m_sampler_bg.unbind(); m_sampler_bg.unbind();
m_sampler_mask.unbind(); m_sampler_stencil.unbind();
tex.unbind(); tex.unbind();
glViewport(vp[0], vp[1], vp[2], vp[3]); glViewport(vp[0], vp[1], vp[2], vp[3]);
@@ -803,6 +854,7 @@ bool ui::Canvas::create(int width, int height)
m_sampler_bg.create(GL_NEAREST); m_sampler_bg.create(GL_NEAREST);
m_sampler_mask.create(GL_LINEAR); m_sampler_mask.create(GL_LINEAR);
m_sampler_stencil.create(GL_LINEAR, GL_REPEAT); m_sampler_stencil.create(GL_LINEAR, GL_REPEAT);
m_sampler_mix.create(GL_LINEAR, GL_REPEAT);
m_plane.create<1>(1, 1); m_plane.create<1>(1, 1);
m_plane_brush.create<1>(1, 1); m_plane_brush.create<1>(1, 1);
m_mesh.create(); m_mesh.create();

View File

@@ -54,11 +54,13 @@ public:
bool m_dirty_stroke = false; bool m_dirty_stroke = false;
static Canvas* I; static Canvas* I;
NodeCanvas* m_node = nullptr;
bool m_alpha_lock = false; bool m_alpha_lock = false;
bool m_touch_lock = true; bool m_touch_lock = true;
glm::mat4 m_mv{ 1 }; glm::mat4 m_mv{ 1 };
glm::mat4 m_proj{ 1 }; glm::mat4 m_proj{ 1 };
glm::vec4 m_box{ 0 }; glm::vec4 m_box{ 0 };
glm::vec4 m_vp{ 0 };
glm::vec2 m_pan{ 0 }; glm::vec2 m_pan{ 0 };
int m_width = 0; int m_width = 0;
int m_height = 0; int m_height = 0;
@@ -73,6 +75,7 @@ public:
Layer m_smask; // selection mask Layer m_smask; // selection mask
bool m_smask_active = false; bool m_smask_active = false;
RTT m_tmp[6]; RTT m_tmp[6];
RTT m_mixer;
Texture2D m_brush_mix; Texture2D m_brush_mix;
Texture2D m_tex[6]; Texture2D m_tex[6];
Texture2D m_tex2[6]; Texture2D m_tex2[6];
@@ -88,6 +91,7 @@ public:
Sampler m_sampler_bg; Sampler m_sampler_bg;
Sampler m_sampler_mask; Sampler m_sampler_mask;
Sampler m_sampler_stencil; Sampler m_sampler_stencil;
Sampler m_sampler_mix;
glm::vec2 m_cam_rot{ 0 }; glm::vec2 m_cam_rot{ 0 };
glm::vec3 m_cam_pos{ 0 }; glm::vec3 m_cam_pos{ 0 };
float m_cam_fov = 85; float m_cam_fov = 85;
@@ -124,6 +128,7 @@ public:
void layer_merge(int source_idx, int dest_idx); void layer_merge(int source_idx, int dest_idx);
void stroke_start(glm::vec2 point, float pressure, const ui::Brush& brush); void stroke_start(glm::vec2 point, float pressure, const ui::Brush& brush);
void stroke_update(glm::vec2 point, float pressure); void stroke_update(glm::vec2 point, float pressure);
void stroke_draw_mix();
void stroke_draw(); void stroke_draw();
void stroke_end(); void stroke_end();
void stroke_cancel(); void stroke_cancel();
@@ -152,7 +157,6 @@ public:
void inject_xmp(std::string jpg_path); void inject_xmp(std::string jpg_path);
ui::Image thumbnail_generate(int w, int h); ui::Image thumbnail_generate(int w, int h);
ui::Image thumbnail_read(std::string data_path); ui::Image thumbnail_read(std::string data_path);
void preview_generate();
void draw_objects(std::function<void(const glm::mat4& camera, const glm::mat4& proj, int i)>); void draw_objects(std::function<void(const glm::mat4& camera, const glm::mat4& proj, int i)>);
void draw_objects(std::function<void(const glm::mat4& camera, const glm::mat4& proj, int i)>, Layer& layer); void draw_objects(std::function<void(const glm::mat4& camera, const glm::mat4& proj, int i)>, Layer& layer);
bool ray_intersect(glm::vec3 ray_origin, glm::vec3 ray_dir, glm::vec3 plane_origin, bool ray_intersect(glm::vec3 ray_origin, glm::vec3 ray_dir, glm::vec3 plane_origin,

View File

@@ -2,6 +2,7 @@
#include "app.h" #include "app.h"
#include "log.h" #include "log.h"
#include "node_canvas.h" #include "node_canvas.h"
#include "node_image_texture.h"
Node* NodeCanvas::clone_instantiate() const Node* NodeCanvas::clone_instantiate() const
{ {
@@ -14,6 +15,7 @@ void NodeCanvas::init()
m_canvas = std::make_unique<ui::Canvas>(); m_canvas = std::make_unique<ui::Canvas>();
m_canvas->create(CANVAS_RES, CANVAS_RES); m_canvas->create(CANVAS_RES, CANVAS_RES);
m_canvas->m_unsaved = false; m_canvas->m_unsaved = false;
m_canvas->m_node = this;
m_sampler.create(GL_NEAREST); m_sampler.create(GL_NEAREST);
m_sampler_linear.create(GL_LINEAR); m_sampler_linear.create(GL_LINEAR);
m_sampler_stencil.create(GL_LINEAR, GL_REPEAT); m_sampler_stencil.create(GL_LINEAR, GL_REPEAT);
@@ -73,6 +75,7 @@ void NodeCanvas::draw()
m_canvas->m_mv = camera; m_canvas->m_mv = camera;
m_canvas->m_proj = proj; m_canvas->m_proj = proj;
m_canvas->m_box = box; m_canvas->m_box = box;
m_canvas->m_vp = c;
// auto plane_mvp = proj * camera * transform * // auto plane_mvp = proj * camera * transform *
// glm::scale(glm::vec3(sz, 1)); // glm::scale(glm::vec3(sz, 1));
@@ -267,6 +270,9 @@ void NodeCanvas::handle_resize(glm::vec2 old_size, glm::vec2 new_size)
{ {
if (new_size.x > m_canvas->m_width) if (new_size.x > m_canvas->m_width)
{ {
m_canvas->m_mixer.create((int)new_size.x, (int)new_size.y);
if (auto img = root()->find<NodeImageTexture>("tex-debug"))
img->tex.assign(m_canvas->m_mixer.getTextureID());
// m_canvas->resize((int)new_size.x, (int)new_size.y); // m_canvas->resize((int)new_size.x, (int)new_size.y);
// m_canvas->clear(); // m_canvas->clear();
} }

View File

@@ -58,6 +58,7 @@ void NodePanelStroke::init_controls()
init_slider(m_tip_flow, "tip-flow", &ui::Brush::m_tip_flow); init_slider(m_tip_flow, "tip-flow", &ui::Brush::m_tip_flow);
init_slider(m_tip_opacity, "tip-opacity", &ui::Brush::m_tip_opacity); init_slider(m_tip_opacity, "tip-opacity", &ui::Brush::m_tip_opacity);
init_slider(m_tip_angle, "tip-angle", &ui::Brush::m_tip_angle); init_slider(m_tip_angle, "tip-angle", &ui::Brush::m_tip_angle);
init_slider(m_tip_mix, "tip-mix", &ui::Brush::m_tip_mix);
init_slider(m_tip_stencil, "tip-stencil", &ui::Brush::m_tip_stencil); init_slider(m_tip_stencil, "tip-stencil", &ui::Brush::m_tip_stencil);
init_slider(m_tip_wet, "tip-wet", &ui::Brush::m_tip_wet); init_slider(m_tip_wet, "tip-wet", &ui::Brush::m_tip_wet);
init_slider(m_tip_noise, "tip-noise", &ui::Brush::m_tip_noise); init_slider(m_tip_noise, "tip-noise", &ui::Brush::m_tip_noise);

View File

@@ -16,6 +16,7 @@ public:
NodeSliderH* m_tip_flow; NodeSliderH* m_tip_flow;
NodeSliderH* m_tip_opacity; NodeSliderH* m_tip_opacity;
NodeSliderH* m_tip_angle; NodeSliderH* m_tip_angle;
NodeSliderH* m_tip_mix;
NodeSliderH* m_tip_stencil; NodeSliderH* m_tip_stencil;
NodeSliderH* m_tip_wet; NodeSliderH* m_tip_wet;
NodeSliderH* m_tip_noise; NodeSliderH* m_tip_noise;

View File

@@ -9,11 +9,13 @@ enum class kShaderUniform : uint16_t
Tex = const_hash("tex"), Tex = const_hash("tex"),
TexFG = const_hash("tex_fg"), TexFG = const_hash("tex_fg"),
TexBG = const_hash("tex_bg"), TexBG = const_hash("tex_bg"),
TexMix = const_hash("tex_mix"),
TexMask = const_hash("tex_mask"), TexMask = const_hash("tex_mask"),
TexStroke = const_hash("tex_stroke"), TexStroke = const_hash("tex_stroke"),
TexStencil= const_hash("tex_stencil"), TexStencil = const_hash("tex_stencil"),
StencilOffset = const_hash("stencil_offset"), StencilOffset = const_hash("stencil_offset"),
StencilAlpha = const_hash("stencil_alpha"), StencilAlpha = const_hash("stencil_alpha"),
MixAlpha = const_hash("mix_alpha"),
Wet = const_hash("wet"), Wet = const_hash("wet"),
Lock = const_hash("lock"), Lock = const_hash("lock"),
Col = const_hash("col"), Col = const_hash("col"),