summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorKonstantin Käfer <mail@kkaefer.com>2015-11-25 12:42:34 +0100
committerJohn Firebaugh <john.firebaugh@gmail.com>2015-12-03 11:41:53 -0800
commit964a1e7b62c3a7e8fd742e16fe842f8a702437e5 (patch)
treeb94ace89c3688577b196893b7988496f8cbc41a3 /src
parentc279fb171700c464c1cdac5cd2da39f142274d8d (diff)
downloadqtlocation-mapboxgl-964a1e7b62c3a7e8fd742e16fe842f8a702437e5.tar.gz
[core] rudimentary support for offsetting lines
Diffstat (limited to 'src')
-rw-r--r--src/mbgl/geometry/line_buffer.cpp11
-rw-r--r--src/mbgl/geometry/line_buffer.hpp3
-rw-r--r--src/mbgl/layer/line_layer.cpp3
-rw-r--r--src/mbgl/layer/line_layer.hpp1
-rw-r--r--src/mbgl/renderer/line_bucket.cpp9
-rw-r--r--src/mbgl/renderer/painter_line.cpp3
-rw-r--r--src/mbgl/shader/line.vertex.glsl12
-rw-r--r--src/mbgl/shader/line_shader.hpp1
-rw-r--r--src/mbgl/shader/linepattern.vertex.glsl14
-rw-r--r--src/mbgl/shader/linepattern_shader.hpp1
-rw-r--r--src/mbgl/shader/linesdf.vertex.glsl14
-rw-r--r--src/mbgl/shader/linesdf_shader.hpp1
12 files changed, 60 insertions, 13 deletions
diff --git a/src/mbgl/geometry/line_buffer.cpp b/src/mbgl/geometry/line_buffer.cpp
index 77a134b468..f775a4589f 100644
--- a/src/mbgl/geometry/line_buffer.cpp
+++ b/src/mbgl/geometry/line_buffer.cpp
@@ -5,7 +5,7 @@
using namespace mbgl;
-GLsizei LineVertexBuffer::add(vertex_type x, vertex_type y, float ex, float ey, int8_t tx, int8_t ty, int32_t linesofar) {
+GLsizei LineVertexBuffer::add(vertex_type x, vertex_type y, float ex, float ey, bool tx, bool ty, int8_t dir, int32_t linesofar) {
GLsizei idx = index();
void *data = addElement();
@@ -16,8 +16,13 @@ GLsizei LineVertexBuffer::add(vertex_type x, vertex_type y, float ex, float ey,
int8_t *extrude = static_cast<int8_t *>(data);
extrude[4] = ::round(extrudeScale * ex);
extrude[5] = ::round(extrudeScale * ey);
- extrude[6] = static_cast<int8_t>(linesofar / 128);
- extrude[7] = static_cast<int8_t>(linesofar % 128);
+
+ // Encode the -1/0/1 direction value into .zw coordinates of a_data, which is normally covered
+ // by linesofar, so we need to merge them.
+ // The z component's first bit, as well as the sign bit is reserved for the direction,
+ // so we need to shift the linesofar.
+ extrude[6] = ((dir < 0) ? -1 : 1) * ((dir ? 1 : 0) | static_cast<int8_t>((linesofar << 1) & 0x7F));
+ extrude[7] = (linesofar >> 6) & 0x7F;
return idx;
}
diff --git a/src/mbgl/geometry/line_buffer.hpp b/src/mbgl/geometry/line_buffer.hpp
index 0835c0298f..aa2dedbceb 100644
--- a/src/mbgl/geometry/line_buffer.hpp
+++ b/src/mbgl/geometry/line_buffer.hpp
@@ -29,8 +29,9 @@ public:
* @param {number} ey extrude normal
* @param {number} tx texture normal
* @param {number} ty texture normal
+ * @param {number} dir direction of the line cap (-1/0/1)
*/
- GLsizei add(vertex_type x, vertex_type y, float ex, float ey, int8_t tx, int8_t ty, int32_t linesofar = 0);
+ GLsizei add(vertex_type x, vertex_type y, float ex, float ey, bool tx, bool ty, int8_t dir, int32_t linesofar = 0);
};
diff --git a/src/mbgl/layer/line_layer.cpp b/src/mbgl/layer/line_layer.cpp
index a3073e3bc0..1e25ed30cb 100644
--- a/src/mbgl/layer/line_layer.cpp
+++ b/src/mbgl/layer/line_layer.cpp
@@ -27,6 +27,7 @@ void LineLayer::parsePaints(const JSVal& layer) {
paint.translateAnchor.parse("line-translate-anchor", layer);
paint.width.parse("line-width", layer);
paint.gapWidth.parse("line-gap-width", layer);
+ paint.offset.parse("line-offset", layer);
paint.blur.parse("line-blur", layer);
paint.dasharray.parse("line-dasharray", layer);
paint.pattern.parse("line-pattern", layer);
@@ -39,6 +40,7 @@ void LineLayer::cascade(const StyleCascadeParameters& parameters) {
paint.translateAnchor.cascade(parameters);
paint.width.cascade(parameters);
paint.gapWidth.cascade(parameters);
+ paint.offset.cascade(parameters);
paint.blur.cascade(parameters);
paint.dasharray.cascade(parameters);
paint.pattern.cascade(parameters);
@@ -59,6 +61,7 @@ bool LineLayer::recalculate(const StyleCalculationParameters& parameters) {
hasTransitions |= paint.translateAnchor.calculate(parameters);
hasTransitions |= paint.width.calculate(parameters);
hasTransitions |= paint.gapWidth.calculate(parameters);
+ hasTransitions |= paint.offset.calculate(parameters);
hasTransitions |= paint.blur.calculate(parameters);
hasTransitions |= paint.dasharray.calculate(parameters);
hasTransitions |= paint.pattern.calculate(parameters);
diff --git a/src/mbgl/layer/line_layer.hpp b/src/mbgl/layer/line_layer.hpp
index 91206a4ccc..d1c654619a 100644
--- a/src/mbgl/layer/line_layer.hpp
+++ b/src/mbgl/layer/line_layer.hpp
@@ -24,6 +24,7 @@ public:
PaintProperty<float> width = 1;
PaintProperty<float> gapWidth = 0;
PaintProperty<float> blur = 0;
+ PaintProperty<float> offset = 0;
PaintProperty<std::vector<float>, Faded<std::vector<float>>> dasharray = { {} };
PaintProperty<std::string, Faded<std::string>> pattern = { "" };
diff --git a/src/mbgl/renderer/line_bucket.cpp b/src/mbgl/renderer/line_bucket.cpp
index 43bb8132de..368c4ce69d 100644
--- a/src/mbgl/renderer/line_bucket.cpp
+++ b/src/mbgl/renderer/line_bucket.cpp
@@ -187,8 +187,9 @@ void LineBucket::addGeometry(const std::vector<Coordinate>& vertices) {
addCurrentVertex(currentVertex, flip, distance, joinNormal, 0, 0, false, startVertex,
triangleStore);
- flip = -flip;
+ addCurrentVertex(currentVertex, -flip, distance, joinNormal, 0, 0, false, startVertex,
+ triangleStore);
} else if (middleVertex && (currentJoin == JoinType::Bevel || currentJoin == JoinType::FakeRound)) {
const bool lineTurnsLeft = flip * (prevNormal.x * nextNormal.y - prevNormal.y * nextNormal.x) > 0;
const float offset = -std::sqrt(miterLength * miterLength - 1);
@@ -334,7 +335,7 @@ void LineBucket::addCurrentVertex(const Coordinate& currentVertex,
vec2<double> extrude = normal * flip;
if (endLeft)
extrude = extrude - (util::perp(normal) * endLeft);
- e3 = vertexBuffer.add(currentVertex.x, currentVertex.y, extrude.x, extrude.y, tx, 0, distance)
+ e3 = vertexBuffer.add(currentVertex.x, currentVertex.y, extrude.x, extrude.y, tx, 0, endLeft, distance)
- startVertex;
if (e1 >= 0 && e2 >= 0) {
triangleStore.emplace_back(e1, e2, e3);
@@ -345,7 +346,7 @@ void LineBucket::addCurrentVertex(const Coordinate& currentVertex,
extrude = normal * (-flip);
if (endRight)
extrude = extrude - (util::perp(normal) * endRight);
- e3 = vertexBuffer.add(currentVertex.x, currentVertex.y, extrude.x, extrude.y, tx, 1, distance)
+ e3 = vertexBuffer.add(currentVertex.x, currentVertex.y, extrude.x, extrude.y, tx, 1, -endRight, distance)
- startVertex;
if (e1 >= 0 && e2 >= 0) {
triangleStore.emplace_back(e1, e2, e3);
@@ -364,7 +365,7 @@ void LineBucket::addPieSliceVertex(const Coordinate& currentVertex,
int8_t ty = lineTurnsLeft;
auto flippedExtrude = extrude * (flip * (lineTurnsLeft ? -1 : 1));
- e3 = vertexBuffer.add(currentVertex.x, currentVertex.y, flippedExtrude.x, flippedExtrude.y, 0, ty, distance)
+ e3 = vertexBuffer.add(currentVertex.x, currentVertex.y, flippedExtrude.x, flippedExtrude.y, 0, ty, 0, distance)
- startVertex;
if (e1 >= 0 && e2 >= 0) {
triangleStore.emplace_back(e1, e2, e3);
diff --git a/src/mbgl/renderer/painter_line.cpp b/src/mbgl/renderer/painter_line.cpp
index 30f03ff030..d9d2d9fc5d 100644
--- a/src/mbgl/renderer/painter_line.cpp
+++ b/src/mbgl/renderer/painter_line.cpp
@@ -97,6 +97,7 @@ void Painter::renderLine(LineBucket& bucket, const LineLayer& layer, const TileI
linesdfShader->u_sdfgamma = lineAtlas->width / (properties.dashLineWidth * std::min(posA.width, posB.width) * 256.0 * data.pixelRatio) / 2;
linesdfShader->u_mix = properties.dasharray.value.t;
linesdfShader->u_extra = extra;
+ linesdfShader->u_offset = properties.offset;
linesdfShader->u_antialiasingmatrix = antialiasingMatrix;
bucket.drawLineSDF(*linesdfShader);
@@ -127,6 +128,7 @@ void Painter::renderLine(LineBucket& bucket, const LineLayer& layer, const TileI
linepatternShader->u_fade = properties.pattern.value.t;
linepatternShader->u_opacity = properties.opacity;
linepatternShader->u_extra = extra;
+ linepatternShader->u_offset = properties.offset;
linepatternShader->u_antialiasingmatrix = antialiasingMatrix;
MBGL_CHECK_ERROR(glActiveTexture(GL_TEXTURE0));
@@ -143,6 +145,7 @@ void Painter::renderLine(LineBucket& bucket, const LineLayer& layer, const TileI
lineShader->u_ratio = ratio;
lineShader->u_blur = blur;
lineShader->u_extra = extra;
+ lineShader->u_offset = properties.offset;
lineShader->u_antialiasingmatrix = antialiasingMatrix;
lineShader->u_color = color;
diff --git a/src/mbgl/shader/line.vertex.glsl b/src/mbgl/shader/line.vertex.glsl
index 980212384b..1bd7f5ef5f 100644
--- a/src/mbgl/shader/line.vertex.glsl
+++ b/src/mbgl/shader/line.vertex.glsl
@@ -14,6 +14,7 @@ uniform mat4 u_matrix;
// shared
uniform float u_ratio;
uniform vec2 u_linewidth;
+uniform float u_offset;
uniform float u_extra;
uniform mat2 u_antialiasingmatrix;
@@ -23,6 +24,7 @@ varying float v_gamma_scale;
void main() {
vec2 a_extrude = a_data.xy;
+ float a_direction = sign(a_data.z) * mod(a_data.z, 2.0);
// We store the texture normals in the most insignificant bit
// transform y so that 0 => -1 and 1 => 1
@@ -36,11 +38,19 @@ void main() {
// of this vertex.
vec2 dist = u_linewidth.s * a_extrude * scale;
+ // Calculate the offset when drawing a line that is to the side of the actual line.
+ // We do this by creating a vector that points towards the extrude, but rotate
+ // it when we're drawing round end points (a_direction = -1 or 1) since their
+ // extrude vector points in another direction.
+ float u = 0.5 * a_direction;
+ float t = 1.0 - abs(u);
+ vec2 offset = u_offset * a_extrude * scale * normal.y * mat2(t, -u, u, t);
+
// Remove the texture normal bit of the position before scaling it with the
// model/view matrix. Add the extrusion vector *after* the model/view matrix
// because we're extruding the line in pixel space, regardless of the current
// tile's zoom level.
- gl_Position = u_matrix * vec4(floor(a_pos * 0.5) + dist / u_ratio, 0.0, 1.0);
+ gl_Position = u_matrix * vec4(floor(a_pos * 0.5) + (offset + dist) / u_ratio, 0.0, 1.0);
// position of y on the screen
float y = gl_Position.y / gl_Position.w;
diff --git a/src/mbgl/shader/line_shader.hpp b/src/mbgl/shader/line_shader.hpp
index 50c209ef24..14e03c2eaf 100644
--- a/src/mbgl/shader/line_shader.hpp
+++ b/src/mbgl/shader/line_shader.hpp
@@ -19,6 +19,7 @@ public:
Uniform<GLfloat> u_ratio = {"u_ratio", *this};
Uniform<GLfloat> u_blur = {"u_blur", *this};
Uniform<GLfloat> u_extra = {"u_extra", *this};
+ Uniform<GLfloat> u_offset = {"u_offset", *this};
UniformMatrix<2> u_antialiasingmatrix = {"u_antialiasingmatrix", *this};
private:
diff --git a/src/mbgl/shader/linepattern.vertex.glsl b/src/mbgl/shader/linepattern.vertex.glsl
index 541c9fc3a7..5b3c468be0 100644
--- a/src/mbgl/shader/linepattern.vertex.glsl
+++ b/src/mbgl/shader/linepattern.vertex.glsl
@@ -17,6 +17,7 @@ uniform mat4 u_exmatrix;
// shared
uniform float u_ratio;
uniform vec2 u_linewidth;
+uniform float u_offset;
uniform vec4 u_color;
uniform float u_extra;
@@ -28,7 +29,8 @@ varying float v_gamma_scale;
void main() {
vec2 a_extrude = a_data.xy;
- float a_linesofar = a_data.z * 128.0 + a_data.w;
+ float a_direction = sign(a_data.z) * mod(a_data.z, 2.0);
+ float a_linesofar = abs(floor(a_data.z / 2.0)) + a_data.w * 64.0;
// We store the texture normals in the most insignificant bit
// transform y so that 0 => -1 and 1 => 1
@@ -42,11 +44,19 @@ void main() {
// of this vertex.
vec2 dist = u_linewidth.s * a_extrude * scale;
+ // Calculate the offset when drawing a line that is to the side of the actual line.
+ // We do this by creating a vector that points towards the extrude, but rotate
+ // it when we're drawing round end points (a_direction = -1 or 1) since their
+ // extrude vector points in another direction.
+ float u = 0.5 * a_direction;
+ float t = 1.0 - abs(u);
+ vec2 offset = u_offset * a_extrude * scale * normal.y * mat2(t, -u, u, t);
+
// Remove the texture normal bit of the position before scaling it with the
// model/view matrix. Add the extrusion vector *after* the model/view matrix
// because we're extruding the line in pixel space, regardless of the current
// tile's zoom level.
- gl_Position = u_matrix * vec4(floor(a_pos / 2.0) + dist.xy / u_ratio, 0.0, 1.0);
+ gl_Position = u_matrix * vec4(floor(a_pos / 2.0) + (offset + dist) / u_ratio, 0.0, 1.0);
v_linesofar = a_linesofar;
// position of y on the screen
diff --git a/src/mbgl/shader/linepattern_shader.hpp b/src/mbgl/shader/linepattern_shader.hpp
index aae550665c..6c83cb0cc3 100644
--- a/src/mbgl/shader/linepattern_shader.hpp
+++ b/src/mbgl/shader/linepattern_shader.hpp
@@ -27,6 +27,7 @@ public:
Uniform<GLfloat> u_fade = {"u_fade", *this};
Uniform<GLfloat> u_opacity = {"u_opacity", *this};
Uniform<GLfloat> u_extra = {"u_extra", *this};
+ Uniform<GLfloat> u_offset = {"u_offset", *this};
UniformMatrix<2> u_antialiasingmatrix = {"u_antialiasingmatrix", *this};
private:
diff --git a/src/mbgl/shader/linesdf.vertex.glsl b/src/mbgl/shader/linesdf.vertex.glsl
index 03851ed533..80516f97c0 100644
--- a/src/mbgl/shader/linesdf.vertex.glsl
+++ b/src/mbgl/shader/linesdf.vertex.glsl
@@ -17,6 +17,7 @@ uniform mat4 u_exmatrix;
// shared
uniform float u_ratio;
uniform vec2 u_linewidth;
+uniform float u_offset;
uniform vec2 u_patternscale_a;
uniform float u_tex_y_a;
uniform vec2 u_patternscale_b;
@@ -32,7 +33,8 @@ varying float v_gamma_scale;
void main() {
vec2 a_extrude = a_data.xy;
- float a_linesofar = a_data.z * 128.0 + a_data.w;
+ float a_direction = sign(a_data.z) * mod(a_data.z, 2.0);
+ float a_linesofar = abs(floor(a_data.z / 2.0)) + a_data.w * 64.0;
// We store the texture normals in the most insignificant bit
// transform y so that 0 => -1 and 1 => 1
@@ -46,11 +48,19 @@ void main() {
// of this vertex.
vec2 dist = u_linewidth.s * a_extrude * scale;
+ // Calculate the offset when drawing a line that is to the side of the actual line.
+ // We do this by creating a vector that points towards the extrude, but rotate
+ // it when we're drawing round end points (a_direction = -1 or 1) since their
+ // extrude vector points in another direction.
+ float u = 0.5 * a_direction;
+ float t = 1.0 - abs(u);
+ vec2 offset = u_offset * a_extrude * scale * normal.y * mat2(t, -u, u, t);
+
// Remove the texture normal bit of the position before scaling it with the
// model/view matrix. Add the extrusion vector *after* the model/view matrix
// because we're extruding the line in pixel space, regardless of the current
// tile's zoom level.
- gl_Position = u_matrix * vec4(floor(a_pos * 0.5) + dist / u_ratio, 0.0, 1.0);
+ gl_Position = u_matrix * vec4(floor(a_pos * 0.5) + (offset + dist) / u_ratio, 0.0, 1.0);
v_tex_a = vec2(a_linesofar * u_patternscale_a.x, normal.y * u_patternscale_a.y + u_tex_y_a);
v_tex_b = vec2(a_linesofar * u_patternscale_b.x, normal.y * u_patternscale_b.y + u_tex_y_b);
diff --git a/src/mbgl/shader/linesdf_shader.hpp b/src/mbgl/shader/linesdf_shader.hpp
index 1fdae14069..2a8bdc6629 100644
--- a/src/mbgl/shader/linesdf_shader.hpp
+++ b/src/mbgl/shader/linesdf_shader.hpp
@@ -26,6 +26,7 @@ public:
Uniform<GLfloat> u_sdfgamma = {"u_sdfgamma", *this};
Uniform<GLfloat> u_mix = {"u_mix", *this};
Uniform<GLfloat> u_extra = {"u_extra", *this};
+ Uniform<GLfloat> u_offset = {"u_offset", *this};
UniformMatrix<2> u_antialiasingmatrix = {"u_antialiasingmatrix", *this};
private: