[drape] improve text rendering

This commit is contained in:
ExMix 2015-11-15 18:33:52 +03:00 committed by r.kuznetsov
parent f642dd2c6b
commit e45757ac50
6 changed files with 73 additions and 80 deletions

View file

@ -1,56 +1,17 @@
varying vec2 v_colorTexCoord;
varying vec2 v_outlineColorTexCoord;
varying vec2 v_maskTexCoord;
uniform sampler2D u_colorTex;
uniform sampler2D u_maskTex;
uniform float u_opacity;
uniform vec4 u_outlineGlyphParams;
uniform vec2 u_glyphParams;
vec4 colorize(vec4 base, vec4 outline, float alpha)
{
if (alpha > u_outlineGlyphParams.w)
return vec4(outline.rgb, 0);
if (alpha > u_outlineGlyphParams.z)
{
float oFactor = smoothstep(u_outlineGlyphParams.w, u_outlineGlyphParams.z, alpha);
return vec4(outline.rgb, mix(0.0, outline.a, oFactor));
}
if (alpha > u_outlineGlyphParams.y)
{
return outline;
}
if (alpha > u_outlineGlyphParams.x)
{
float oFactor = smoothstep(u_outlineGlyphParams.x, u_outlineGlyphParams.y, alpha);
return mix(base, outline, oFactor);
}
return base;
}
vec4 without_outline(vec4 base, float alpha)
{
if (alpha > u_glyphParams.x)
{
float oFactor = smoothstep(u_glyphParams.x, u_glyphParams.y, alpha);
return vec4(base.rgb, mix(base.a, 0.0, oFactor));
}
return base;
}
uniform float u_contrast;
uniform float u_gamma;
void main (void)
{
vec4 base = texture2D(u_colorTex, v_colorTexCoord);
vec4 outline = texture2D(u_colorTex, v_outlineColorTexCoord);
float alpha = texture2D(u_maskTex, v_maskTexCoord).a;
vec4 finalColor;
if (outline.a > 0.1)
finalColor = colorize(base, outline, 1.0 - alpha);
else
finalColor = without_outline(base, 1.0 - alpha);
finalColor.a *= u_opacity;
gl_FragColor = finalColor;
vec4 glyphColor = texture2D(u_colorTex, v_colorTexCoord);
float dist = texture2D(u_maskTex, v_maskTexCoord).a;
float alpha = smoothstep(u_contrast - u_gamma, u_contrast + u_gamma, dist) * u_opacity;
glyphColor.a *= alpha;
gl_FragColor = glyphColor;
}

View file

@ -6,19 +6,26 @@ attribute vec2 a_maskTexCoord;
uniform mat4 modelView;
uniform mat4 projection;
uniform float u_isOutlinePass;
varying vec2 v_colorTexCoord;
varying vec2 v_maskTexCoord;
varying vec2 v_outlineColorTexCoord;
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 * modelView;
highp vec4 shiftedPos = vec4(a_normal, 0, 0) + pos;
lowp vec4 pos = (a_position + vec4(Zero, Zero, depthShift, Zero)) * modelView;
highp vec4 shiftedPos = vec4(a_normal, Zero, Zero) + pos;
gl_Position = shiftedPos * projection;
v_colorTexCoord = a_colorTexCoord;
v_colorTexCoord = a_colorTexCoord * notOutline + a_outlineColorTexCoord * isOutline;
v_maskTexCoord = a_maskTexCoord;
v_outlineColorTexCoord = a_outlineColorTexCoord;
}

View file

@ -120,7 +120,10 @@ void FrontendRenderer::AcceptMessage(ref_ptr<Message> message)
if (!IsUserMarkLayer(key))
m_tileTree->ProcessTile(key, GetCurrentZoomLevel(), state, move(bucket));
else
{
m_userMarkRenderGroups.emplace_back(make_unique_dp<UserMarkRenderGroup>(state, key, move(bucket)));
m_userMarkRenderGroups.back()->SetRenderParams(program, make_ref(&m_generalUniforms));
}
break;
}
@ -411,6 +414,8 @@ void FrontendRenderer::AddToRenderGroup(vector<drape_ptr<RenderGroup>> & groups,
TileKey const & newTile)
{
drape_ptr<RenderGroup> group = make_unique_dp<RenderGroup>(state, newTile);
ref_ptr<dp::GpuProgram> program = m_gpuProgramManager->GetProgram(state.GetProgramIndex());
group->SetRenderParams(program, make_ref(&m_generalUniforms));
group->AddBucket(move(renderBucket));
groups.push_back(move(group));
}
@ -639,15 +644,6 @@ void FrontendRenderer::RenderScene(ScreenBase const & modelView)
void FrontendRenderer::RenderSingleGroup(ScreenBase const & modelView, ref_ptr<BaseRenderGroup> group)
{
group->UpdateAnimation();
dp::GLState const & state = group->GetState();
ref_ptr<dp::GpuProgram> program = m_gpuProgramManager->GetProgram(state.GetProgramIndex());
program->Bind();
ApplyState(state, program);
ApplyUniforms(m_generalUniforms, program);
ApplyUniforms(group->GetUniforms(), program);
group->Render(modelView);
}

View file

@ -12,6 +12,12 @@
namespace df
{
void BaseRenderGroup::SetRenderParams(ref_ptr<dp::GpuProgram> shader, ref_ptr<dp::UniformValuesStorage> generalUniforms)
{
m_shader = shader;
m_generalUniforms = generalUniforms;
}
void BaseRenderGroup::UpdateAnimation()
{
m_uniforms.SetFloatValue("u_opacity", 1.0);
@ -21,15 +27,6 @@ RenderGroup::RenderGroup(dp::GLState const & state, df::TileKey const & tileKey)
: TBase(state, tileKey)
, m_pendingOnDelete(false)
{
if (state.GetProgramIndex() == gpu::TEXT_PROGRAM)
{
auto const & params = VisualParams::Instance().GetGlyphVisualParams();
m_uniforms.SetFloatValue("u_outlineGlyphParams",
params.m_outlineMinStart, params.m_outlineMinEnd,
params.m_outlineMaxStart, params.m_outlineMaxEnd);
m_uniforms.SetFloatValue("u_glyphParams",
params.m_alphaGlyphMin, params.m_alphaGlyphMax);
}
}
RenderGroup::~RenderGroup()
@ -39,6 +36,8 @@ RenderGroup::~RenderGroup()
void RenderGroup::Update(ScreenBase const & modelView)
{
ASSERT(m_shader != nullptr, ());
ASSERT(m_generalUniforms != nullptr, ());
for(drape_ptr<dp::RenderBucket> & renderBucket : m_renderBuckets)
renderBucket->Update(modelView);
}
@ -48,14 +47,44 @@ void RenderGroup::CollectOverlay(ref_ptr<dp::OverlayTree> tree)
if (m_pendingOnDelete)
return;
ASSERT(m_shader != nullptr, ());
ASSERT(m_generalUniforms != nullptr, ());
for(drape_ptr<dp::RenderBucket> & renderBucket : m_renderBuckets)
renderBucket->CollectOverlayHandles(tree, GetOpacity() < 1.0);
}
void RenderGroup::Render(ScreenBase const & screen)
{
for(drape_ptr<dp::RenderBucket> & renderBucket : m_renderBuckets)
renderBucket->Render(screen);
ASSERT(m_shader != nullptr, ());
ASSERT(m_generalUniforms != nullptr, ());
m_shader->Bind();
dp::ApplyState(m_state, m_shader);
dp::ApplyUniforms(*(m_generalUniforms.get()), m_shader);
if (m_state.GetProgramIndex() == gpu::TEXT_PROGRAM)
{
m_uniforms.SetFloatValue("u_contrast", 0.05f);
m_uniforms.SetFloatValue("u_gamma", 0.01f);
m_uniforms.SetFloatValue("u_isOutlinePass", 1.0f);
dp::ApplyUniforms(m_uniforms, m_shader);
for(drape_ptr<dp::RenderBucket> & renderBucket : m_renderBuckets)
renderBucket->Render(screen);
m_uniforms.SetFloatValue("u_contrast", 0.45f);
m_uniforms.SetFloatValue("u_gamma", 0.05f);
m_uniforms.SetFloatValue("u_isOutlinePass", 0.0f);
dp::ApplyUniforms(m_uniforms, m_shader);
for(drape_ptr<dp::RenderBucket> & renderBucket : m_renderBuckets)
renderBucket->Render(screen);
}
else
{
dp::ApplyUniforms(m_uniforms, m_shader);
for(drape_ptr<dp::RenderBucket> & renderBucket : m_renderBuckets)
renderBucket->Render(screen);
}
}
void RenderGroup::AddBucket(drape_ptr<dp::RenderBucket> && bucket)

View file

@ -25,6 +25,8 @@ public:
: m_state(state)
, m_tileKey(tileKey) {}
void SetRenderParams(ref_ptr<dp::GpuProgram> shader, ref_ptr<dp::UniformValuesStorage> generalUniforms);
dp::GLState const & GetState() const { return m_state; }
TileKey const & GetTileKey() const { return m_tileKey; }
dp::UniformValuesStorage const & GetUniforms() const { return m_uniforms; }
@ -34,7 +36,9 @@ public:
protected:
dp::GLState m_state;
ref_ptr<dp::GpuProgram> m_shader;
dp::UniformValuesStorage m_uniforms;
ref_ptr<dp::UniformValuesStorage> m_generalUniforms;
private:
TileKey m_tileKey;

View file

@ -24,8 +24,7 @@ public:
dp::TextureManager::ColorRegion const & color,
dp::TextureManager::ColorRegion const & outline,
gpu::TTextStaticVertexBuffer & buffer)
: m_depthShift(0.0f, 0.0f, 0.0f)
, m_pivot(pivot)
: m_pivot(pivot)
, m_colorCoord(glsl::ToVec2(color.GetTexRect().Center()))
, m_outlineCoord(glsl::ToVec2(outline.GetTexRect().Center()))
, m_buffer(buffer)
@ -35,16 +34,13 @@ public:
void operator() (dp::TextureManager::GlyphRegion const & glyph)
{
m2::RectF const & mask = glyph.GetTexRect();
glsl::vec3 pivot = m_pivot + m_depthShift;
m_buffer.push_back(gpu::TextStaticVertex(pivot, m_colorCoord, m_outlineCoord, glsl::ToVec2(mask.LeftTop())));
m_buffer.push_back(gpu::TextStaticVertex(pivot, m_colorCoord, m_outlineCoord, glsl::ToVec2(mask.LeftBottom())));
m_buffer.push_back(gpu::TextStaticVertex(pivot, m_colorCoord, m_outlineCoord, glsl::ToVec2(mask.RightTop())));
m_buffer.push_back(gpu::TextStaticVertex(pivot, m_colorCoord, m_outlineCoord, glsl::ToVec2(mask.RightBottom())));
m_depthShift += glsl::vec3(0.0f, 0.0f, 1.0f);
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())));
}
protected:
glsl::vec3 m_depthShift;
glsl::vec3 const & m_pivot;
glsl::vec2 m_colorCoord;
glsl::vec2 m_outlineCoord;