diff --git a/drape/drape.pro b/drape/drape.pro index 0011b6386d..ba1f059f15 100644 --- a/drape/drape.pro +++ b/drape/drape.pro @@ -34,7 +34,8 @@ OTHER_FILES += \ shaders/ruler_vertex_shader.vsh \ shaders/shader_index.txt \ shaders/text_fragment_shader.fsh \ - shaders/text_vertex_shader.vsh \ shaders/texturing_fragment_shader.fsh \ shaders/texturing_vertex_shader.vsh \ shaders/user_mark.vsh \ + shaders/text_outlined_vertex_shader.vsh \ + shaders/text_vertex_shader.vsh \ diff --git a/drape/shaders/shader_index.txt b/drape/shaders/shader_index.txt index afb2b8034a..edeff4488f 100644 --- a/drape/shaders/shader_index.txt +++ b/drape/shaders/shader_index.txt @@ -1,3 +1,4 @@ +TEXT_OUTLINED_PROGRAM text_outlined_vertex_shader.vsh text_fragment_shader.fsh TEXT_PROGRAM text_vertex_shader.vsh text_fragment_shader.fsh AREA_PROGRAM area_vertex_shader.vsh solid_color_fragment_shader.fsh TEXTURING_PROGRAM texturing_vertex_shader.vsh texturing_fragment_shader.fsh diff --git a/drape/shaders/text_fragment_shader.fsh b/drape/shaders/text_fragment_shader.fsh index 7e9d33e713..132daeaaa1 100755 --- a/drape/shaders/text_fragment_shader.fsh +++ b/drape/shaders/text_fragment_shader.fsh @@ -1,14 +1,23 @@ -varying vec2 v_colorTexCoord; varying vec2 v_maskTexCoord; +#ifdef ENABLE_VTF +varying lowp vec4 v_color; +#else +varying vec2 v_colorTexCoord; uniform sampler2D u_colorTex; +#endif + uniform sampler2D u_maskTex; uniform float u_opacity; uniform vec2 u_contrastGamma; void main (void) { - vec4 glyphColor = texture2D(u_colorTex, v_colorTexCoord); +#ifdef ENABLE_VTF + lowp vec4 glyphColor = v_color; +#else + lowp vec4 glyphColor = texture2D(u_colorTex, v_colorTexCoord); +#endif float dist = texture2D(u_maskTex, v_maskTexCoord).a; float alpha = smoothstep(u_contrastGamma.x - u_contrastGamma.y, u_contrastGamma.x + u_contrastGamma.y, dist) * u_opacity; glyphColor.a *= alpha; diff --git a/drape/shaders/text_outlined_vertex_shader.vsh b/drape/shaders/text_outlined_vertex_shader.vsh new file mode 100755 index 0000000000..6f0c4b96b3 --- /dev/null +++ b/drape/shaders/text_outlined_vertex_shader.vsh @@ -0,0 +1,42 @@ +attribute vec4 a_position; +attribute vec2 a_normal; +attribute vec2 a_colorTexCoord; +attribute vec2 a_outlineColorTexCoord; +attribute vec2 a_maskTexCoord; + +uniform mat4 modelView; +uniform mat4 projection; +uniform float u_isOutlinePass; + +#ifdef ENABLE_VTF +uniform sampler2D u_colorTex; +varying lowp vec4 v_color; +#else +varying vec2 v_colorTexCoord; +#endif + +varying vec2 v_maskTexCoord; + +const float Zero = 0.0; +const float One = 1.0; +const float BaseDepthShift = -10.0; + +void main() +{ + float isOutline = step(0.5, u_isOutlinePass); + float notOutline = One - isOutline; + float depthShift = BaseDepthShift * isOutline; + + // Here we intentionally decrease precision of 'pos' calculation + // to eliminate jittering effect in process of billboard reconstruction. + lowp vec4 pos = (a_position + vec4(Zero, Zero, depthShift, Zero)) * modelView; + highp vec4 shiftedPos = vec4(a_normal, Zero, Zero) + pos; + gl_Position = shiftedPos * projection; + vec2 colorTexCoord = a_colorTexCoord * notOutline + a_outlineColorTexCoord * isOutline; +#ifdef ENABLE_VTF + v_color = texture2D(u_colorTex, colorTexCoord); +#else + v_colorTexCoord = colorTexCoord; +#endif + v_maskTexCoord = a_maskTexCoord; +} diff --git a/drape/shaders/text_vertex_shader.vsh b/drape/shaders/text_vertex_shader.vsh old mode 100755 new mode 100644 index 4592b4f9d7..c455044164 --- a/drape/shaders/text_vertex_shader.vsh +++ b/drape/shaders/text_vertex_shader.vsh @@ -1,31 +1,35 @@ attribute vec4 a_position; attribute vec2 a_normal; attribute vec2 a_colorTexCoord; -attribute vec2 a_outlineColorTexCoord; attribute vec2 a_maskTexCoord; uniform mat4 modelView; uniform mat4 projection; uniform float u_isOutlinePass; +#ifdef ENABLE_VTF +uniform sampler2D u_colorTex; +varying lowp vec4 v_color; +#else varying vec2 v_colorTexCoord; +#endif + varying vec2 v_maskTexCoord; const float Zero = 0.0; const float One = 1.0; -const float BaseDepthShoft = -10.0; void main() { - float isOutline = step(0.5, u_isOutlinePass); - float notOutline = One - isOutline; - float depthShift = BaseDepthShoft * isOutline; - // Here we intentionally decrease precision of 'pos' calculation // to eliminate jittering effect in process of billboard reconstruction. - lowp vec4 pos = (a_position + vec4(Zero, Zero, depthShift, Zero)) * modelView; + lowp vec4 pos = a_position * modelView; highp vec4 shiftedPos = vec4(a_normal, Zero, Zero) + pos; gl_Position = shiftedPos * projection; - v_colorTexCoord = a_colorTexCoord * notOutline + a_outlineColorTexCoord * isOutline; +#ifdef ENABLE_VTF + v_color = texture2D(u_colorTex, a_colorTexCoord); +#else + v_colorTexCoord = a_colorTexCoord; +#endif v_maskTexCoord = a_maskTexCoord; } diff --git a/drape/utils/vertex_decl.cpp b/drape/utils/vertex_decl.cpp index 7d0776f2a3..f0501bf986 100644 --- a/drape/utils/vertex_decl.cpp +++ b/drape/utils/vertex_decl.cpp @@ -11,6 +11,7 @@ enum VertexType Area, SolidTexturing, TextStatic, + TextOutlinedStatic, TextDynamic, Line, DashedLine, @@ -54,18 +55,31 @@ dp::BindingInfo SolidTexturingBindingInit() dp::BindingInfo TextStaticBindingInit() { - static_assert(sizeof(TextStaticVertex) == (sizeof(TextStaticVertex::TPosition) + - 3 * sizeof(TextStaticVertex::TTexCoord)), ""); + static_assert(sizeof(TextStaticVertex) == (sizeof(TextOutlinedStaticVertex::TPosition) + + 2 * sizeof(TextOutlinedStaticVertex::TTexCoord)), ""); - dp::BindingFiller filler(4); + dp::BindingFiller filler(3); filler.FillDecl("a_position"); filler.FillDecl("a_colorTexCoord"); - filler.FillDecl("a_outlineColorTexCoord"); filler.FillDecl("a_maskTexCoord"); return filler.m_info; } +dp::BindingInfo TextOutlinedStaticBindingInit() +{ + static_assert(sizeof(TextOutlinedStaticVertex) == (sizeof(TextOutlinedStaticVertex::TPosition) + + 3 * sizeof(TextOutlinedStaticVertex::TTexCoord)), ""); + + dp::BindingFiller filler(4); + filler.FillDecl("a_position"); + filler.FillDecl("a_colorTexCoord"); + filler.FillDecl("a_outlineColorTexCoord"); + filler.FillDecl("a_maskTexCoord"); + + return filler.m_info; +} + dp::BindingInfo TextDynamicBindingInit() { static_assert(sizeof(TextDynamicVertex) == sizeof(TextDynamicVertex::TNormal), ""); @@ -125,6 +139,7 @@ TInitFunction g_initFunctions[TypeCount] = &AreaBindingInit, &SolidTexturingBindingInit, &TextStaticBindingInit, + &TextOutlinedStaticBindingInit, &TextDynamicBindingInit, &LineBindingInit, &DashedLineBindingInit, @@ -182,7 +197,7 @@ dp::BindingInfo const & SolidTexturingVertex::GetBindingInfo() return GetBinding(SolidTexturing); } -TextStaticVertex::TextStaticVertex() +TextOutlinedStaticVertex::TextOutlinedStaticVertex() : m_position(0.0, 0.0, 0.0) , m_colorTexCoord(0.0, 0.0) , m_outlineTexCoord(0.0, 0.0) @@ -190,7 +205,7 @@ TextStaticVertex::TextStaticVertex() { } -TextStaticVertex::TextStaticVertex(TPosition const & position, TTexCoord const & colorTexCoord, +TextOutlinedStaticVertex::TextOutlinedStaticVertex(TPosition const & position, TTexCoord const & colorTexCoord, TTexCoord const & outlineTexCoord, TTexCoord const & maskTexCoord) : m_position(position) , m_colorTexCoord(colorTexCoord) @@ -199,9 +214,9 @@ TextStaticVertex::TextStaticVertex(TPosition const & position, TTexCoord const & { } -dp::BindingInfo const & TextStaticVertex::GetBindingInfo() +dp::BindingInfo const & TextOutlinedStaticVertex::GetBindingInfo() { - return GetBinding(TextStatic); + return GetBinding(TextOutlinedStatic); } TextDynamicVertex::TextDynamicVertex() @@ -279,5 +294,27 @@ dp::BindingInfo const & RouteVertex::GetBindingInfo() return GetBinding(Route); } +TextStaticVertex::TextStaticVertex() + : m_position(0.0, 0.0, 0.0) + , m_colorTexCoord(0.0, 0.0) + , m_maskTexCoord(0.0, 0.0) +{ + +} + +TextStaticVertex::TextStaticVertex(TPosition const & position, TTexCoord const & colorTexCoord, + TTexCoord const & maskTexCoord) + : m_position(position) + , m_colorTexCoord(colorTexCoord) + , m_maskTexCoord(maskTexCoord) +{ + +} + +dp::BindingInfo const & TextStaticVertex::GetBindingInfo() +{ + return GetBinding(TextStatic); +} + } //namespace gpu diff --git a/drape/utils/vertex_decl.hpp b/drape/utils/vertex_decl.hpp index 165e9fde24..3ff91e2a6e 100644 --- a/drape/utils/vertex_decl.hpp +++ b/drape/utils/vertex_decl.hpp @@ -42,9 +42,23 @@ typedef buffer_vector TSolidTexVertexBuffer; struct TextStaticVertex : BaseVertex { -public: TextStaticVertex(); - TextStaticVertex(TPosition const & position, TTexCoord const & colorTexCoord, + TextStaticVertex(TPosition const & position, TTexCoord const & colorTexCoord, TTexCoord const & maskTexCoord); + + TPosition m_position; + TTexCoord m_colorTexCoord; + TTexCoord m_maskTexCoord; + + static dp::BindingInfo const & GetBindingInfo(); +}; + +typedef buffer_vector TTextStaticVertexBuffer; + +struct TextOutlinedStaticVertex : BaseVertex +{ +public: + TextOutlinedStaticVertex(); + TextOutlinedStaticVertex(TPosition const & position, TTexCoord const & colorTexCoord, TTexCoord const & outlineTexCoord, TTexCoord const & maskTexCoord); TPosition m_position; @@ -55,7 +69,7 @@ public: static dp::BindingInfo const & GetBindingInfo(); }; -typedef buffer_vector TTextStaticVertexBuffer; +typedef buffer_vector TTextOutlinedStaticVertexBuffer; struct TextDynamicVertex : BaseVertex { diff --git a/drape/vertex_array_buffer.cpp b/drape/vertex_array_buffer.cpp index f2c6b8bd9f..1b2331da54 100644 --- a/drape/vertex_array_buffer.cpp +++ b/drape/vertex_array_buffer.cpp @@ -163,7 +163,7 @@ uint32_t VertexArrayBuffer::GetAvailableVertexCount() const TBuffersMap::const_iterator it = m_staticBuffers.begin(); uint32_t prev = it->second->GetBuffer()->GetAvailableSize(); for (; it != m_staticBuffers.end(); ++it) - ASSERT(prev == it->second->GetBuffer()->GetAvailableSize(), ()); + ASSERT_EQUAL(prev, it->second->GetBuffer()->GetAvailableSize(), ()); #endif return m_staticBuffers.begin()->second->GetBuffer()->GetAvailableSize(); diff --git a/drape_frontend/gui/gui_text.cpp b/drape_frontend/gui/gui_text.cpp index 8b80113ddb..53cffb1609 100644 --- a/drape_frontend/gui/gui_text.cpp +++ b/drape_frontend/gui/gui_text.cpp @@ -107,7 +107,7 @@ dp::BindingInfo const & StaticLabel::Vertex::GetBindingInfo() return *info.get(); } -StaticLabel::LabelResult::LabelResult() : m_state(gpu::TEXT_PROGRAM, dp::GLState::Gui) {} +StaticLabel::LabelResult::LabelResult() : m_state(gpu::TEXT_OUTLINED_PROGRAM, dp::GLState::Gui) {} char const * StaticLabel::DefaultDelim = "\n"; @@ -282,7 +282,7 @@ dp::BindingInfo const & MutableLabel::DynamicVertex::GetBindingInfo() return *info.get(); } -MutableLabel::PrecacheResult::PrecacheResult() : m_state(gpu::TEXT_PROGRAM, dp::GLState::Gui) {} +MutableLabel::PrecacheResult::PrecacheResult() : m_state(gpu::TEXT_OUTLINED_PROGRAM, dp::GLState::Gui) {} MutableLabel::MutableLabel(dp::Anchor anchor) : m_anchor(anchor) diff --git a/drape_frontend/path_text_shape.cpp b/drape_frontend/path_text_shape.cpp index cc43581112..815d5eebed 100644 --- a/drape_frontend/path_text_shape.cpp +++ b/drape_frontend/path_text_shape.cpp @@ -114,6 +114,86 @@ uint64_t PathTextShape::GetOverlayPriority() const return dp::CalculateOverlayPriority(m_params.m_minVisibleScale, m_params.m_rank, m_params.m_depth); } +void PathTextShape::DrawPathTextPlain(ref_ptr textures, + ref_ptr batcher, + unique_ptr && layout, + buffer_vector const & offsets) const +{ + dp::TextureManager::ColorRegion color; + textures->GetColorRegion(m_params.m_textFont.m_color, color); + + dp::GLState state(gpu::TEXT_PROGRAM, dp::GLState::OverlayLayer); + state.SetColorTexture(color.GetTexture()); + state.SetMaskTexture(layout->GetMaskTexture()); + + ASSERT(!offsets.empty(), ()); + gpu::TTextStaticVertexBuffer staticBuffer; + gpu::TTextDynamicVertexBuffer dynBuffer; + SharedTextLayout layoutPtr(layout.release()); + for (float offset : offsets) + { + staticBuffer.clear(); + dynBuffer.clear(); + + Spline::iterator iter = m_spline.CreateIterator(); + iter.Advance(offset); + layoutPtr->CacheStaticGeometry(glsl::vec3(glsl::ToVec2(iter.m_pos), m_params.m_depth), + color, staticBuffer); + + dynBuffer.resize(staticBuffer.size(), gpu::TextDynamicVertex(glsl::vec2(0.0, 0.0))); + + dp::AttributeProvider provider(2, staticBuffer.size()); + provider.InitStream(0, gpu::TextStaticVertex::GetBindingInfo(), make_ref(staticBuffer.data())); + provider.InitStream(1, gpu::TextDynamicVertex::GetBindingInfo(), make_ref(dynBuffer.data())); + + drape_ptr handle = make_unique_dp(m_spline, layoutPtr, offset, + GetOverlayPriority(), + textures); + batcher->InsertListOfStrip(state, make_ref(&provider), move(handle), 4); + } +} + +void PathTextShape::DrawPathTextOutlined(ref_ptr textures, + ref_ptr batcher, + unique_ptr && layout, + buffer_vector const & offsets) const +{ + dp::TextureManager::ColorRegion color; + dp::TextureManager::ColorRegion outline; + textures->GetColorRegion(m_params.m_textFont.m_color, color); + textures->GetColorRegion(m_params.m_textFont.m_outlineColor, outline); + + dp::GLState state(gpu::TEXT_OUTLINED_PROGRAM, dp::GLState::OverlayLayer); + state.SetColorTexture(color.GetTexture()); + state.SetMaskTexture(layout->GetMaskTexture()); + + ASSERT(!offsets.empty(), ()); + gpu::TTextOutlinedStaticVertexBuffer staticBuffer; + gpu::TTextDynamicVertexBuffer dynBuffer; + SharedTextLayout layoutPtr(layout.release()); + for (float offset : offsets) + { + staticBuffer.clear(); + dynBuffer.clear(); + + Spline::iterator iter = m_spline.CreateIterator(); + iter.Advance(offset); + layoutPtr->CacheStaticGeometry(glsl::vec3(glsl::ToVec2(iter.m_pos), m_params.m_depth), + color, outline, staticBuffer); + + dynBuffer.resize(staticBuffer.size(), gpu::TextDynamicVertex(glsl::vec2(0.0, 0.0))); + + dp::AttributeProvider provider(2, staticBuffer.size()); + provider.InitStream(0, gpu::TextOutlinedStaticVertex::GetBindingInfo(), make_ref(staticBuffer.data())); + provider.InitStream(1, gpu::TextDynamicVertex::GetBindingInfo(), make_ref(dynBuffer.data())); + + drape_ptr handle = make_unique_dp(m_spline, layoutPtr, offset, + GetOverlayPriority(), + textures); + batcher->InsertListOfStrip(state, make_ref(&provider), move(handle), 4); + } +} + void PathTextShape::Draw(ref_ptr batcher, ref_ptr textures) const { unique_ptr layout = make_unique(strings::MakeUniString(m_params.m_text), @@ -177,40 +257,10 @@ void PathTextShape::Draw(ref_ptr batcher, ref_ptrGetColorRegion(m_params.m_textFont.m_color, color); - textures->GetColorRegion(m_params.m_textFont.m_outlineColor, outline); - - dp::GLState state(gpu::TEXT_PROGRAM, dp::GLState::OverlayLayer); - state.SetColorTexture(color.GetTexture()); - state.SetMaskTexture(layout->GetMaskTexture()); - - ASSERT(!offsets.empty(), ()); - gpu::TTextStaticVertexBuffer staticBuffer; - gpu::TTextDynamicVertexBuffer dynBuffer; - SharedTextLayout layoutPtr(layout.release()); - for (float offset : offsets) - { - staticBuffer.clear(); - dynBuffer.clear(); - - Spline::iterator iter = m_spline.CreateIterator(); - iter.Advance(offset); - layoutPtr->CacheStaticGeometry(glsl::vec3(glsl::ToVec2(iter.m_pos), m_params.m_depth), - color, outline, staticBuffer); - - dynBuffer.resize(staticBuffer.size(), gpu::TextDynamicVertex(glsl::vec2(0.0, 0.0))); - - dp::AttributeProvider provider(2, staticBuffer.size()); - provider.InitStream(0, gpu::TextStaticVertex::GetBindingInfo(), make_ref(staticBuffer.data())); - provider.InitStream(1, gpu::TextDynamicVertex::GetBindingInfo(), make_ref(dynBuffer.data())); - - drape_ptr handle = make_unique_dp(m_spline, layoutPtr, offset, - GetOverlayPriority(), - textures); - batcher->InsertListOfStrip(state, make_ref(&provider), move(handle), 4); - } + if (m_params.m_textFont.m_outlineColor == dp::Color::Transparent()) + DrawPathTextPlain(textures, batcher, move(layout), offsets); + else + DrawPathTextOutlined(textures, batcher, move(layout), offsets); } } diff --git a/drape_frontend/path_text_shape.hpp b/drape_frontend/path_text_shape.hpp index cf1806568d..ea7c0951c4 100644 --- a/drape_frontend/path_text_shape.hpp +++ b/drape_frontend/path_text_shape.hpp @@ -8,6 +8,7 @@ namespace df { +class PathTextLayout; class PathTextShape : public MapShape { public: @@ -18,6 +19,15 @@ public: private: uint64_t GetOverlayPriority() const; + void DrawPathTextPlain(ref_ptr textures, + ref_ptr batcher, + unique_ptr && layout, + buffer_vector const & offests) const; + void DrawPathTextOutlined(ref_ptr textures, + ref_ptr batcher, + unique_ptr && layout, + buffer_vector const & offsets) const; + m2::SharedSpline m_spline; PathTextViewParams m_params; }; diff --git a/drape_frontend/render_group.cpp b/drape_frontend/render_group.cpp index cd1739fcb5..9e95a1a0a5 100755 --- a/drape_frontend/render_group.cpp +++ b/drape_frontend/render_group.cpp @@ -73,10 +73,10 @@ void RenderGroup::Render(ScreenBase const & screen) { BaseRenderGroup::Render(screen); - if (m_state.GetProgramIndex() == gpu::TEXT_PROGRAM) + auto const & params = df::VisualParams::Instance().GetGlyphVisualParams(); + int programIndex = m_state.GetProgramIndex(); + if (programIndex == gpu::TEXT_OUTLINED_PROGRAM) { - auto const & params = df::VisualParams::Instance().GetGlyphVisualParams(); - m_uniforms.SetFloatValue("u_contrastGamma", params.m_outlineContrast, params.m_outlineGamma); m_uniforms.SetFloatValue("u_isOutlinePass", 1.0f); dp::ApplyUniforms(m_uniforms, m_shader); @@ -90,6 +90,13 @@ void RenderGroup::Render(ScreenBase const & screen) for(auto & renderBucket : m_renderBuckets) renderBucket->Render(screen); } + else if(programIndex == gpu::TEXT_PROGRAM) + { + m_uniforms.SetFloatValue("u_contrastGamma", params.m_contrast, params.m_gamma); + dp::ApplyUniforms(m_uniforms, m_shader); + for(auto & renderBucket : m_renderBuckets) + renderBucket->Render(screen); + } else { dp::ApplyUniforms(m_uniforms, m_shader); diff --git a/drape_frontend/text_handle.cpp b/drape_frontend/text_handle.cpp index a095ceb879..8bd55a03b7 100644 --- a/drape_frontend/text_handle.cpp +++ b/drape_frontend/text_handle.cpp @@ -67,7 +67,7 @@ bool TextHandle::Update(ScreenBase const & screen) bool TextHandle::IndexesRequired() const { - return false; + return true; } void TextHandle::SetForceUpdateNormals(bool forceUpdate) const diff --git a/drape_frontend/text_layout.cpp b/drape_frontend/text_layout.cpp index ec5f6da827..c2f96ef02e 100644 --- a/drape_frontend/text_layout.cpp +++ b/drape_frontend/text_layout.cpp @@ -22,11 +22,9 @@ class TextGeometryGenerator public: TextGeometryGenerator(glsl::vec3 const & pivot, dp::TextureManager::ColorRegion const & color, - dp::TextureManager::ColorRegion const & outline, gpu::TTextStaticVertexBuffer & buffer) : m_pivot(pivot) , m_colorCoord(glsl::ToVec2(color.GetTexRect().Center())) - , m_outlineCoord(glsl::ToVec2(outline.GetTexRect().Center())) , m_buffer(buffer) { } @@ -34,16 +32,15 @@ public: void operator() (dp::TextureManager::GlyphRegion const & glyph) { m2::RectF const & mask = glyph.GetTexRect(); - m_buffer.push_back(gpu::TextStaticVertex(m_pivot, m_colorCoord, m_outlineCoord, glsl::ToVec2(mask.LeftTop()))); - m_buffer.push_back(gpu::TextStaticVertex(m_pivot, m_colorCoord, m_outlineCoord, glsl::ToVec2(mask.LeftBottom()))); - m_buffer.push_back(gpu::TextStaticVertex(m_pivot, m_colorCoord, m_outlineCoord, glsl::ToVec2(mask.RightTop()))); - m_buffer.push_back(gpu::TextStaticVertex(m_pivot, m_colorCoord, m_outlineCoord, glsl::ToVec2(mask.RightBottom()))); + m_buffer.push_back(gpu::TextStaticVertex(m_pivot, m_colorCoord, glsl::ToVec2(mask.LeftTop()))); + m_buffer.push_back(gpu::TextStaticVertex(m_pivot, m_colorCoord, glsl::ToVec2(mask.LeftBottom()))); + m_buffer.push_back(gpu::TextStaticVertex(m_pivot, m_colorCoord, glsl::ToVec2(mask.RightTop()))); + m_buffer.push_back(gpu::TextStaticVertex(m_pivot, m_colorCoord, glsl::ToVec2(mask.RightBottom()))); } protected: glsl::vec3 const & m_pivot; glsl::vec2 m_colorCoord; - glsl::vec2 m_outlineCoord; gpu::TTextStaticVertexBuffer & m_buffer; }; @@ -54,9 +51,89 @@ public: StraigthTextGeometryGenerator(glsl::vec3 const & pivot, glsl::vec2 const & pixelOffset, float textRatio, dp::TextureManager::ColorRegion const & color, - dp::TextureManager::ColorRegion const & outline, gpu::TTextStaticVertexBuffer & staticBuffer, gpu::TTextDynamicVertexBuffer & dynBuffer) + : TBase(pivot, color, staticBuffer) + , m_penPosition(pixelOffset) + , m_buffer(dynBuffer) + , m_textRatio(textRatio) + { + } + + void operator()(dp::TextureManager::GlyphRegion const & glyph) + { + if (!glyph.IsValid()) + return; + m2::PointF pixelSize = m2::PointF(glyph.GetPixelSize()) * m_textRatio; + + float const xOffset = glyph.GetOffsetX() * m_textRatio; + float const yOffset = glyph.GetOffsetY() * m_textRatio; + + float const upVector = -static_cast(pixelSize.y) - yOffset; + float const bottomVector = -yOffset; + + if (m_isFirstGlyph) + { + m_isFirstGlyph = false; + m_penPosition += glsl::vec2(-xOffset, 0.0f); + } + + m_buffer.push_back(gpu::TextDynamicVertex(m_penPosition + glsl::vec2(xOffset, bottomVector))); + m_buffer.push_back(gpu::TextDynamicVertex(m_penPosition + glsl::vec2(xOffset, upVector))); + m_buffer.push_back(gpu::TextDynamicVertex(m_penPosition + glsl::vec2(pixelSize.x + xOffset, bottomVector))); + m_buffer.push_back(gpu::TextDynamicVertex(m_penPosition + glsl::vec2(pixelSize.x + xOffset, upVector))); + m_penPosition += glsl::vec2(glyph.GetAdvanceX() * m_textRatio, glyph.GetAdvanceY() * m_textRatio); + + TBase::operator()(glyph); + } + +private: + glsl::vec2 m_penPosition; + gpu::TTextDynamicVertexBuffer & m_buffer; + float m_textRatio = 0.0f; + bool m_isFirstGlyph = true; +}; + +class TextOutlinedGeometryGenerator +{ +public: + TextOutlinedGeometryGenerator(glsl::vec3 const & pivot, + dp::TextureManager::ColorRegion const & color, + dp::TextureManager::ColorRegion const & outline, + gpu::TTextOutlinedStaticVertexBuffer & buffer) + : m_pivot(pivot) + , m_colorCoord(glsl::ToVec2(color.GetTexRect().Center())) + , m_outlineCoord(glsl::ToVec2(outline.GetTexRect().Center())) + , m_buffer(buffer) + { + } + + void operator() (dp::TextureManager::GlyphRegion const & glyph) + { + m2::RectF const & mask = glyph.GetTexRect(); + m_buffer.push_back(gpu::TextOutlinedStaticVertex(m_pivot, m_colorCoord, m_outlineCoord, glsl::ToVec2(mask.LeftTop()))); + m_buffer.push_back(gpu::TextOutlinedStaticVertex(m_pivot, m_colorCoord, m_outlineCoord, glsl::ToVec2(mask.LeftBottom()))); + m_buffer.push_back(gpu::TextOutlinedStaticVertex(m_pivot, m_colorCoord, m_outlineCoord, glsl::ToVec2(mask.RightTop()))); + m_buffer.push_back(gpu::TextOutlinedStaticVertex(m_pivot, m_colorCoord, m_outlineCoord, glsl::ToVec2(mask.RightBottom()))); + } + +protected: + glsl::vec3 const & m_pivot; + glsl::vec2 m_colorCoord; + glsl::vec2 m_outlineCoord; + gpu::TTextOutlinedStaticVertexBuffer & m_buffer; +}; + +class StraigthTextOutlinedGeometryGenerator : public TextOutlinedGeometryGenerator +{ + typedef TextOutlinedGeometryGenerator TBase; +public: + StraigthTextOutlinedGeometryGenerator(glsl::vec3 const & pivot, glsl::vec2 const & pixelOffset, + float textRatio, + dp::TextureManager::ColorRegion const & color, + dp::TextureManager::ColorRegion const & outline, + gpu::TTextOutlinedStaticVertexBuffer & staticBuffer, + gpu::TTextDynamicVertexBuffer & dynBuffer) : TBase(pivot, color, outline, staticBuffer) , m_penPosition(pixelOffset) , m_buffer(dynBuffer) @@ -324,6 +401,24 @@ StraightTextLayout::StraightTextLayout(strings::UniString const & text, float fo void StraightTextLayout::Cache(glm::vec3 const & pivot, glm::vec2 const & pixelOffset, dp::TextureManager::ColorRegion const & colorRegion, dp::TextureManager::ColorRegion const & outlineRegion, + gpu::TTextOutlinedStaticVertexBuffer & staticBuffer, + gpu::TTextDynamicVertexBuffer & dynamicBuffer) const +{ + size_t beginOffset = 0; + for (pair const & node : m_offsets) + { + size_t endOffset = node.first; + StraigthTextOutlinedGeometryGenerator generator(pivot, pixelOffset + node.second, m_textSizeRatio, + colorRegion, outlineRegion, staticBuffer, dynamicBuffer); + for (size_t index = beginOffset; index < endOffset && index < m_metrics.size(); ++index) + generator(m_metrics[index]); + + beginOffset = endOffset; + } +} + +void StraightTextLayout::Cache(glm::vec3 const & pivot, glm::vec2 const & pixelOffset, + dp::TextureManager::ColorRegion const & color, gpu::TTextStaticVertexBuffer & staticBuffer, gpu::TTextDynamicVertexBuffer & dynamicBuffer) const { @@ -332,7 +427,7 @@ void StraightTextLayout::Cache(glm::vec3 const & pivot, glm::vec2 const & pixelO { size_t endOffset = node.first; StraigthTextGeometryGenerator generator(pivot, pixelOffset + node.second, m_textSizeRatio, - colorRegion, outlineRegion, staticBuffer, dynamicBuffer); + color, staticBuffer, dynamicBuffer); for (size_t index = beginOffset; index < endOffset && index < m_metrics.size(); ++index) generator(m_metrics[index]); @@ -349,9 +444,16 @@ PathTextLayout::PathTextLayout(strings::UniString const & text, float fontSize, void PathTextLayout::CacheStaticGeometry(glm::vec3 const & pivot, dp::TextureManager::ColorRegion const & colorRegion, dp::TextureManager::ColorRegion const & outlineRegion, + gpu::TTextOutlinedStaticVertexBuffer & staticBuffer) const +{ + TextOutlinedGeometryGenerator gen(pivot, colorRegion, outlineRegion, staticBuffer); + for_each(m_metrics.begin(), m_metrics.end(), gen); +} + +void PathTextLayout::CacheStaticGeometry(glm::vec3 const & pivot, dp::TextureManager::ColorRegion const & colorRegion, gpu::TTextStaticVertexBuffer & staticBuffer) const { - TextGeometryGenerator gen(pivot, colorRegion, outlineRegion, staticBuffer); + TextGeometryGenerator gen(pivot, colorRegion, staticBuffer); for_each(m_metrics.begin(), m_metrics.end(), gen); } diff --git a/drape_frontend/text_layout.hpp b/drape_frontend/text_layout.hpp index 2d596695e7..28407b88bc 100644 --- a/drape_frontend/text_layout.hpp +++ b/drape_frontend/text_layout.hpp @@ -65,6 +65,11 @@ public: void Cache(glsl::vec3 const & pivot, glsl::vec2 const & pixelOffset, dp::TextureManager::ColorRegion const & colorRegion, dp::TextureManager::ColorRegion const & outlineRegion, + gpu::TTextOutlinedStaticVertexBuffer & staticBuffer, + gpu::TTextDynamicVertexBuffer & dynamicBuffer) const; + + void Cache(glsl::vec3 const & pivot, glsl::vec2 const & pixelOffset, + dp::TextureManager::ColorRegion const & color, gpu::TTextStaticVertexBuffer & staticBuffer, gpu::TTextDynamicVertexBuffer & dynamicBuffer) const; @@ -85,6 +90,10 @@ public: void CacheStaticGeometry(glsl::vec3 const & pivot, dp::TextureManager::ColorRegion const & colorRegion, dp::TextureManager::ColorRegion const & outlineRegion, + gpu::TTextOutlinedStaticVertexBuffer & staticBuffer) const; + + void CacheStaticGeometry(glsl::vec3 const & pivot, + dp::TextureManager::ColorRegion const & colorRegion, gpu::TTextStaticVertexBuffer & staticBuffer) const; bool CacheDynamicGeometry(m2::Spline::iterator const & iter, diff --git a/drape_frontend/text_shape.cpp b/drape_frontend/text_shape.cpp index cd6d3b9121..854b862550 100644 --- a/drape_frontend/text_shape.cpp +++ b/drape_frontend/text_shape.cpp @@ -126,8 +126,26 @@ void TextShape::Draw(ref_ptr batcher, ref_ptr t } void TextShape::DrawSubString(StraightTextLayout const & layout, dp::FontDecl const & font, - glsl::vec2 const & baseOffset, ref_ptr batcher, - ref_ptr textures, bool isPrimary, bool isOptional) const + glm::vec2 const & baseOffset, ref_ptr batcher, + ref_ptr textures, + bool isPrimary, bool isOptional) const +{ + dp::Color outlineColor = isPrimary ? m_params.m_primaryTextFont.m_outlineColor + : m_params.m_secondaryTextFont.m_outlineColor; + + if (outlineColor == dp::Color::Transparent()) + { + DrawSubStringPlain(layout, font, baseOffset,batcher, textures, isPrimary, isOptional); + } + else + { + DrawSubStringOutlined(layout, font, baseOffset, batcher, textures, isPrimary, isOptional); + } +} + +void TextShape::DrawSubStringPlain(StraightTextLayout const & layout, dp::FontDecl const & font, + glm::vec2 const & baseOffset, ref_ptr batcher, + ref_ptr textures, bool isPrimary, bool isOptional) const { gpu::TTextStaticVertexBuffer staticBuffer; gpu::TTextDynamicVertexBuffer dynamicBuffer; @@ -137,10 +155,7 @@ void TextShape::DrawSubString(StraightTextLayout const & layout, dp::FontDecl co textures->GetColorRegion(font.m_outlineColor, outline); layout.Cache(glsl::vec3(glsl::ToVec2(m_basePoint), m_params.m_depth), - baseOffset, - color, outline, - staticBuffer, - dynamicBuffer); + baseOffset, color, staticBuffer, dynamicBuffer); dp::GLState state(gpu::TEXT_PROGRAM, dp::GLState::OverlayLayer); ASSERT(color.GetTexture() == outline.GetTexture(), ()); @@ -170,6 +185,49 @@ void TextShape::DrawSubString(StraightTextLayout const & layout, dp::FontDecl co batcher->InsertListOfStrip(state, make_ref(&provider), move(handle), 4); } +void TextShape::DrawSubStringOutlined(StraightTextLayout const & layout, dp::FontDecl const & font, + glm::vec2 const & baseOffset, ref_ptr batcher, + ref_ptr textures, bool isPrimary, bool isOptional) const +{ + gpu::TTextOutlinedStaticVertexBuffer staticBuffer; + gpu::TTextDynamicVertexBuffer dynamicBuffer; + + dp::TextureManager::ColorRegion color, outline; + textures->GetColorRegion(font.m_color, color); + textures->GetColorRegion(font.m_outlineColor, outline); + + layout.Cache(glsl::vec3(glsl::ToVec2(m_basePoint), m_params.m_depth), + baseOffset, color, outline, staticBuffer, dynamicBuffer); + + dp::GLState state(gpu::TEXT_OUTLINED_PROGRAM, dp::GLState::OverlayLayer); + ASSERT(color.GetTexture() == outline.GetTexture(), ()); + state.SetColorTexture(color.GetTexture()); + state.SetMaskTexture(layout.GetMaskTexture()); + + gpu::TTextDynamicVertexBuffer initialDynBuffer(dynamicBuffer.size()); + + m2::PointU const & pixelSize = layout.GetPixelSize(); + + drape_ptr handle = make_unique_dp(m_params.m_featureID, + layout.GetText(), + m_params.m_anchor, + glsl::ToVec2(m_basePoint), + glsl::vec2(pixelSize.x, pixelSize.y), + baseOffset, + GetOverlayPriority(), + textures, + isOptional, + move(dynamicBuffer)); + handle->SetOverlayRank(m_hasPOI ? (isPrimary ? dp::OverlayRank1 : dp::OverlayRank2) : dp::OverlayRank0); + handle->SetExtendingSize(m_params.m_extendingSize); + + dp::AttributeProvider provider(2, staticBuffer.size()); + provider.InitStream(0, gpu::TextOutlinedStaticVertex::GetBindingInfo(), make_ref(staticBuffer.data())); + provider.InitStream(1, gpu::TextDynamicVertex::GetBindingInfo(), make_ref(initialDynBuffer.data())); + batcher->InsertListOfStrip(state, make_ref(&provider), move(handle), 4); +} + + uint64_t TextShape::GetOverlayPriority() const { // Overlay priority for text shapes considers the existance of secondary string and length of primary text. diff --git a/drape_frontend/text_shape.hpp b/drape_frontend/text_shape.hpp index 06d4cf9043..28d1a6ccff 100644 --- a/drape_frontend/text_shape.hpp +++ b/drape_frontend/text_shape.hpp @@ -24,6 +24,13 @@ private: glsl::vec2 const & baseOffset, ref_ptr batcher, ref_ptr textures, bool isPrimary, bool isOptional) const; + void DrawSubStringPlain(StraightTextLayout const & layout, dp::FontDecl const & font, + glsl::vec2 const & baseOffset, ref_ptr batcher, + ref_ptr textures, bool isPrimary, bool isOptional) const; + void DrawSubStringOutlined(StraightTextLayout const & layout, dp::FontDecl const & font, + glsl::vec2 const & baseOffset, ref_ptr batcher, + ref_ptr textures, bool isPrimary, bool isOptional) const; + uint64_t GetOverlayPriority() const; m2::PointF m_basePoint;