summaryrefslogtreecommitdiff
path: root/src/mbgl/shaders
diff options
context:
space:
mode:
authorAnand Thakker <anandthakker@users.noreply.github.com>2017-04-06 15:29:59 -0400
committerGitHub <noreply@github.com>2017-04-06 15:29:59 -0400
commit693c9f3641b3189b4cd439049904c95a516ae609 (patch)
tree8341a16f57ff184a2fe9e085c490e8762eb206ce /src/mbgl/shaders
parentf9cc044357d60dd5cf15ba951384529f88802089 (diff)
downloadqtlocation-mapboxgl-693c9f3641b3189b4cd439049904c95a516ae609.tar.gz
[core] Add DDS support for {text,icon}-size (#8593)
* Update gl-js and generate style code * Factor out packUint8Pair() helper function * Draft implementation of DDS for {text,icon}-size Ports https://github.com/mapbox/mapbox-gl-js/pull/4455 * Fix text-size/composite-function-line-placement test * Refactor to PaintPropertyBinders-like strategy * Dedupe gl::Program construction * Use exponential function base for interpolation * Dedupe coveringZoomStops method * Fixup tests * Fix CI errors (hidden within #if block)
Diffstat (limited to 'src/mbgl/shaders')
-rw-r--r--src/mbgl/shaders/preludes.cpp18
-rw-r--r--src/mbgl/shaders/symbol_icon.cpp51
-rw-r--r--src/mbgl/shaders/symbol_sdf.cpp82
3 files changed, 124 insertions, 27 deletions
diff --git a/src/mbgl/shaders/preludes.cpp b/src/mbgl/shaders/preludes.cpp
index 806e655285..cca0f3e3f1 100644
--- a/src/mbgl/shaders/preludes.cpp
+++ b/src/mbgl/shaders/preludes.cpp
@@ -43,17 +43,25 @@ vec4 evaluate_zoom_function_4(const vec4 value0, const vec4 value1, const vec4 v
}
}
+// Unpack a pair of values that have been packed into a single float.
+// The packed values are assumed to be 8-bit unsigned integers, and are
+// packed like so:
+// packedValue = floor(input[0]) * 256 + input[1],
+vec2 unpack_float(const float packedValue) {
+ float v0 = floor(packedValue / 256.0);
+ return vec2(v0, packedValue - v0 * 256.0);
+}
+
// To minimize the number of attributes needed in the mapbox-gl-native shaders,
// we encode a 4-component color into a pair of floats (i.e. a vec2) as follows:
// [ floor(color.r * 255) * 256 + color.g * 255,
// floor(color.b * 255) * 256 + color.g * 255 ]
vec4 decode_color(const vec2 encodedColor) {
- float r = floor(encodedColor[0]/256.0)/255.0;
- float g = (encodedColor[0] - r*256.0*255.0)/255.0;
- float b = floor(encodedColor[1]/256.0)/255.0;
- float a = (encodedColor[1] - b*256.0*255.0)/255.0;
- return vec4(r, g, b, a);
+ return vec4(
+ unpack_float(encodedColor[0]) / 255.0,
+ unpack_float(encodedColor[1]) / 255.0
+ );
}
// Unpack a pair of paint values and interpolate between them.
diff --git a/src/mbgl/shaders/symbol_icon.cpp b/src/mbgl/shaders/symbol_icon.cpp
index 9adda0ba16..b6fbed428e 100644
--- a/src/mbgl/shaders/symbol_icon.cpp
+++ b/src/mbgl/shaders/symbol_icon.cpp
@@ -9,9 +9,16 @@ const char* symbol_icon::name = "symbol_icon";
const char* symbol_icon::vertexSource = R"MBGL_SHADER(
attribute vec4 a_pos_offset;
-attribute vec2 a_texture_pos;
attribute vec4 a_data;
+// icon-size data (see symbol_sdf.vertex.glsl for more)
+attribute vec3 a_size;
+uniform bool u_is_size_zoom_constant;
+uniform bool u_is_size_feature_constant;
+uniform mediump float u_size_t; // used to interpolate between zoom stops when size is a composite function
+uniform mediump float u_size; // used when size is both zoom and feature constant
+uniform mediump float u_layout_size; // used when size is feature constant
+
uniform lowp float a_opacity_t;
attribute lowp vec2 a_opacity;
varying lowp float opacity;
@@ -19,6 +26,7 @@ varying lowp float opacity;
// matrix is for the vertex position.
uniform mat4 u_matrix;
+uniform bool u_is_text;
uniform mediump float u_zoom;
uniform bool u_rotate_with_map;
uniform vec2 u_extrude_scale;
@@ -34,16 +42,45 @@ void main() {
vec2 a_pos = a_pos_offset.xy;
vec2 a_offset = a_pos_offset.zw;
- vec2 a_tex = a_texture_pos.xy;
- mediump float a_labelminzoom = a_data[0];
- mediump vec2 a_zoom = a_data.pq;
+ vec2 a_tex = a_data.xy;
+ mediump vec2 label_data = unpack_float(a_data[2]);
+ mediump float a_labelminzoom = label_data[0];
+ mediump vec2 a_zoom = unpack_float(a_data[3]);
mediump float a_minzoom = a_zoom[0];
mediump float a_maxzoom = a_zoom[1];
- // u_zoom is the current zoom level adjusted for the change in font size
- mediump float z = 2.0 - step(a_minzoom, u_zoom) - (1.0 - step(a_maxzoom, u_zoom));
+ float size;
+ // In order to accommodate placing labels around corners in
+ // symbol-placement: line, each glyph in a label could have multiple
+ // "quad"s only one of which should be shown at a given zoom level.
+ // The min/max zoom assigned to each quad is based on the font size at
+ // the vector tile's zoom level, which might be different than at the
+ // currently rendered zoom level if text-size is zoom-dependent.
+ // Thus, we compensate for this difference by calculating an adjustment
+ // based on the scale of rendered text size relative to layout text size.
+ mediump float layoutSize;
+ if (!u_is_size_zoom_constant && !u_is_size_feature_constant) {
+ size = mix(a_size[0], a_size[1], u_size_t) / 10.0;
+ layoutSize = a_size[2] / 10.0;
+ } else if (u_is_size_zoom_constant && !u_is_size_feature_constant) {
+ size = a_size[0] / 10.0;
+ layoutSize = size;
+ } else if (!u_is_size_zoom_constant && u_is_size_feature_constant) {
+ size = u_size;
+ layoutSize = u_layout_size;
+ } else {
+ size = u_size;
+ layoutSize = u_size;
+ }
+
+ float fontScale = u_is_text ? size / 24.0 : size;
+
+ mediump float zoomAdjust = log2(size / layoutSize);
+ mediump float adjustedZoom = (u_zoom - zoomAdjust) * 10.0;
+ // result: z = 0 if a_minzoom <= adjustedZoom < a_maxzoom, and 1 otherwise
+ mediump float z = 2.0 - step(a_minzoom, adjustedZoom) - (1.0 - step(a_maxzoom, adjustedZoom));
- vec2 extrude = u_extrude_scale * (a_offset / 64.0);
+ vec2 extrude = fontScale * u_extrude_scale * (a_offset / 64.0);
if (u_rotate_with_map) {
gl_Position = u_matrix * vec4(a_pos + extrude, 0, 1);
gl_Position.z += z * gl_Position.w;
diff --git a/src/mbgl/shaders/symbol_sdf.cpp b/src/mbgl/shaders/symbol_sdf.cpp
index 7cbc9babf5..194e624036 100644
--- a/src/mbgl/shaders/symbol_sdf.cpp
+++ b/src/mbgl/shaders/symbol_sdf.cpp
@@ -10,9 +10,23 @@ const char* symbol_sdf::vertexSource = R"MBGL_SHADER(
const float PI = 3.141592653589793;
attribute vec4 a_pos_offset;
-attribute vec2 a_texture_pos;
attribute vec4 a_data;
+// contents of a_size vary based on the type of property value
+// used for {text,icon}-size.
+// For constants, a_size is disabled.
+// For source functions, we bind only one value per vertex: the value of {text,icon}-size evaluated for the current feature.
+// For composite functions:
+// [ text-size(lowerZoomStop, feature),
+// text-size(upperZoomStop, feature),
+// layoutSize == text-size(layoutZoomLevel, feature) ]
+attribute vec3 a_size;
+uniform bool u_is_size_zoom_constant;
+uniform bool u_is_size_feature_constant;
+uniform mediump float u_size_t; // used to interpolate between zoom stops when size is a composite function
+uniform mediump float u_size; // used when size is both zoom and feature constant
+uniform mediump float u_layout_size; // used when size is feature constant
+
uniform lowp float a_fill_color_t;
attribute highp vec4 a_fill_color;
varying highp vec4 fill_color;
@@ -32,6 +46,7 @@ varying lowp float halo_blur;
// matrix is for the vertex position.
uniform mat4 u_matrix;
+uniform bool u_is_text;
uniform mediump float u_zoom;
uniform bool u_rotate_with_map;
uniform bool u_pitch_with_map;
@@ -45,6 +60,7 @@ uniform vec2 u_texsize;
varying vec2 v_tex;
varying vec2 v_fade_tex;
varying float v_gamma_scale;
+varying float v_size;
void main() {
fill_color = unpack_mix_vec4(a_fill_color, a_fill_color_t);
@@ -56,24 +72,57 @@ void main() {
vec2 a_pos = a_pos_offset.xy;
vec2 a_offset = a_pos_offset.zw;
- vec2 a_tex = a_texture_pos.xy;
- mediump float a_labelminzoom = a_data[0];
- mediump vec2 a_zoom = a_data.pq;
+ vec2 a_tex = a_data.xy;
+
+ mediump vec2 label_data = unpack_float(a_data[2]);
+ mediump float a_labelminzoom = label_data[0];
+ mediump float a_labelangle = label_data[1];
+
+ mediump vec2 a_zoom = unpack_float(a_data[3]);
mediump float a_minzoom = a_zoom[0];
mediump float a_maxzoom = a_zoom[1];
- // u_zoom is the current zoom level adjusted for the change in font size
- mediump float z = 2.0 - step(a_minzoom, u_zoom) - (1.0 - step(a_maxzoom, u_zoom));
+ // In order to accommodate placing labels around corners in
+ // symbol-placement: line, each glyph in a label could have multiple
+ // "quad"s only one of which should be shown at a given zoom level.
+ // The min/max zoom assigned to each quad is based on the font size at
+ // the vector tile's zoom level, which might be different than at the
+ // currently rendered zoom level if text-size is zoom-dependent.
+ // Thus, we compensate for this difference by calculating an adjustment
+ // based on the scale of rendered text size relative to layout text size.
+ mediump float layoutSize;
+ if (!u_is_size_zoom_constant && !u_is_size_feature_constant) {
+ v_size = mix(a_size[0], a_size[1], u_size_t) / 10.0;
+ layoutSize = a_size[2] / 10.0;
+ } else if (u_is_size_zoom_constant && !u_is_size_feature_constant) {
+ v_size = a_size[0] / 10.0;
+ layoutSize = v_size;
+ } else if (!u_is_size_zoom_constant && u_is_size_feature_constant) {
+ v_size = u_size;
+ layoutSize = u_layout_size;
+ } else {
+ v_size = u_size;
+ layoutSize = u_size;
+ }
+
+ float fontScale = u_is_text ? v_size / 24.0 : v_size;
+
+ mediump float zoomAdjust = log2(v_size / layoutSize);
+ mediump float adjustedZoom = (u_zoom - zoomAdjust) * 10.0;
+ // result: z = 0 if a_minzoom <= adjustedZoom < a_maxzoom, and 1 otherwise
+ // Used below to move the vertex out of the clip space for when the current
+ // zoom is out of the glyph's zoom range.
+ mediump float z = 2.0 - step(a_minzoom, adjustedZoom) - (1.0 - step(a_maxzoom, adjustedZoom));
// pitch-alignment: map
// rotation-alignment: map | viewport
if (u_pitch_with_map) {
- lowp float angle = u_rotate_with_map ? (a_data[1] / 256.0 * 2.0 * PI) : u_bearing;
+ lowp float angle = u_rotate_with_map ? (a_labelangle / 256.0 * 2.0 * PI) : u_bearing;
lowp float asin = sin(angle);
lowp float acos = cos(angle);
mat2 RotationMatrix = mat2(acos, asin, -1.0 * asin, acos);
vec2 offset = RotationMatrix * a_offset;
- vec2 extrude = u_extrude_scale * (offset / 64.0);
+ vec2 extrude = fontScale * u_extrude_scale * (offset / 64.0);
gl_Position = u_matrix * vec4(a_pos + extrude, 0, 1);
gl_Position.z += z * gl_Position.w;
// pitch-alignment: viewport
@@ -84,7 +133,7 @@ void main() {
// it goes from 0% foreshortening to up to around 70% foreshortening
lowp float pitchfactor = 1.0 - cos(u_pitch * sin(u_pitch * 0.75));
- lowp float lineangle = a_data[1] / 256.0 * 2.0 * PI;
+ lowp float lineangle = a_labelangle / 256.0 * 2.0 * PI;
// use the lineangle to position points a,b along the line
// project the points and calculate the label angle in projected space
@@ -97,13 +146,13 @@ void main() {
mat2 RotationMatrix = mat2(acos, -1.0 * asin, asin, acos);
vec2 offset = RotationMatrix * (vec2((1.0-pitchfactor)+(pitchfactor*cos(angle*2.0)), 1.0) * a_offset);
- vec2 extrude = u_extrude_scale * (offset / 64.0);
+ vec2 extrude = fontScale * u_extrude_scale * (offset / 64.0);
gl_Position = u_matrix * vec4(a_pos, 0, 1) + vec4(extrude, 0, 0);
gl_Position.z += z * gl_Position.w;
// pitch-alignment: viewport
// rotation-alignment: viewport
} else {
- vec2 extrude = u_extrude_scale * (a_offset / 64.0);
+ vec2 extrude = fontScale * u_extrude_scale * (a_offset / 64.0);
gl_Position = u_matrix * vec4(a_pos, 0, 1) + vec4(extrude, 0, 0);
}
@@ -127,12 +176,13 @@ varying lowp float halo_blur;
uniform sampler2D u_texture;
uniform sampler2D u_fadetexture;
-uniform lowp float u_font_scale;
uniform highp float u_gamma_scale;
+uniform bool u_is_text;
varying vec2 v_tex;
varying vec2 v_fade_tex;
varying float v_gamma_scale;
+varying float v_size;
void main() {
@@ -141,13 +191,15 @@ void main() {
+ float fontScale = u_is_text ? v_size / 24.0 : v_size;
+
lowp vec4 color = fill_color;
- highp float gamma = EDGE_GAMMA / u_gamma_scale;
+ highp float gamma = EDGE_GAMMA / (fontScale * u_gamma_scale);
lowp float buff = (256.0 - 64.0) / 256.0;
if (u_is_halo) {
color = halo_color;
- gamma = (halo_blur * 1.19 / SDF_PX + EDGE_GAMMA) / u_gamma_scale;
- buff = (6.0 - halo_width / u_font_scale) / SDF_PX;
+ gamma = (halo_blur * 1.19 / SDF_PX + EDGE_GAMMA) / (fontScale * u_gamma_scale);
+ buff = (6.0 - halo_width / fontScale) / SDF_PX;
}
lowp float dist = texture2D(u_texture, v_tex).a;