[core] rudimentary support for offsetting lines

This commit is contained in:
Konstantin Käfer
2015-11-25 12:42:34 +01:00
committed by John Firebaugh
parent c279fb1717
commit 964a1e7b62
13 changed files with 61 additions and 14 deletions

View File

@@ -26,7 +26,7 @@
],
"devDependencies": {
"aws-sdk": "^2.2.19",
"mapbox-gl-test-suite": "mapbox/mapbox-gl-test-suite#b345658107e1772dbf7e24c4a8e53590cb78521d",
"mapbox-gl-test-suite": "mapbox/mapbox-gl-test-suite#a9f967740f1045e0ecaa5d7ebd9afbd7e84d0f94",
"node-gyp": "^3.2.0",
"request": "^2.67.0",
"tape": "^4.2.2"

View File

@@ -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;
}

View File

@@ -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);
};

View File

@@ -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);

View File

@@ -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 = { "" };

View File

@@ -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);

View File

@@ -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;

View File

@@ -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;

View File

@@ -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:

View File

@@ -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

View File

@@ -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:

View File

@@ -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);

View File

@@ -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: