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 more symbol paint properties #4226

Merged
merged 8 commits into from
Feb 8, 2017
Merged
10 changes: 8 additions & 2 deletions src/data/bucket/symbol_bucket.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,21 @@ const symbolInterfaces = {
elementArrayType: elementArrayType,
paintAttributes: [
{name: 'a_fill_color', property: 'text-color', type: 'Uint8'},
{name: 'a_halo_color', property: 'text-halo-color', type: 'Uint8'}
{name: 'a_halo_color', property: 'text-halo-color', type: 'Uint8'},
{name: 'a_halo_width', property: 'text-halo-width', type: 'Uint16', multiplier: 10},
{name: 'a_halo_blur', property: 'text-halo-blur', type: 'Uint16', multiplier: 10},
{name: 'a_opacity', property: 'text-opacity', type: 'Uint8', multiplier: 255}
]
},
icon: {
layoutVertexArrayType: layoutVertexArrayType,
elementArrayType: elementArrayType,
paintAttributes: [
{name: 'a_fill_color', property: 'icon-color', type: 'Uint8'},
{name: 'a_halo_color', property: 'icon-halo-color', type: 'Uint8'}
{name: 'a_halo_color', property: 'icon-halo-color', type: 'Uint8'},
{name: 'a_halo_width', property: 'icon-halo-width', type: 'Uint16', multiplier: 10},
{name: 'a_halo_blur', property: 'icon-halo-blur', type: 'Uint16', multiplier: 10},
{name: 'a_opacity', property: 'icon-opacity', type: 'Uint8', multiplier: 255}
]
},
collisionBox: {
Expand Down
40 changes: 12 additions & 28 deletions src/render/draw_symbol.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,6 @@ const pixelsToTileUnits = require('../source/pixels_to_tile_units');

module.exports = drawSymbols;

const sdfPx = 8;
const blurOffset = 1.19;
const haloOffset = 6;
const gamma = 0.105 / browser.devicePixelRatio;

function drawSymbols(painter, sourceCache, layer, coords) {
if (painter.isOpaquePass) return;

Expand Down Expand Up @@ -43,23 +38,15 @@ function drawSymbols(painter, sourceCache, layer, coords) {
// icon-pitch-alignment is not yet implemented
// and we simply inherit the rotation alignment
layer.layout['icon-rotation-alignment'],
layer.layout['icon-size'],
layer.paint['icon-halo-width'],
layer.paint['icon-halo-color'],
layer.paint['icon-halo-blur'],
layer.paint['icon-opacity']
layer.layout['icon-size']
);

drawLayerSymbols(painter, sourceCache, layer, coords, true,
layer.paint['text-translate'],
layer.paint['text-translate-anchor'],
layer.layout['text-rotation-alignment'],
layer.layout['text-pitch-alignment'],
layer.layout['text-size'],
layer.paint['text-halo-width'],
layer.paint['text-halo-color'],
layer.paint['text-halo-blur'],
layer.paint['text-opacity']
layer.layout['text-size']
);

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

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

if (!isText && painter.style.sprite && !painter.style.sprite.loaded())
return;
Expand Down Expand Up @@ -104,7 +91,7 @@ function drawLayerSymbols(painter, sourceCache, layer, coords, isText, translate
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);
bucket.iconsNeedLinear, isText ? bucket.adjustedTextSize : bucket.adjustedIconSize);
}

painter.enableTileClippingMask(coord);
Expand All @@ -113,7 +100,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);
pitchWithMap, size);

prevFontstack = bucket.fontstack;
}
Expand All @@ -122,7 +109,7 @@ function drawLayerSymbols(painter, sourceCache, layer, coords, isText, translate
}

function setSymbolDrawState(program, painter, isText, isSDF, rotateWithMap, pitchWithMap, fontstack, size,
iconsNeedLinear, adjustedSize, opacity) {
iconsNeedLinear, adjustedSize) {

const gl = painter.gl;
const tr = painter.transform;
Expand Down Expand Up @@ -160,12 +147,10 @@ function setSymbolDrawState(program, painter, isText, isSDF, rotateWithMap, pitc
gl.uniform1f(program.u_pitch, tr.pitch / 360 * 2 * Math.PI);
gl.uniform1f(program.u_bearing, tr.bearing / 360 * 2 * Math.PI);
gl.uniform1f(program.u_aspect_ratio, tr.width / tr.height);

gl.uniform1f(program.u_opacity, opacity);
}

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

const gl = painter.gl;
const tr = painter.transform;
Expand All @@ -181,19 +166,18 @@ function drawTileSymbols(program, painter, layer, tile, buffers, isText, isSDF,
}

if (isSDF) {
const haloWidthProperty = `${isText ? 'text' : 'icon'}-halo-width`;
const hasHalo = !layer.isPaintValueFeatureConstant(haloWidthProperty) || layer.paint[haloWidthProperty];
const gammaScale = fontScale * (pitchWithMap ? Math.cos(tr._pitch) : 1) * tr.cameraToCenterDistance;
gl.uniform1f(program.u_font_scale, fontScale);
gl.uniform1f(program.u_gamma_scale, gammaScale);

if (haloWidth) { // Draw halo underneath the text.
gl.uniform1f(program.u_gamma, (haloBlur * blurOffset / sdfPx + gamma) / gammaScale);
gl.uniform1f(program.u_buffer, (haloOffset - haloWidth / fontScale) / sdfPx);
if (hasHalo) { // Draw halo underneath the text.
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.uniform1f(program.u_buffer, (256 - 64) / 256);
}

drawSymbolElements(buffers, layer, gl, program);
Expand Down
8 changes: 6 additions & 2 deletions src/render/painter.js
Original file line number Diff line number Diff line change
Expand Up @@ -370,14 +370,18 @@ class Painter {
definesSource += '#define OVERDRAW_INSPECTOR;\n';
}

const fragmentSource = configuration.applyPragmas(definesSource + shaders.prelude.fragmentSource + definition.fragmentSource, 'fragment');
const vertexSource = configuration.applyPragmas(definesSource + shaders.prelude.vertexSource + definition.vertexSource, 'vertex');

// console.log(fragmentSource.split('\n').map((l, i) => `${i}: ${l}`).join('\n'))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

accidental //?

const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, configuration.applyPragmas(definesSource + shaders.prelude.fragmentSource + definition.fragmentSource, 'fragment'));
gl.shaderSource(fragmentShader, fragmentSource);
gl.compileShader(fragmentShader);
assert(gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS), gl.getShaderInfoLog(fragmentShader));
gl.attachShader(program, fragmentShader);

const vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, configuration.applyPragmas(definesSource + shaders.prelude.vertexSource + definition.vertexSource, 'vertex'));
gl.shaderSource(vertexShader, vertexSource);
gl.compileShader(vertexShader);
assert(gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS), gl.getShaderInfoLog(vertexShader));
gl.attachShader(program, vertexShader);
Expand Down
7 changes: 5 additions & 2 deletions src/shaders/symbol_icon.fragment.glsl
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
uniform sampler2D u_texture;
uniform sampler2D u_fadetexture;
uniform lowp float u_opacity;

#pragma mapbox: define lowp float opacity

varying vec2 v_tex;
varying vec2 v_fade_tex;

void main() {
lowp float alpha = texture2D(u_fadetexture, v_fade_tex).a * u_opacity;
#pragma mapbox: initialize lowp float opacity

lowp float alpha = texture2D(u_fadetexture, v_fade_tex).a * opacity;
gl_FragColor = texture2D(u_texture, v_tex) * alpha;

#ifdef OVERDRAW_INSPECTOR
Expand Down
3 changes: 3 additions & 0 deletions src/shaders/symbol_icon.vertex.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ attribute vec2 a_offset;
attribute vec2 a_texture_pos;
attribute vec4 a_data;

#pragma mapbox: define lowp float opacity

// matrix is for the vertex position.
uniform mat4 u_matrix;
Expand All @@ -17,6 +18,8 @@ varying vec2 v_tex;
varying vec2 v_fade_tex;

void main() {
#pragma mapbox: initialize lowp float opacity

vec2 a_tex = a_texture_pos.xy;
mediump float a_labelminzoom = a_data[0];
mediump vec2 a_zoom = a_data.pq;
Expand Down
28 changes: 21 additions & 7 deletions src/shaders/symbol_sdf.fragment.glsl
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
#define SDF_PX 8.0
#define BLUR_OFFSET 1.19
#define HALO_OFFSET 6.0
#define GAMMA 0.105/DEVICE_PIXEL_RATIO
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Opinion Below 👇

I find some of these constant names cryptic:

  • What's the difference between GAMMA and gamma?
  • What's meant by SDF_PX? SDF pixels?
  • Why is halp_blur multiplied by BLUR_OFFSET?
  • What's a buff? Is it a buffer?

I prefer a very clear constant name (ideally googleable) to a magic number, and a magic number to a cryptic constant name.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LOL, I totally agree with you that these names are cryptic. And here I must confess, I just did a lazy/dumb transcription from draw_symbol.js (where these constants / calculations lived before this), without actually discerning what they meant. Lemme see if I can decipher them into more meaningful names.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you 🙇. If you can't come up with a meaningful name, feel free to inline.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lucaswoj I inlined a couple of them, but chose to leave SDF_PX and EDGE_GAMMA (my weak attempt at renaming GAMMA), because they are used in more than one place -- I did not want to inline them and then later lose track of the fact that both "8.0"s are supposed to mean the same thing. Filed a follow up ticket though: #4229


uniform bool u_is_halo;
#pragma mapbox: define lowp vec4 fill_color
#pragma mapbox: define lowp vec4 halo_color
uniform bool u_is_halo;
#pragma mapbox: define lowp float opacity
#pragma mapbox: define lowp float halo_width
#pragma mapbox: define lowp float halo_blur

uniform sampler2D u_texture;
uniform sampler2D u_fadetexture;
uniform lowp float u_opacity;
uniform lowp float u_buffer;
uniform lowp float u_gamma;
uniform lowp float u_font_scale;
uniform lowp float u_gamma_scale;

varying vec2 v_tex;
varying vec2 v_fade_tex;
Expand All @@ -15,18 +22,25 @@ varying float v_gamma_scale;
void main() {
#pragma mapbox: initialize lowp vec4 fill_color
#pragma mapbox: initialize lowp vec4 halo_color
#pragma mapbox: initialize lowp float opacity
#pragma mapbox: initialize lowp float halo_width
#pragma mapbox: initialize lowp float halo_blur

lowp vec4 color = fill_color;
lowp float gamma = GAMMA / u_gamma_scale;
lowp float buff = (256.0 - 64.0) / 256.0;
if (u_is_halo) {
color = halo_color;
gamma = (halo_blur * BLUR_OFFSET / SDF_PX + GAMMA) / u_gamma_scale;
buff = (HALO_OFFSET - halo_width / u_font_scale) / SDF_PX;
}

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;
lowp float gamma_scaled = gamma * v_gamma_scale;
lowp float alpha = smoothstep(buff - gamma_scaled, buff + gamma_scaled, dist) * fade_alpha;

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

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

#pragma mapbox: define lowp vec4 fill_color
#pragma mapbox: define lowp vec4 halo_color
#pragma mapbox: define lowp float opacity
#pragma mapbox: define lowp float halo_width
#pragma mapbox: define lowp float halo_blur

// matrix is for the vertex position.
uniform mat4 u_matrix;
Expand All @@ -28,6 +31,9 @@ varying float v_gamma_scale;
void main() {
#pragma mapbox: initialize lowp vec4 fill_color
#pragma mapbox: initialize lowp vec4 halo_color
#pragma mapbox: initialize lowp float opacity
#pragma mapbox: initialize lowp float halo_width
#pragma mapbox: initialize lowp float halo_blur

vec2 a_tex = a_texture_pos.xy;
mediump float a_labelminzoom = a_data[0];
Expand Down
6 changes: 6 additions & 0 deletions src/style-spec/reference/v8.json
Original file line number Diff line number Diff line change
Expand Up @@ -2479,6 +2479,7 @@
"maximum": 1,
"function": "interpolated",
"zoom-function": true,
"property-function": true,
"transition": true,
"requires": [
"icon-image"
Expand Down Expand Up @@ -2541,6 +2542,7 @@
"minimum": 0,
"function": "interpolated",
"zoom-function": true,
"property-function": true,
"transition": true,
"units": "pixels",
"doc": "Distance of halo to the icon outline.",
Expand All @@ -2563,6 +2565,7 @@
"minimum": 0,
"function": "interpolated",
"zoom-function": true,
"property-function": true,
"transition": true,
"units": "pixels",
"doc": "Fade out the halo towards the outside.",
Expand Down Expand Up @@ -2641,6 +2644,7 @@
"maximum": 1,
"function": "interpolated",
"zoom-function": true,
"property-function": true,
"transition": true,
"requires": [
"text-field"
Expand Down Expand Up @@ -2703,6 +2707,7 @@
"minimum": 0,
"function": "interpolated",
"zoom-function": true,
"property-function": true,
"transition": true,
"units": "pixels",
"doc": "Distance of halo to the font outline. Max text halo width is 1/4 of the font-size.",
Expand All @@ -2725,6 +2730,7 @@
"minimum": 0,
"function": "interpolated",
"zoom-function": true,
"property-function": true,
"transition": true,
"units": "pixels",
"doc": "The halo's fadeout distance towards the outside.",
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,71 @@
{
"version": 8,
"metadata": {
"test": {
"width": 64,
"height": 64,
"skipped": {
"native": "https://github.com/mapbox/mapbox-gl-native/issues/7866"
}
}
},
"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-halo-width": 3,
"icon-halo-color": "green",
"icon-halo-blur": {
"property": "x",
"stops": [
[
0,
1
],
[
1,
3
]
]
}
}
}
]
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading