[drape] text rendering optimization.

This commit is contained in:
ExMix 2015-12-05 16:11:02 +03:00
parent d25f807261
commit e867277b03
17 changed files with 430 additions and 79 deletions

View file

@ -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 \

View file

@ -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

View file

@ -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;

View file

@ -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;
}

20
drape/shaders/text_vertex_shader.vsh Executable file → Normal file
View file

@ -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;
}

View file

@ -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<TextStaticVertex> filler(4);
dp::BindingFiller<TextStaticVertex> filler(3);
filler.FillDecl<TextStaticVertex::TPosition>("a_position");
filler.FillDecl<TextStaticVertex::TTexCoord>("a_colorTexCoord");
filler.FillDecl<TextStaticVertex::TTexCoord>("a_outlineColorTexCoord");
filler.FillDecl<TextStaticVertex::TTexCoord>("a_maskTexCoord");
return filler.m_info;
}
dp::BindingInfo TextOutlinedStaticBindingInit()
{
static_assert(sizeof(TextOutlinedStaticVertex) == (sizeof(TextOutlinedStaticVertex::TPosition) +
3 * sizeof(TextOutlinedStaticVertex::TTexCoord)), "");
dp::BindingFiller<TextOutlinedStaticVertex> filler(4);
filler.FillDecl<TextOutlinedStaticVertex::TPosition>("a_position");
filler.FillDecl<TextOutlinedStaticVertex::TTexCoord>("a_colorTexCoord");
filler.FillDecl<TextOutlinedStaticVertex::TTexCoord>("a_outlineColorTexCoord");
filler.FillDecl<TextOutlinedStaticVertex::TTexCoord>("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

View file

@ -42,9 +42,23 @@ typedef buffer_vector<SolidTexturingVertex, 128> 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<TextStaticVertex, 128> 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<TextStaticVertex, 128> TTextStaticVertexBuffer;
typedef buffer_vector<TextOutlinedStaticVertex, 128> TTextOutlinedStaticVertexBuffer;
struct TextDynamicVertex : BaseVertex
{

View file

@ -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();

View file

@ -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)

View file

@ -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<dp::TextureManager> textures,
ref_ptr<dp::Batcher> batcher,
unique_ptr<PathTextLayout> && layout,
buffer_vector<float, 32> 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<dp::OverlayHandle> handle = make_unique_dp<PathTextHandle>(m_spline, layoutPtr, offset,
GetOverlayPriority(),
textures);
batcher->InsertListOfStrip(state, make_ref(&provider), move(handle), 4);
}
}
void PathTextShape::DrawPathTextOutlined(ref_ptr<dp::TextureManager> textures,
ref_ptr<dp::Batcher> batcher,
unique_ptr<PathTextLayout> && layout,
buffer_vector<float, 32> 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<dp::OverlayHandle> handle = make_unique_dp<PathTextHandle>(m_spline, layoutPtr, offset,
GetOverlayPriority(),
textures);
batcher->InsertListOfStrip(state, make_ref(&provider), move(handle), 4);
}
}
void PathTextShape::Draw(ref_ptr<dp::Batcher> batcher, ref_ptr<dp::TextureManager> textures) const
{
unique_ptr<PathTextLayout> layout = make_unique<PathTextLayout>(strings::MakeUniString(m_params.m_text),
@ -177,40 +257,10 @@ void PathTextShape::Draw(ref_ptr<dp::Batcher> batcher, ref_ptr<dp::TextureManage
offsets.push_back((textHalfLength + (textLength + offset) * (i + 1)) * scalePtoG);
}
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_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<dp::OverlayHandle> handle = make_unique_dp<PathTextHandle>(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);
}
}

View file

@ -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<dp::TextureManager> textures,
ref_ptr<dp::Batcher> batcher,
unique_ptr<PathTextLayout> && layout,
buffer_vector<float, 32> const & offests) const;
void DrawPathTextOutlined(ref_ptr<dp::TextureManager> textures,
ref_ptr<dp::Batcher> batcher,
unique_ptr<PathTextLayout> && layout,
buffer_vector<float, 32> const & offsets) const;
m2::SharedSpline m_spline;
PathTextViewParams m_params;
};

View file

@ -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);

View file

@ -67,7 +67,7 @@ bool TextHandle::Update(ScreenBase const & screen)
bool TextHandle::IndexesRequired() const
{
return false;
return true;
}
void TextHandle::SetForceUpdateNormals(bool forceUpdate) const

View file

@ -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<int32_t>(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<size_t, glsl::vec2> 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);
}

View file

@ -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,

View file

@ -126,8 +126,26 @@ void TextShape::Draw(ref_ptr<dp::Batcher> batcher, ref_ptr<dp::TextureManager> t
}
void TextShape::DrawSubString(StraightTextLayout const & layout, dp::FontDecl const & font,
glsl::vec2 const & baseOffset, ref_ptr<dp::Batcher> batcher,
ref_ptr<dp::TextureManager> textures, bool isPrimary, bool isOptional) const
glm::vec2 const & baseOffset, ref_ptr<dp::Batcher> batcher,
ref_ptr<dp::TextureManager> 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<dp::Batcher> batcher,
ref_ptr<dp::TextureManager> 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<dp::Batcher> batcher,
ref_ptr<dp::TextureManager> 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<dp::OverlayHandle> handle = make_unique_dp<StraightTextHandle>(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.

View file

@ -24,6 +24,13 @@ private:
glsl::vec2 const & baseOffset, ref_ptr<dp::Batcher> batcher,
ref_ptr<dp::TextureManager> textures, bool isPrimary, bool isOptional) const;
void DrawSubStringPlain(StraightTextLayout const & layout, dp::FontDecl const & font,
glsl::vec2 const & baseOffset, ref_ptr<dp::Batcher> batcher,
ref_ptr<dp::TextureManager> textures, bool isPrimary, bool isOptional) const;
void DrawSubStringOutlined(StraightTextLayout const & layout, dp::FontDecl const & font,
glsl::vec2 const & baseOffset, ref_ptr<dp::Batcher> batcher,
ref_ptr<dp::TextureManager> textures, bool isPrimary, bool isOptional) const;
uint64_t GetOverlayPriority() const;
m2::PointF m_basePoint;