summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAnsis Brammanis <brammanis@gmail.com>2015-08-14 18:06:14 +0300
committerAnsis Brammanis <brammanis@gmail.com>2015-08-24 18:41:50 -0400
commit494489f9a06b538b900c2da5286ead4ab95805f1 (patch)
tree1b9efb91c1f346602c1866565e8bee128b796198 /src
parentbe36ce01983a97dc24125abf97258a6a0a9baa4d (diff)
downloadqtlocation-mapboxgl-494489f9a06b538b900c2da5286ead4ab95805f1.tar.gz
fix symbol rendering in perspective view
Diffstat (limited to 'src')
-rw-r--r--src/mbgl/renderer/painter.cpp4
-rw-r--r--src/mbgl/renderer/painter_symbol.cpp63
-rw-r--r--src/mbgl/shader/icon.vertex.glsl12
-rw-r--r--src/mbgl/shader/icon_shader.hpp2
-rw-r--r--src/mbgl/shader/sdf.fragment.glsl4
-rw-r--r--src/mbgl/shader/sdf.vertex.glsl18
-rw-r--r--src/mbgl/shader/sdf_shader.hpp2
7 files changed, 84 insertions, 21 deletions
diff --git a/src/mbgl/renderer/painter.cpp b/src/mbgl/renderer/painter.cpp
index 4b5503bcca..7f06b2345c 100644
--- a/src/mbgl/renderer/painter.cpp
+++ b/src/mbgl/renderer/painter.cpp
@@ -155,9 +155,7 @@ void Painter::changeMatrix() {
state.pixel_y() - state.getWidth() / 2.0f, 0);
// The extrusion matrix.
- matrix::identity(extrudeMatrix);
- matrix::multiply(extrudeMatrix, projMatrix, extrudeMatrix);
- matrix::rotate_z(extrudeMatrix, extrudeMatrix, state.getAngle());
+ matrix::ortho(extrudeMatrix, 0, state.getWidth(), state.getHeight(), 0, 0, -1);
// The native matrix is a 1:1 matrix that paints the coordinates at the
// same screen position as the vertex specifies.
diff --git a/src/mbgl/renderer/painter_symbol.cpp b/src/mbgl/renderer/painter_symbol.cpp
index 5c2db77096..c64f32620a 100644
--- a/src/mbgl/renderer/painter_symbol.cpp
+++ b/src/mbgl/renderer/painter_symbol.cpp
@@ -28,25 +28,40 @@ void Painter::renderSDF(SymbolBucket &bucket,
{
mat4 vtxMatrix = translatedMatrix(matrix, styleProperties.translate, id, styleProperties.translate_anchor);
- mat4 exMatrix;
- matrix::copy(exMatrix, projMatrix);
-
bool aligned_with_map = (bucketProperties.rotation_alignment == RotationAlignmentType::Map);
- const float angleOffset = aligned_with_map ? state.getAngle() : 0;
-
- if (angleOffset) {
- matrix::rotate_z(exMatrix, exMatrix, angleOffset);
+ bool skewed = aligned_with_map;
+ mat4 exMatrix;
+ float s;
+ float gammaScale;
+
+ if (skewed) {
+ matrix::identity(exMatrix);
+ s = 4096.0f / util::tileSize / id.overscaling / std::pow(2, state.getZoom() - id.z);
+ gammaScale = 1.0f / std::cos(state.getPitch());
+ } else {
+ exMatrix = extrudeMatrix;
+ s = state.getAltitude();
+ gammaScale = 1.0f;
}
+ matrix::scale(exMatrix, exMatrix, s, s, 1);
// If layerStyle.size > bucket.info.fontSize then labels may collide
float fontSize = styleProperties.size;
float fontScale = fontSize / sdfFontSize;
matrix::scale(exMatrix, exMatrix, fontScale, fontScale, 1.0f);
+ // calculate how much longer the real world distance is at the top of the screen
+ // than at the middle of the screen.
+ float topedgelength = std::sqrt(std::pow(state.getHeight(), 2) / 4.0f * (1.0f + std::pow(state.getAltitude(), 2)));
+ float x = state.getHeight() / 2.0f * std::tan(state.getPitch());
+ float extra = (topedgelength + x) / topedgelength - 1;
+
useProgram(sdfShader.program);
sdfShader.u_matrix = vtxMatrix;
sdfShader.u_exmatrix = exMatrix;
sdfShader.u_texsize = texsize;
+ sdfShader.u_skewed = skewed;
+ sdfShader.u_extra = extra;
// adjust min/max zooms for variable font sies
float zoomAdjust = std::log(fontSize / bucketProperties.size) / std::log(2);
@@ -70,7 +85,7 @@ void Painter::renderSDF(SymbolBucket &bucket,
// We're drawing in the translucent pass which is bottom-to-top, so we need
// to draw the halo first.
if (styleProperties.halo_color[3] > 0.0f && styleProperties.halo_width > 0.0f) {
- sdfShader.u_gamma = styleProperties.halo_blur * blurOffset / fontScale / sdfPx + gamma;
+ sdfShader.u_gamma = (styleProperties.halo_blur * blurOffset / fontScale / sdfPx + gamma) * gammaScale;
if (styleProperties.opacity < 1.0f) {
Color color = styleProperties.halo_color;
@@ -91,7 +106,7 @@ void Painter::renderSDF(SymbolBucket &bucket,
// Then, we draw the text/icon over the halo
if (styleProperties.color[3] > 0.0f) {
- sdfShader.u_gamma = gamma;
+ sdfShader.u_gamma = gamma * gammaScale;
if (styleProperties.opacity < 1.0f) {
Color color = styleProperties.color;
@@ -120,7 +135,6 @@ void Painter::renderSymbol(SymbolBucket &bucket, const StyleLayer &layer_desc, c
const auto &properties = layer_desc.getProperties<SymbolProperties>();
const auto &layout = bucket.layout;
- config.depthTest = true;
config.depthMask = GL_FALSE;
if (bucket.hasCollisionBoxData()) {
@@ -150,6 +164,8 @@ void Painter::renderSymbol(SymbolBucket &bucket, const StyleLayer &layer_desc, c
config.stencilTest = drawAcrossEdges ? false : true;
if (bucket.hasIconData()) {
+ config.depthTest = layout.icon.rotation_alignment == RotationAlignmentType::Map;
+
bool sdf = bucket.sdfIcons;
const float angleOffset =
@@ -160,7 +176,8 @@ void Painter::renderSymbol(SymbolBucket &bucket, const StyleLayer &layer_desc, c
const float fontSize = properties.icon.size;
const float fontScale = fontSize / 1.0f;
- spriteAtlas->bind(state.isChanging() || layout.placement == PlacementType::Line || angleOffset != 0 || fontScale != 1 || sdf);
+ spriteAtlas->bind(state.isChanging() || layout.placement == PlacementType::Line
+ || angleOffset != 0 || fontScale != 1 || sdf || state.getPitch() != 0);
if (sdf) {
renderSDF(bucket,
@@ -175,19 +192,33 @@ void Painter::renderSymbol(SymbolBucket &bucket, const StyleLayer &layer_desc, c
} else {
mat4 vtxMatrix = translatedMatrix(matrix, properties.icon.translate, id, properties.icon.translate_anchor);
+ bool skewed = layout.icon.rotation_alignment == RotationAlignmentType::Map;
mat4 exMatrix;
- matrix::copy(exMatrix, projMatrix);
-
- if (angleOffset) {
- matrix::rotate_z(exMatrix, exMatrix, angleOffset);
+ float s;
+
+ if (skewed) {
+ matrix::identity(exMatrix);
+ s = 4096.0f / util::tileSize / id.overscaling / std::pow(2, state.getZoom() - id.z);
+ } else {
+ exMatrix = extrudeMatrix;
+ s = state.getAltitude();
}
+ matrix::scale(exMatrix, exMatrix, s, s, 1);
matrix::scale(exMatrix, exMatrix, fontScale, fontScale, 1.0f);
+ // calculate how much longer the real world distance is at the top of the screen
+ // than at the middle of the screen.
+ float topedgelength = std::sqrt(std::pow(state.getHeight(), 2) / 4.0f * (1.0f + std::pow(state.getAltitude(), 2)));
+ float x = state.getHeight() / 2.0f * std::tan(state.getPitch());
+ float extra = (topedgelength + x) / topedgelength - 1;
+
useProgram(iconShader->program);
iconShader->u_matrix = vtxMatrix;
iconShader->u_exmatrix = exMatrix;
iconShader->u_texsize = {{ float(spriteAtlas->getWidth()) / 4.0f, float(spriteAtlas->getHeight()) / 4.0f }};
+ iconShader->u_skewed = skewed;
+ iconShader->u_extra = extra;
// adjust min/max zooms for variable font sies
float zoomAdjust = std::log(fontSize / layout.icon.size) / std::log(2);
@@ -205,6 +236,8 @@ void Painter::renderSymbol(SymbolBucket &bucket, const StyleLayer &layer_desc, c
}
if (bucket.hasTextData()) {
+ config.depthTest = layout.text.rotation_alignment == RotationAlignmentType::Map;
+
glyphAtlas->bind();
renderSDF(bucket,
diff --git a/src/mbgl/shader/icon.vertex.glsl b/src/mbgl/shader/icon.vertex.glsl
index 549570021d..3850e01ab7 100644
--- a/src/mbgl/shader/icon.vertex.glsl
+++ b/src/mbgl/shader/icon.vertex.glsl
@@ -14,6 +14,8 @@ uniform float u_minfadezoom;
uniform float u_maxfadezoom;
uniform float u_fadezoom;
uniform float u_opacity;
+uniform bool u_skewed;
+uniform float u_extra;
uniform vec2 u_texsize;
@@ -51,7 +53,15 @@ void main() {
// if label has been faded out, clip it
z += step(v_alpha, 0.0);
- gl_Position = u_matrix * vec4(a_pos, 0, 1) + u_exmatrix * vec4(a_offset / 64.0, z, 0);
+ if (u_skewed) {
+ vec4 extrude = u_exmatrix * vec4(a_offset / 64.0, 0, 0);
+ gl_Position = u_matrix * vec4(a_pos + extrude.xy, 0, 1);
+ gl_Position.z += z * gl_Position.w;
+ } else {
+ vec4 extrude = u_exmatrix * vec4(a_offset / 64.0, z, 0);
+ gl_Position = u_matrix * vec4(a_pos, 0, 1) + extrude;
+ }
+
v_tex = a_tex / u_texsize;
v_alpha *= u_opacity;
diff --git a/src/mbgl/shader/icon_shader.hpp b/src/mbgl/shader/icon_shader.hpp
index b6156ae9a0..18b0fce37b 100644
--- a/src/mbgl/shader/icon_shader.hpp
+++ b/src/mbgl/shader/icon_shader.hpp
@@ -21,6 +21,8 @@ public:
Uniform<float> u_fadezoom = {"u_fadezoom", *this};
Uniform<float> u_opacity = {"u_opacity", *this};
Uniform<std::array<float, 2>> u_texsize = {"u_texsize", *this};
+ Uniform<int32_t> u_skewed = {"u_skewed", *this};
+ Uniform<float> u_extra = {"u_extra", *this};
private:
int32_t a_pos = -1;
diff --git a/src/mbgl/shader/sdf.fragment.glsl b/src/mbgl/shader/sdf.fragment.glsl
index d72d61dab1..a77e959e53 100644
--- a/src/mbgl/shader/sdf.fragment.glsl
+++ b/src/mbgl/shader/sdf.fragment.glsl
@@ -5,9 +5,11 @@ uniform float u_gamma;
varying vec2 v_tex;
varying float v_alpha;
+varying float v_gamma_scale;
void main() {
float dist = texture2D(u_texture, v_tex).a;
- float alpha = smoothstep(u_buffer - u_gamma, u_buffer + u_gamma, dist) * v_alpha;
+ float gamma = u_gamma * v_gamma_scale;
+ float alpha = smoothstep(u_buffer - gamma, u_buffer + gamma, dist) * v_alpha;
gl_FragColor = u_color * alpha;
}
diff --git a/src/mbgl/shader/sdf.vertex.glsl b/src/mbgl/shader/sdf.vertex.glsl
index 192459f9da..5d2e1ce249 100644
--- a/src/mbgl/shader/sdf.vertex.glsl
+++ b/src/mbgl/shader/sdf.vertex.glsl
@@ -13,11 +13,14 @@ uniform float u_fadedist;
uniform float u_minfadezoom;
uniform float u_maxfadezoom;
uniform float u_fadezoom;
+uniform bool u_skewed;
+uniform float u_extra;
uniform vec2 u_texsize;
varying vec2 v_tex;
varying float v_alpha;
+varying float v_gamma_scale;
void main() {
vec2 a_tex = a_data1.xy;
@@ -48,6 +51,19 @@ void main() {
// if label has been faded out, clip it
show *= (1.0 - step(v_alpha, 0.0));
- gl_Position = u_matrix * vec4(a_pos, 0, 1) + u_exmatrix * vec4(a_offset * show / 64.0, 0, 0);
+ if (u_skewed) {
+ vec4 extrude = u_exmatrix * vec4(a_offset * show / 64.0, 0, 0);
+ gl_Position = u_matrix * vec4(a_pos + extrude.xy, 0, 1);
+ } else {
+ vec4 extrude = u_exmatrix * vec4(a_offset * show / 64.0, 0, 0);
+ gl_Position = u_matrix * vec4(a_pos, 0, 1) + extrude;
+ }
+
+ // position of y on the screen
+ float y = gl_Position.y / gl_Position.w;
+ // how much features are squished in all directions by the perspectiveness
+ float perspective_scale = 1.0 / (1.0 - y * u_extra);
+ v_gamma_scale = perspective_scale;
+
v_tex = a_tex / u_texsize;
}
diff --git a/src/mbgl/shader/sdf_shader.hpp b/src/mbgl/shader/sdf_shader.hpp
index 36dfa30d3e..181788ab16 100644
--- a/src/mbgl/shader/sdf_shader.hpp
+++ b/src/mbgl/shader/sdf_shader.hpp
@@ -23,6 +23,8 @@ public:
Uniform<float> u_minfadezoom = {"u_minfadezoom", *this};
Uniform<float> u_maxfadezoom = {"u_maxfadezoom", *this};
Uniform<float> u_fadezoom = {"u_fadezoom", *this};
+ Uniform<int32_t> u_skewed = {"u_skewed", *this};
+ Uniform<float> u_extra = {"u_extra", *this};
protected:
int32_t a_pos = -1;