diff --git a/data/layout.xml b/data/layout.xml
index 2147222..78b791b 100644
--- a/data/layout.xml
+++ b/data/layout.xml
@@ -801,7 +801,7 @@
-->
-
-
+
+
diff --git a/engine/canvas.cpp b/engine/canvas.cpp
index 20af869..4b021e8 100644
--- a/engine/canvas.cpp
+++ b/engine/canvas.cpp
@@ -235,6 +235,7 @@ void ui::Canvas::stroke_draw_mix()
if (m_layers[layer_index].m_opacity == .0f)
continue;
+ glm::mat4 proj = glm::perspective(glm::radians(m_cam_fov), (float)m_mixer.getWidth() / m_mixer.getHeight(), 0.1f, 1000.f);
auto plane_mvp_z = m_proj * m_mv *
m_plane_transform[plane_index] *
//glm::scale(glm::vec3(1, -1, 1)) *
@@ -294,151 +295,139 @@ void ui::Canvas::stroke_draw()
glActiveTexture(GL_TEXTURE3);
m_mixer.bindTexture();
- for (int i = 0; i < 6; i++)
- {
- // check if plane is even visible
- glm::vec4 forward = m_mv * glm::vec4(0, 0, 1, 1);
- float dot = glm::dot(xyz(forward), m_plane_normal[i]);
- // TODO: use better threshold than 0.3
- // some trigonometric shit, tangent and stuff
-// if (dot < -0.3f)
-// continue;
+ glDisable(GL_BLEND);
+ ShaderManager::use(ui::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_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);
- m_tmp[i].bindFramebuffer();
-
- glActiveTexture(GL_TEXTURE1);
- m_tex[i].bind(); // bg, copy of framebuffer (copied before drawing)
-
- if (m_use_instanced)
+ for (const auto& s : samples)
+ {
+ if (m_mixer_idle)
{
- glEnable(GL_BLEND);
- ShaderManager::use(kShader::BrushStroke);
- ShaderManager::u_vec4(kShaderUniform::Col, m_brush.m_tip_color);
- ShaderManager::u_int(kShaderUniform::Tex, 0);
- m_mesh.draw(samples, ortho_proj);
+ m_mixer_sample = s;
+ m_mixer_idle = false;
}
- else
+
+ static glm::vec2 UV2[4];
+ for (int j = 0; j < 4; j++)
{
- glDisable(GL_BLEND);
- ShaderManager::use(ui::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_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);
- for (const auto& s : samples)
+ 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(m_mixer.getWidth(), m_mixer.getHeight()) * m_mixer_scale;
+ UV2[j].y = 1 - UV2[j].y;
+ }
+
+ for (int i = 0; i < 6; i++)
+ {
+ // check if plane is even visible
+ glm::vec4 forward = m_mv * glm::vec4(0, 0, 1, 1);
+ float dot = glm::dot(xyz(forward), m_plane_normal[i]);
+ // TODO: use better threshold than 0.3
+ // some trigonometric shit, tangent and stuff
+ // if (dot < -0.3f)
+ // continue;
+
+
+ glm::vec2 dx(s.size * 0.5f, 0), dy(0, s.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
+ };
+ static glm::vec4 P[4];
+ int intersected = 0;
+ int inside = 0;
+ for (int j = 0; j < 4; j++)
{
- glm::vec2 dx(s.size * 0.5f, 0), dy(0, s.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
- };
- static glm::vec4 P[4];
- static glm::vec2 UV2[4];
- int intersected = 0;
- int inside = 0;
- if (m_mixer_idle)
+ glm::vec3 ray_origin, ray_dir;
+ point_unproject(s.pos + off[j] * glm::orientate2(-s.angle), { 0, 0, zw(m_box) }, m_mv, m_proj, ray_origin, ray_dir);
+
+ glm::vec3 hit;
+ if (ray_intersect(ray_origin, ray_dir, m_plane_origin[i], m_plane_normal[i], m_plane_tangent[i], hit))
{
- m_mixer_sample = s;
- m_mixer_idle = false;
+ glm::mat4 plane_camera = glm::lookAt(m_plane_origin[i], m_plane_normal[i], m_plane_tangent[i]);
+ glm::vec4 plane_local = plane_camera * glm::vec4(hit, 1);
+ if (glm::abs(plane_local.x) < 1.5f && glm::abs(plane_local.y) < 1.5f)
+ {
+ inside++;
+ }
+ P[j].x = -(plane_local.x * 0.5f - 0.5f) * m_width;
+ P[j].y = (plane_local.y * 0.5f + 0.5f) * m_height;
+ intersected++;
}
- for (int j = 0; j < 4; j++)
+ else
{
- glm::vec3 ray_origin, ray_dir;
- point_unproject(s.pos + off[j] * glm::orientate2(-s.angle), { 0, 0, zw(m_box) }, m_mv, m_proj, ray_origin, ray_dir);
-
- {
- 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(m_mixer.getWidth(), m_mixer.getHeight());
- UV2[j].y = 1 - UV2[j].y;
- }
-
- glm::vec3 hit;
- if (ray_intersect(ray_origin, ray_dir, m_plane_origin[i], m_plane_normal[i], m_plane_tangent[i], hit))
- {
- glm::mat4 plane_camera = glm::lookAt(m_plane_origin[i], m_plane_normal[i], m_plane_tangent[i]);
- glm::vec4 plane_local = plane_camera * glm::vec4(hit, 1);
- if (glm::abs(plane_local.x) < 1.5f && glm::abs(plane_local.y) < 1.5f)
- {
- inside++;
- }
- P[j].x = -(plane_local.x * 0.5f - 0.5f) * m_width;
- P[j].y = (plane_local.y * 0.5f + 0.5f) * m_height;
- intersected++;
- }
- else
- {
// if (i==0)
// LOG("no intersection with plane %d", i);
- break;
- }
+ break;
}
-
- m_mixer_sample = s;
-
- if (intersected < 4 || inside == 0)
- continue;
-
- m_dirty_face[i] = true;
-
- glm::vec2 bb_min(m_width, m_height);
- glm::vec2 bb_max(0, 0);
- for (int j = 0; j < 4; j++)
- {
- bb_min = glm::max({ 0, 0 }, glm::min(bb_min, xy(P[j])));
- bb_max = glm::min({ m_width, m_height }, glm::max(bb_max, xy(P[j])));
- }
- auto bb_sz = bb_max - bb_min;
-
- glm::vec2 pad(1);
- glm::ivec2 tex_pos = glm::clamp(glm::floor(bb_min) - pad , { 0, 0 }, { m_width, m_height });
- glm::ivec2 tex_sz = glm::clamp(glm::ceil(bb_sz ) + pad*2.f, { 0, 0 }, (glm::vec2)(glm::ivec2(m_width, m_height) - tex_pos));
- #ifndef __IOS__
- glCopyTexSubImage2D(GL_TEXTURE_2D, 0,
- tex_pos.x, tex_pos.y,
- tex_pos.x, tex_pos.y,
- tex_sz.x, tex_sz.y);
- #endif
-
- m_dirty_box[i] = glm::vec4(
- glm::min(xy(m_dirty_box[i]), (glm::vec2)tex_pos),
- glm::max(zw(m_dirty_box[i]), (glm::vec2)(tex_pos + tex_sz))
- );
-
- 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);
- m_plane_brush.update_vertices(P, nullptr, UV2);
- m_plane_brush.draw_fill();
}
+
+ if (intersected < 4 || inside == 0)
+ continue;
+
+ m_dirty_face[i] = true;
+
+ m_tmp[i].bindFramebuffer();
+
+ glActiveTexture(GL_TEXTURE1);
+ m_tex[i].bind(); // bg, copy of framebuffer (copied before drawing)
+
+
+ glm::vec2 bb_min(m_width, m_height);
+ glm::vec2 bb_max(0, 0);
+ for (int j = 0; j < 4; j++)
+ {
+ bb_min = glm::max({ 0, 0 }, glm::min(bb_min, xy(P[j])));
+ bb_max = glm::min({ m_width, m_height }, glm::max(bb_max, xy(P[j])));
+ }
+ auto bb_sz = bb_max - bb_min;
+
+ glm::vec2 pad(1);
+ glm::ivec2 tex_pos = glm::clamp(glm::floor(bb_min) - pad , { 0, 0 }, { m_width, m_height });
+ glm::ivec2 tex_sz = glm::clamp(glm::ceil(bb_sz ) + pad*2.f, { 0, 0 }, (glm::vec2)(glm::ivec2(m_width, m_height) - tex_pos));
+ #ifndef __IOS__
+ glCopyTexSubImage2D(GL_TEXTURE_2D, 0,
+ tex_pos.x, tex_pos.y,
+ tex_pos.x, tex_pos.y,
+ tex_sz.x, tex_sz.y);
+ #endif
+
+ m_dirty_box[i] = glm::vec4(
+ glm::min(xy(m_dirty_box[i]), (glm::vec2)tex_pos),
+ glm::max(zw(m_dirty_box[i]), (glm::vec2)(tex_pos + tex_sz))
+ );
+
+ 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);
+ m_plane_brush.update_vertices(P, nullptr, UV2);
+ m_plane_brush.draw_fill();
+
+ glActiveTexture(GL_TEXTURE1);
+ m_tex[i].unbind();
+
+ m_tmp[i].unbindFramebuffer();
}
-// if (m_alpha_lock)
-// {
-// glActiveTexture(GL_TEXTURE2);
-// m_layers[m_current_layer_idx].m_rtt[i].unbindTexture();
-// }
-
- glActiveTexture(GL_TEXTURE1);
- m_tex[i].unbind();
-
- m_tmp[i].unbindFramebuffer();
- }
+ m_mixer_sample = s;
+ }
glDisable(GL_BLEND);
diff --git a/engine/canvas.h b/engine/canvas.h
index 18edf14..d06e87f 100644
--- a/engine/canvas.h
+++ b/engine/canvas.h
@@ -76,6 +76,7 @@ public:
bool m_smask_active = false;
RTT m_tmp[6];
RTT m_mixer;
+ float m_mixer_scale = 0.25f;
ui::StrokeSample m_mixer_sample;
bool m_mixer_idle = true;
Texture2D m_brush_mix;
diff --git a/engine/node_canvas.cpp b/engine/node_canvas.cpp
index 931b3d0..5c40203 100644
--- a/engine/node_canvas.cpp
+++ b/engine/node_canvas.cpp
@@ -270,7 +270,7 @@ void NodeCanvas::handle_resize(glm::vec2 old_size, glm::vec2 new_size)
{
if (new_size.x > m_canvas->m_width)
{
- m_canvas->m_mixer.create((int)new_size.x, (int)new_size.y);
+ m_canvas->m_mixer.create((int)new_size.x * m_canvas->m_mixer_scale, (int)new_size.y * m_canvas->m_mixer_scale);
if (auto img = root()->find("tex-debug"))
img->tex.assign(m_canvas->m_mixer.getTextureID());
// m_canvas->resize((int)new_size.x, (int)new_size.y);