diff --git a/drape/drape.pro b/drape/drape.pro index 8fcb03c34b..d8f1ffc0ee 100644 --- a/drape/drape.pro +++ b/drape/drape.pro @@ -26,3 +26,7 @@ OTHER_FILES += \ shaders/texturing_fragment_shader.fsh \ shaders/texturing_vertex_shader.vsh \ shaders/user_mark.vsh \ + +DISTFILES += \ + shaders/circle_shader.fsh \ + shaders/circle_shader.vsh diff --git a/drape/shaders/circle_shader.fsh b/drape/shaders/circle_shader.fsh new file mode 100644 index 0000000000..9571d23325 --- /dev/null +++ b/drape/shaders/circle_shader.fsh @@ -0,0 +1,13 @@ +uniform sampler2D u_colorTex; +uniform float u_opacity; + +varying vec2 v_colorTexCoords; +varying vec3 v_radius; + +void main(void) +{ + vec4 finalColor = texture2D(u_colorTex, v_colorTexCoords); + float stepValue = step(pow(v_radius.z, 2.0), pow(v_radius.x, 2.0) + pow(v_radius.y, 2.0)); + finalColor.a = finalColor.a * u_opacity * (1.0 - stepValue); + gl_FragColor = finalColor; +} diff --git a/drape/shaders/circle_shader.vsh b/drape/shaders/circle_shader.vsh new file mode 100644 index 0000000000..c69aa2f3c3 --- /dev/null +++ b/drape/shaders/circle_shader.vsh @@ -0,0 +1,16 @@ +attribute vec3 a_position; +attribute vec3 a_normal; +attribute vec2 a_colorTexCoords; + +uniform mat4 modelView; +uniform mat4 projection; + +varying vec3 v_radius; +varying vec2 v_colorTexCoords; + +void main(void) +{ + gl_Position = (vec4(a_normal.xy, 0, 0) + vec4(a_position, 1) * modelView) * projection; + v_colorTexCoords = a_colorTexCoords; + v_radius = a_normal; +} diff --git a/drape/shaders/shader_index.txt b/drape/shaders/shader_index.txt index c1ce4fbdc7..d1a03dc76e 100644 --- a/drape/shaders/shader_index.txt +++ b/drape/shaders/shader_index.txt @@ -1,7 +1,9 @@ -LINE_PROGRAM line_vertex_shader.vsh line_fragment_shader.fsh TEXT_PROGRAM text_vertex_shader.vsh text_fragment_shader.fsh TEXTURING_PROGRAM texturing_vertex_shader.vsh texturing_fragment_shader.fsh +LINE_PROGRAM line_vertex_shader.vsh line_fragment_shader.fsh +CAP_JOIN_PROGRAM circle_shader.vsh circle_shader.fsh DASHED_LINE_PROGRAM dashed_vertex_shader.vsh dashed_fragment_shader.fsh +PATH_SYMBOL_LINE texturing_vertex_shader.vsh texturing_fragment_shader.fsh COMPASS_PROGRAM compass_vertex_shader.vsh texturing_fragment_shader.fsh RULER_PROGRAM ruler_vertex_shader.vsh texturing_fragment_shader.fsh ACCURACY_PROGRAM position_accuracy_shader.vsh texturing_fragment_shader.fsh diff --git a/drape/shaders/text_fragment_shader.fsh b/drape/shaders/text_fragment_shader.fsh index a3757e267f..1ae3c5147a 100755 --- a/drape/shaders/text_fragment_shader.fsh +++ b/drape/shaders/text_fragment_shader.fsh @@ -1,4 +1,3 @@ - varying vec2 v_colorTexCoord; varying vec2 v_outlineColorTexCoord; varying vec2 v_maskTexCoord; diff --git a/drape_frontend/line_shape.cpp b/drape_frontend/line_shape.cpp index 9320891bc9..0b57a019f2 100644 --- a/drape_frontend/line_shape.cpp +++ b/drape_frontend/line_shape.cpp @@ -62,11 +62,13 @@ template class BaseLineBuilder : public ILineShapeInfo { public: - BaseLineBuilder(dp::TextureManager::ColorRegion const & color, float pxHalfWidth, - size_t geometrySize, size_t joinsSize) + BaseLineBuilder(dp::TextureManager::ColorRegion const & color, float pxHalfWidth, float depth, + size_t geometrySize, size_t joinsSize, dp::LineCap lineCap) : m_color(color) , m_colorCoord(glsl::ToVec2(m_color.GetTexRect().Center())) , m_pxHalfWidth(pxHalfWidth) + , m_depth(depth) + , m_lineCap(lineCap) { m_geometry.reserve(geometrySize); m_joinGeom.reserve(joinsSize); @@ -109,6 +111,26 @@ public: return m_pxHalfWidth; } + dp::BindingInfo const & GetCapBindingInfo() override + { + return GetBindingInfo(); + } + + dp::GLState GetCapState() override + { + return GetState(); + } + + ref_ptr GetCapData() override + { + return ref_ptr(); + } + + size_t GetCapSize() override + { + return 0; + } + protected: using V = TVertex; using TGeometryBuffer = vector; @@ -116,9 +138,13 @@ protected: TGeometryBuffer m_geometry; TGeometryBuffer m_joinGeom; + vector m_normalBuffer; + dp::TextureManager::ColorRegion m_color; glsl::vec2 const m_colorCoord; float const m_pxHalfWidth; + float m_depth; + dp::LineCap m_lineCap; }; class SolidLineBuilder : public BaseLineBuilder @@ -126,9 +152,31 @@ class SolidLineBuilder : public BaseLineBuilder using TBase = BaseLineBuilder; using TNormal = gpu::LineVertex::TNormal; + struct CapVertex + { + using TPosition = gpu::LineVertex::TPosition; + using TNormal = gpu::LineVertex::TNormal; + using TTexCoord = gpu::LineVertex::TTexCoord; + + CapVertex() {} + CapVertex(TPosition const & pos, TNormal const & normal, TTexCoord const & color) + : m_position(pos) + , m_normal(normal) + , m_color(color) + { + } + + TPosition m_position; + TNormal m_normal; + TTexCoord m_color; + }; + + using TCapBuffer = vector; + public: - SolidLineBuilder(dp::TextureManager::ColorRegion const & color, float const pxHalfWidth, size_t pointsInSpline) - : TBase(color, pxHalfWidth, pointsInSpline * 2, (pointsInSpline - 2) * 8) + SolidLineBuilder(dp::TextureManager::ColorRegion const & color, float const pxHalfWidth, + float const depth, size_t pointsInSpline, dp::LineCap lineCap) + : TBase(color, pxHalfWidth, depth, pointsInSpline * 2, (pointsInSpline - 2) * 8, lineCap) { } @@ -139,6 +187,45 @@ public: return state; } + dp::BindingInfo const & GetCapBindingInfo() override + { + if (m_lineCap != dp::RoundCap) + return TBase::GetCapBindingInfo(); + + static unique_ptr s_capInfo; + if (s_capInfo == nullptr) + { + dp::BindingFiller filler(3); + filler.FillDecl("a_position"); + filler.FillDecl("a_normal"); + filler.FillDecl("a_colorTexCoords"); + + s_capInfo.reset(new dp::BindingInfo(filler.m_info)); + } + + return *s_capInfo; + } + + dp::GLState GetCapState() override + { + if (m_lineCap != dp::RoundCap) + return TBase::GetCapState(); + + dp::GLState state(gpu::CAP_JOIN_PROGRAM, dp::GLState::GeometryLayer); + state.SetColorTexture(m_color.GetTexture()); + return state; + } + + ref_ptr GetCapData() override + { + return make_ref(m_capGeometry.data()); + } + + size_t GetCapSize() override + { + return m_capGeometry.size(); + } + void SubmitVertex(LineSegment const & segment, glsl::vec3 const & pivot, glsl::vec2 const & normal, bool isLeft, float offsetFromStart) { @@ -160,10 +247,52 @@ public: } } + void SubmitCap(LineSegment const & segment, bool isStart) + { + EPointType const type = isStart ? StartPoint : EndPoint; + if (m_lineCap != dp::RoundCap) + { + m_normalBuffer.reserve(24); + + float const sign = isStart ? -1.0 : 1.0; + GenerateCapNormals(m_lineCap, + segment.m_leftNormals[type], + segment.m_rightNormals[type], + sign * segment.m_tangent, + GetHalfWidth(), isStart, m_normalBuffer); + + SubmitJoin(glsl::vec3(segment.m_points[type], m_depth), m_normalBuffer); + m_normalBuffer.clear(); + } + else + { + m_capGeometry.reserve(8); + + glsl::vec2 const pos = segment.m_points[type]; + float const radius = GetHalfWidth(); + + m_capGeometry.push_back(CapVertex(CapVertex::TPosition(pos, m_depth), + CapVertex::TNormal(-radius, radius, radius), + CapVertex::TTexCoord(m_colorCoord))); + m_capGeometry.push_back(CapVertex(CapVertex::TPosition(pos, m_depth), + CapVertex::TNormal(-radius, -radius, radius), + CapVertex::TTexCoord(m_colorCoord))); + m_capGeometry.push_back(CapVertex(CapVertex::TPosition(pos, m_depth), + CapVertex::TNormal(radius, radius, radius), + CapVertex::TTexCoord(m_colorCoord))); + m_capGeometry.push_back(CapVertex(CapVertex::TPosition(pos, m_depth), + CapVertex::TNormal(radius, -radius, radius), + CapVertex::TTexCoord(m_colorCoord))); + } + } + float GetSide(bool isLeft) { return isLeft ? 1.0 : -1.0; } + +private: + TCapBuffer m_capGeometry; }; class DashedLineBuilder : public BaseLineBuilder @@ -173,9 +302,9 @@ class DashedLineBuilder : public BaseLineBuilder public: DashedLineBuilder(dp::TextureManager::ColorRegion const & color, dp::TextureManager::StippleRegion const & stipple, - float glbHalfWidth, float pxHalfWidth, float baseGtoP, - size_t pointsInSpline) - : TBase(color, pxHalfWidth, pointsInSpline * 8, (pointsInSpline - 2) * 8) + float glbHalfWidth, float pxHalfWidth, float const depth, + float baseGtoP, size_t pointsInSpline, dp::LineCap lineCap) + : TBase(color, pxHalfWidth, depth, pointsInSpline * 8, (pointsInSpline - 2) * 8, lineCap) , m_texCoordGen(stipple, baseGtoP) , m_glbHalfWidth(glbHalfWidth) , m_baseGtoPScale(baseGtoP) @@ -220,6 +349,22 @@ public: } } + void SubmitCap(LineSegment const & segment, bool isStart) + { + m_normalBuffer.reserve(24); + + EPointType const type = isStart ? StartPoint : EndPoint; + float const sign = isStart ? -1.0 : 1.0; + GenerateCapNormals(m_lineCap, + segment.m_leftNormals[type], + segment.m_rightNormals[type], + sign * segment.m_tangent, + GetHalfWidth(), isStart, m_normalBuffer); + + SubmitJoin(glsl::vec3(segment.m_points[type], m_depth), m_normalBuffer); + m_normalBuffer.clear(); + } + private: TextureCoordGenerator m_texCoordGen; float const m_glbHalfWidth; @@ -243,7 +388,8 @@ void LineShape::Prepare(ref_ptr textures) const if (m_params.m_pattern.empty()) { - auto builder = make_unique(colorRegion, pxHalfWidth, m_spline->GetPath().size()); + auto builder = make_unique(colorRegion, pxHalfWidth, m_params.m_depth, + m_spline->GetPath().size(), m_params.m_cap); Construct(*builder); m_lineShapeInfo = move(builder); } @@ -255,8 +401,8 @@ void LineShape::Prepare(ref_ptr textures) const float const glbHalfWidth = pxHalfWidth / m_params.m_baseGtoPScale; auto builder = make_unique(colorRegion, maskRegion, glbHalfWidth, - pxHalfWidth, m_params.m_baseGtoPScale, - m_spline->GetPath().size()); + pxHalfWidth, m_params.m_depth, m_params.m_baseGtoPScale, + m_spline->GetPath().size(), m_params.m_cap); Construct(*builder); m_lineShapeInfo = move(builder); } @@ -336,32 +482,8 @@ void LineShape::Construct(TBuilder & builder) const } } - vector normals; - normals.reserve(24); - - { - LineSegment const & segment = segments[0]; - GenerateCapNormals(m_params.m_cap, - segment.m_leftNormals[StartPoint], - segment.m_rightNormals[StartPoint], - -segment.m_tangent, - halfWidth, true /* isStart */, normals); - - builder.SubmitJoin(glsl::vec3(segment.m_points[StartPoint], m_params.m_depth), normals); - normals.clear(); - } - - { - size_t index = segments.size() - 1; - LineSegment const & segment = segments[index]; - GenerateCapNormals(m_params.m_cap, - segment.m_leftNormals[EndPoint], - segment.m_rightNormals[EndPoint], - segment.m_tangent, - halfWidth, false /* isStart */, normals); - - builder.SubmitJoin(glsl::vec3(segment.m_points[EndPoint], m_params.m_depth), normals); - } + builder.SubmitCap(segments[0], true /* isStart */); + builder.SubmitCap(segments[segments.size() - 1], false /* isStart */); } void LineShape::Draw(ref_ptr batcher, ref_ptr textures) const @@ -383,6 +505,14 @@ void LineShape::Draw(ref_ptr batcher, ref_ptr t joinsProvider.InitStream(0, m_lineShapeInfo->GetBindingInfo(), m_lineShapeInfo->GetJoinData()); batcher->InsertTriangleList(state, make_ref(&joinsProvider)); } + + size_t capSize = m_lineShapeInfo->GetCapSize(); + if (capSize > 0) + { + dp::AttributeProvider capProvider(1, capSize); + capProvider.InitStream(0, m_lineShapeInfo->GetCapBindingInfo(), m_lineShapeInfo->GetCapData()); + batcher->InsertListOfStrip(m_lineShapeInfo->GetCapState(), make_ref(&capProvider), dp::Batcher::VertexPerQuad); + } } } // namespace df diff --git a/drape_frontend/line_shape.hpp b/drape_frontend/line_shape.hpp index 7abda3815f..b1f583e645 100644 --- a/drape_frontend/line_shape.hpp +++ b/drape_frontend/line_shape.hpp @@ -26,6 +26,11 @@ public: virtual ref_ptr GetJoinData() = 0; virtual size_t GetJoinSize() = 0; + + virtual dp::BindingInfo const & GetCapBindingInfo() = 0; + virtual dp::GLState GetCapState() = 0; + virtual ref_ptr GetCapData() = 0; + virtual size_t GetCapSize() = 0; }; class LineShape : public MapShape diff --git a/drape_frontend/path_symbol_shape.cpp b/drape_frontend/path_symbol_shape.cpp index 0b5d9b1c20..ccaf96178b 100644 --- a/drape_frontend/path_symbol_shape.cpp +++ b/drape_frontend/path_symbol_shape.cpp @@ -58,7 +58,7 @@ void PathSymbolShape::Draw(ref_ptr batcher, ref_ptr