diff --git a/drape/shaders/traffic_fragment_shader.fsh b/drape/shaders/traffic_fragment_shader.fsh index e7d10f0e9d..f432f86b62 100644 --- a/drape/shaders/traffic_fragment_shader.fsh +++ b/drape/shaders/traffic_fragment_shader.fsh @@ -5,9 +5,13 @@ varying float v_halfLength; uniform sampler2D u_colorTex; uniform sampler2D u_maskTex; uniform float u_opacity; +uniform float u_outline; const float kAntialiasingThreshold = 0.92; +const float kOutlineThreshold1 = 0.8; +const float kOutlineThreshold2 = 0.5; + const vec3 kLightArrow = vec3(1.0, 1.0, 1.0); const vec3 kDarkArrow = vec3(107.0 / 255.0, 81.0 / 255.0, 20.0 / 255.0); @@ -20,6 +24,11 @@ void main(void) vec4 mask = texture2D(u_maskTex, v_maskTexCoord); color.a = u_opacity * (1.0 - smoothstep(kAntialiasingThreshold, 1.0, abs(v_halfLength))); color.rgb = mix(color.rgb, mask.rgb * mix(kLightArrow, kDarkArrow, step(alphaCode, 0.6)), mask.a); + if (u_outline > 0.0) + { + color.rgb = mix(color.rgb, vec3(1.0, 1.0, 1.0), step(kOutlineThreshold1, abs(v_halfLength))); + color.rgb = mix(color.rgb, vec3(1.0, 1.0, 1.0), smoothstep(kOutlineThreshold2, kOutlineThreshold1, abs(v_halfLength))); + } gl_FragColor = color; } else diff --git a/drape_frontend/message_subclasses.hpp b/drape_frontend/message_subclasses.hpp index db3b2645b3..c460b16c6e 100644 --- a/drape_frontend/message_subclasses.hpp +++ b/drape_frontend/message_subclasses.hpp @@ -1051,8 +1051,8 @@ public: , m_needInvalidate(false) {} - UpdateTrafficMessage(TrafficSegmentsColoring const & segmentsColoring, bool needInvalidate) - : m_segmentsColoring(segmentsColoring) + UpdateTrafficMessage(TrafficSegmentsColoring && segmentsColoring, bool needInvalidate) + : m_segmentsColoring(move(segmentsColoring)) , m_needInvalidate(needInvalidate) {} diff --git a/drape_frontend/rule_drawer.cpp b/drape_frontend/rule_drawer.cpp index 2d7a3c60d8..3ada0a3f72 100644 --- a/drape_frontend/rule_drawer.cpp +++ b/drape_frontend/rule_drawer.cpp @@ -50,10 +50,10 @@ void ExtractTrafficGeometry(FeatureType const & f, df::RoadClass const & roadCla static vector directions = {traffic::TrafficInfo::RoadSegmentId::kForwardDirection, traffic::TrafficInfo::RoadSegmentId::kReverseDirection}; auto & segments = geometry[f.GetID().m_mwmId]; - segments.reserve(segments.size() + directions.size() * (polyline.GetPoints().size() - 1)); - for (uint16_t segmentIndex = 0; segmentIndex + 1 < static_cast(polyline.GetPoints().size()); segmentIndex++) + segments.reserve(segments.size() + directions.size() * (polyline.GetSize() - 1)); + for (uint16_t segmentIndex = 0; segmentIndex + 1 < static_cast(polyline.GetSize()); ++segmentIndex) { - for (size_t dirIndex = 0; dirIndex < directions.size(); dirIndex++) + for (size_t dirIndex = 0; dirIndex < directions.size(); ++dirIndex) { auto const sid = traffic::TrafficInfo::RoadSegmentId(f.GetID().m_index, segmentIndex, directions[dirIndex]); bool const isReversed = (directions[dirIndex] == traffic::TrafficInfo::RoadSegmentId::kReverseDirection); @@ -275,20 +275,29 @@ void RuleDrawer::operator()(FeatureType const & f) if (m_trafficEnabled && zoomLevel >= kRoadClass0ZoomLevel) { + vector points; + points.reserve(f.GetPointsCount()); + f.ForEachPoint([&points](m2::PointD const & p) { points.emplace_back(p); }, FeatureType::BEST_GEOMETRY); + m2::PolylineD const polyline(points); + + struct Checker + { + vector m_highwayClasses; + int m_zoomLevel; + df::RoadClass m_roadClass; + }; + static Checker const checkers[] = { + {{ftypes::HighwayClass::Trunk, ftypes::HighwayClass::Primary}, kRoadClass0ZoomLevel, df::RoadClass::Class0}, + {{ftypes::HighwayClass::Secondary, ftypes::HighwayClass::Tertiary}, kRoadClass1ZoomLevel, df::RoadClass::Class1}, + {{ftypes::HighwayClass::LivingStreet, ftypes::HighwayClass::Service}, kRoadClass2ZoomLevel, df::RoadClass::Class2} + }; + auto const highwayClass = ftypes::GetHighwayClass(f); - if (highwayClass == ftypes::HighwayClass::Trunk || highwayClass == ftypes::HighwayClass::Primary) + for (size_t i = 0; i < ARRAY_SIZE(checkers); ++i) { - ExtractTrafficGeometry(f, df::RoadClass::Class0, apply.GetPolyline(), m_trafficGeometry); - } - else if ((highwayClass == ftypes::HighwayClass::Secondary || highwayClass == ftypes::HighwayClass::Tertiary) && - zoomLevel >= kRoadClass1ZoomLevel) - { - ExtractTrafficGeometry(f, df::RoadClass::Class1, apply.GetPolyline(), m_trafficGeometry); - } - else if ((highwayClass == ftypes::HighwayClass::LivingStreet || highwayClass == ftypes::HighwayClass::Service) && - zoomLevel >= kRoadClass2ZoomLevel) - { - ExtractTrafficGeometry(f, df::RoadClass::Class2, apply.GetPolyline(), m_trafficGeometry); + auto const & classes = checkers[i].m_highwayClasses; + if (find(classes.begin(), classes.end(), highwayClass) != classes.end() && zoomLevel >= checkers[i].m_zoomLevel) + ExtractTrafficGeometry(f, checkers[i].m_roadClass, polyline, m_trafficGeometry); } } } diff --git a/drape_frontend/traffic_generator.cpp b/drape_frontend/traffic_generator.cpp index 8b6fd94a68..a692852b2b 100644 --- a/drape_frontend/traffic_generator.cpp +++ b/drape_frontend/traffic_generator.cpp @@ -198,8 +198,8 @@ void TrafficGenerator::FlushSegmentsGeometry(TileKey const & tileKey, TrafficSeg auto coloringIt = m_coloring.find(geomIt->first); if (coloringIt != m_coloring.end()) { - for (size_t i = 0; i < roadClasses.size(); i++) - m_batchersPool->ReserveBatcher(TrafficBatcherKey(geomIt->first, tileKey, roadClasses[i])); + for (auto const & roadClass : roadClasses) + m_batchersPool->ReserveBatcher(TrafficBatcherKey(geomIt->first, tileKey, roadClass)); auto & coloring = coloringIt->second; for (size_t i = 0; i < geomIt->second.size(); i++) @@ -216,7 +216,8 @@ void TrafficGenerator::FlushSegmentsGeometry(TileKey const & tileKey, TrafficSeg vector staticGeometry; vector dynamicGeometry; - GenerateSegment(colorRegion, g.m_polyline, tileKey.GetGlobalRect().Center(), staticGeometry, dynamicGeometry); + bool const generateCaps = (tileKey.m_zoomLevel > kOutlineMinZoomLevel); + GenerateSegment(colorRegion, g.m_polyline, tileKey.GetGlobalRect().Center(), generateCaps, staticGeometry, dynamicGeometry); ASSERT_EQUAL(staticGeometry.size(), dynamicGeometry.size(), ()); if ((staticGeometry.size() + dynamicGeometry.size()) == 0) @@ -233,8 +234,8 @@ void TrafficGenerator::FlushSegmentsGeometry(TileKey const & tileKey, TrafficSeg } } - for (size_t i = 0; i < roadClasses.size(); i++) - m_batchersPool->ReleaseBatcher(TrafficBatcherKey(geomIt->first, tileKey, roadClasses[i])); + for (auto const & roadClass : roadClasses) + m_batchersPool->ReleaseBatcher(TrafficBatcherKey(geomIt->first, tileKey, roadClass)); } } @@ -243,23 +244,13 @@ void TrafficGenerator::FlushSegmentsGeometry(TileKey const & tileKey, TrafficSeg bool TrafficGenerator::UpdateColoring(TrafficSegmentsColoring const & coloring) { - // Check for new mwm's in coloring. bool hasNew = false; for (auto it = coloring.begin(); it != coloring.end(); ++it) { - auto const coloringIt = m_coloring.find(it->first); - if (coloringIt == m_coloring.end()) - { + if (!hasNew && m_coloring.find(it->first) == m_coloring.end()) hasNew = true; - break; - } + m_coloring[it->first] = it->second; } - - // Update coloring. - for (auto it = coloring.begin(); it != coloring.end(); ++it) - m_coloring.erase(it->first); - m_coloring.insert(coloring.begin(), coloring.end()); - return hasNew; } @@ -286,7 +277,7 @@ void TrafficGenerator::FlushGeometry(TrafficBatcherKey const & key, dp::GLState void TrafficGenerator::GenerateSegment(dp::TextureManager::ColorRegion const & colorRegion, m2::PolylineD const & polyline, m2::PointD const & tileCenter, - vector & staticGeometry, + bool generateCaps, vector & staticGeometry, vector & dynamicGeometry) { vector const & path = polyline.GetPoints(); @@ -343,7 +334,7 @@ void TrafficGenerator::GenerateSegment(dp::TextureManager::ColorRegion const & c } // Generate caps. - if (firstFilled) + if (generateCaps && firstFilled) { int const kSegmentsCount = 4; vector normals; diff --git a/drape_frontend/traffic_generator.hpp b/drape_frontend/traffic_generator.hpp index 7e9450baa3..3703285bc6 100644 --- a/drape_frontend/traffic_generator.hpp +++ b/drape_frontend/traffic_generator.hpp @@ -36,6 +36,7 @@ enum class RoadClass : uint8_t int constexpr kRoadClass0ZoomLevel = 10; int constexpr kRoadClass1ZoomLevel = 12; int constexpr kRoadClass2ZoomLevel = 14; +int constexpr kOutlineMinZoomLevel = 13; struct TrafficSegmentID { @@ -192,9 +193,9 @@ private: { if (lhs.m_mwmId == rhs.m_mwmId) { - if (lhs.m_tileKey == rhs.m_tileKey) + if (lhs.m_tileKey.EqualStrict(rhs.m_tileKey)) return lhs.m_roadClass < rhs.m_roadClass; - return lhs.m_tileKey < rhs.m_tileKey; + return lhs.m_tileKey.LessStrict(rhs.m_tileKey); } return lhs.m_mwmId < rhs.m_mwmId; } @@ -202,7 +203,7 @@ private: void GenerateSegment(dp::TextureManager::ColorRegion const & colorRegion, m2::PolylineD const & polyline, m2::PointD const & tileCenter, - vector & staticGeometry, + bool generateCaps, vector & staticGeometry, vector & dynamicGeometry); void FillColorsCache(ref_ptr textures); @@ -211,9 +212,6 @@ private: TrafficSegmentsColoring m_coloring; - //map m_segments; - - //set m_segmentsCache; array(traffic::SpeedGroup::Count)> m_colorsCache; bool m_colorsCacheValid = false; bool m_colorsCacheRefreshed = false; diff --git a/drape_frontend/traffic_renderer.cpp b/drape_frontend/traffic_renderer.cpp index ca55154ba0..7d9ed2b914 100644 --- a/drape_frontend/traffic_renderer.cpp +++ b/drape_frontend/traffic_renderer.cpp @@ -20,7 +20,7 @@ namespace { int const kMinVisibleArrowZoomLevel = 16; -int const kRoadClass2MinVisibleArrowZoomLevel = 18; +int const kRoadClass2MinVisibleArrowZoomLevel = 17; float const kTrafficArrowAspect = 24.0f / 8.0f; @@ -29,15 +29,15 @@ float const kLeftWidthInPixel[] = // 1 2 3 4 5 6 7 8 9 10 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, //11 12 13 14 15 16 17 18 19 20 - 0.75f, 0.75f, 1.0f, 2.0f, 2.0f, 3.0f, 3.0f, 4.0f, 5.0f, 8.0f + 0.75f, 0.75f, 0.75f, 2.0f, 2.0f, 3.0f, 3.0f, 4.0f, 5.0f, 8.0f }; float const kRightWidthInPixel[] = { // 1 2 3 4 5 6 7 8 9 10 - 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 3.0f, 3.0f, + 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 3.0f, 4.0f, //11 12 13 14 15 16 17 18 19 20 - 3.0f, 3.0f, 3.0f, 2.0f, 2.0f, 3.0f, 3.0f, 4.0f, 5.0f, 8.0f + 4.0f, 4.0f, 4.0f, 2.0f, 2.0f, 3.0f, 3.0f, 4.0f, 5.0f, 8.0f }; float const kRoadClass1WidthScalar[] = @@ -45,7 +45,7 @@ float const kRoadClass1WidthScalar[] = // 1 2 3 4 5 6 7 8 9 10 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, //11 12 13 14 15 16 17 18 19 20 - 0.0f, 0.4f, 0.5f, 0.6f, 0.8f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f + 0.0f, 0.2f, 0.3f, 0.6f, 0.8f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f }; float const kRoadClass2WidthScalar[] = @@ -53,7 +53,7 @@ float const kRoadClass2WidthScalar[] = // 1 2 3 4 5 6 7 8 9 10 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, //11 12 13 14 15 16 17 18 19 20 - 0.0f, 0.0f, 0.0f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.8f, 1.0f + 0.0f, 0.0f, 0.0f, 0.2f, 0.3f, 0.5f, 0.7f, 0.8f, 0.9f, 1.0f }; float CalculateHalfWidth(ScreenBase const & screen, RoadClass const & roadClass, bool left) @@ -179,6 +179,7 @@ void TrafficRenderer::RenderTraffic(ScreenBase const & screen, int zoomLevel, float invLeftPixelLength = 0.0f; float rightPixelHalfWidth = 0.0f; int minVisibleArrowZoomLevel = kMinVisibleArrowZoomLevel; + float outline = 0.0f; if (renderData.m_bucket->GetOverlayHandlesCount() > 0) { @@ -186,7 +187,11 @@ void TrafficRenderer::RenderTraffic(ScreenBase const & screen, int zoomLevel, ASSERT(handle != nullptr, ()); int visibleZoomLevel = kRoadClass0ZoomLevel; - if (handle->GetRoadClass() == RoadClass::Class1) + if (handle->GetRoadClass() == RoadClass::Class0) + { + outline = (zoomLevel <= kOutlineMinZoomLevel ? 1.0 : 0.0); + } + else if (handle->GetRoadClass() == RoadClass::Class1) { visibleZoomLevel = kRoadClass1ZoomLevel; } @@ -215,6 +220,7 @@ void TrafficRenderer::RenderTraffic(ScreenBase const & screen, int zoomLevel, math::Matrix const mv = renderData.m_tileKey.GetTileBasedModelView(screen); uniforms.SetMatrix4x4Value("modelView", mv.m_data); uniforms.SetFloatValue("u_opacity", 1.0f); + uniforms.SetFloatValue("u_outline", outline); uniforms.SetFloatValue("u_trafficParams", leftPixelHalfWidth, rightPixelHalfWidth, invLeftPixelLength, zoomLevel >= minVisibleArrowZoomLevel ? 1.0f : 0.0f); dp::ApplyUniforms(uniforms, program);