Skip to content

Commit

Permalink
Add basic support for line-color property functions
Browse files Browse the repository at this point in the history
  • Loading branch information
Lucas Wojciechowski committed Aug 18, 2016
1 parent dc81c54 commit e4c7367
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 59 deletions.
22 changes: 20 additions & 2 deletions js/data/bucket/line_bucket.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,16 @@ LineBucket.prototype.programInterfaces = {
components: 4,
type: 'Uint8'
}]),
paintAttributes: [{
name: 'a_color',
components: 4,
type: 'Uint8',
getValue: function(layer, globalProperties, featureProperties) {
return layer.getPaintValue("line-color", globalProperties, featureProperties);
},
multiplier: 255,
paintProperty: 'line-color'
}],
elementArrayType: new Bucket.ElementArrayType()
}
};
Expand All @@ -88,6 +98,7 @@ LineBucket.prototype.addFeature = function(feature) {
for (var i = 0; i < lines.length; i++) {
this.addLine(
lines[i],
feature.properties,
this.layer.layout['line-join'],
this.layer.layout['line-cap'],
this.layer.layout['line-miter-limit'],
Expand All @@ -96,7 +107,7 @@ LineBucket.prototype.addFeature = function(feature) {
}
};

LineBucket.prototype.addLine = function(vertices, join, cap, miterLimit, roundLimit) {
LineBucket.prototype.addLine = function(vertices, featureProperties, join, cap, miterLimit, roundLimit) {

var len = vertices.length;
// If the line has duplicate vertices at the end, adjust length to remove them.
Expand All @@ -116,7 +127,8 @@ LineBucket.prototype.addLine = function(vertices, join, cap, miterLimit, roundLi
closed = firstVertex.equals(lastVertex);

// we could be more precise, but it would only save a negligible amount of space
this.prepareArrayGroup('line', len * 10);
var group = this.prepareArrayGroup('line', len * 10);
var startIndex = group.layoutVertexArray.length;

// a line may not have coincident points
if (len === 2 && closed) return;
Expand Down Expand Up @@ -347,6 +359,12 @@ LineBucket.prototype.addLine = function(vertices, join, cap, miterLimit, roundLi
startOfLine = false;
}

this.populatePaintArrays(
'line', {zoom: this.zoom},
featureProperties,
group,
startIndex
);
};

/**
Expand Down
126 changes: 75 additions & 51 deletions js/render/draw_line.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,23 @@ module.exports = function drawLine(painter, source, layer, coords) {
// don't draw zero-width lines
if (layer.paint['line-width'] <= 0) return;

for (var k = 0; k < coords.length; k++) {
drawLineTile(painter, source, layer, coords[k]);
}

};

function drawLineTile(painter, source, layer, coord) {
var tile = source.getTile(coord);
var bucket = tile.getBucket(layer);
if (!bucket) return;
var bufferGroups = bucket.bufferGroups.line;
if (!bufferGroups) return;

var gl = painter.gl;

var programOptions = bucket.paintAttributes.line[layer.id];

// the distance over which the line edge fades out.
// Retina devices need a smaller distance to avoid aliasing.
var antialiasing = 1 / browser.devicePixelRatio;
Expand All @@ -49,7 +66,12 @@ module.exports = function drawLine(painter, source, layer, coords) {
var program, posA, posB, imagePosA, imagePosB;

if (dasharray) {
program = painter.useProgram('linesdfpattern');
program = painter.useProgram(
'linesdfpattern',
programOptions.defines,
programOptions.vertexPragmas,
programOptions.fragmentPragmas
);

gl.uniform1f(program.u_linewidth, layer.paint['line-width'] / 2);
gl.uniform1f(program.u_gapwidth, layer.paint['line-gap-width'] / 2);
Expand Down Expand Up @@ -77,7 +99,12 @@ module.exports = function drawLine(painter, source, layer, coords) {
imagePosB = painter.spriteAtlas.getPosition(image.to, true);
if (!imagePosA || !imagePosB) return;

program = painter.useProgram('linepattern');
program = painter.useProgram(
'linepattern',
programOptions.defines,
programOptions.vertexPragmas,
programOptions.fragmentPragmas
);

gl.uniform1i(program.u_image, 0);
gl.activeTexture(gl.TEXTURE0);
Expand All @@ -98,7 +125,12 @@ module.exports = function drawLine(painter, source, layer, coords) {
gl.uniformMatrix2fv(program.u_antialiasingmatrix, false, antialiasingMatrix);

} else {
program = painter.useProgram('line');
program = painter.useProgram(
'line',
programOptions.defines,
programOptions.vertexPragmas,
programOptions.fragmentPragmas
);

gl.uniform1f(program.u_linewidth, layer.paint['line-width'] / 2);
gl.uniform1f(program.u_gapwidth, layer.paint['line-gap-width'] / 2);
Expand All @@ -111,53 +143,45 @@ module.exports = function drawLine(painter, source, layer, coords) {
gl.uniform1f(program.u_opacity, layer.paint['line-opacity']);
}

for (var k = 0; k < coords.length; k++) {
var coord = coords[k];
var tile = source.getTile(coord);
var bucket = tile.getBucket(layer);
if (!bucket) continue;
var bufferGroups = bucket.bufferGroups.line;
if (!bufferGroups) continue;

painter.enableTileClippingMask(coord);

// set uniforms that are different for each tile
var posMatrix = painter.translatePosMatrix(coord.posMatrix, tile, layer.paint['line-translate'], layer.paint['line-translate-anchor']);
gl.uniformMatrix4fv(program.u_matrix, false, posMatrix);

var ratio = 1 / pixelsToTileUnits(tile, 1, painter.transform.zoom);

if (dasharray) {
var widthA = posA.width * dasharray.fromScale;
var widthB = posB.width * dasharray.toScale;
var scaleA = [1 / pixelsToTileUnits(tile, widthA, painter.transform.tileZoom), -posA.height / 2];
var scaleB = [1 / pixelsToTileUnits(tile, widthB, painter.transform.tileZoom), -posB.height / 2];
var gamma = painter.lineAtlas.width / (Math.min(widthA, widthB) * 256 * browser.devicePixelRatio) / 2;
gl.uniform1f(program.u_ratio, ratio);
gl.uniform2fv(program.u_patternscale_a, scaleA);
gl.uniform2fv(program.u_patternscale_b, scaleB);
gl.uniform1f(program.u_sdfgamma, gamma);

} else if (image) {
gl.uniform1f(program.u_ratio, ratio);
gl.uniform2fv(program.u_pattern_size_a, [
pixelsToTileUnits(tile, imagePosA.size[0] * image.fromScale, painter.transform.tileZoom),
imagePosB.size[1]
]);
gl.uniform2fv(program.u_pattern_size_b, [
pixelsToTileUnits(tile, imagePosB.size[0] * image.toScale, painter.transform.tileZoom),
imagePosB.size[1]
]);

} else {
gl.uniform1f(program.u_ratio, ratio);
}

for (var i = 0; i < bufferGroups.length; i++) {
var group = bufferGroups[i];
group.vaos[layer.id].bind(gl, program, group.layoutVertexBuffer, group.elementBuffer);
gl.drawElements(gl.TRIANGLES, group.elementBuffer.length * 3, gl.UNSIGNED_SHORT, 0);
}
painter.enableTileClippingMask(coord);

// set uniforms that are different for each tile
var posMatrix = painter.translatePosMatrix(coord.posMatrix, tile, layer.paint['line-translate'], layer.paint['line-translate-anchor']);
gl.uniformMatrix4fv(program.u_matrix, false, posMatrix);

var ratio = 1 / pixelsToTileUnits(tile, 1, painter.transform.zoom);

if (dasharray) {
var widthA = posA.width * dasharray.fromScale;
var widthB = posB.width * dasharray.toScale;
var scaleA = [1 / pixelsToTileUnits(tile, widthA, painter.transform.tileZoom), -posA.height / 2];
var scaleB = [1 / pixelsToTileUnits(tile, widthB, painter.transform.tileZoom), -posB.height / 2];
var gamma = painter.lineAtlas.width / (Math.min(widthA, widthB) * 256 * browser.devicePixelRatio) / 2;
gl.uniform1f(program.u_ratio, ratio);
gl.uniform2fv(program.u_patternscale_a, scaleA);
gl.uniform2fv(program.u_patternscale_b, scaleB);
gl.uniform1f(program.u_sdfgamma, gamma);

} else if (image) {
gl.uniform1f(program.u_ratio, ratio);
gl.uniform2fv(program.u_pattern_size_a, [
pixelsToTileUnits(tile, imagePosA.size[0] * image.fromScale, painter.transform.tileZoom),
imagePosB.size[1]
]);
gl.uniform2fv(program.u_pattern_size_b, [
pixelsToTileUnits(tile, imagePosB.size[0] * image.toScale, painter.transform.tileZoom),
imagePosB.size[1]
]);

} else {
gl.uniform1f(program.u_ratio, ratio);
}

};
bucket.setUniforms(gl, 'line', program, layer, {zoom: painter.transform.zoom});

for (var i = 0; i < bufferGroups.length; i++) {
var group = bufferGroups[i];
group.vaos[layer.id].bind(gl, program, group.layoutVertexBuffer, group.elementBuffer, group.paintVertexBuffers[layer.id]);
gl.drawElements(gl.TRIANGLES, group.elementBuffer.length * 3, gl.UNSIGNED_SHORT, 0);
}
}
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"gl-matrix": "^2.3.1",
"grid-index": "^1.0.0",
"mapbox-gl-function": "^1.2.1",
"mapbox-gl-shaders": "mapbox/mapbox-gl-shaders#de2ab007455aa2587c552694c68583f94c9f2747",
"mapbox-gl-shaders": "mapbox/mapbox-gl-shaders#df162476980d9ee2ab6f8d0cf5a06e27aac60472",
"mapbox-gl-style-spec": "mapbox/mapbox-gl-style-spec#83b1a3e5837d785af582efd5ed1a212f2df6a4ae",
"mapbox-gl-supported": "^1.2.0",
"pbf": "^1.3.2",
Expand Down Expand Up @@ -62,7 +62,7 @@
"istanbul": "^0.4.2",
"json-loader": "^0.5.4",
"lodash": "^4.13.1",
"mapbox-gl-test-suite": "mapbox/mapbox-gl-test-suite#7babab52fb02788ebbc38384139bf350e8e38552",
"mapbox-gl-test-suite": "mapbox/mapbox-gl-test-suite#15e18375321393364907208715ab82c5a9c70f60",
"memory-fs": "^0.3.0",
"minifyify": "^7.0.1",
"nyc": "6.4.0",
Expand Down
8 changes: 4 additions & 4 deletions test/js/data/line_bucket.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,27 +28,27 @@ test('LineBucket', function(t) {
// should throw in the future?
t.equal(bucket.addLine([
new Point(0, 0)
]), undefined);
], {}), undefined);

// should also throw in the future?
// this is a closed single-segment line
t.equal(bucket.addLine([
new Point(0, 0),
new Point(0, 0)
]), undefined);
], {}), undefined);

t.equal(bucket.addLine([
new Point(0, 0),
new Point(10, 10),
new Point(10, 20)
]), undefined);
], {}), undefined);

t.equal(bucket.addLine([
new Point(0, 0),
new Point(10, 10),
new Point(10, 20),
new Point(0, 0)
]), undefined);
], {}), undefined);

t.equal(bucket.addFeature(feature), undefined);

Expand Down

0 comments on commit e4c7367

Please sign in to comment.