mixer working with scaling factor
This commit is contained in:
@@ -801,7 +801,7 @@
|
||||
<text text="#opengl #fromscratch #c++" font-face="arial" font-size="11" margin="0 0 0 10" color=".2 .5 1 1"/>
|
||||
</border>-->
|
||||
</node>
|
||||
<image-texture id="tex-debug" positioning="absolute" position="0 0" width="300" height="300"></image-texture>
|
||||
<!--<color-picker/>-->
|
||||
<!-- <image-texture id="tex-debug" positioning="absolute" position="0 0" width="300" height="300"></image-texture> -->
|
||||
<!-- <color-picker/> -->
|
||||
</layout>
|
||||
</root>
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<NodeImageTexture>("tex-debug"))
|
||||
img->tex.assign(m_canvas->m_mixer.getTextureID());
|
||||
// m_canvas->resize((int)new_size.x, (int)new_size.y);
|
||||
|
||||
Reference in New Issue
Block a user