From ab1d72dd6f465d7277ee9036923f841257b5ae4d Mon Sep 17 00:00:00 2001 From: ExMix Date: Mon, 29 Jun 2015 19:06:59 +0300 Subject: [PATCH] [drape] Move dashed lines to separate shader. Remove all discards from shaders. --- drape/binding_info.hpp | 23 ++ drape/drape.pro | 2 + drape/shaders/dashed_fragment_shader.fsh | 14 + drape/shaders/dashed_vertex_shader.vsh | 26 ++ drape/shaders/line_fragment_shader.fsh | 6 - drape/shaders/line_vertex_shader.vsh | 2 - drape/shaders/shader_index.txt | 1 + drape/shaders/texturing_fragment_shader.fsh | 3 - drape/utils/vertex_decl.cpp | 172 +++------ drape/utils/vertex_decl.hpp | 13 +- drape_frontend/frontend_renderer.cpp | 1 + drape_frontend/line_shape.cpp | 385 +++++++++++++------- drape_frontend/line_shape.hpp | 4 + 13 files changed, 398 insertions(+), 254 deletions(-) create mode 100644 drape/shaders/dashed_fragment_shader.fsh create mode 100644 drape/shaders/dashed_vertex_shader.vsh diff --git a/drape/binding_info.hpp b/drape/binding_info.hpp index 70e0a27402..eee6513df2 100644 --- a/drape/binding_info.hpp +++ b/drape/binding_info.hpp @@ -55,4 +55,27 @@ uint8_t FillDecl(size_t index, string const & attrName, dp::BindingInfo & info, return sizeof(TFieldType); } +template +class BindingFiller +{ +public: + BindingFiller(uint8_t count, uint8_t id = 0) + : m_info(count, id) + { + } + + template + void FillDecl(string const & attrName) + { + m_offset += dp::FillDecl(m_index, attrName, m_info, m_offset); + ++m_index; + } + + dp::BindingInfo m_info; + +private: + size_t m_index = 0; + uint8_t m_offset = 0; +}; + } // namespace dp diff --git a/drape/drape.pro b/drape/drape.pro index 396cc46639..8fcb03c34b 100644 --- a/drape/drape.pro +++ b/drape/drape.pro @@ -13,6 +13,8 @@ SOURCES += glfunctions.cpp OTHER_FILES += \ shaders/compass_vertex_shader.vsh \ + shaders/dashed_fragment_shader.fsh \ + shaders/dashed_vertex_shader.vsh \ shaders/line_fragment_shader.fsh \ shaders/line_vertex_shader.vsh \ shaders/my_position_shader.vsh \ diff --git a/drape/shaders/dashed_fragment_shader.fsh b/drape/shaders/dashed_fragment_shader.fsh new file mode 100644 index 0000000000..9a1aefb669 --- /dev/null +++ b/drape/shaders/dashed_fragment_shader.fsh @@ -0,0 +1,14 @@ +varying vec2 v_colorTexCoord; +varying vec2 v_maskTexCoord; + +uniform sampler2D u_colorTex; +uniform sampler2D u_maskTex; +uniform float u_opacity; + +void main(void) +{ + vec4 color = texture2D(u_colorTex, v_colorTexCoord); + vec4 mask = texture2D(u_maskTex, v_maskTexCoord); + color.a = color.a * mask.a * u_opacity; + gl_FragColor = color; +} diff --git a/drape/shaders/dashed_vertex_shader.vsh b/drape/shaders/dashed_vertex_shader.vsh new file mode 100644 index 0000000000..841b05c998 --- /dev/null +++ b/drape/shaders/dashed_vertex_shader.vsh @@ -0,0 +1,26 @@ +attribute vec3 a_position; +attribute vec2 a_normal; +attribute vec2 a_colorTexCoord; +attribute vec2 a_maskTexCoord; + +uniform mat4 modelView; +uniform mat4 projection; + +varying vec2 v_colorTexCoord; +varying vec2 v_maskTexCoord; + +void main(void) +{ + float halfWidth = length(a_normal); + vec2 transformedAxisPos = (vec4(a_position.xy, 0.0, 1.0) * modelView).xy; + if (halfWidth != 0.0) + { + vec4 glbShiftPos = vec4(a_position.xy + a_normal, 0.0, 1.0); + vec2 shiftPos = (glbShiftPos * modelView).xy; + transformedAxisPos = transformedAxisPos + normalize(shiftPos - transformedAxisPos) * halfWidth; + } + + v_colorTexCoord = a_colorTexCoord; + v_maskTexCoord = a_maskTexCoord; + gl_Position = vec4(transformedAxisPos, a_position.z, 1.0) * projection; +} diff --git a/drape/shaders/line_fragment_shader.fsh b/drape/shaders/line_fragment_shader.fsh index 785d84ee00..0a8f31cf80 100644 --- a/drape/shaders/line_fragment_shader.fsh +++ b/drape/shaders/line_fragment_shader.fsh @@ -1,16 +1,10 @@ varying vec2 v_colorTexCoord; -varying vec2 v_maskTexCoord; uniform sampler2D u_colorTex; -uniform sampler2D u_maskTex; uniform float u_opacity; void main(void) { - float mask = texture2D(u_maskTex, v_maskTexCoord).a; - if (mask < 0.1) - discard; - vec4 color = texture2D(u_colorTex, v_colorTexCoord); color.a *= u_opacity; gl_FragColor = color; diff --git a/drape/shaders/line_vertex_shader.vsh b/drape/shaders/line_vertex_shader.vsh index 841b05c998..565651a566 100644 --- a/drape/shaders/line_vertex_shader.vsh +++ b/drape/shaders/line_vertex_shader.vsh @@ -1,7 +1,6 @@ attribute vec3 a_position; attribute vec2 a_normal; attribute vec2 a_colorTexCoord; -attribute vec2 a_maskTexCoord; uniform mat4 modelView; uniform mat4 projection; @@ -21,6 +20,5 @@ void main(void) } v_colorTexCoord = a_colorTexCoord; - v_maskTexCoord = a_maskTexCoord; gl_Position = vec4(transformedAxisPos, a_position.z, 1.0) * projection; } diff --git a/drape/shaders/shader_index.txt b/drape/shaders/shader_index.txt index 5a89f758b4..d4986ad751 100644 --- a/drape/shaders/shader_index.txt +++ b/drape/shaders/shader_index.txt @@ -1,5 +1,6 @@ LINE_PROGRAM line_vertex_shader.vsh line_fragment_shader.fsh TEXTURING_PROGRAM texturing_vertex_shader.vsh texturing_fragment_shader.fsh +DASHED_LINE_PROGRAM dashed_vertex_shader.vsh dashed_fragment_shader.fsh TEXT_PROGRAM text_vertex_shader.vsh text_fragment_shader.fsh COMPASS_PROGRAM compass_vertex_shader.vsh texturing_fragment_shader.fsh RULER_PROGRAM ruler_vertex_shader.vsh texturing_fragment_shader.fsh diff --git a/drape/shaders/texturing_fragment_shader.fsh b/drape/shaders/texturing_fragment_shader.fsh index 8cce8ee43e..1f70af3dca 100644 --- a/drape/shaders/texturing_fragment_shader.fsh +++ b/drape/shaders/texturing_fragment_shader.fsh @@ -6,9 +6,6 @@ varying vec2 v_colorTexCoords; void main(void) { vec4 finalColor = texture2D(u_colorTex, v_colorTexCoords); - if (finalColor.a < 0.1) - discard; - finalColor.a *= u_opacity; gl_FragColor = finalColor; } diff --git a/drape/utils/vertex_decl.cpp b/drape/utils/vertex_decl.cpp index 67627c6860..55992caf5d 100644 --- a/drape/utils/vertex_decl.cpp +++ b/drape/utils/vertex_decl.cpp @@ -12,6 +12,7 @@ enum VertexType TextStatic, TextDynamic, Line, + DashedLine, Route, TypeCount }; @@ -30,121 +31,64 @@ dp::BindingInfo SolidTexturingBindingInit() sizeof(SolidTexturingVertex::TNormal) + sizeof(SolidTexturingVertex::TTexCoord)), ""); - dp::BindingInfo info(3); + dp::BindingFiller filler(3); + filler.FillDecl("a_position"); + filler.FillDecl("a_normal"); + filler.FillDecl("a_colorTexCoords"); - dp::BindingDecl & posDecl = info.GetBindingDecl(0); - posDecl.m_attributeName = "a_position"; - posDecl.m_componentCount = glsl::GetComponentCount(); - posDecl.m_componentType = gl_const::GLFloatType; - posDecl.m_offset = 0; - posDecl.m_stride = sizeof(SolidTexturingVertex); - - dp::BindingDecl & normalDecl = info.GetBindingDecl(1); - normalDecl.m_attributeName = "a_normal"; - normalDecl.m_componentCount = glsl::GetComponentCount(); - normalDecl.m_componentType = gl_const::GLFloatType; - normalDecl.m_offset = sizeof(SolidTexturingVertex::TPosition); - normalDecl.m_stride = posDecl.m_stride; - - dp::BindingDecl & colorTexCoordDecl = info.GetBindingDecl(2); - colorTexCoordDecl.m_attributeName = "a_colorTexCoords"; - colorTexCoordDecl.m_componentCount = glsl::GetComponentCount(); - colorTexCoordDecl.m_componentType = gl_const::GLFloatType; - colorTexCoordDecl.m_offset = normalDecl.m_offset + sizeof(SolidTexturingVertex::TNormal); - colorTexCoordDecl.m_stride = posDecl.m_stride; - - return info; + return filler.m_info; } dp::BindingInfo TextStaticBindingInit() { static_assert(sizeof(TextStaticVertex) == (sizeof(TextStaticVertex::TPosition) + 3 * sizeof(TextStaticVertex::TTexCoord)), ""); - dp::BindingInfo info(4); - dp::BindingDecl & posDecl = info.GetBindingDecl(0); - posDecl.m_attributeName = "a_position"; - posDecl.m_componentCount = glsl::GetComponentCount(); - posDecl.m_componentType = gl_const::GLFloatType; - posDecl.m_offset = 0; - posDecl.m_stride = sizeof(TextStaticVertex); + dp::BindingFiller filler(4); + filler.FillDecl("a_position"); + filler.FillDecl("a_colorTexCoord"); + filler.FillDecl("a_outlineColorTexCoord"); + filler.FillDecl("a_maskTexCoord"); - dp::BindingDecl & colorDecl = info.GetBindingDecl(1); - colorDecl.m_attributeName = "a_colorTexCoord"; - colorDecl.m_componentCount = glsl::GetComponentCount(); - colorDecl.m_componentType = gl_const::GLFloatType; - colorDecl.m_offset = sizeof(TextStaticVertex::TPosition); - colorDecl.m_stride = posDecl.m_stride; - - dp::BindingDecl & outlineDecl = info.GetBindingDecl(2); - outlineDecl.m_attributeName = "a_outlineColorTexCoord"; - outlineDecl.m_componentCount = glsl::GetComponentCount(); - outlineDecl.m_componentType = gl_const::GLFloatType; - outlineDecl.m_offset = colorDecl.m_offset + sizeof(TextStaticVertex::TTexCoord); - outlineDecl.m_stride = posDecl.m_stride; - - dp::BindingDecl & maskDecl = info.GetBindingDecl(3); - maskDecl.m_attributeName = "a_maskTexCoord"; - maskDecl.m_componentCount = glsl::GetComponentCount(); - maskDecl.m_componentType = gl_const::GLFloatType; - maskDecl.m_offset = outlineDecl.m_offset + sizeof(TextStaticVertex::TTexCoord); - maskDecl.m_stride = posDecl.m_stride; - - return info; + return filler.m_info; } dp::BindingInfo TextDynamicBindingInit() { static_assert(sizeof(TextDynamicVertex) == sizeof(TextDynamicVertex::TNormal), ""); - dp::BindingInfo info(1, TextDynamicVertex::GetDynamicStreamID()); - dp::BindingDecl & decl = info.GetBindingDecl(0); - decl.m_attributeName = "a_normal"; - decl.m_componentCount = glsl::GetComponentCount(); - decl.m_componentType = gl_const::GLFloatType; - decl.m_offset = 0; - decl.m_stride = sizeof(TextDynamicVertex); + dp::BindingFiller filler(1, TextDynamicVertex::GetDynamicStreamID()); + filler.FillDecl("a_normal"); - return info; + return filler.m_info; } dp::BindingInfo LineBindingInit() { static_assert(sizeof(LineVertex) == sizeof(LineVertex::TPosition) + sizeof(LineVertex::TNormal) + - 2 * sizeof(LineVertex::TTexCoord), ""); - dp::BindingInfo info(4); -> + sizeof(LineVertex::TTexCoord), ""); + dp::BindingFiller filler(3); + filler.FillDecl("a_position"); + filler.FillDecl("a_normal"); + filler.FillDecl("a_colorTexCoord"); - dp::BindingDecl & posDecl = info.GetBindingDecl(0); - posDecl.m_attributeName = "a_position"; - posDecl.m_componentCount = glsl::GetComponentCount(); - posDecl.m_componentType = gl_const::GLFloatType; - posDecl.m_offset = 0; - posDecl.m_stride = sizeof(LineVertex); + return filler.m_info; +} - dp::BindingDecl & normalDecl = info.GetBindingDecl(1); - normalDecl.m_attributeName = "a_normal"; - normalDecl.m_componentCount = glsl::GetComponentCount(); - normalDecl.m_componentType = gl_const::GLFloatType; - normalDecl.m_offset = posDecl.m_offset + sizeof(LineVertex::TPosition); - normalDecl.m_stride = posDecl.m_stride; +dp::BindingInfo DashedLineBindingInit() +{ + static_assert(sizeof(DashedLineVertex) == sizeof(DashedLineVertex::TPosition) + + sizeof(DashedLineVertex::TNormal) + + 2 * sizeof(DashedLineVertex::TTexCoord), ""); - dp::BindingDecl & colorDecl = info.GetBindingDecl(2); - colorDecl.m_attributeName = "a_colorTexCoord"; - colorDecl.m_componentCount = glsl::GetComponentCount(); - colorDecl.m_componentType = gl_const::GLFloatType; - colorDecl.m_offset = normalDecl.m_offset + sizeof(LineVertex::TNormal); - colorDecl.m_stride = posDecl.m_stride; + dp::BindingFiller filler(4); + filler.FillDecl("a_position"); + filler.FillDecl("a_normal"); + filler.FillDecl("a_colorTexCoord"); + filler.FillDecl("a_maskTexCoord"); - dp::BindingDecl & maskDecl = info.GetBindingDecl(3); - maskDecl.m_attributeName = "a_maskTexCoord"; - maskDecl.m_componentCount = glsl::GetComponentCount(); - maskDecl.m_componentType = gl_const::GLFloatType; - maskDecl.m_offset = colorDecl.m_offset + sizeof(LineVertex::TTexCoord); - maskDecl.m_stride = posDecl.m_stride; - - return info; + return filler.m_info; } dp::BindingInfo RouteBindingInit() @@ -152,30 +96,13 @@ dp::BindingInfo RouteBindingInit() STATIC_ASSERT(sizeof(RouteVertex) == sizeof(RouteVertex::TPosition) + sizeof(RouteVertex::TNormal) + sizeof(RouteVertex::TLength)); - dp::BindingInfo info(3); - dp::BindingDecl & posDecl = info.GetBindingDecl(0); - posDecl.m_attributeName = "a_position"; - posDecl.m_componentCount = glsl::GetComponentCount(); - posDecl.m_componentType = gl_const::GLFloatType; - posDecl.m_offset = 0; - posDecl.m_stride = sizeof(RouteVertex); + dp::BindingFiller filler(3); + filler.FillDecl("a_position"); + filler.FillDecl("a_normal"); + filler.FillDecl("a_length"); - dp::BindingDecl & normalDecl = info.GetBindingDecl(1); - normalDecl.m_attributeName = "a_normal"; - normalDecl.m_componentCount = glsl::GetComponentCount(); - normalDecl.m_componentType = gl_const::GLFloatType; - 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; + return filler.m_info; } BindingNode g_bindingNodes[TypeCount]; @@ -185,6 +112,7 @@ TInitFunction g_initFunctions[TypeCount] = &TextStaticBindingInit, &TextDynamicBindingInit, &LineBindingInit, + &DashedLineBindingInit, &RouteBindingInit }; @@ -268,16 +196,13 @@ LineVertex::LineVertex() : m_position(0.0, 0.0, 0.0) , m_normal(0.0, 0.0) , m_colorTexCoord(0.0, 0.0) - , m_maskTexCoord(0.0, 0.0) { } -LineVertex::LineVertex(TPosition const & position, TNormal const & normal, - TTexCoord const & color, TTexCoord const & mask) +LineVertex::LineVertex(TPosition const & position, TNormal const & normal, TTexCoord const & color) : m_position(position) , m_normal(normal) , m_colorTexCoord(color) - , m_maskTexCoord(mask) { } @@ -286,6 +211,23 @@ dp::BindingInfo const & LineVertex::GetBindingInfo() return GetBinding(Line); } +DashedLineVertex::DashedLineVertex() + : m_maskTexCoord(0.0, 0.0) +{ +} + +DashedLineVertex::DashedLineVertex(TPosition const & position, TNormal const & normal, + TTexCoord const & color, TTexCoord const & mask) + : LineVertex(position, normal, color) + , m_maskTexCoord(mask) +{ +} + +dp::BindingInfo const & DashedLineVertex::GetBindingInfo() +{ + return GetBinding(DashedLine); +} + RouteVertex::RouteVertex() : m_position(0.0, 0.0, 0.0) , m_normal(0.0, 0.0) diff --git a/drape/utils/vertex_decl.hpp b/drape/utils/vertex_decl.hpp index bd689cfd6a..6840dddcae 100644 --- a/drape/utils/vertex_decl.hpp +++ b/drape/utils/vertex_decl.hpp @@ -62,12 +62,21 @@ typedef buffer_vector TTextDynamicVertexBuffer; struct LineVertex : BaseVertex { LineVertex(); - LineVertex(TPosition const & position, TNormal const & normal, - TTexCoord const & color, TTexCoord const & mask); + LineVertex(TPosition const & position, TNormal const & normal, TTexCoord const & color); TPosition m_position; TNormal m_normal; TTexCoord m_colorTexCoord; + + static dp::BindingInfo const & GetBindingInfo(); +}; + +struct DashedLineVertex : LineVertex +{ + DashedLineVertex(); + DashedLineVertex(TPosition const & position, TNormal const & normal, + TTexCoord const & color, TTexCoord const & mask); + TTexCoord m_maskTexCoord; static dp::BindingInfo const & GetBindingInfo(); diff --git a/drape_frontend/frontend_renderer.cpp b/drape_frontend/frontend_renderer.cpp index bbbb1bcd31..8c5f4a359e 100755 --- a/drape_frontend/frontend_renderer.cpp +++ b/drape_frontend/frontend_renderer.cpp @@ -751,6 +751,7 @@ void FrontendRenderer::Routine::Do() context->setDefaultFramebuffer(); bool const hasAsyncRoutines = m_renderer.m_texMng->UpdateDynamicTextures(); m_renderer.RenderScene(modelView); + GLFunctions::glFlush(); bool const animActive = InterpolationHolder::Instance().Advance(frameTime); modelView = m_renderer.UpdateScene(viewChanged); diff --git a/drape_frontend/line_shape.cpp b/drape_frontend/line_shape.cpp index 8ba6ceaab3..4fb588404c 100644 --- a/drape_frontend/line_shape.cpp +++ b/drape_frontend/line_shape.cpp @@ -18,55 +18,206 @@ namespace df namespace { - using LV = gpu::LineVertex; - using TGeometryBuffer = buffer_vector; - class TextureCoordGenerator +class TextureCoordGenerator +{ +public: + TextureCoordGenerator(dp::TextureManager::StippleRegion const & region, float const baseGtoPScale) + : m_region(region) + , m_baseGtoPScale(baseGtoPScale) + , m_maskLength(static_cast(m_region.GetMaskPixelLength())) { - public: - TextureCoordGenerator(float const baseGtoPScale) - : m_baseGtoPScale(baseGtoPScale) + } + + float GetUvOffsetByDistance(float distance) const + { + return (distance * m_baseGtoPScale / m_maskLength); + } + + glsl::vec2 GetTexCoordsByDistance(float distance) const + { + float normalizedOffset = min(GetUvOffsetByDistance(distance), 1.0f); + return GetTexCoords(normalizedOffset); + } + + glsl::vec2 GetTexCoords(float normalizedOffset) const + { + m2::RectF const & texRect = m_region.GetTexRect(); + return glsl::vec2(texRect.minX() + normalizedOffset * texRect.SizeX(), texRect.Center().y); + } + + float GetMaskLength() const { return m_maskLength; } + + dp::TextureManager::StippleRegion const & GetRegion() + { + return m_region; + } + +private: + dp::TextureManager::StippleRegion m_region; + float const m_baseGtoPScale; + float m_maskLength = 0.0f; +}; + +template +class BaseLineBuilder +{ +public: + BaseLineBuilder(dp::TextureManager::ColorRegion const & color, float pxHalfWidth) + : m_color(color) + , m_colorCoord(glsl::ToVec2(m_color.GetTexRect().Center())) + , m_pxHalfWidth(pxHalfWidth) + { + } + + void GetTexturingInfo(float const globalLength, int & steps, float & maskSize) + { + UNUSED_VALUE(globalLength); + UNUSED_VALUE(steps); + UNUSED_VALUE(maskSize); + } + + dp::BindingInfo const & GetBindingInfo() + { + return TVertex::GetBindingInfo(); + } + + ref_ptr GetLineData() + { + return make_ref(m_geometry.data()); + } + + size_t GetLineSize() + { + return m_geometry.size(); + } + + ref_ptr GetJoinData() + { + return make_ref(m_joinGeom.data()); + } + + size_t GetJoinSize() + { + return m_joinGeom.size(); + } + + float GetHalfWidth() + { + return m_pxHalfWidth; + } + +protected: + using V = TVertex; + using TGeometryBuffer = buffer_vector; + + TGeometryBuffer m_geometry; + TGeometryBuffer m_joinGeom; + + dp::TextureManager::ColorRegion m_color; + glsl::vec2 const m_colorCoord; + float const m_pxHalfWidth; +}; + +class SolidLineBuilder : public BaseLineBuilder +{ + using TBase = BaseLineBuilder; + +public: + SolidLineBuilder(dp::TextureManager::ColorRegion const & color, float const pxHalfWidth) + : TBase(color, pxHalfWidth) + { + } + + dp::GLState GetState() + { + dp::GLState state(gpu::LINE_PROGRAM, dp::GLState::GeometryLayer); + state.SetColorTexture(m_color.GetTexture()); + return state; + } + + void SubmitVertex(LineSegment const & segment, glsl::vec3 const & pivot, + glsl::vec2 const & normal, float offsetFromStart) + { + UNUSED_VALUE(segment); + UNUSED_VALUE(offsetFromStart); + + m_geometry.emplace_back(V(pivot, m_pxHalfWidth * normal, m_colorCoord)); + } + + void SubmitJoin(glsl::vec3 const & pivot, vector const & normals) + { + size_t const trianglesCount = normals.size() / 3; + for (int j = 0; j < trianglesCount; j++) { + size_t baseIndex = 3 * j; + m_joinGeom.push_back(V(pivot, normals[baseIndex + 0], m_colorCoord)); + m_joinGeom.push_back(V(pivot, normals[baseIndex + 1], m_colorCoord)); + m_joinGeom.push_back(V(pivot, normals[baseIndex + 2], m_colorCoord)); } + } +}; - void SetRegion(dp::TextureManager::StippleRegion const & region, bool isSolid) +class DashedLineBuilder : public BaseLineBuilder +{ + using TBase = BaseLineBuilder; + +public: + DashedLineBuilder(dp::TextureManager::ColorRegion const & color, + dp::TextureManager::StippleRegion const & stipple, + float glbHalfWidth, float pxHalfWidth, float baseGtoP) + : TBase(color, pxHalfWidth) + , m_texCoordGen(stipple, baseGtoP) + , m_glbHalfWidth(glbHalfWidth) + , m_baseGtoPScale(baseGtoP) + { + } + + void GetTexturingInfo(float const globalLength, int & steps, float & maskSize) + { + float const pixelLen = globalLength * m_baseGtoPScale; + steps = static_cast((pixelLen + m_texCoordGen.GetMaskLength() - 1) / m_texCoordGen.GetMaskLength()); + maskSize = globalLength / steps; + } + + dp::GLState GetState() + { + dp::GLState state(gpu::DASHED_LINE_PROGRAM, dp::GLState::GeometryLayer); + state.SetColorTexture(m_color.GetTexture()); + state.SetMaskTexture(m_texCoordGen.GetRegion().GetTexture()); + return state; + } + + void SubmitVertex(LineSegment const & segment, glsl::vec3 const & pivot, + glsl::vec2 const & normal, float offsetFromStart) + { + float distance = GetProjectionLength(pivot.xy() + m_glbHalfWidth * normal, + segment.m_points[StartPoint], + segment.m_points[EndPoint]) - offsetFromStart; + + m_geometry.emplace_back(V(pivot, m_pxHalfWidth * normal, m_colorCoord, m_texCoordGen.GetTexCoordsByDistance(distance))); + } + + void SubmitJoin(glsl::vec3 const & pivot, vector const & normals) + { + size_t const trianglesCount = normals.size() / 3; + for (int j = 0; j < trianglesCount; j++) { - m_isSolid = isSolid; - m_region = region; - if (!m_isSolid) - m_maskLength = static_cast(m_region.GetMaskPixelLength()); + size_t baseIndex = 3 * j; + glsl::vec2 texCoord = m_texCoordGen.GetTexCoords(0.0f); + m_joinGeom.push_back(V(pivot, normals[baseIndex + 0], m_colorCoord, texCoord)); + m_joinGeom.push_back(V(pivot, normals[baseIndex + 1], m_colorCoord, texCoord)); + m_joinGeom.push_back(V(pivot, normals[baseIndex + 2], m_colorCoord, texCoord)); } + } - float GetUvOffsetByDistance(float distance) const - { - return m_isSolid ? 1.0 : (distance * m_baseGtoPScale / m_maskLength); - } +private: + TextureCoordGenerator m_texCoordGen; + float const m_glbHalfWidth; + float const m_baseGtoPScale; +}; - glsl::vec2 GetTexCoordsByDistance(float distance) const - { - float normalizedOffset = min(GetUvOffsetByDistance(distance), 1.0f); - return GetTexCoords(normalizedOffset); - } - - glsl::vec2 GetTexCoords(float normalizedOffset) const - { - m2::RectF const & texRect = m_region.GetTexRect(); - if (m_isSolid) - return glsl::ToVec2(texRect.Center()); - - return glsl::vec2(texRect.minX() + normalizedOffset * texRect.SizeX(), texRect.Center().y); - } - - float GetMaskLength() const { return m_maskLength; } - bool IsSolid() const { return m_isSolid; } - - private: - float const m_baseGtoPScale; - dp::TextureManager::StippleRegion m_region; - float m_maskLength = 0.0f; - bool m_isSolid = true; - }; -} +} // namespace LineShape::LineShape(m2::SharedSpline const & spline, LineViewParams const & params) @@ -76,58 +227,19 @@ LineShape::LineShape(m2::SharedSpline const & spline, ASSERT_GREATER(m_spline->GetPath().size(), 1, ()); } -void LineShape::Draw(ref_ptr batcher, ref_ptr textures) const +template +void LineShape::Draw(TBuilder & builder, ref_ptr batcher) const { - TGeometryBuffer geometry; - TGeometryBuffer joinsGeometry; vector const & path = m_spline->GetPath(); ASSERT(path.size() > 1, ()); - // set up uv-generator - dp::TextureManager::ColorRegion colorRegion; - textures->GetColorRegion(m_params.m_color, colorRegion); - glsl::vec2 colorCoord(glsl::ToVec2(colorRegion.GetTexRect().Center())); - - TextureCoordGenerator texCoordGen(m_params.m_baseGtoPScale); - dp::TextureManager::StippleRegion maskRegion; - if (m_params.m_pattern.empty()) - textures->GetStippleRegion(dp::TextureManager::TStipplePattern{1}, maskRegion); - else - textures->GetStippleRegion(m_params.m_pattern, maskRegion); - - texCoordGen.SetRegion(maskRegion, m_params.m_pattern.empty()); - - float const halfWidth = m_params.m_width / 2.0f; - float const glbHalfWidth = halfWidth / m_params.m_baseGtoPScale; - // skip joins generation + float const halfWidth = builder.GetHalfWidth(); float const joinsGenerationThreshold = 2.5f; bool generateJoins = true; if (halfWidth <= joinsGenerationThreshold) generateJoins = false; - auto const getLineVertex = [&](LineSegment const & segment, glsl::vec3 const & pivot, - glsl::vec2 const & normal, float offsetFromStart) - { - float distance = GetProjectionLength(pivot.xy() + glbHalfWidth * normal, - segment.m_points[StartPoint], - segment.m_points[EndPoint]) - offsetFromStart; - - return LV(pivot, halfWidth * normal, colorCoord, texCoordGen.GetTexCoordsByDistance(distance)); - }; - - auto const generateTriangles = [&](glsl::vec3 const & pivot, vector const & normals) - { - size_t const trianglesCount = normals.size() / 3; - for (int j = 0; j < trianglesCount; j++) - { - glsl::vec2 const uv = texCoordGen.GetTexCoords(0.0f); - joinsGeometry.push_back(LV(pivot, normals[3 * j], colorCoord, uv)); - joinsGeometry.push_back(LV(pivot, normals[3 * j + 1], colorCoord, uv)); - joinsGeometry.push_back(LV(pivot, normals[3 * j + 2], colorCoord, uv)); - } - }; - // constuct segments vector segments; segments.reserve(path.size() - 1); @@ -146,12 +258,7 @@ void LineShape::Draw(ref_ptr batcher, ref_ptr t float const initialGlobalLength = glsl::length(segments[i].m_points[EndPoint] - segments[i].m_points[StartPoint]); int steps = 1; float maskSize = initialGlobalLength; - if (!texCoordGen.IsSolid()) - { - float const pixelLen = initialGlobalLength * m_params.m_baseGtoPScale; - steps = static_cast((pixelLen + texCoordGen.GetMaskLength() - 1) / texCoordGen.GetMaskLength()); - maskSize = initialGlobalLength / steps; - } + builder.GetTexturingInfo(initialGlobalLength, steps, maskSize); // generate main geometry float currentSize = 0; @@ -166,10 +273,10 @@ void LineShape::Draw(ref_ptr batcher, ref_ptr t glsl::vec2 const leftNormal = GetNormal(segments[i], true /* isLeft */, BaseNormal); glsl::vec2 const rightNormal = GetNormal(segments[i], false /* isLeft */, BaseNormal); - geometry.push_back(getLineVertex(segments[i], currentStartPivot, rightNormal, offsetFromStart)); - geometry.push_back(getLineVertex(segments[i], currentStartPivot, leftNormal, offsetFromStart)); - geometry.push_back(getLineVertex(segments[i], newPivot, rightNormal, offsetFromStart)); - geometry.push_back(getLineVertex(segments[i], newPivot, leftNormal, offsetFromStart)); + builder.SubmitVertex(segments[i], currentStartPivot, rightNormal, offsetFromStart); + builder.SubmitVertex(segments[i], currentStartPivot, leftNormal, offsetFromStart); + builder.SubmitVertex(segments[i], newPivot, rightNormal, offsetFromStart); + builder.SubmitVertex(segments[i], newPivot, leftNormal, offsetFromStart); currentStartPivot = newPivot; } @@ -190,48 +297,74 @@ void LineShape::Draw(ref_ptr batcher, ref_ptr t GenerateJoinNormals(m_params.m_join, n1, n2, halfWidth, segments[i].m_hasLeftJoin[EndPoint], widthScalar, normals); - generateTriangles(glsl::vec3(segments[i].m_points[EndPoint], m_params.m_depth), normals); - } - - // generate caps - if (i == 0) - { - vector normals; - normals.reserve(24); - GenerateCapNormals(m_params.m_cap, segments[i].m_leftNormals[StartPoint], - segments[i].m_rightNormals[StartPoint], -segments[i].m_tangent, - halfWidth, true /* isStart */, normals); - - generateTriangles(glsl::vec3(segments[i].m_points[StartPoint], m_params.m_depth), normals); - } - - if (i == segments.size() - 1) - { - vector normals; - normals.reserve(24); - GenerateCapNormals(m_params.m_cap, segments[i].m_leftNormals[EndPoint], - segments[i].m_rightNormals[EndPoint], segments[i].m_tangent, - halfWidth, false /* isStart */, normals); - - generateTriangles(glsl::vec3(segments[i].m_points[EndPoint], m_params.m_depth), normals); + builder.SubmitJoin(glsl::vec3(segments[i].m_points[EndPoint], m_params.m_depth), normals); } } - dp::GLState state(gpu::LINE_PROGRAM, dp::GLState::GeometryLayer); - state.SetColorTexture(colorRegion.GetTexture()); - state.SetMaskTexture(maskRegion.GetTexture()); + vector normals; + normals.reserve(24); - dp::AttributeProvider provider(1, geometry.size()); - provider.InitStream(0, gpu::LineVertex::GetBindingInfo(), make_ref(geometry.data())); - batcher->InsertListOfStrip(state, make_ref(&provider), 4); - - if (!joinsGeometry.empty()) { - dp::AttributeProvider joinsProvider(1, joinsGeometry.size()); - joinsProvider.InitStream(0, gpu::LineVertex::GetBindingInfo(), make_ref(joinsGeometry.data())); + 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); + } + + dp::GLState state = builder.GetState(); + + dp::AttributeProvider provider(1, builder.GetLineSize()); + provider.InitStream(0, builder.GetBindingInfo(), builder.GetLineData()); + batcher->InsertListOfStrip(state, make_ref(&provider), dp::Batcher::VertexPerQuad); + + size_t joinSize = builder.GetJoinSize(); + if (joinSize > 0) + { + dp::AttributeProvider joinsProvider(1, joinSize); + joinsProvider.InitStream(0, builder.GetBindingInfo(), builder.GetJoinData()); batcher->InsertTriangleList(state, make_ref(&joinsProvider)); } } +void LineShape::Draw(ref_ptr batcher, ref_ptr textures) const +{ + dp::TextureManager::ColorRegion colorRegion; + textures->GetColorRegion(m_params.m_color, colorRegion); + float const pxHalfWidth = m_params.m_width / 2.0f; + + if (m_params.m_pattern.empty()) + { + SolidLineBuilder builder(colorRegion, pxHalfWidth); + Draw(builder, batcher); + } + else + { + dp::TextureManager::StippleRegion maskRegion; + textures->GetStippleRegion(m_params.m_pattern, maskRegion); + + float const glbHalfWidth = pxHalfWidth / m_params.m_baseGtoPScale; + + DashedLineBuilder builder(colorRegion, maskRegion, glbHalfWidth, pxHalfWidth, m_params.m_baseGtoPScale); + Draw(builder, batcher); + } +} + } // namespace df diff --git a/drape_frontend/line_shape.hpp b/drape_frontend/line_shape.hpp index ae87698c56..2e9070c65c 100644 --- a/drape_frontend/line_shape.hpp +++ b/drape_frontend/line_shape.hpp @@ -16,6 +16,10 @@ public: virtual void Draw(ref_ptr batcher, ref_ptr textures) const; +private: + template + void Draw(TBuilder & builder, ref_ptr batcher) const; + private: LineViewParams m_params; m2::SharedSpline m_spline;