Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
Lucas Wojciechowski committed Jan 14, 2016
1 parent c1d8e06 commit 27e0443
Show file tree
Hide file tree
Showing 11 changed files with 197 additions and 91 deletions.
2 changes: 1 addition & 1 deletion debug/random.geojson

Large diffs are not rendered by default.

7 changes: 6 additions & 1 deletion debug/site.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,12 @@ map.on('style.load', function() {
"source": "geojson-random-points",
"paint": {
"circle-radius": 5,
"circle-color": "#f0f"
"circle-opacity": 0.5,
"circle-color": {
range: ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet'],
domain: [0, 16, 32, 48, 64, 80, 100],
property: 'mapbox'
}
}
});

Expand Down
74 changes: 67 additions & 7 deletions js/data/bucket.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,8 @@ function Bucket(options) {
this[this.getAddMethodName(shaderName, 'vertex')] = createVertexAddMethod(
shaderName,
shader,
this.getBufferName(shaderName, 'vertex')
this.getBufferName(shaderName, 'vertex'),
this._getEnabledAttributes(shaderName)
);
}
}
Expand Down Expand Up @@ -122,7 +123,7 @@ Bucket.prototype.resetBuffers = function(buffers) {
if (shader.vertexBuffer && !buffers[vertexBufferName]) {
buffers[vertexBufferName] = new Buffer({
type: Buffer.BufferType.VERTEX,
attributes: shader.attributes
attributes: this._getEnabledAttributes(shaderName)
});
}

Expand Down Expand Up @@ -150,6 +151,61 @@ Bucket.prototype.resetBuffers = function(buffers) {
}
};

Bucket.prototype._getEnabledAttributes = function(shaderName) {
return this.shaders[shaderName].attributes.filter(function(attribute) {
return !attribute.isDisabled || !attribute.isDisabled.call(this);
}, this);
};

/**
* Set the attribute pointers in a WebGL context
* @private
* @param gl The WebGL context
* @param shader The active WebGL shader
* @param {number} offset The offset of the attribute data in the currently bound GL buffer.
*/
Bucket.prototype.setAttribPointers = function(shaderName, gl, glShader, offset, args) {
var attributes = this.shaders[shaderName].attributes;

// Set disabled attributes
for (var i = 0; i < attributes.length; i++) {
var attribute = attributes[i];
var glAttribute = glShader['a_' + attribute.name];
if (attribute.isDisabled && attribute.isDisabled.call(this)) {
gl.disableVertexAttribArray(glAttribute);
gl['vertexAttrib' + attribute.components + 'fv'](glAttribute, this._getAttributeValue(shaderName, attribute, args));
}
}

// Set enabled attributes
this.buffers[this.getBufferName(shaderName, 'vertex')].setAttribPointers(gl, glShader, offset);
};

var _getAttributeValueCache = {};
// TODO break the function creation logic into a separate function
Bucket.prototype._getAttributeValue = function(shaderName, attribute, args) {
if (!_getAttributeValueCache[shaderName]) _getAttributeValueCache[shaderName] = {};

if (!_getAttributeValueCache[shaderName][attribute.name]) {
var bodyArgs = this.shaders[shaderName].attributeArgs;
var body = 'return ';
if (Array.isArray(attribute.value)) {
body += '[' + attribute.value.join(', ') + ']';
} else {
body += attribute.value;
}
_getAttributeValueCache[shaderName][attribute.name] = new Function(bodyArgs, body);
}

var value = _getAttributeValueCache[shaderName][attribute.name].apply(this, args);

if (attribute.multiplier) {
return value.map(function(v) { return v * attribute.multiplier; });
} else {
return value;
}
};

/**
* Get the name of the method used to add an item to a buffer.
* @param {string} shaderName The name of the shader that will use the buffer
Expand Down Expand Up @@ -218,12 +274,12 @@ function createPaintProperties(layer, zoom) {
}

var createVertexAddMethodCache = {};
function createVertexAddMethod(shaderName, shader, bufferName) {
function createVertexAddMethod(shaderName, shader, bufferName, enabledAttributes) {
var body = '';

var pushArgs = [];
for (var i = 0; i < shader.attributes.length; i++) {
var attribute = shader.attributes[i];
for (var i = 0; i < enabledAttributes.length; i++) {
var attribute = enabledAttributes[i];

var attributePushArgs = [];
if (Array.isArray(attribute.value)) {
Expand All @@ -236,13 +292,17 @@ function createVertexAddMethod(shaderName, shader, bufferName) {
}
}

var multipliedAttributePushArgs;
if (attribute.multiplier) {
multipliedAttributePushArgs = [];
for (var k = 0; k < attributePushArgs.length; k++) {
attributePushArgs[k] += '*' + attribute.multiplier;
multipliedAttributePushArgs[k] = attributePushArgs[k] + '*' + attribute.multiplier;
}
} else {
multipliedAttributePushArgs = attributePushArgs;
}

pushArgs = pushArgs.concat(attributePushArgs);
pushArgs = pushArgs.concat(multipliedAttributePushArgs);
}

body += 'return this.buffers.' + bufferName + '.push(' + pushArgs.join(',') + ');';
Expand Down
26 changes: 18 additions & 8 deletions js/data/circle_bucket.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

var Bucket = require('./bucket');
var util = require('../util/util');
var StyleFunction = require('../style/style_function');
var parseColor = require('../style/parse_color');

module.exports = CircleBucket;

Expand All @@ -14,7 +16,9 @@ var EXTENT = 4096;
* vector that is where it points.
* @private
*/
function CircleBucket() {
function CircleBucket(options) {
this.opacityFunction = StyleFunction.create({function: 'interpolated'}, options.layer.paint['circle-opacity'] || 1);
this.colorFunction = StyleFunction.create({function: 'interpolated'}, parseColor(options.layer.paint['circle-color'] || [0, 0, 0, 1]));
Bucket.apply(this, arguments);
}

Expand All @@ -25,7 +29,7 @@ CircleBucket.prototype.shaders = {
vertexBuffer: true,
elementBuffer: true,

attributeArgs: ['x', 'y', 'extrudeX', 'extrudeY', 'paint'],
attributeArgs: ['global', 'feature', 'x', 'y', 'extrudeX', 'extrudeY'],

attributes: [{
name: 'pos',
Expand All @@ -39,12 +43,18 @@ CircleBucket.prototype.shaders = {
name: 'color',
components: 4,
type: Bucket.AttributeType.UNSIGNED_BYTE,
value: 'paint["circle-color"]',
multiplier: 255
value: 'this.premultiplyColor(this.colorFunction(global, feature), this.opacityFunction(global, feature))',
multiplier: 255,
isDisabled: function() { return this.colorFunction.isFeatureConstant && this.opacityFunction.isFeatureConstant; }
}]
}
};

CircleBucket.prototype.premultiplyColor = function(color, additionalOpacity) {
var opacity = color[3] * additionalOpacity;
return [color[0] * opacity, color[1] * opacity, color[2] * opacity, opacity];
};

CircleBucket.prototype.addFeature = function(feature) {

var geometries = feature.loadGeometry()[0];
Expand All @@ -66,10 +76,10 @@ CircleBucket.prototype.addFeature = function(feature) {
// │ 0 1 │
// └─────────┘

var index = this.addCircleVertex(x, y, -1, -1, this.paintProperties) - group.vertexStartIndex;
this.addCircleVertex(x, y, 1, -1, this.paintProperties);
this.addCircleVertex(x, y, 1, 1, this.paintProperties);
this.addCircleVertex(x, y, -1, 1, this.paintProperties);
var index = this.addCircleVertex(null, feature.properties, x, y, -1, -1) - group.vertexStartIndex;
this.addCircleVertex(null, feature.properties, x, y, 1, -1);
this.addCircleVertex(null, feature.properties, x, y, 1, 1);
this.addCircleVertex(null, feature.properties, x, y, -1, 1);
group.vertexLength += 4;

this.addCircleElement(index, index + 1, index + 2);
Expand Down
7 changes: 4 additions & 3 deletions js/render/draw_circle.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ function drawCircles(painter, source, layer, coords) {
var antialias = 1 / browser.devicePixelRatio / layer.paint['circle-radius'];

gl.disableVertexAttribArray(shader.a_blur);
gl.vertexAttrib1f(shader.a_blur, Math.max(layer.paint['circle-blur'], antialias) * 255);
gl.vertexAttrib1f(shader.a_blur, Math.max(layer.paint['circle-blur'], antialias));

gl.disableVertexAttribArray(shader.a_size);
gl.vertexAttrib1f(shader.a_size, layer.paint['circle-radius'] * 255);
gl.vertexAttrib1f(shader.a_size, layer.paint['circle-radius']);

for (var i = 0; i < coords.length; i++) {
var coord = coords[i];
Expand All @@ -39,6 +39,7 @@ function drawCircles(painter, source, layer, coords) {
if (!tile.elementGroups[layer.ref || layer.id].circle) continue;

var elementGroups = tile.elementGroups[layer.ref || layer.id].circle;
var bucket = tile.buckets[layer.ref || layer.id];
var vertex = tile.buffers.circleVertex;
var elements = tile.buffers.circleElement;

Expand All @@ -55,7 +56,7 @@ function drawCircles(painter, source, layer, coords) {
var offset = group.vertexStartIndex * vertex.itemSize;

vertex.bind(gl);
vertex.setAttribPointers(gl, shader, offset);
bucket.setAttribPointers('circle', gl, shader, offset, [{$zoom: painter.transform.zoom}]);

elements.bind(gl);

Expand Down
4 changes: 4 additions & 0 deletions js/render/gl_util.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,10 @@ exports.extend = function(context) {
}
};

context.vertexAttrib1fv = function(attribute, values) {
context.vertexAttrib1f(attribute, values[0]);
};

context.vertexAttrib2fv = function(attribute, values) {
context.vertexAttrib2f(attribute, values[0], values[1]);
};
Expand Down
2 changes: 1 addition & 1 deletion js/source/tile.js
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ function unserializeBuffers(input) {
function unserializeBuckets(input, buffers) {
var output = {};
for (var i = 0; i < input.length; i++) {
var bucket = new Bucket(util.extend(input[i], {buffers: buffers}));
var bucket = Bucket.create(util.extend(input[i], {buffers: buffers}));
output[bucket.id] = bucket;
}
return output;
Expand Down
47 changes: 47 additions & 0 deletions js/style/parse_color.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
'use strict';

var parseCSSColor = require('csscolorparser').parseCSSColor;
var util = require('../util/util');

var colorCache = {};

function parseColor(input) {

if (colorCache[input]) {
return colorCache[input];

// RGBA array
} else if (Array.isArray(input)) {
return input;

// style function
} else if (input && input.range) {
return util.extend({}, input, {
range: input.range.map(parseColor)
});

// legacy style function
} else if (input && input.stops) {
return util.extend({}, input, {
stops: input.stops.map(function(step) {
return [step[0], parseColor(step[1])];
})
});

// Color string
} else if (typeof input === 'string') {
var output = colorDowngrade(parseCSSColor(input));
colorCache[input] = output;
return output;

} else {
throw new Error('Invalid color ' + input);
}

}

function colorDowngrade(color) {
return [color[0] / 255, color[1] / 255, color[2] / 255, color[3]];
}

module.exports = parseColor;
70 changes: 3 additions & 67 deletions js/style/style_declaration.js
Original file line number Diff line number Diff line change
@@ -1,36 +1,7 @@
'use strict';

var parseCSSColor = require('csscolorparser').parseCSSColor;
var createGLFunction = require('mapbox-gl-function');
var util = require('../util/util');

function createBackwardsCompatibleGLFunction(reference, parameters) {
if (parameters.stops) {
var domain = [];
var range = [];

for (var i = 0; i < parameters.stops.length; i++) {
domain.push(parameters.stops[i][0]);
range.push(parameters.stops[i][1]);
}

parameters.domain = domain;
parameters.range = range;
delete parameters.stops;

if (reference.function === 'interpolated') {
parameters.type = 'exponential';
} else {
parameters.domain.shift();
parameters.type = 'interval';
}
}

var fun = createGLFunction(parameters);
return function(zoom) {
return fun({$zoom: zoom});
};
}
var StyleFunction = require('./style_function');
var parseColor = require('./parse_color');

module.exports = StyleDeclaration;

Expand All @@ -51,7 +22,7 @@ function StyleDeclaration(reference, value) {
this.value = value;
}

this.calculate = createBackwardsCompatibleGLFunction(reference, this.value);
this.calculate = StyleFunction.createBackwardsCompatible(reference, this.value);

if (reference.function !== 'interpolated' && reference.transition) {
this.calculate = transitioned(this.calculate);
Expand Down Expand Up @@ -87,38 +58,3 @@ function transitioned(calculate) {
};
};
}

var colorCache = {};

function parseColor(input) {

if (colorCache[input]) {
return colorCache[input];

// RGBA array
} else if (Array.isArray(input)) {
return input;

// GL function
} else if (input && input.stops) {
return util.extend({}, input, {
stops: input.stops.map(function(step) {
return [step[0], parseColor(step[1])];
})
});

// Color string
} else if (typeof input === 'string') {
var output = colorDowngrade(parseCSSColor(input));
colorCache[input] = output;
return output;

} else {
throw new Error('Invalid color ' + input);
}

}

function colorDowngrade(color) {
return [color[0] / 255, color[1] / 255, color[2] / 255, color[3] / 1];
}
Loading

0 comments on commit 27e0443

Please sign in to comment.