diff options
author | Anand Thakker <anandthakker@users.noreply.github.com> | 2017-04-06 15:29:59 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-04-06 15:29:59 -0400 |
commit | 693c9f3641b3189b4cd439049904c95a516ae609 (patch) | |
tree | 8341a16f57ff184a2fe9e085c490e8762eb206ce /src/mbgl/shaders | |
parent | f9cc044357d60dd5cf15ba951384529f88802089 (diff) | |
download | qtlocation-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.cpp | 18 | ||||
-rw-r--r-- | src/mbgl/shaders/symbol_icon.cpp | 51 | ||||
-rw-r--r-- | src/mbgl/shaders/symbol_sdf.cpp | 82 |
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; |