From afe8f28d0c4f4d28f2448e214476ebea7b2a397d Mon Sep 17 00:00:00 2001 From: "r.kuznetsov" Date: Mon, 8 Jun 2015 17:32:44 +0300 Subject: [PATCH] Added route clipping --- drape/shaders/route_fragment_shader.fsh | 12 +++++++ drape/shaders/route_vertex_shader.vsh | 16 ++++++--- drape/utils/vertex_decl.cpp | 16 +++++++-- drape/utils/vertex_decl.hpp | 5 ++- drape_frontend/line_shape.cpp | 10 ------ drape_frontend/line_shape_helper.cpp | 11 ++++++ drape_frontend/line_shape_helper.hpp | 3 ++ drape_frontend/route_shape.cpp | 46 +++++++++++++++++-------- drape_head/testing_engine.cpp | 4 ++- 9 files changed, 89 insertions(+), 34 deletions(-) diff --git a/drape/shaders/route_fragment_shader.fsh b/drape/shaders/route_fragment_shader.fsh index c2db173581..5ebf5b1bfd 100644 --- a/drape/shaders/route_fragment_shader.fsh +++ b/drape/shaders/route_fragment_shader.fsh @@ -1,9 +1,21 @@ +varying vec2 v_length; + +uniform vec2 u_halfWidth; uniform vec4 u_color; +uniform float u_clipLength; void main(void) { if (u_color.a < 0.1) discard; + if (v_length.x < u_clipLength) + { + float dist = u_clipLength - v_length.x; + float r = dist * dist + v_length.y * v_length.y - u_halfWidth.y * u_halfWidth.y; + if (r > 0.0) + discard; + } + gl_FragColor = u_color; } diff --git a/drape/shaders/route_vertex_shader.vsh b/drape/shaders/route_vertex_shader.vsh index d075be76e8..1bd43cdc53 100644 --- a/drape/shaders/route_vertex_shader.vsh +++ b/drape/shaders/route_vertex_shader.vsh @@ -1,24 +1,32 @@ attribute vec3 a_position; attribute vec2 a_normal; +attribute vec2 a_length; uniform mat4 modelView; uniform mat4 projection; -uniform float u_halfWidth; +uniform vec2 u_halfWidth; + +varying vec2 v_length; void main(void) { - float halfWidth = length(a_normal); + float normalLen = length(a_normal); vec2 transformedAxisPos = (vec4(a_position.xy, 0.0, 1.0) * modelView).xy; - if (u_halfWidth != 0.0 && halfWidth != 0.0) + vec2 len = vec2(a_length.x, 0.0); + if (u_halfWidth.x != 0.0 && normalLen != 0.0) { - vec2 norm = a_normal * u_halfWidth; + vec2 norm = a_normal * u_halfWidth.x; float actualHalfWidth = length(norm); vec4 glbShiftPos = vec4(a_position.xy + norm, 0.0, 1.0); vec2 shiftPos = (glbShiftPos * modelView).xy; transformedAxisPos = transformedAxisPos + normalize(shiftPos - transformedAxisPos) * actualHalfWidth; + + if (u_halfWidth.y != 0.0) + len = vec2(a_length.x + a_length.y * u_halfWidth.y, u_halfWidth.y); } + v_length = len; gl_Position = vec4(transformedAxisPos, a_position.z, 1.0) * projection; } diff --git a/drape/utils/vertex_decl.cpp b/drape/utils/vertex_decl.cpp index d701afb2f2..b4c4d72ce9 100644 --- a/drape/utils/vertex_decl.cpp +++ b/drape/utils/vertex_decl.cpp @@ -150,8 +150,9 @@ dp::BindingInfo LineBindingInit() dp::BindingInfo RouteBindingInit() { STATIC_ASSERT(sizeof(RouteVertex) == sizeof(RouteVertex::TPosition) + - sizeof(RouteVertex::TNormal)); - dp::BindingInfo info(2); + sizeof(RouteVertex::TNormal) + + sizeof(RouteVertex::TLength)); + dp::BindingInfo info(3); dp::BindingDecl & posDecl = info.GetBindingDecl(0); posDecl.m_attributeName = "a_position"; @@ -167,6 +168,13 @@ dp::BindingInfo RouteBindingInit() normalDecl.m_offset = posDecl.m_offset + sizeof(RouteVertex::TPosition); normalDecl.m_stride = posDecl.m_stride; + dp::BindingDecl & lengthDecl = info.GetBindingDecl(2); + lengthDecl.m_attributeName = "a_length"; + lengthDecl.m_componentCount = glsl::GetComponentCount(); + lengthDecl.m_componentType = gl_const::GLFloatType; + lengthDecl.m_offset = normalDecl.m_offset + sizeof(RouteVertex::TNormal); + lengthDecl.m_stride = posDecl.m_stride; + return info; } @@ -281,11 +289,13 @@ dp::BindingInfo const & LineVertex::GetBindingInfo() RouteVertex::RouteVertex() : m_position(0.0, 0.0, 0.0) , m_normal(0.0, 0.0) + , m_length(0.0, 0.0) {} -RouteVertex::RouteVertex(TPosition const & position, TNormal const & normal) +RouteVertex::RouteVertex(TPosition const & position, TNormal const & normal, TLength const & length) : m_position(position) , m_normal(normal) + , m_length(length) {} dp::BindingInfo const & RouteVertex::GetBindingInfo() diff --git a/drape/utils/vertex_decl.hpp b/drape/utils/vertex_decl.hpp index c779d05a31..2491772c85 100644 --- a/drape/utils/vertex_decl.hpp +++ b/drape/utils/vertex_decl.hpp @@ -75,11 +75,14 @@ struct LineVertex : BaseVertex struct RouteVertex : BaseVertex { + typedef glsl::vec2 TLength; + RouteVertex(); - RouteVertex(TPosition const & position, TNormal const & normal); + RouteVertex(TPosition const & position, TNormal const & normal, TLength const & length); TPosition m_position; TNormal m_normal; + TLength m_length; static dp::BindingInfo const & GetBindingInfo(); }; diff --git a/drape_frontend/line_shape.cpp b/drape_frontend/line_shape.cpp index aefb8e4777..7098b5b4a5 100644 --- a/drape_frontend/line_shape.cpp +++ b/drape_frontend/line_shape.cpp @@ -66,16 +66,6 @@ namespace float m_maskLength = 0.0f; bool m_isSolid = true; }; - - float GetProjectionLength(glsl::vec2 const & newPoint, glsl::vec2 const & startPoint, - glsl::vec2 const & endPoint) - { - glsl::vec2 const v1 = endPoint - startPoint; - glsl::vec2 const v2 = newPoint - startPoint; - float const squareLen = glsl::dot(v1, v1); - float const proj = glsl::dot(v1, v2) / squareLen; - return sqrt(squareLen) * my::clamp(proj, 0.0f, 1.0f); - } } LineShape::LineShape(m2::SharedSpline const & spline, diff --git a/drape_frontend/line_shape_helper.cpp b/drape_frontend/line_shape_helper.cpp index b60e47b7da..afa3e574ef 100644 --- a/drape_frontend/line_shape_helper.cpp +++ b/drape_frontend/line_shape_helper.cpp @@ -217,4 +217,15 @@ glsl::vec2 GetNormal(LineSegment const & segment, bool isLeft, ENormalType norma segment.m_rightWidthScalar[index].x * segment.m_rightNormals[index]; } +float GetProjectionLength(glsl::vec2 const & newPoint, glsl::vec2 const & startPoint, + glsl::vec2 const & endPoint) +{ + glsl::vec2 const v1 = endPoint - startPoint; + glsl::vec2 const v2 = newPoint - startPoint; + float const squareLen = glsl::dot(v1, v1); + float const proj = glsl::dot(v1, v2) / squareLen; + return sqrt(squareLen) * my::clamp(proj, 0.0f, 1.0f); +} + } // namespace df + diff --git a/drape_frontend/line_shape_helper.hpp b/drape_frontend/line_shape_helper.hpp index 5fe92bf6e5..cac35994ca 100644 --- a/drape_frontend/line_shape_helper.hpp +++ b/drape_frontend/line_shape_helper.hpp @@ -54,4 +54,7 @@ void GenerateCapNormals(dp::LineCap capType, glsl::vec2 const & normal1, glsl::v glsl::vec2 GetNormal(LineSegment const & segment, bool isLeft, ENormalType normalType); +float GetProjectionLength(glsl::vec2 const & newPoint, glsl::vec2 const & startPoint, glsl::vec2 const & endPoint); + } // namespace df + diff --git a/drape_frontend/route_shape.cpp b/drape_frontend/route_shape.cpp index 8968f407d0..e7da939336 100644 --- a/drape_frontend/route_shape.cpp +++ b/drape_frontend/route_shape.cpp @@ -33,14 +33,15 @@ void RouteShape::Draw(ref_ptr batcher) const vector const & path = m_polyline.GetPoints(); ASSERT(path.size() > 1, ()); - auto const generateTriangles = [&](glsl::vec3 const & pivot, vector const & normals) + auto const generateTriangles = [&](glsl::vec3 const & pivot, vector const & normals, + glsl::vec2 const & length) { size_t const trianglesCount = normals.size() / 3; for (int j = 0; j < trianglesCount; j++) { - joinsGeometry.push_back(RV(pivot, normals[3 * j])); - joinsGeometry.push_back(RV(pivot, normals[3 * j + 1])); - joinsGeometry.push_back(RV(pivot, normals[3 * j + 2])); + joinsGeometry.push_back(RV(pivot, normals[3 * j], length)); + joinsGeometry.push_back(RV(pivot, normals[3 * j + 1], length)); + joinsGeometry.push_back(RV(pivot, normals[3 * j + 2], length)); } }; @@ -50,6 +51,7 @@ void RouteShape::Draw(ref_ptr batcher) const ConstructLineSegments(path, segments); // build geometry + float length = 0; for (size_t i = 0; i < segments.size(); i++) { UpdateNormals(&segments[i], (i > 0) ? &segments[i - 1] : nullptr, @@ -59,15 +61,27 @@ void RouteShape::Draw(ref_ptr batcher) const glsl::vec3 const startPivot = glsl::vec3(segments[i].m_points[StartPoint], m_params.m_depth); glsl::vec3 const endPivot = glsl::vec3(segments[i].m_points[EndPoint], m_params.m_depth); - geometry.push_back(RV(startPivot, glsl::vec2(0, 0))); - geometry.push_back(RV(startPivot, GetNormal(segments[i], true /* isLeft */, StartNormal))); - geometry.push_back(RV(endPivot, glsl::vec2(0, 0))); - geometry.push_back(RV(endPivot, GetNormal(segments[i], true /* isLeft */, EndNormal))); + float const endLength = length + glsl::length(segments[i].m_points[EndPoint] - segments[i].m_points[StartPoint]); - geometry.push_back(RV(startPivot, GetNormal(segments[i], false /* isLeft */, StartNormal))); - geometry.push_back(RV(startPivot, glsl::vec2(0, 0))); - geometry.push_back(RV(endPivot, GetNormal(segments[i], false /* isLeft */, EndNormal))); - geometry.push_back(RV(endPivot, glsl::vec2(0, 0))); + glsl::vec2 const leftNormalStart = GetNormal(segments[i], true /* isLeft */, StartNormal); + glsl::vec2 const rightNormalStart = GetNormal(segments[i], false /* isLeft */, StartNormal); + glsl::vec2 const leftNormalEnd = GetNormal(segments[i], true /* isLeft */, EndNormal); + glsl::vec2 const rightNormalEnd = GetNormal(segments[i], false /* isLeft */, EndNormal); + + float const projLeftStart = -segments[i].m_leftWidthScalar[StartPoint].y; + float const projLeftEnd = segments[i].m_leftWidthScalar[EndPoint].y; + float const projRightStart = -segments[i].m_rightWidthScalar[StartPoint].y; + float const projRightEnd = segments[i].m_rightWidthScalar[EndPoint].y; + + geometry.push_back(RV(startPivot, glsl::vec2(0, 0), glsl::vec2(length, 0))); + geometry.push_back(RV(startPivot, leftNormalStart, glsl::vec2(length, projLeftStart))); + geometry.push_back(RV(endPivot, glsl::vec2(0, 0), glsl::vec2(endLength, 0))); + geometry.push_back(RV(endPivot, leftNormalEnd, glsl::vec2(endLength, projLeftEnd))); + + geometry.push_back(RV(startPivot, rightNormalStart, glsl::vec2(length, projRightStart))); + geometry.push_back(RV(startPivot, glsl::vec2(0, 0), glsl::vec2(length, 0))); + geometry.push_back(RV(endPivot, rightNormalEnd, glsl::vec2(endLength, projRightEnd))); + geometry.push_back(RV(endPivot, glsl::vec2(0, 0), glsl::vec2(endLength, 0))); // generate joins if (i < segments.size() - 1) @@ -84,7 +98,7 @@ void RouteShape::Draw(ref_ptr batcher) const normals.reserve(24); GenerateJoinNormals(dp::RoundJoin, n1, n2, 1.0f, segments[i].m_hasLeftJoin[EndPoint], widthScalar, normals); - generateTriangles(glsl::vec3(segments[i].m_points[EndPoint], m_params.m_depth), normals); + generateTriangles(glsl::vec3(segments[i].m_points[EndPoint], m_params.m_depth), normals, glsl::vec2(endLength, 0)); } // generate caps @@ -96,7 +110,7 @@ void RouteShape::Draw(ref_ptr batcher) const segments[i].m_rightNormals[StartPoint], -segments[i].m_tangent, 1.0f, true /* isStart */, normals); - generateTriangles(glsl::vec3(segments[i].m_points[StartPoint], m_params.m_depth), normals); + generateTriangles(glsl::vec3(segments[i].m_points[StartPoint], m_params.m_depth), normals, glsl::vec2(length, 0)); } if (i == segments.size() - 1) @@ -107,8 +121,10 @@ void RouteShape::Draw(ref_ptr batcher) const segments[i].m_rightNormals[EndPoint], segments[i].m_tangent, 1.0f, false /* isStart */, normals); - generateTriangles(glsl::vec3(segments[i].m_points[EndPoint], m_params.m_depth), normals); + generateTriangles(glsl::vec3(segments[i].m_points[EndPoint], m_params.m_depth), normals, glsl::vec2(endLength, 0)); } + + length = endLength; } dp::GLState state(gpu::ROUTE_PROGRAM, dp::GLState::GeometryLayer); diff --git a/drape_head/testing_engine.cpp b/drape_head/testing_engine.cpp index 1816c45bb0..da8907a17a 100644 --- a/drape_head/testing_engine.cpp +++ b/drape_head/testing_engine.cpp @@ -446,7 +446,9 @@ void TestingEngine::DrawImpl() { m_generalUniforms.SetFloatValue("u_opacity", 1.0f); m_generalUniforms.SetFloatValue("u_color", 0.0f, 0.0f, 1.0f, 0.7f); - m_generalUniforms.SetFloatValue("u_halfWidth", 5.0f); + m_generalUniforms.SetFloatValue("u_halfWidth", 15.0f, 15.0f * m_modelView.GetScale()); + + m_generalUniforms.SetFloatValue("u_clipLength", 8.4f); dp::Batcher::TFlushFn flushFn = bind(&df::TestingEngine::OnFlushData, this, _1, _2); m_batcher->StartSession(flushFn);