optimize stroke drawing

This commit is contained in:
2018-12-07 00:45:14 +01:00
parent 4980105d51
commit bbdad5a857
7 changed files with 131 additions and 69 deletions

View File

@@ -343,6 +343,47 @@ void Canvas::stroke_draw()
auto& stencil = TextureManager::get(const_hash("data/paper.jpg"));
auto ortho_proj = glm::ortho(0.f, (float)m_width, 0.f, (float)m_height, -1.f, 1.f);
std::vector<vertex_t> B{
vertex_t{ {0, 0, 1, 1}, {0, 0}, {0, 0} },
vertex_t{ {0, 0, 1, 1}, {0, 1}, {0, 1} },
vertex_t{ {0, 0, 1, 1}, {1, 1}, {1, 1} },
vertex_t{ {0, 0, 1, 1}, {1, 0}, {1, 0} },
};
glViewport(0, 0, m_width, m_height);
glActiveTexture(GL_TEXTURE0);
tex.bind();
m_sampler_brush.bind(0);
m_sampler_bg.bind(1);
m_sampler_stencil.bind(2);
m_sampler.bind(3);
//m_sampler_linear.bind(5);
glActiveTexture(GL_TEXTURE2);
stencil.bind();
glActiveTexture(GL_TEXTURE3);
m_mixer.bindTexture();
glDisable(GL_BLEND);
ShaderManager::use(kShader::Stroke);
ShaderManager::u_int(kShaderUniform::Tex, 0); // brush
#ifndef __IOS__
ShaderManager::u_int(kShaderUniform::TexBG, 1); // bg
#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);
ShaderManager::u_float(kShaderUniform::MixAlpha, m_brush.m_tip_mix);
ShaderManager::u_float(kShaderUniform::Wet, m_brush.m_tip_wet);
ShaderManager::u_float(kShaderUniform::Noise, m_brush.m_tip_noise);
auto unp_vp = zw(m_box);
auto unp_inv = glm::inverse(m_proj * m_mv);
for (const auto& s : samples)
{
if (m_mixer_idle)
@@ -352,30 +393,13 @@ void Canvas::stroke_draw()
}
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 = (xy(m_mixer_sample.pos) + off[j] * glm::orientate2(-s.angle) + glm::vec2(0, 1)) / zoom;
UV2[j] = p / sz;
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);
}
glm::vec2 dx_mix(m_mixer_sample.size * 0.5f, 0), dy_mix(0, m_mixer_sample.size * 0.5f);
glm::vec2 off_mix[4] = {
-dx_mix - dy_mix, // A - bottom-left
-dx_mix + dy_mix, // B - top-left
+dx_mix + dy_mix, // C - top-right
+dx_mix - dy_mix, // D - bottom-right
};
// P is the initial square centered at the cursor location
glm::vec2 dx(s.size * 0.5f, 0), dy(0, s.size * 0.5f);
glm::vec2 off[4] = {
@@ -384,48 +408,23 @@ void Canvas::stroke_draw()
+dx + dy, // C - top-right
+dx - dy, // D - bottom-right
};
std::vector<vertex_t> B{
vertex_t{ {0, 0, 1, 1}, {0, 0}, {0, 0} },
vertex_t{ {0, 0, 1, 1}, {0, 1}, {0, 1} },
vertex_t{ {0, 0, 1, 1}, {1, 1}, {1, 1} },
vertex_t{ {0, 0, 1, 1}, {1, 0}, {1, 0} },
};
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 = (xy(m_mixer_sample.pos) + off_mix[j] * glm::orientate2(-s.angle) + glm::vec2(0, 1)) / zoom;
UV2[j] = p / sz;
bb_min = glm::max({ 0, 0 }, glm::min(bb_min, p));
bb_max = glm::min(sz, glm::max(bb_max, p));
B[j].pos = glm::vec4(xy(s.pos) + off[j] * glm::orientate2(-s.angle), 1, 1);
B[j].uvs2 = UV2[j];
}
auto bb_sz = bb_max - bb_min;
glViewport(0, 0, m_width, m_height);
glActiveTexture(GL_TEXTURE0);
tex.bind();
m_sampler_brush.bind(0);
m_sampler_bg.bind(1);
m_sampler_stencil.bind(2);
m_sampler.bind(3);
//m_sampler_linear.bind(5);
glActiveTexture(GL_TEXTURE2);
stencil.bind();
glActiveTexture(GL_TEXTURE3);
m_mixer.bindTexture();
glDisable(GL_BLEND);
ShaderManager::use(kShader::Stroke);
ShaderManager::u_int(kShaderUniform::Tex, 0); // brush
#ifndef __IOS__
ShaderManager::u_int(kShaderUniform::TexBG, 1); // bg
#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);
ShaderManager::u_float(kShaderUniform::MixAlpha, m_brush.m_tip_mix);
ShaderManager::u_float(kShaderUniform::Wet, m_brush.m_tip_wet);
ShaderManager::u_float(kShaderUniform::Noise, m_brush.m_tip_noise);
if (m_brush.m_tip_mix > 0.f)
stroke_draw_mix(bb_min, bb_sz);
for (int i = 0; i < 6; i++)
{
@@ -439,17 +438,21 @@ void Canvas::stroke_draw()
int intersected = 0;
int inside = 0;
// face is the 2d shape of the cube plane i projected onto the window space
auto face = face_to_shape2D(i);
// intersect P with the current face to clip diverging points from the plane
auto P = poly_intersect(B, face);
auto P = poly_intersect(B, m_plane_shape[i]);
for (int j = 0; j < P.size(); j++)
{
glm::vec3 ray_origin, ray_dir;
if (s.pos.z == 0)
{
point_unproject(P[j].pos, { 0, 0, zw(m_box) }, m_mv, m_proj, ray_origin, ray_dir);
//point_unproject(P[j].pos, { 0, 0, zw(m_box) }, m_mv, m_proj, ray_origin, ray_dir);
auto clip_space = glm::vec2(P[j].pos.x, unp_vp.y - P[j].pos.y - 1.f) / unp_vp * 2.f - 1.f;
auto wp0 = unp_inv * glm::vec4(clip_space, 0, 1);
auto wp1 = unp_inv * glm::vec4(clip_space, .5, 1);
ray_origin = xyz(wp0 / wp0.w);
ray_dir = glm::normalize(xyz(wp1 / wp1.w) - ray_origin);
}
else
{
@@ -526,13 +529,31 @@ void Canvas::stroke_draw()
glm::max(zw(m_dirty_box[i]), (glm::vec2)(tex_pos + tex_sz))
);
ShaderManager::use(kShader::Stroke);
//ShaderManager::use(kShader::Stroke);
ShaderManager::u_mat4(kShaderUniform::MVP, ortho_proj);
ShaderManager::u_vec4(kShaderUniform::Col, glm::vec4(s.col, m_brush.m_tip_color.a));
ShaderManager::u_float(kShaderUniform::Alpha, s.flow);
P = triangulate_simple(P);
m_brush_shape.update_vertices(P.data(), P.size());
if (P.size() == 4)
{
static vertex_t rect[6];
rect[0] = P[0];
rect[1] = P[1];
rect[2] = P[2];
rect[3] = P[0];
rect[4] = P[2];
rect[5] = P[3];
m_brush_shape.update_vertices(rect, 6);
}
else if (P.size() == 3)
{
m_brush_shape.update_vertices(P.data(), P.size());
}
else
{
P = triangulate_simple(P);
m_brush_shape.update_vertices(P.data(), P.size());
}
m_brush_shape.draw_fill();
/*