diff options
author | Ansis Brammanis <brammanis@gmail.com> | 2015-08-14 18:06:14 +0300 |
---|---|---|
committer | Ansis Brammanis <brammanis@gmail.com> | 2015-08-24 18:41:50 -0400 |
commit | 494489f9a06b538b900c2da5286ead4ab95805f1 (patch) | |
tree | 1b9efb91c1f346602c1866565e8bee128b796198 /src | |
parent | be36ce01983a97dc24125abf97258a6a0a9baa4d (diff) | |
download | qtlocation-mapboxgl-494489f9a06b538b900c2da5286ead4ab95805f1.tar.gz |
fix symbol rendering in perspective view
Diffstat (limited to 'src')
-rw-r--r-- | src/mbgl/renderer/painter.cpp | 4 | ||||
-rw-r--r-- | src/mbgl/renderer/painter_symbol.cpp | 63 | ||||
-rw-r--r-- | src/mbgl/shader/icon.vertex.glsl | 12 | ||||
-rw-r--r-- | src/mbgl/shader/icon_shader.hpp | 2 | ||||
-rw-r--r-- | src/mbgl/shader/sdf.fragment.glsl | 4 | ||||
-rw-r--r-- | src/mbgl/shader/sdf.vertex.glsl | 18 | ||||
-rw-r--r-- | src/mbgl/shader/sdf_shader.hpp | 2 |
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; |