summaryrefslogtreecommitdiff
path: root/src/mbgl/renderer/line_bucket.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mbgl/renderer/line_bucket.cpp')
-rw-r--r--src/mbgl/renderer/line_bucket.cpp70
1 files changed, 55 insertions, 15 deletions
diff --git a/src/mbgl/renderer/line_bucket.cpp b/src/mbgl/renderer/line_bucket.cpp
index 83c5b43776..ba50e6b1f0 100644
--- a/src/mbgl/renderer/line_bucket.cpp
+++ b/src/mbgl/renderer/line_bucket.cpp
@@ -6,13 +6,14 @@
#include <mbgl/shader/linesdf_shader.hpp>
#include <mbgl/shader/linepattern_shader.hpp>
#include <mbgl/util/math.hpp>
-#include <mbgl/platform/gl.hpp>
+#include <mbgl/util/constants.hpp>
+#include <mbgl/gl/gl.hpp>
#include <cassert>
using namespace mbgl;
-LineBucket::LineBucket() {
+LineBucket::LineBucket(float overscaling_) : overscaling(overscaling_) {
}
LineBucket::~LineBucket() {
@@ -25,6 +26,21 @@ void LineBucket::addGeometry(const GeometryCollection& geometryCollection) {
}
}
+
+/*
+ * Sharp corners cause dashed lines to tilt because the distance along the line
+ * is the same at both the inner and outer corners. To improve the appearance of
+ * dashed lines we add extra points near sharp corners so that a smaller part
+ * of the line is tilted.
+ *
+ * COS_HALF_SHARP_CORNER controls how sharp a corner has to be for us to add an
+ * extra vertex. The default is 75 degrees.
+ *
+ * The newly created vertices are placed SHARP_CORNER_OFFSET pixels from the corner.
+ */
+const float COS_HALF_SHARP_CORNER = std::cos(75.0 / 2.0 * (M_PI / 180.0));
+const float SHARP_CORNER_OFFSET = 15.0f;
+
void LineBucket::addGeometry(const std::vector<Coordinate>& vertices) {
const GLsizei len = [&vertices] {
GLsizei l = static_cast<GLsizei>(vertices.size());
@@ -42,6 +58,8 @@ void LineBucket::addGeometry(const std::vector<Coordinate>& vertices) {
const float miterLimit = layout.join == JoinType::Bevel ? 1.05f : float(layout.miterLimit);
+ const double sharpCornerOffset = SHARP_CORNER_OFFSET * (util::EXTENT / (512.0 * overscaling));
+
const Coordinate firstVertex = vertices.front();
const Coordinate lastVertex = vertices[len - 1];
const bool closed = firstVertex == lastVertex;
@@ -98,10 +116,6 @@ void LineBucket::addGeometry(const std::vector<Coordinate>& vertices) {
currentVertex = vertices[i];
- // Calculate how far along the line the currentVertex is
- if (prevVertex)
- distance += util::dist<double>(currentVertex, prevVertex);
-
// Calculate the normal towards the next vertex in this line. In case
// there is no next vertex, pretend that the line is continuing straight,
// meaning that we are just using the previous normal.
@@ -134,6 +148,18 @@ void LineBucket::addGeometry(const std::vector<Coordinate>& vertices) {
const float cosHalfAngle = joinNormal.x * nextNormal.x + joinNormal.y * nextNormal.y;
const float miterLength = cosHalfAngle != 0 ? 1 / cosHalfAngle: 1;
+ const bool isSharpCorner = cosHalfAngle < COS_HALF_SHARP_CORNER && prevVertex && nextVertex;
+
+ if (isSharpCorner && i > 0) {
+ const double prevSegmentLength = util::dist<double>(currentVertex, prevVertex);
+ if (prevSegmentLength > 2.0 * sharpCornerOffset) {
+ Coordinate newPrevVertex = currentVertex - (util::round(vec2<double>(currentVertex - prevVertex) * (sharpCornerOffset / prevSegmentLength)));
+ distance += util::dist<double>(newPrevVertex, prevVertex);
+ addCurrentVertex(newPrevVertex, flip, distance, prevNormal, 0, 0, false, startVertex, triangleStore);
+ prevVertex = newPrevVertex;
+ }
+ }
+
// The join if a middle vertex, otherwise the cap
const bool middleVertex = prevVertex && nextVertex;
JoinType currentJoin = layout.join;
@@ -167,6 +193,10 @@ void LineBucket::addGeometry(const std::vector<Coordinate>& vertices) {
}
}
+ // Calculate how far along the line the currentVertex is
+ if (prevVertex)
+ distance += util::dist<double>(currentVertex, prevVertex);
+
if (middleVertex && currentJoin == JoinType::Miter) {
joinNormal = joinNormal * miterLength;
addCurrentVertex(currentVertex, flip, distance, joinNormal, 0, 0, false, startVertex,
@@ -295,6 +325,16 @@ void LineBucket::addGeometry(const std::vector<Coordinate>& vertices) {
}
}
+ if (isSharpCorner && i < len - 1) {
+ const double nextSegmentLength = util::dist<double>(currentVertex, nextVertex);
+ if (nextSegmentLength > 2 * sharpCornerOffset) {
+ Coordinate newCurrentVertex = currentVertex + util::round(vec2<double>(nextVertex - currentVertex) * (sharpCornerOffset / nextSegmentLength));
+ distance += util::dist<double>(newCurrentVertex, currentVertex);
+ addCurrentVertex(newCurrentVertex, flip, distance, nextNormal, 0, 0, false, startVertex, triangleStore);
+ currentVertex = newCurrentVertex;
+ }
+ }
+
startOfLine = false;
}
@@ -378,9 +418,9 @@ void LineBucket::addPieSliceVertex(const Coordinate& currentVertex,
}
}
-void LineBucket::upload() {
- vertexBuffer.upload();
- triangleElementsBuffer.upload();
+void LineBucket::upload(gl::GLObjectStore& glObjectStore) {
+ vertexBuffer.upload(glObjectStore);
+ triangleElementsBuffer.upload(glObjectStore);
// From now on, we're only going to render during the translucent pass.
uploaded = true;
@@ -397,7 +437,7 @@ bool LineBucket::hasData() const {
return !triangleGroups.empty();
}
-void LineBucket::drawLines(LineShader& shader) {
+void LineBucket::drawLines(LineShader& shader, gl::GLObjectStore& glObjectStore) {
GLbyte* vertex_index = BUFFER_OFFSET(0);
GLbyte* elements_index = BUFFER_OFFSET(0);
for (auto& group : triangleGroups) {
@@ -405,7 +445,7 @@ void LineBucket::drawLines(LineShader& shader) {
if (!group->elements_length) {
continue;
}
- group->array[0].bind(shader, vertexBuffer, triangleElementsBuffer, vertex_index);
+ group->array[0].bind(shader, vertexBuffer, triangleElementsBuffer, vertex_index, glObjectStore);
MBGL_CHECK_ERROR(glDrawElements(GL_TRIANGLES, group->elements_length * 3, GL_UNSIGNED_SHORT,
elements_index));
vertex_index += group->vertex_length * vertexBuffer.itemSize;
@@ -413,7 +453,7 @@ void LineBucket::drawLines(LineShader& shader) {
}
}
-void LineBucket::drawLineSDF(LineSDFShader& shader) {
+void LineBucket::drawLineSDF(LineSDFShader& shader, gl::GLObjectStore& glObjectStore) {
GLbyte* vertex_index = BUFFER_OFFSET(0);
GLbyte* elements_index = BUFFER_OFFSET(0);
for (auto& group : triangleGroups) {
@@ -421,7 +461,7 @@ void LineBucket::drawLineSDF(LineSDFShader& shader) {
if (!group->elements_length) {
continue;
}
- group->array[2].bind(shader, vertexBuffer, triangleElementsBuffer, vertex_index);
+ group->array[2].bind(shader, vertexBuffer, triangleElementsBuffer, vertex_index, glObjectStore);
MBGL_CHECK_ERROR(glDrawElements(GL_TRIANGLES, group->elements_length * 3, GL_UNSIGNED_SHORT,
elements_index));
vertex_index += group->vertex_length * vertexBuffer.itemSize;
@@ -429,7 +469,7 @@ void LineBucket::drawLineSDF(LineSDFShader& shader) {
}
}
-void LineBucket::drawLinePatterns(LinepatternShader& shader) {
+void LineBucket::drawLinePatterns(LinepatternShader& shader, gl::GLObjectStore& glObjectStore) {
GLbyte* vertex_index = BUFFER_OFFSET(0);
GLbyte* elements_index = BUFFER_OFFSET(0);
for (auto& group : triangleGroups) {
@@ -437,7 +477,7 @@ void LineBucket::drawLinePatterns(LinepatternShader& shader) {
if (!group->elements_length) {
continue;
}
- group->array[1].bind(shader, vertexBuffer, triangleElementsBuffer, vertex_index);
+ group->array[1].bind(shader, vertexBuffer, triangleElementsBuffer, vertex_index, glObjectStore);
MBGL_CHECK_ERROR(glDrawElements(GL_TRIANGLES, group->elements_length * 3, GL_UNSIGNED_SHORT,
elements_index));
vertex_index += group->vertex_length * vertexBuffer.itemSize;