From dd4c8e4445efdc373a72ded488e22b1a1c4d635b Mon Sep 17 00:00:00 2001 From: Daria Volvenkova Date: Mon, 2 Jul 2018 14:11:06 +0300 Subject: [PATCH] Render circles as transit line joins. --- drape_frontend/render_group.cpp | 6 +- drape_frontend/transit_scheme_builder.cpp | 90 +++++++++++----------- drape_frontend/transit_scheme_builder.hpp | 3 +- drape_frontend/transit_scheme_renderer.cpp | 1 + shaders/CMakeLists.txt | 6 +- shaders/GL/shader_index.txt | 1 + shaders/GL/transit_circle.fsh.glsl | 19 +++++ shaders/GL/transit_circle.vsh.glsl | 30 ++++++++ shaders/gl_program_params.cpp | 1 + shaders/program_params.hpp | 2 + shaders/programs.hpp | 2 + 11 files changed, 111 insertions(+), 50 deletions(-) create mode 100644 shaders/GL/transit_circle.fsh.glsl create mode 100644 shaders/GL/transit_circle.vsh.glsl diff --git a/drape_frontend/render_group.cpp b/drape_frontend/render_group.cpp index 31104db36a..6d324a34c1 100755 --- a/drape_frontend/render_group.cpp +++ b/drape_frontend/render_group.cpp @@ -237,13 +237,13 @@ UserMarkRenderGroup::UserMarkRenderGroup(dp::GLState const & state, TileKey cons void UserMarkRenderGroup::UpdateAnimation() { BaseRenderGroup::UpdateAnimation(); - float interplationT = 1.0f; + float interpolation = 1.0f; if (m_animation) { auto const t = static_cast(m_animation->GetOpacity()); - interplationT = m_mapping.GetValue(t); + interpolation = m_mapping.GetValue(t); } - m_uniforms.SetFloatValue("u_interpolation", interplationT); + m_uniforms.SetFloatValue("u_interpolation", interpolation); } bool UserMarkRenderGroup::IsUserPoint() const diff --git a/drape_frontend/transit_scheme_builder.cpp b/drape_frontend/transit_scheme_builder.cpp index f32e9bc057..6565d55394 100644 --- a/drape_frontend/transit_scheme_builder.cpp +++ b/drape_frontend/transit_scheme_builder.cpp @@ -52,14 +52,14 @@ std::string const kTransitStopInnerColor = "TransitStopInnerMarker"; float const kTransitMarkTextSize = 12.0f; -struct TransitLineStaticVertex +struct TransitStaticVertex { using TPosition = glsl::vec3; using TNormal = glsl::vec4; using TColor = glsl::vec4; - TransitLineStaticVertex() = default; - TransitLineStaticVertex(TPosition const & position, TNormal const & normal, + TransitStaticVertex() = default; + TransitStaticVertex(TPosition const & position, TNormal const & normal, TColor const & color) : m_position(position), m_normal(normal), m_color(color) {} @@ -76,41 +76,50 @@ struct SchemeSegment glsl::vec2 m_leftNormal; glsl::vec2 m_rightNormal; }; -using TGeometryBuffer = std::vector; +using TGeometryBuffer = std::vector; dp::BindingInfo const & GetTransitStaticBindingInfo() { static unique_ptr s_info; if (s_info == nullptr) { - dp::BindingFiller filler(3); - filler.FillDecl("a_position"); - filler.FillDecl("a_normal"); - filler.FillDecl("a_color"); + dp::BindingFiller filler(3); + filler.FillDecl("a_position"); + filler.FillDecl("a_normal"); + filler.FillDecl("a_color"); s_info.reset(new dp::BindingInfo(filler.m_info)); } return *s_info; } -void SubmitStaticVertex(glsl::vec3 const & pivot, glsl::vec2 const & normal, float side, - glsl::vec4 const & color, TGeometryBuffer & geometry) +void GenerateLineCaps(std::vector const & segments, glsl::vec4 const & color, + float lineOffset, float halfWidth, float depth, dp::Batcher & batcher) { - geometry.emplace_back(pivot, TransitLineStaticVertex::TNormal(normal, side, 0.0), color); -} + using TV = TransitStaticVertex; -void GenerateJoinsTriangles(glsl::vec3 const & pivot, - std::vector const & normals, - glsl::vec2 const & offset, - glsl::vec4 const & color, - TGeometryBuffer & joinsGeometry) -{ - size_t const trianglesCount = normals.size() / 3; - for (size_t j = 0; j < trianglesCount; j++) + TGeometryBuffer geometry; + geometry.reserve(segments.size() * 3); + + for (auto const & segment : segments) { - SubmitStaticVertex(pivot, normals[3 * j] + offset, 1.0f, color, joinsGeometry); - SubmitStaticVertex(pivot, normals[3 * j + 1] + offset, 1.0f, color, joinsGeometry); - SubmitStaticVertex(pivot, normals[3 * j + 2] + offset, 1.0f, color, joinsGeometry); + // Here we use an equilateral triangle to render a circle (incircle of a triangle). + static float const kSqrt3 = sqrt(3.0f); + auto const offset = lineOffset * segment.m_rightNormal; + auto const pivot = glsl::vec3(segment.m_p2, depth); + + auto const n1 = glsl::vec2(-2.0 * halfWidth, -halfWidth); + auto const n2 = glsl::vec2(2.0 * halfWidth, -halfWidth); + auto const n3 = glsl::vec2(0.0f, (2.0f * kSqrt3 - 1.0f) * halfWidth); + + geometry.emplace_back(pivot, TV::TNormal(-offset, n1), color); + geometry.emplace_back(pivot, TV::TNormal(-offset, n2), color); + geometry.emplace_back(pivot, TV::TNormal(-offset, n3), color); } + + dp::AttributeProvider provider(1 /* stream count */, static_cast(geometry.size())); + provider.InitStream(0 /* stream index */, GetTransitStaticBindingInfo(), make_ref(geometry.data())); + auto state = CreateGLState(gpu::Program::TransitCircle, RenderState::TransitSchemeLayer); + batcher.InsertTriangleList(state, make_ref(&provider)); } struct TitleInfo @@ -537,7 +546,6 @@ void TransitSchemeBuilder::GenerateShapes(MwmSet::MwmId const & mwmId) auto const linesCount = shape.second.m_forwardLines.size() + shape.second.m_backwardLines.size(); auto shapeOffset = -static_cast(linesCount / 2) * 2.0f - 1.0f * static_cast(linesCount % 2) + 1.0f; auto const shapeOffsetIncrement = 2.0f; - auto const lineHalfWidth = 0.8f; std::vector> coloredLines; for (auto lineId : shape.second.m_forwardLines) @@ -559,7 +567,8 @@ void TransitSchemeBuilder::GenerateShapes(MwmSet::MwmId const & mwmId) auto const & lineId = coloredLine.second; auto const depth = scheme.m_lines.at(lineId).m_depth; - GenerateLine(shape.second.m_polyline, scheme.m_pivot, colorConst, shapeOffset, lineHalfWidth, depth, batcher); + GenerateLine(shape.second.m_polyline, scheme.m_pivot, colorConst, shapeOffset, + kTransitLineHalfWidth, depth, batcher); shapeOffset += shapeOffsetIncrement; } } @@ -728,7 +737,7 @@ void TransitSchemeBuilder::GenerateMarker(m2::PointD const & pt, m2::PointD widt float scaleWidth, float scaleHeight, float depth, dp::Color const & color, dp::Batcher & batcher) { - using TV = TransitLineStaticVertex; + using TV = TransitStaticVertex; scaleWidth = (scaleWidth - 1.0f) / linesCountWidth + 1.0f; scaleHeight = (scaleHeight - 1.0f) / linesCountHeight + 1.0f; @@ -760,9 +769,11 @@ void TransitSchemeBuilder::GenerateMarker(m2::PointD const & pt, m2::PointD widt } void TransitSchemeBuilder::GenerateLine(std::vector const & path, m2::PointD const & pivot, - dp::Color const & colorConst, float lineOffset, float lineHalfWidth, + dp::Color const & colorConst, float lineOffset, float halfWidth, float depth, dp::Batcher & batcher) { + using TV = TransitStaticVertex; + TGeometryBuffer geometry; auto const color = glsl::vec4(colorConst.GetRedF(), colorConst.GetGreenF(), colorConst.GetBlueF(), 1.0f /* alpha */); size_t const kAverageSize = path.size() * 6; @@ -787,30 +798,21 @@ void TransitSchemeBuilder::GenerateLine(std::vector const & path, m2 auto const endPivot = glsl::vec3(segment.m_p2, depth); auto const offset = lineOffset * segment.m_rightNormal; - SubmitStaticVertex(startPivot, segment.m_rightNormal * lineHalfWidth - offset, -lineHalfWidth, color, geometry); - SubmitStaticVertex(startPivot, segment.m_leftNormal * lineHalfWidth - offset, lineHalfWidth, color, geometry); - SubmitStaticVertex(endPivot, segment.m_rightNormal * lineHalfWidth - offset, -lineHalfWidth, color, geometry); - SubmitStaticVertex(endPivot, segment.m_rightNormal * lineHalfWidth - offset, -lineHalfWidth, color, geometry); - SubmitStaticVertex(startPivot, segment.m_leftNormal * lineHalfWidth - offset, lineHalfWidth, color, geometry); - SubmitStaticVertex(endPivot, segment.m_leftNormal * lineHalfWidth - offset, lineHalfWidth, color, geometry); + geometry.emplace_back(startPivot, TV::TNormal(segment.m_rightNormal * halfWidth - offset, -halfWidth, 0.0), color); + geometry.emplace_back(startPivot, TV::TNormal(segment.m_leftNormal * halfWidth - offset, halfWidth, 0.0), color); + geometry.emplace_back(endPivot, TV::TNormal(segment.m_rightNormal * halfWidth - offset, -halfWidth, 0.0), color); + geometry.emplace_back(endPivot, TV::TNormal(segment.m_rightNormal * halfWidth - offset, -halfWidth, 0.0), color); + geometry.emplace_back(startPivot, TV::TNormal(segment.m_leftNormal * halfWidth - offset, halfWidth, 0.0), color); + geometry.emplace_back(endPivot, TV::TNormal(segment.m_leftNormal * halfWidth - offset, halfWidth, 0.0), color); segments.emplace_back(std::move(segment)); } - for (size_t i = 0; i < segments.size(); ++i) - { - int const kSegmentsCount = 4; - vector normals; - normals.reserve(kAverageCapSize); - GenerateCapNormals(dp::RoundCap, segments[i].m_leftNormal, segments[i].m_rightNormal, segments[i].m_tangent, - lineHalfWidth, false /* isStart */, normals, kSegmentsCount); - GenerateJoinsTriangles(glsl::vec3(segments[i].m_p2, depth), normals, -lineOffset * segments[i].m_rightNormal, - color, geometry); - } - dp::AttributeProvider provider(1 /* stream count */, static_cast(geometry.size())); provider.InitStream(0 /* stream index */, GetTransitStaticBindingInfo(), make_ref(geometry.data())); auto state = CreateGLState(gpu::Program::Transit, RenderState::TransitSchemeLayer); batcher.InsertTriangleList(state, make_ref(&provider)); + + GenerateLineCaps(segments, color, lineOffset, halfWidth, depth, batcher); } } // namespace df diff --git a/drape_frontend/transit_scheme_builder.hpp b/drape_frontend/transit_scheme_builder.hpp index 256f468601..60c2229949 100644 --- a/drape_frontend/transit_scheme_builder.hpp +++ b/drape_frontend/transit_scheme_builder.hpp @@ -15,6 +15,7 @@ namespace df { int constexpr kTransitSchemeMinZoomLevel = 10; +float constexpr kTransitLineHalfWidth = 0.8f; extern std::vector const kTransitLinesWidthInPixel; @@ -154,7 +155,7 @@ private: ref_ptr textures, dp::Batcher & batcher); void GenerateLine(std::vector const & path, m2::PointD const & pivot, dp::Color const & colorConst, - float lineOffset, float lineHalfWidth, float depth, dp::Batcher & batcher); + float lineOffset, float halfWidth, float depth, dp::Batcher & batcher); using TransitSchemes = std::map; TransitSchemes m_schemes; diff --git a/drape_frontend/transit_scheme_renderer.cpp b/drape_frontend/transit_scheme_renderer.cpp index 10931d7c4e..aa90042778 100644 --- a/drape_frontend/transit_scheme_renderer.cpp +++ b/drape_frontend/transit_scheme_renderer.cpp @@ -180,6 +180,7 @@ void TransitSchemeRenderer::RenderLines(ScreenBase const & screen, ref_ptrRender(false /* draw as line */); diff --git a/shaders/CMakeLists.txt b/shaders/CMakeLists.txt index da41002904..1a61cfbaa2 100644 --- a/shaders/CMakeLists.txt +++ b/shaders/CMakeLists.txt @@ -98,10 +98,12 @@ set( GL/traffic.vsh.glsl GL/traffic_line.fsh.glsl GL/traffic_line.vsh.glsl - GL/transit_marker.fsh.glsl - GL/transit_marker.vsh.glsl GL/transit.fsh.glsl GL/transit.vsh.glsl + GL/transit_circle.fsh.glsl + GL/transit_circle.vsh.glsl + GL/transit_marker.fsh.glsl + GL/transit_marker.vsh.glsl GL/user_mark.fsh.glsl GL/user_mark.vsh.glsl GL/user_mark_billboard.vsh.glsl diff --git a/shaders/GL/shader_index.txt b/shaders/GL/shader_index.txt index 713e91d276..26b82eb11a 100644 --- a/shaders/GL/shader_index.txt +++ b/shaders/GL/shader_index.txt @@ -13,6 +13,7 @@ Area3d area3d.vsh.glsl texturing3d.fsh.glsl Area3dOutline area3d_outline.vsh.glsl solid_color.fsh.glsl Line line.vsh.glsl line.fsh.glsl CapJoin circle.vsh.glsl circle.fsh.glsl +TransitCircle transit_circle.vsh.glsl transit_circle.fsh.glsl DashedLine dashed_line.vsh.glsl dashed_line.fsh.glsl PathSymbol path_symbol.vsh.glsl texturing.fsh.glsl HatchingArea hatching_area.vsh.glsl hatching_area.fsh.glsl diff --git a/shaders/GL/transit_circle.fsh.glsl b/shaders/GL/transit_circle.fsh.glsl new file mode 100644 index 0000000000..c47d3bd404 --- /dev/null +++ b/shaders/GL/transit_circle.fsh.glsl @@ -0,0 +1,19 @@ +varying vec3 v_radius; +varying vec4 v_color; + +#ifdef SAMSUNG_GOOGLE_NEXUS +uniform sampler2D u_colorTex; +#endif + +const float aaPixelsCount = 2.5; + +void main() +{ + vec4 finalColor = v_color; + + float smallRadius = v_radius.z - aaPixelsCount; + float stepValue = smoothstep(smallRadius * smallRadius, v_radius.z * v_radius.z, + dot(v_radius.xy, v_radius.xy)); + finalColor.a = finalColor.a * (1.0 - stepValue); + gl_FragColor = samsungGoogleNexusWorkaround(finalColor); +} diff --git a/shaders/GL/transit_circle.vsh.glsl b/shaders/GL/transit_circle.vsh.glsl new file mode 100644 index 0000000000..b2bc5c1d6d --- /dev/null +++ b/shaders/GL/transit_circle.vsh.glsl @@ -0,0 +1,30 @@ +attribute vec3 a_position; +attribute vec4 a_normal; +attribute vec4 a_color; + +uniform mat4 u_modelView; +uniform mat4 u_projection; +uniform mat4 u_pivotTransform; + +uniform float u_lineHalfWidth; +uniform float u_maxRadius; + +varying vec3 v_radius; +varying vec4 v_color; + +void main() +{ + vec2 normal = a_normal.xy; + vec2 transformedAxisPos = (vec4(a_position.xy, 0.0, 1.0) * u_modelView).xy; + if (dot(normal, normal) != 0.0) + { + vec2 norm = normal * u_lineHalfWidth; + transformedAxisPos = calcLineTransformedAxisPos(transformedAxisPos, a_position.xy + norm, + u_modelView, length(norm)); + } + transformedAxisPos += a_normal.zw * u_lineHalfWidth; + vec4 pos = vec4(transformedAxisPos, a_position.z, 1.0) * u_projection; + gl_Position = applyPivotTransform(pos, u_pivotTransform, 0.0); + v_color = a_color; + v_radius = vec3(a_normal.zw, u_maxRadius) * u_lineHalfWidth; +} diff --git a/shaders/gl_program_params.cpp b/shaders/gl_program_params.cpp index 7b0c022638..9b9e2a9b26 100644 --- a/shaders/gl_program_params.cpp +++ b/shaders/gl_program_params.cpp @@ -129,6 +129,7 @@ void GLProgramParamsSetter::Apply(ref_ptr program, TransitProgra Parameter::CheckApply(guard, "u_pivotTransform", params.m_pivotTransform); Parameter::CheckApply(guard, "u_params", params.m_params); Parameter::CheckApply(guard, "u_lineHalfWidth", params.m_lineHalfWidth); + Parameter::CheckApply(guard, "u_maxRadius", params.m_maxRadius); } void GLProgramParamsSetter::Apply(ref_ptr program, GuiProgramParams const & params) diff --git a/shaders/program_params.hpp b/shaders/program_params.hpp index ccdfe604c4..35e0eb0740 100644 --- a/shaders/program_params.hpp +++ b/shaders/program_params.hpp @@ -128,9 +128,11 @@ struct TransitProgramParams glsl::mat4 m_pivotTransform; glsl::vec3 m_params; float m_lineHalfWidth = 0.0f; + float m_maxRadius = 0.0f; BIND_PROGRAMS(TransitProgramParams, Program::Transit, + Program::TransitCircle, Program::TransitMarker) }; diff --git a/shaders/programs.hpp b/shaders/programs.hpp index 39a867226c..1a5379b141 100644 --- a/shaders/programs.hpp +++ b/shaders/programs.hpp @@ -24,6 +24,7 @@ enum class Program Area3dOutline, Line, CapJoin, + TransitCircle, DashedLine, PathSymbol, HatchingArea, @@ -79,6 +80,7 @@ inline std::string DebugPrint(Program p) case Program::Area3dOutline: return "Area3dOutline"; case Program::Line: return "Line"; case Program::CapJoin: return "CapJoin"; + case Program::TransitCircle: return "TransitCircle"; case Program::DashedLine: return "DashedLine"; case Program::PathSymbol: return "PathSymbol"; case Program::HatchingArea: return "HatchingArea";