Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable property functions for {text,icon}-{color,halo-color} #4186

Merged
merged 4 commits into from
Feb 7, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 18 additions & 6 deletions src/data/bucket/symbol_bucket.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,19 @@ const layoutVertexArrayType = createVertexArrayType([
const symbolInterfaces = {
glyph: {
layoutVertexArrayType: layoutVertexArrayType,
elementArrayType: elementArrayType
elementArrayType: elementArrayType,
paintAttributes: [
{name: 'a_fill_color', property: 'text-color', type: 'Uint8'},
{name: 'a_halo_color', property: 'text-halo-color', type: 'Uint8'}
]
},
icon: {
layoutVertexArrayType: layoutVertexArrayType,
elementArrayType: elementArrayType
elementArrayType: elementArrayType,
paintAttributes: [
{name: 'a_fill_color', property: 'icon-color', type: 'Uint8'},
{name: 'a_halo_color', property: 'icon-halo-color', type: 'Uint8'}
]
},
collisionBox: {
layoutVertexArrayType: createVertexArrayType([
Expand Down Expand Up @@ -447,7 +455,7 @@ class SymbolBucket {
this.symbolInstances.sort((a, b) => {
const aRotated = (sin * a.anchor.x + cos * a.anchor.y) | 0;
const bRotated = (sin * b.anchor.x + cos * b.anchor.y) | 0;
return (aRotated - bRotated) || (b.index - a.index);
return (aRotated - bRotated) || (b.featureIndex - a.featureIndex);
});
}

Expand Down Expand Up @@ -497,14 +505,14 @@ class SymbolBucket {
if (hasText) {
collisionTile.insertCollisionFeature(textCollisionFeature, glyphScale, layout['text-ignore-placement']);
if (glyphScale <= maxScale) {
this.addSymbols(this.arrays.glyph, symbolInstance.glyphQuads, glyphScale, layout['text-keep-upright'], textAlongLine, collisionTile.angle, symbolInstance.writingModes);
this.addSymbols(this.arrays.glyph, symbolInstance.glyphQuads, glyphScale, layout['text-keep-upright'], textAlongLine, collisionTile.angle, symbolInstance.featureProperties, symbolInstance.writingModes);
}
}

if (hasIcon) {
collisionTile.insertCollisionFeature(iconCollisionFeature, iconScale, layout['icon-ignore-placement']);
if (iconScale <= maxScale) {
this.addSymbols(this.arrays.icon, symbolInstance.iconQuads, iconScale, layout['icon-keep-upright'], iconAlongLine, collisionTile.angle);
this.addSymbols(this.arrays.icon, symbolInstance.iconQuads, iconScale, layout['icon-keep-upright'], iconAlongLine, collisionTile.angle, symbolInstance.featureProperties);
}
}

Expand All @@ -513,7 +521,7 @@ class SymbolBucket {
if (showCollisionBoxes) this.addToDebugBuffers(collisionTile);
}

addSymbols(arrays, quads, scale, keepUpright, alongLine, placementAngle, writingModes) {
addSymbols(arrays, quads, scale, keepUpright, alongLine, placementAngle, featureProperties, writingModes) {
const elementArray = arrays.elementArray;
const layoutVertexArray = arrays.layoutVertexArray;

Expand Down Expand Up @@ -561,6 +569,8 @@ class SymbolBucket {
segment.vertexLength += 4;
segment.primitiveLength += 2;
}

arrays.populatePaintArrays(featureProperties);
}

addToDebugBuffers(collisionTile) {
Expand Down Expand Up @@ -652,6 +662,8 @@ class SymbolBucket {
glyphQuads,
iconQuads,
anchor,
featureIndex,
featureProperties,
writingModes
});
}
Expand Down
10 changes: 9 additions & 1 deletion src/data/program_configuration.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
'use strict';

const assert = require('assert');
const createVertexArrayType = require('./vertex_array_type');
const util = require('../util/util');

Expand Down Expand Up @@ -34,6 +35,7 @@ class ProgramConfiguration {

for (const attributeConfig of attributes) {
const attribute = normalizePaintAttribute(attributeConfig, layer);
assert(/^a_/.test(attribute.name));
const name = attribute.name.slice(2);

if (layer.isPaintValueFeatureConstant(attribute.property)) {
Expand Down Expand Up @@ -210,7 +212,13 @@ function getPaintAttributeValue(attribute, layer, globalProperties, featurePrope
}

function normalizePaintAttribute(attribute, layer) {
const name = attribute.property.replace(`${layer.type}-`, '').replace(/-/g, '_');
let name = attribute.name;

// by default, construct the shader variable name for paint attribute
// `layertype-some-property` as `some_property`
if (!name) {
name = attribute.property.replace(`${layer.type}-`, '').replace(/-/g, '_');
}
const isColor = layer._paintSpecifications[attribute.property].type === 'color';

return util.extend({
Expand Down
26 changes: 15 additions & 11 deletions src/render/draw_symbol.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,7 @@ function drawSymbols(painter, sourceCache, layer, coords) {
layer.paint['icon-halo-width'],
layer.paint['icon-halo-color'],
layer.paint['icon-halo-blur'],
layer.paint['icon-opacity'],
layer.paint['icon-color']
layer.paint['icon-opacity']
);

drawLayerSymbols(painter, sourceCache, layer, coords, true,
Expand All @@ -60,8 +59,7 @@ function drawSymbols(painter, sourceCache, layer, coords) {
layer.paint['text-halo-width'],
layer.paint['text-halo-color'],
layer.paint['text-halo-blur'],
layer.paint['text-opacity'],
layer.paint['text-color']
layer.paint['text-opacity']
);

if (sourceCache.map.showCollisionBoxes) {
Expand All @@ -70,7 +68,7 @@ function drawSymbols(painter, sourceCache, layer, coords) {
}

function drawLayerSymbols(painter, sourceCache, layer, coords, isText, translate, translateAnchor,
rotationAlignment, pitchAlignment, size, haloWidth, haloColor, haloBlur, opacity, color) {
rotationAlignment, pitchAlignment, size, haloWidth, haloColor, haloBlur, opacity) {

if (!isText && painter.style.sprite && !painter.style.sprite.loaded())
return;
Expand All @@ -96,11 +94,14 @@ function drawLayerSymbols(painter, sourceCache, layer, coords, isText, translate
if (!bucket) continue;
const buffers = isText ? bucket.buffers.glyph : bucket.buffers.icon;
if (!buffers || !buffers.segments.length) continue;
const layerData = buffers.layerData[layer.id];
const programConfiguration = layerData.programConfiguration;

const isSDF = isText || bucket.sdfIcons;

if (!program || bucket.fontstack !== prevFontstack) {
program = painter.useProgram(isSDF ? 'symbolSDF' : 'symbolIcon');
program = painter.useProgram(isSDF ? 'symbolSDF' : 'symbolIcon', programConfiguration);
programConfiguration.setUniforms(gl, program, layer, {zoom: painter.transform.zoom});

setSymbolDrawState(program, painter, isText, isSDF, rotateWithMap, pitchWithMap, bucket.fontstack, size,
bucket.iconsNeedLinear, isText ? bucket.adjustedTextSize : bucket.adjustedIconSize, opacity);
Expand All @@ -112,7 +113,7 @@ function drawLayerSymbols(painter, sourceCache, layer, coords, isText, translate
painter.translatePosMatrix(coord.posMatrix, tile, translate, translateAnchor));

drawTileSymbols(program, painter, layer, tile, buffers, isText, isSDF,
pitchWithMap, size, haloWidth, haloColor, haloBlur, color);
pitchWithMap, size, haloWidth, haloColor, haloBlur);

prevFontstack = bucket.fontstack;
}
Expand Down Expand Up @@ -164,7 +165,7 @@ function setSymbolDrawState(program, painter, isText, isSDF, rotateWithMap, pitc
}

function drawTileSymbols(program, painter, layer, tile, buffers, isText, isSDF,
pitchWithMap, size, haloWidth, haloColor, haloBlur, color) {
pitchWithMap, size, haloWidth, haloColor, haloBlur) {

const gl = painter.gl;
const tr = painter.transform;
Expand All @@ -184,23 +185,26 @@ function drawTileSymbols(program, painter, layer, tile, buffers, isText, isSDF,

if (haloWidth) { // Draw halo underneath the text.
gl.uniform1f(program.u_gamma, (haloBlur * blurOffset / sdfPx + gamma) / gammaScale);
gl.uniform4fv(program.u_color, haloColor);
gl.uniform1f(program.u_buffer, (haloOffset - haloWidth / fontScale) / sdfPx);
gl.uniform1f(program.u_is_halo, 1);

drawSymbolElements(buffers, layer, gl, program);
}

gl.uniform1f(program.u_is_halo, 0);
gl.uniform1f(program.u_gamma, gamma / gammaScale);
gl.uniform4fv(program.u_color, color);
gl.uniform1f(program.u_buffer, (256 - 64) / 256);
}

drawSymbolElements(buffers, layer, gl, program);
}

function drawSymbolElements(buffers, layer, gl, program) {
const layerData = buffers.layerData[layer.id];
const paintVertexBuffer = layerData && layerData.paintVertexBuffer;

for (const segment of buffers.segments) {
segment.vaos[layer.id].bind(gl, program, buffers.layoutVertexBuffer, buffers.elementBuffer, null, segment.vertexOffset);
segment.vaos[layer.id].bind(gl, program, buffers.layoutVertexBuffer, buffers.elementBuffer, paintVertexBuffer, segment.vertexOffset);
gl.drawElements(gl.TRIANGLES, segment.primitiveLength * 3, gl.UNSIGNED_SHORT, segment.primitiveOffset * 3 * 2);
}
}
15 changes: 13 additions & 2 deletions src/shaders/symbol_sdf.fragment.glsl
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
#pragma mapbox: define lowp vec4 fill_color
#pragma mapbox: define lowp vec4 halo_color
uniform bool u_is_halo;

uniform sampler2D u_texture;
uniform sampler2D u_fadetexture;
uniform lowp vec4 u_color;
uniform lowp float u_opacity;
uniform lowp float u_buffer;
uniform lowp float u_gamma;
Expand All @@ -10,12 +13,20 @@ varying vec2 v_fade_tex;
varying float v_gamma_scale;

void main() {
#pragma mapbox: initialize lowp vec4 fill_color
#pragma mapbox: initialize lowp vec4 halo_color

lowp vec4 color = fill_color;
if (u_is_halo) {
color = halo_color;
}

lowp float dist = texture2D(u_texture, v_tex).a;
lowp float fade_alpha = texture2D(u_fadetexture, v_fade_tex).a;
lowp float gamma = u_gamma * v_gamma_scale;
lowp float alpha = smoothstep(u_buffer - gamma, u_buffer + gamma, dist) * fade_alpha;

gl_FragColor = u_color * (alpha * u_opacity);
gl_FragColor = color * (alpha * u_opacity);

#ifdef OVERDRAW_INSPECTOR
gl_FragColor = vec4(1.0);
Expand Down
5 changes: 5 additions & 0 deletions src/shaders/symbol_sdf.vertex.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ attribute vec2 a_offset;
attribute vec2 a_texture_pos;
attribute vec4 a_data;

#pragma mapbox: define lowp vec4 fill_color
#pragma mapbox: define lowp vec4 halo_color

// matrix is for the vertex position.
uniform mat4 u_matrix;
Expand All @@ -24,6 +26,9 @@ varying vec2 v_fade_tex;
varying float v_gamma_scale;

void main() {
#pragma mapbox: initialize lowp vec4 fill_color
#pragma mapbox: initialize lowp vec4 halo_color

vec2 a_tex = a_texture_pos.xy;
mediump float a_labelminzoom = a_data[0];
mediump vec2 a_zoom = a_data.pq;
Expand Down
4 changes: 4 additions & 0 deletions src/style-spec/reference/v8.json
Original file line number Diff line number Diff line change
Expand Up @@ -2498,6 +2498,7 @@
"default": "#000000",
"function": "interpolated",
"zoom-function": true,
"property-function": true,
"transition": true,
"doc": "The color of the icon. This can only be used with sdf icons.",
"requires": [
Expand All @@ -2518,6 +2519,7 @@
"default": "rgba(0, 0, 0, 0)",
"function": "interpolated",
"zoom-function": true,
"property-function": true,
"transition": true,
"doc": "The color of the icon's halo. Icon halos can only be used with SDF icons.",
"requires": [
Expand Down Expand Up @@ -2659,6 +2661,7 @@
"default": "#000000",
"function": "interpolated",
"zoom-function": true,
"property-function": true,
"transition": true,
"requires": [
"text-field"
Expand All @@ -2678,6 +2681,7 @@
"default": "rgba(0, 0, 0, 0)",
"function": "interpolated",
"zoom-function": true,
"property-function": true,
"transition": true,
"doc": "The color of the text's halo, which helps it stand out from backgrounds.",
"requires": [
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
{
"version": 8,
"metadata": {
"test": {
"width": 64,
"height": 64
}
},
"sources": {
"geojson": {
"type": "geojson",
"data": {
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": { "x": 0 },
"geometry": {
"type": "Point",
"coordinates": [
0,
-10
]
}
},
{
"type": "Feature",
"properties": { "x": 1 },
"geometry": {
"type": "Point",
"coordinates": [
0,
10
]
}
}
]
}
}
},
"sprite": "local://sprites/sprite",
"layers": [
{
"id": "symbol",
"type": "symbol",
"source": "geojson",
"layout": {
"icon-image": "dot.sdf"
},
"paint": {
"icon-color": {
"property": "x",
"stops": [
[
0,
"blue"
],
[
1,
"red"
]
]
}
}
}
]
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading