implement perspective correct interpolation to the 2D window space clipped brush stroke sample.
This commit is contained in:
@@ -423,15 +423,29 @@ void ui::Canvas::stroke_draw()
|
||||
+ dx + dy, // C - top-right
|
||||
+ dx - dy, // D - bottom-right
|
||||
};
|
||||
static glm::vec4 P[4];
|
||||
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);
|
||||
// P is the initial square centered at the cursor location
|
||||
std::vector<vertex_t> P{
|
||||
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} },
|
||||
};
|
||||
for (int j = 0; j < 4; j++)
|
||||
P[j].pos = glm::vec4(xy(s.pos) + off[j] * glm::orientate2(-s.angle), 1, 1);
|
||||
// intersect P with the current face to clip diverging points from the plane
|
||||
P = poly_intersect(P, face);
|
||||
|
||||
for (int j = 0; j < P.size(); j++)
|
||||
{
|
||||
glm::vec3 ray_origin, ray_dir;
|
||||
if (s.pos.z == 0)
|
||||
{
|
||||
point_unproject(xy(s.pos) + off[j] * glm::orientate2(-s.angle), { 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);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -451,19 +465,29 @@ void ui::Canvas::stroke_draw()
|
||||
{
|
||||
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;
|
||||
P[j].pos.x = -(plane_local.x * 0.5f - 0.5f) * m_width;
|
||||
P[j].pos.y = (plane_local.y * 0.5f + 0.5f) * m_height;
|
||||
P[j].uvs2 = UV2[j];
|
||||
|
||||
// Black magic - BEWARE!
|
||||
// interpolation perspective correction, use the current camera projection to correct the interpolation
|
||||
// because the new shape will have z fixed with an ortho projection when drawn to the face
|
||||
// we need to imitate the same perspective as the once in the camera
|
||||
// see: https://www.scratchapixel.com/lessons/3d-basic-rendering/rasterization-practical-implementation/perspective-correct-interpolation-vertex-attributes
|
||||
auto hit_cam = m_mv * glm::vec4(hit, 1);
|
||||
P[j].pos.z = hit_cam.z;
|
||||
P[j].uvs *= hit_cam.z;
|
||||
P[j].uvs2 *= hit_cam.z;
|
||||
|
||||
intersected++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// if (i==0)
|
||||
// LOG("no intersection with plane %d", i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (intersected < 4 || inside == 0)
|
||||
if (intersected < 3 || inside == 0)
|
||||
continue;
|
||||
|
||||
m_dirty_face[i] = true;
|
||||
@@ -473,13 +497,12 @@ void ui::Canvas::stroke_draw()
|
||||
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++)
|
||||
for (int j = 0; j < P.size(); 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])));
|
||||
bb_min = glm::max({ 0, 0 }, glm::min(bb_min, xy(P[j].pos)));
|
||||
bb_max = glm::min({ m_width, m_height }, glm::max(bb_max, xy(P[j].pos)));
|
||||
}
|
||||
auto bb_sz = bb_max - bb_min;
|
||||
|
||||
@@ -498,11 +521,41 @@ void ui::Canvas::stroke_draw()
|
||||
glm::max(zw(m_dirty_box[i]), (glm::vec2)(tex_pos + tex_sz))
|
||||
);
|
||||
|
||||
ShaderManager::use(ui::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);
|
||||
m_plane_brush.update_vertices(P, nullptr, UV2);
|
||||
m_plane_brush.draw_fill();
|
||||
|
||||
P = triangulate_simple(P);
|
||||
m_brush_shape.update_vertices(P.data(), P.size());
|
||||
m_brush_shape.draw_fill();
|
||||
|
||||
/*
|
||||
// draw sample wireframe
|
||||
std::vector<vertex_t> lines;
|
||||
for (int vi = 0; vi < P.size(); vi += 3)
|
||||
{
|
||||
auto a = P[vi];
|
||||
auto b = P[(vi + 1) % P.size()];
|
||||
auto c = P[(vi + 2) % P.size()];
|
||||
a.pos.z = b.pos.z = c.pos.z = 0;
|
||||
|
||||
lines.push_back(a);
|
||||
lines.push_back(b);
|
||||
|
||||
lines.push_back(b);
|
||||
lines.push_back(c);
|
||||
|
||||
lines.push_back(c);
|
||||
lines.push_back(a);
|
||||
}
|
||||
|
||||
ShaderManager::use(kShader::Color);
|
||||
ShaderManager::u_vec4(kShaderUniform::Col, { s.col, 1 });
|
||||
ShaderManager::u_mat4(kShaderUniform::MVP, ortho_proj);
|
||||
m_brush_shape.update_vertices(lines.data(), lines.size());
|
||||
m_brush_shape.draw_stroke();
|
||||
*/
|
||||
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
m_tex[i].unbind();
|
||||
@@ -950,6 +1003,7 @@ bool ui::Canvas::create(int width, int height)
|
||||
m_sampler_mix.create(GL_NEAREST, GL_REPEAT);
|
||||
m_plane.create<1>(1, 1);
|
||||
m_plane_brush.create<1>(1, 1);
|
||||
m_brush_shape.create();
|
||||
m_mesh.create();
|
||||
m_brush_mix.create(8, 8);
|
||||
for (auto& l : m_layers)
|
||||
@@ -2039,8 +2093,8 @@ std::vector<glm::vec2> ui::Canvas::face_to_shape2D(int plane_index)
|
||||
{
|
||||
auto pt_clip = m_proj * glm::vec4(p, 1);
|
||||
pt_clip = pt_clip / pt_clip.w;
|
||||
glm::vec2 pt_screen = (glm::vec2(pt_clip) * glm::vec2(1,-1) * 0.5f + 0.5f) * zw(m_vp);
|
||||
//pt_screen.y = m_vp.w - pt_screen.y - 1;
|
||||
glm::vec2 pt_screen = (glm::vec2(pt_clip) * 0.5f + 0.5f) * zw(m_vp);
|
||||
pt_screen.y = m_vp.w - pt_screen.y - 1;
|
||||
points.push_back(pt_screen);
|
||||
}
|
||||
return points;
|
||||
@@ -2065,11 +2119,8 @@ std::vector<vertex_t> ui::Canvas::triangulate_simple(const std::vector<vertex_t>
|
||||
vertex_t vertex;
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
auto p = t->GetPoint(i);
|
||||
auto index = std::distance(points.data(), p);
|
||||
vertex.pos = glm::vec4(p->x, p->y, 0, 1);
|
||||
vertex.uvs = vertices[index].uvs;
|
||||
ret.push_back(vertex);
|
||||
auto index = std::distance(points.data(), t->GetPoint(i));
|
||||
ret.push_back(vertices[index]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user