From 692f5e0a9f5321ee2932a976a8eb9e0a83fc3352 Mon Sep 17 00:00:00 2001 From: Molly Lloyd Date: Wed, 1 Mar 2017 11:28:31 -0800 Subject: Pack min + max into one attribute :muscle: Some devices supported by Mapbox GL provide only 8 vertex attributes; this change packs existing attributes to get us just under that limit. For properties using a composite function, pack the min and max values into a single attribute with two logical components instead of using two separate attributes and buffers. Special logic is included for color attributes, whose integer components must be packed into the available bits of floating-point attributes. (We don't have access to ivec types in GL ES 2.0.) For source functions, continue to bind just a one-component attribute even though the GLSL type is vec2 (or vec4 for colors). The type-checking done by gl::Attribute is relaxed slightly to accommodate this. --- src/mbgl/gl/attribute.cpp | 2 +- src/mbgl/gl/attribute.hpp | 46 ++++++++--- src/mbgl/programs/attributes.hpp | 96 ++++++++++++----------- src/mbgl/programs/symbol_program.hpp | 8 +- src/mbgl/shaders/circle.cpp | 35 ++++----- src/mbgl/shaders/fill.cpp | 10 +-- src/mbgl/shaders/fill_outline.cpp | 10 +-- src/mbgl/shaders/fill_outline_pattern.cpp | 5 +- src/mbgl/shaders/fill_pattern.cpp | 5 +- src/mbgl/shaders/line.cpp | 25 +++--- src/mbgl/shaders/line_pattern.cpp | 20 ++--- src/mbgl/shaders/line_sdf.cpp | 25 +++--- src/mbgl/shaders/preludes.cpp | 25 ++++++ src/mbgl/shaders/symbol_icon.cpp | 12 +-- src/mbgl/shaders/symbol_sdf.cpp | 31 ++++---- src/mbgl/style/paint_property_binder.hpp | 123 +++++++++++------------------- 16 files changed, 234 insertions(+), 244 deletions(-) (limited to 'src') diff --git a/src/mbgl/gl/attribute.cpp b/src/mbgl/gl/attribute.cpp index 2c16dac3fc..ff313fdcd0 100644 --- a/src/mbgl/gl/attribute.cpp +++ b/src/mbgl/gl/attribute.cpp @@ -38,7 +38,7 @@ void VariableAttributeBinding::bind(Context& context, MBGL_CHECK_ERROR(glEnableVertexAttribArray(location)); MBGL_CHECK_ERROR(glVertexAttribPointer( location, - static_cast(N), + static_cast(attributeSize), static_cast(DataTypeOf), static_cast(IsNormalized), static_cast(vertexSize), diff --git a/src/mbgl/gl/attribute.hpp b/src/mbgl/gl/attribute.hpp index 6300ebb56b..43e2c2d794 100644 --- a/src/mbgl/gl/attribute.hpp +++ b/src/mbgl/gl/attribute.hpp @@ -17,10 +17,12 @@ class VariableAttributeBinding { public: VariableAttributeBinding(BufferID vertexBuffer_, std::size_t vertexSize_, - std::size_t attributeOffset_) + std::size_t attributeOffset_, + std::size_t attributeSize_ = N) : vertexBuffer(vertexBuffer_), vertexSize(vertexSize_), - attributeOffset(attributeOffset_) + attributeOffset(attributeOffset_), + attributeSize(attributeSize_) {} void bind(Context&, AttributeLocation, optional>&, std::size_t vertexOffset) const; @@ -29,13 +31,15 @@ public: const VariableAttributeBinding& rhs) { return lhs.vertexBuffer == rhs.vertexBuffer && lhs.vertexSize == rhs.vertexSize - && lhs.attributeOffset == rhs.attributeOffset; + && lhs.attributeOffset == rhs.attributeOffset + && lhs.attributeSize == rhs.attributeSize; } private: BufferID vertexBuffer; std::size_t vertexSize; std::size_t attributeOffset; + std::size_t attributeSize; }; template @@ -58,9 +62,16 @@ private: std::array value; }; +/* + gl::Attribute manages the binding of a constant value or vertex buffer to a GL program attribute. + - T is the underlying primitive type (exposed as Attribute::ValueType) + - N is the number of components in the attribute declared in the shader (exposed as Attribute::Dimensions) +*/ template class Attribute { public: + using ValueType = T; + static constexpr size_t Dimensions = N; using Value = std::array; using VariableBinding = VariableAttributeBinding; @@ -72,6 +83,25 @@ public: ConstantBinding, VariableBinding>; + /* + Create a variable (i.e. data-driven) binding for this attribute. The `attributeSize` + parameter may be used to override the number of components available in the buffer for + each vertex. Thus, a buffer with only one float for each vertex can be bound to a + `vec2` attribute + */ + template + static VariableBinding variableBinding(const VertexBuffer& buffer, + std::size_t attributeIndex, + std::size_t attributeSize = N) { + static_assert(std::is_standard_layout::value, "vertex type must use standard layout"); + return VariableBinding { + buffer.buffer, + sizeof(Vertex), + Vertex::attributeOffsets[attributeIndex], + attributeSize + }; + } + static void bind(Context& context, const Location& location, optional& oldBinding, @@ -223,15 +253,7 @@ public: template static Bindings allVariableBindings(const VertexBuffer& buffer) { - static_assert(std::is_standard_layout::value, "vertex type must use standard layout"); - - return Bindings { - typename As::VariableBinding { - buffer.buffer, - sizeof(Vertex), - Vertex::attributeOffsets[Index] - }... - }; + return Bindings { As::variableBinding(buffer, Index)... }; } static void bind(Context& context, diff --git a/src/mbgl/programs/attributes.hpp b/src/mbgl/programs/attributes.hpp index bb90f2c13c..a2e0772762 100644 --- a/src/mbgl/programs/attributes.hpp +++ b/src/mbgl/programs/attributes.hpp @@ -13,6 +13,7 @@ namespace attributes { MBGL_DEFINE_ATTRIBUTE(int16_t, 2, a_pos); MBGL_DEFINE_ATTRIBUTE(int16_t, 2, a_extrude); +MBGL_DEFINE_ATTRIBUTE(int16_t, 4, a_pos_offset); MBGL_DEFINE_ATTRIBUTE(uint16_t, 2, a_texture_pos); template @@ -27,19 +28,30 @@ struct a_offset : gl::Attribute { // Paint attributes +/* + ZoomInterpolatedAttribute is a 'compound' attribute, representing two values of the + the base attribute Attr. These two values are provided to the shader to allow interpolation + between zoom levels, without the need to repopulate vertex buffers each frame as the map is + being zoomed. +*/ template -struct Min : Attr { - static auto name() { - static const std::string name = Attr::name() + std::string("_min"); - return name.c_str(); - } -}; +struct ZoomInterpolatedAttribute : gl::Attribute { + using Value = typename gl::Attribute::Value; -template -struct Max : Attr { static auto name() { - static const std::string name = Attr::name() + std::string("_max"); - return name.c_str(); + return Attr::name(); + } + + template + static Value value(const InputType& min, const InputType& max){ + auto minValue = Attr::value(min); + auto maxValue = Attr::value(max); + Value result = {{}}; + for (size_t i = 0; i < Attr::Dimensions; i++) { + result[i] = minValue[i]; + result[Attr::Dimensions+i] = maxValue[i]; + } + return result; } }; @@ -51,70 +63,62 @@ struct InterpolationUniform : gl::UniformScalar, floa } }; -struct a_color : gl::Attribute, 4> { +/* + Encode a four-component color value into a pair of floats. Since csscolorparser + uses 8-bit precision for each color component, for each float we use the upper 8 + bits for one component (e.g. (color.r * 255) * 256), and the lower 8 for another. + + Also note: + - Colors come in as floats 0..1, so we scale by 255. + - Casting the scaled values to ints is important: without doing this, e.g., the + fractional part of the `r` component would corrupt the lower-8 bits of the encoded + value, which must be reserved for the `g` component. +*/ +static std::array encodeColor (const Color& color) { + const auto v1 = static_cast( static_cast(color.r*255)*256 + color.g*255); + const auto v2 = static_cast( static_cast(color.b*255)*256 + color.a*255); + return {{ static_cast(v1), static_cast(v2) }}; +} + +struct a_color : gl::Attribute { static auto name() { return "a_color"; } static Value value(const Color& color) { - return {{ - gl::Normalized(color.r), - gl::Normalized(color.g), - gl::Normalized(color.b), - gl::Normalized(color.a) - }}; + return encodeColor(color); } }; // used in the symbol sdf shader -struct a_fill_color : gl::Attribute, 4> { +struct a_fill_color : gl::Attribute { static auto name() { return "a_fill_color"; } static Value value(const Color& color) { - return {{ - gl::Normalized(color.r), - gl::Normalized(color.g), - gl::Normalized(color.b), - gl::Normalized(color.a) - }}; + return encodeColor(color); } }; // used in the symbol sdf shader -struct a_halo_color : gl::Attribute, 4> { +struct a_halo_color : gl::Attribute { static auto name() { return "a_halo_color"; } - static Value value(const Color& color) { - return {{ - gl::Normalized(color.r), - gl::Normalized(color.g), - gl::Normalized(color.b), - gl::Normalized(color.a) - }}; + static Value value(const Color& color) { + return encodeColor(color); } }; -struct a_stroke_color : gl::Attribute, 4> { +struct a_stroke_color : gl::Attribute { static auto name() { return "a_stroke_color"; } static Value value(const Color& color) { - return {{ - gl::Normalized(color.r), - gl::Normalized(color.g), - gl::Normalized(color.b), - gl::Normalized(color.a) - }}; + return encodeColor(color); } }; -struct a_outline_color : gl::Attribute, 4> { +struct a_outline_color : gl::Attribute { static auto name() { return "a_outline_color"; } static Value value(const Color& color) { - return {{ - gl::Normalized(color.r), - gl::Normalized(color.g), - gl::Normalized(color.b), - gl::Normalized(color.a) - }}; + return encodeColor(color); } }; diff --git a/src/mbgl/programs/symbol_program.hpp b/src/mbgl/programs/symbol_program.hpp index 0537c25a2c..fdd1aa5c3b 100644 --- a/src/mbgl/programs/symbol_program.hpp +++ b/src/mbgl/programs/symbol_program.hpp @@ -35,8 +35,7 @@ MBGL_DEFINE_UNIFORM_SCALAR(float, u_gamma_scale); } // namespace uniforms struct SymbolLayoutAttributes : gl::Attributes< - attributes::a_pos, - attributes::a_offset<2>, + attributes::a_pos_offset, attributes::a_texture_pos, attributes::a_data<4>> { @@ -49,11 +48,10 @@ struct SymbolLayoutAttributes : gl::Attributes< float labelminzoom, uint8_t labelangle) { return Vertex { + // combining pos and offset to reduce number of vertex attributes passed to shader (8 max for some devices) {{ static_cast(a.x), - static_cast(a.y) - }}, - {{ + static_cast(a.y), static_cast(::round(o.x * 64)), // use 1/64 pixels for placement static_cast(::round(o.y * 64)) }}, diff --git a/src/mbgl/shaders/circle.cpp b/src/mbgl/shaders/circle.cpp index 4b2bb7cecf..b479f1d40c 100644 --- a/src/mbgl/shaders/circle.cpp +++ b/src/mbgl/shaders/circle.cpp @@ -14,45 +14,38 @@ uniform vec2 u_extrude_scale; attribute vec2 a_pos; uniform lowp float a_color_t; -attribute lowp vec4 a_color_min; -attribute lowp vec4 a_color_max; +attribute lowp vec4 a_color; varying lowp vec4 color; uniform lowp float a_radius_t; -attribute mediump float a_radius_min; -attribute mediump float a_radius_max; +attribute mediump vec2 a_radius; varying mediump float radius; uniform lowp float a_blur_t; -attribute lowp float a_blur_min; -attribute lowp float a_blur_max; +attribute lowp vec2 a_blur; varying lowp float blur; uniform lowp float a_opacity_t; -attribute lowp float a_opacity_min; -attribute lowp float a_opacity_max; +attribute lowp vec2 a_opacity; varying lowp float opacity; uniform lowp float a_stroke_color_t; -attribute lowp vec4 a_stroke_color_min; -attribute lowp vec4 a_stroke_color_max; +attribute lowp vec4 a_stroke_color; varying lowp vec4 stroke_color; uniform lowp float a_stroke_width_t; -attribute mediump float a_stroke_width_min; -attribute mediump float a_stroke_width_max; +attribute mediump vec2 a_stroke_width; varying mediump float stroke_width; uniform lowp float a_stroke_opacity_t; -attribute lowp float a_stroke_opacity_min; -attribute lowp float a_stroke_opacity_max; +attribute lowp vec2 a_stroke_opacity; varying lowp float stroke_opacity; varying vec2 v_extrude; varying lowp float v_antialiasblur; void main(void) { - color = mix(a_color_min, a_color_max, a_color_t); - radius = mix(a_radius_min, a_radius_max, a_radius_t); - blur = mix(a_blur_min, a_blur_max, a_blur_t); - opacity = mix(a_opacity_min, a_opacity_max, a_opacity_t); - stroke_color = mix(a_stroke_color_min, a_stroke_color_max, a_stroke_color_t); - stroke_width = mix(a_stroke_width_min, a_stroke_width_max, a_stroke_width_t); - stroke_opacity = mix(a_stroke_opacity_min, a_stroke_opacity_max, a_stroke_opacity_t); + color = unpack_mix_vec4(a_color, a_color_t); + radius = unpack_mix_vec2(a_radius, a_radius_t); + blur = unpack_mix_vec2(a_blur, a_blur_t); + opacity = unpack_mix_vec2(a_opacity, a_opacity_t); + stroke_color = unpack_mix_vec4(a_stroke_color, a_stroke_color_t); + stroke_width = unpack_mix_vec2(a_stroke_width, a_stroke_width_t); + stroke_opacity = unpack_mix_vec2(a_stroke_opacity, a_stroke_opacity_t); // unencode the extrusion vector that we snuck into the a_pos vector v_extrude = vec2(mod(a_pos, 2.0) * 2.0 - 1.0); diff --git a/src/mbgl/shaders/fill.cpp b/src/mbgl/shaders/fill.cpp index d0fc3a7033..a1fba4d749 100644 --- a/src/mbgl/shaders/fill.cpp +++ b/src/mbgl/shaders/fill.cpp @@ -12,17 +12,15 @@ attribute vec2 a_pos; uniform mat4 u_matrix; uniform lowp float a_color_t; -attribute lowp vec4 a_color_min; -attribute lowp vec4 a_color_max; +attribute lowp vec4 a_color; varying lowp vec4 color; uniform lowp float a_opacity_t; -attribute lowp float a_opacity_min; -attribute lowp float a_opacity_max; +attribute lowp vec2 a_opacity; varying lowp float opacity; void main() { - color = mix(a_color_min, a_color_max, a_color_t); - opacity = mix(a_opacity_min, a_opacity_max, a_opacity_t); + color = unpack_mix_vec4(a_color, a_color_t); + opacity = unpack_mix_vec2(a_opacity, a_opacity_t); gl_Position = u_matrix * vec4(a_pos, 0, 1); } diff --git a/src/mbgl/shaders/fill_outline.cpp b/src/mbgl/shaders/fill_outline.cpp index d6f8d63715..74201b518d 100644 --- a/src/mbgl/shaders/fill_outline.cpp +++ b/src/mbgl/shaders/fill_outline.cpp @@ -15,17 +15,15 @@ uniform vec2 u_world; varying vec2 v_pos; uniform lowp float a_outline_color_t; -attribute lowp vec4 a_outline_color_min; -attribute lowp vec4 a_outline_color_max; +attribute lowp vec4 a_outline_color; varying lowp vec4 outline_color; uniform lowp float a_opacity_t; -attribute lowp float a_opacity_min; -attribute lowp float a_opacity_max; +attribute lowp vec2 a_opacity; varying lowp float opacity; void main() { - outline_color = mix(a_outline_color_min, a_outline_color_max, a_outline_color_t); - opacity = mix(a_opacity_min, a_opacity_max, a_opacity_t); + outline_color = unpack_mix_vec4(a_outline_color, a_outline_color_t); + opacity = unpack_mix_vec2(a_opacity, a_opacity_t); gl_Position = u_matrix * vec4(a_pos, 0, 1); v_pos = (gl_Position.xy / gl_Position.w + 1.0) / 2.0 * u_world; diff --git a/src/mbgl/shaders/fill_outline_pattern.cpp b/src/mbgl/shaders/fill_outline_pattern.cpp index 6e9d6ad9a1..5e38023382 100644 --- a/src/mbgl/shaders/fill_outline_pattern.cpp +++ b/src/mbgl/shaders/fill_outline_pattern.cpp @@ -24,12 +24,11 @@ varying vec2 v_pos_b; varying vec2 v_pos; uniform lowp float a_opacity_t; -attribute lowp float a_opacity_min; -attribute lowp float a_opacity_max; +attribute lowp vec2 a_opacity; varying lowp float opacity; void main() { - opacity = mix(a_opacity_min, a_opacity_max, a_opacity_t); + opacity = unpack_mix_vec2(a_opacity, a_opacity_t); gl_Position = u_matrix * vec4(a_pos, 0, 1); diff --git a/src/mbgl/shaders/fill_pattern.cpp b/src/mbgl/shaders/fill_pattern.cpp index 329a292eed..0357fed40e 100644 --- a/src/mbgl/shaders/fill_pattern.cpp +++ b/src/mbgl/shaders/fill_pattern.cpp @@ -22,12 +22,11 @@ varying vec2 v_pos_a; varying vec2 v_pos_b; uniform lowp float a_opacity_t; -attribute lowp float a_opacity_min; -attribute lowp float a_opacity_max; +attribute lowp vec2 a_opacity; varying lowp float opacity; void main() { - opacity = mix(a_opacity_min, a_opacity_max, a_opacity_t); + opacity = unpack_mix_vec2(a_opacity, a_opacity_t); gl_Position = u_matrix * vec4(a_pos, 0, 1); diff --git a/src/mbgl/shaders/line.cpp b/src/mbgl/shaders/line.cpp index bd3256ad3b..dc4aa774dc 100644 --- a/src/mbgl/shaders/line.cpp +++ b/src/mbgl/shaders/line.cpp @@ -34,32 +34,27 @@ varying vec2 v_width2; varying float v_gamma_scale; uniform lowp float a_color_t; -attribute lowp vec4 a_color_min; -attribute lowp vec4 a_color_max; +attribute lowp vec4 a_color; varying lowp vec4 color; uniform lowp float a_blur_t; -attribute lowp float a_blur_min; -attribute lowp float a_blur_max; +attribute lowp vec2 a_blur; varying lowp float blur; uniform lowp float a_opacity_t; -attribute lowp float a_opacity_min; -attribute lowp float a_opacity_max; +attribute lowp vec2 a_opacity; varying lowp float opacity; uniform lowp float a_gapwidth_t; -attribute mediump float a_gapwidth_min; -attribute mediump float a_gapwidth_max; +attribute mediump vec2 a_gapwidth; varying mediump float gapwidth; uniform lowp float a_offset_t; -attribute lowp float a_offset_min; -attribute lowp float a_offset_max; +attribute lowp vec2 a_offset; varying lowp float offset; void main() { - color = mix(a_color_min, a_color_max, a_color_t); - blur = mix(a_blur_min, a_blur_max, a_blur_t); - opacity = mix(a_opacity_min, a_opacity_max, a_opacity_t); - gapwidth = mix(a_gapwidth_min, a_gapwidth_max, a_gapwidth_t); - offset = mix(a_offset_min, a_offset_max, a_offset_t); + color = unpack_mix_vec4(a_color, a_color_t); + blur = unpack_mix_vec2(a_blur, a_blur_t); + opacity = unpack_mix_vec2(a_opacity, a_opacity_t); + gapwidth = unpack_mix_vec2(a_gapwidth, a_gapwidth_t); + offset = unpack_mix_vec2(a_offset, a_offset_t); vec2 a_extrude = a_data.xy - 128.0; float a_direction = mod(a_data.z, 4.0) - 1.0; diff --git a/src/mbgl/shaders/line_pattern.cpp b/src/mbgl/shaders/line_pattern.cpp index 2be98deab3..f52a8e2157 100644 --- a/src/mbgl/shaders/line_pattern.cpp +++ b/src/mbgl/shaders/line_pattern.cpp @@ -37,27 +37,23 @@ varying float v_linesofar; varying float v_gamma_scale; uniform lowp float a_blur_t; -attribute lowp float a_blur_min; -attribute lowp float a_blur_max; +attribute lowp vec2 a_blur; varying lowp float blur; uniform lowp float a_opacity_t; -attribute lowp float a_opacity_min; -attribute lowp float a_opacity_max; +attribute lowp vec2 a_opacity; varying lowp float opacity; uniform lowp float a_offset_t; -attribute lowp float a_offset_min; -attribute lowp float a_offset_max; +attribute lowp vec2 a_offset; varying lowp float offset; uniform lowp float a_gapwidth_t; -attribute mediump float a_gapwidth_min; -attribute mediump float a_gapwidth_max; +attribute mediump vec2 a_gapwidth; varying mediump float gapwidth; void main() { - blur = mix(a_blur_min, a_blur_max, a_blur_t); - opacity = mix(a_opacity_min, a_opacity_max, a_opacity_t); - offset = mix(a_offset_min, a_offset_max, a_offset_t); - gapwidth = mix(a_gapwidth_min, a_gapwidth_max, a_gapwidth_t); + blur = unpack_mix_vec2(a_blur, a_blur_t); + opacity = unpack_mix_vec2(a_opacity, a_opacity_t); + offset = unpack_mix_vec2(a_offset, a_offset_t); + gapwidth = unpack_mix_vec2(a_gapwidth, a_gapwidth_t); vec2 a_extrude = a_data.xy - 128.0; float a_direction = mod(a_data.z, 4.0) - 1.0; diff --git a/src/mbgl/shaders/line_sdf.cpp b/src/mbgl/shaders/line_sdf.cpp index 5f01cf00c0..cd0d4ac318 100644 --- a/src/mbgl/shaders/line_sdf.cpp +++ b/src/mbgl/shaders/line_sdf.cpp @@ -42,32 +42,27 @@ varying vec2 v_tex_b; varying float v_gamma_scale; uniform lowp float a_color_t; -attribute lowp vec4 a_color_min; -attribute lowp vec4 a_color_max; +attribute lowp vec4 a_color; varying lowp vec4 color; uniform lowp float a_blur_t; -attribute lowp float a_blur_min; -attribute lowp float a_blur_max; +attribute lowp vec2 a_blur; varying lowp float blur; uniform lowp float a_opacity_t; -attribute lowp float a_opacity_min; -attribute lowp float a_opacity_max; +attribute lowp vec2 a_opacity; varying lowp float opacity; uniform lowp float a_gapwidth_t; -attribute mediump float a_gapwidth_min; -attribute mediump float a_gapwidth_max; +attribute mediump vec2 a_gapwidth; varying mediump float gapwidth; uniform lowp float a_offset_t; -attribute lowp float a_offset_min; -attribute lowp float a_offset_max; +attribute lowp vec2 a_offset; varying lowp float offset; void main() { - color = mix(a_color_min, a_color_max, a_color_t); - blur = mix(a_blur_min, a_blur_max, a_blur_t); - opacity = mix(a_opacity_min, a_opacity_max, a_opacity_t); - gapwidth = mix(a_gapwidth_min, a_gapwidth_max, a_gapwidth_t); - offset = mix(a_offset_min, a_offset_max, a_offset_t); + color = unpack_mix_vec4(a_color, a_color_t); + blur = unpack_mix_vec2(a_blur, a_blur_t); + opacity = unpack_mix_vec2(a_opacity, a_opacity_t); + gapwidth = unpack_mix_vec2(a_gapwidth, a_gapwidth_t); + offset = unpack_mix_vec2(a_offset, a_offset_t); vec2 a_extrude = a_data.xy - 128.0; float a_direction = mod(a_data.z, 4.0) - 1.0; diff --git a/src/mbgl/shaders/preludes.cpp b/src/mbgl/shaders/preludes.cpp index a0e9414ceb..806e655285 100644 --- a/src/mbgl/shaders/preludes.cpp +++ b/src/mbgl/shaders/preludes.cpp @@ -43,6 +43,31 @@ vec4 evaluate_zoom_function_4(const vec4 value0, const vec4 value1, const vec4 v } } + +// 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); +} + +// Unpack a pair of paint values and interpolate between them. +float unpack_mix_vec2(const vec2 packedValue, const float t) { + return mix(packedValue[0], packedValue[1], t); +} + +// Unpack a pair of paint values and interpolate between them. +vec4 unpack_mix_vec4(const vec4 packedColors, const float t) { + vec4 minColor = decode_color(vec2(packedColors[0], packedColors[1])); + vec4 maxColor = decode_color(vec2(packedColors[2], packedColors[3])); + return mix(minColor, maxColor, t); +} + // The offset depends on how many pixels are between the world origin and the edge of the tile: // vec2 offset = mod(pixel_coord, size) // diff --git a/src/mbgl/shaders/symbol_icon.cpp b/src/mbgl/shaders/symbol_icon.cpp index 5945f1f3b1..9adda0ba16 100644 --- a/src/mbgl/shaders/symbol_icon.cpp +++ b/src/mbgl/shaders/symbol_icon.cpp @@ -7,14 +7,13 @@ namespace shaders { const char* symbol_icon::name = "symbol_icon"; const char* symbol_icon::vertexSource = R"MBGL_SHADER( -attribute vec2 a_pos; -attribute vec2 a_offset; + +attribute vec4 a_pos_offset; attribute vec2 a_texture_pos; attribute vec4 a_data; uniform lowp float a_opacity_t; -attribute lowp float a_opacity_min; -attribute lowp float a_opacity_max; +attribute lowp vec2 a_opacity; varying lowp float opacity; // matrix is for the vertex position. @@ -30,7 +29,10 @@ varying vec2 v_tex; varying vec2 v_fade_tex; void main() { - opacity = mix(a_opacity_min, a_opacity_max, a_opacity_t); + opacity = unpack_mix_vec2(a_opacity, a_opacity_t); + + 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]; diff --git a/src/mbgl/shaders/symbol_sdf.cpp b/src/mbgl/shaders/symbol_sdf.cpp index ccb4b9cee6..76399dbb55 100644 --- a/src/mbgl/shaders/symbol_sdf.cpp +++ b/src/mbgl/shaders/symbol_sdf.cpp @@ -9,30 +9,24 @@ const char* symbol_sdf::name = "symbol_sdf"; const char* symbol_sdf::vertexSource = R"MBGL_SHADER( const float PI = 3.141592653589793; -attribute vec2 a_pos; -attribute vec2 a_offset; +attribute vec4 a_pos_offset; attribute vec2 a_texture_pos; attribute vec4 a_data; uniform lowp float a_fill_color_t; -attribute lowp vec4 a_fill_color_min; -attribute lowp vec4 a_fill_color_max; +attribute lowp vec4 a_fill_color; varying lowp vec4 fill_color; uniform lowp float a_halo_color_t; -attribute lowp vec4 a_halo_color_min; -attribute lowp vec4 a_halo_color_max; +attribute lowp vec4 a_halo_color; varying lowp vec4 halo_color; uniform lowp float a_opacity_t; -attribute lowp float a_opacity_min; -attribute lowp float a_opacity_max; +attribute lowp vec2 a_opacity; varying lowp float opacity; uniform lowp float a_halo_width_t; -attribute lowp float a_halo_width_min; -attribute lowp float a_halo_width_max; +attribute lowp vec2 a_halo_width; varying lowp float halo_width; uniform lowp float a_halo_blur_t; -attribute lowp float a_halo_blur_min; -attribute lowp float a_halo_blur_max; +attribute lowp vec2 a_halo_blur; varying lowp float halo_blur; // matrix is for the vertex position. @@ -53,11 +47,14 @@ varying vec2 v_fade_tex; varying float v_gamma_scale; void main() { - fill_color = mix(a_fill_color_min, a_fill_color_max, a_fill_color_t); - halo_color = mix(a_halo_color_min, a_halo_color_max, a_halo_color_t); - opacity = mix(a_opacity_min, a_opacity_max, a_opacity_t); - halo_width = mix(a_halo_width_min, a_halo_width_max, a_halo_width_t); - halo_blur = mix(a_halo_blur_min, a_halo_blur_max, a_halo_blur_t); + fill_color = unpack_mix_vec4(a_fill_color, a_fill_color_t); + halo_color = unpack_mix_vec4(a_halo_color, a_halo_color_t); + opacity = unpack_mix_vec2(a_opacity, a_opacity_t); + halo_width = unpack_mix_vec2(a_halo_width, a_halo_width_t); + halo_blur = unpack_mix_vec2(a_halo_blur, a_halo_blur_t); + + 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]; diff --git a/src/mbgl/style/paint_property_binder.hpp b/src/mbgl/style/paint_property_binder.hpp index 79c7692b2f..17c99fe1d9 100644 --- a/src/mbgl/style/paint_property_binder.hpp +++ b/src/mbgl/style/paint_property_binder.hpp @@ -11,8 +11,11 @@ namespace style { template class ConstantPaintPropertyBinder { public: - using Attribute = A; - using AttributeValue = typename Attribute::Value; + using BaseAttribute = A; + using BaseAttributeValue = typename BaseAttribute::Value; + using BaseAttributeBinding = typename BaseAttribute::Binding; + + using Attribute = attributes::ZoomInterpolatedAttribute; using AttributeBinding = typename Attribute::Binding; ConstantPaintPropertyBinder(T constant_) @@ -22,16 +25,13 @@ public: void populateVertexVector(const GeometryTileFeature&, std::size_t) {} void upload(gl::Context&) {} - AttributeBinding minAttributeBinding(const PossiblyEvaluatedPropertyValue& currentValue) const { + AttributeBinding attributeBinding(const PossiblyEvaluatedPropertyValue& currentValue) const { + auto val = currentValue.constantOr(constant); return typename Attribute::ConstantBinding { - Attribute::value(currentValue.constantOr(constant)) + Attribute::value(val, val) }; } - AttributeBinding maxAttributeBinding(const PossiblyEvaluatedPropertyValue&) const { - return AttributeBinding(); - } - float interpolationFactor(float) const { return 0.0f; } @@ -43,12 +43,13 @@ private: template class SourceFunctionPaintPropertyBinder { public: - using Attribute = A; - using AttributeValue = typename Attribute::Value; - using AttributeBinding = typename Attribute::Binding; + using BaseAttribute = A; + using BaseAttributeValue = typename BaseAttribute::Value; + using BaseAttributeBinding = typename BaseAttribute::Binding; + using BaseVertex = typename gl::Attributes::Vertex; - using Attributes = gl::Attributes; - using Vertex = typename Attributes::Vertex; + using Attribute = attributes::ZoomInterpolatedAttribute; + using AttributeBinding = typename Attribute::Binding; SourceFunctionPaintPropertyBinder(SourceFunction function_, T defaultValue_) : function(std::move(function_)), @@ -56,9 +57,10 @@ public: } void populateVertexVector(const GeometryTileFeature& feature, std::size_t length) { - AttributeValue value = Attribute::value(function.evaluate(feature, defaultValue)); + auto val = function.evaluate(feature, defaultValue); + BaseAttributeValue value = BaseAttribute::value(val); for (std::size_t i = vertexVector.vertexSize(); i < length; ++i) { - vertexVector.emplace_back(Vertex { value }); + vertexVector.emplace_back(BaseVertex { value }); } } @@ -66,21 +68,17 @@ public: vertexBuffer = context.createVertexBuffer(std::move(vertexVector)); } - AttributeBinding minAttributeBinding(const PossiblyEvaluatedPropertyValue& currentValue) const { + AttributeBinding attributeBinding(const PossiblyEvaluatedPropertyValue& currentValue) const { if (currentValue.isConstant()) { + auto val = *currentValue.constant(); return typename Attribute::ConstantBinding { - Attribute::value(*currentValue.constant()) + Attribute::value(val, val) }; } else { - return Attributes::allVariableBindings(*vertexBuffer) - .template get(); + return Attribute::variableBinding(*vertexBuffer, 0, BaseAttribute::Dimensions); } } - AttributeBinding maxAttributeBinding(const PossiblyEvaluatedPropertyValue&) const { - return AttributeBinding(); - } - float interpolationFactor(float) const { return 0.0f; } @@ -88,22 +86,17 @@ public: private: SourceFunction function; T defaultValue; - gl::VertexVector vertexVector; - optional> vertexBuffer; + gl::VertexVector vertexVector; + optional> vertexBuffer; }; template class CompositeFunctionPaintPropertyBinder { public: - using Attribute = A; + using Attribute = attributes::ZoomInterpolatedAttribute; using AttributeValue = typename Attribute::Value; using AttributeBinding = typename Attribute::Binding; - - using MinAttribute = attributes::Min; - using MaxAttribute = attributes::Max; - - using Attributes = gl::Attributes; - using Vertex = typename Attributes::Vertex; + using Vertex = typename gl::Attributes::Vertex; CompositeFunctionPaintPropertyBinder(CompositeFunction function_, float zoom, T defaultValue_) : function(std::move(function_)), @@ -113,10 +106,9 @@ public: void populateVertexVector(const GeometryTileFeature& feature, std::size_t length) { Range range = function.evaluate(std::get<1>(coveringRanges), feature, defaultValue); - AttributeValue min = Attribute::value(range.min); - AttributeValue max = Attribute::value(range.max); + AttributeValue minMax = Attribute::value(range.min, range.max); for (std::size_t i = vertexVector.vertexSize(); i < length; ++i) { - vertexVector.emplace_back(Vertex { min, max }); + vertexVector.emplace_back(Vertex { minMax }); } } @@ -124,23 +116,14 @@ public: vertexBuffer = context.createVertexBuffer(std::move(vertexVector)); } - AttributeBinding minAttributeBinding(const PossiblyEvaluatedPropertyValue& currentValue) const { + AttributeBinding attributeBinding(const PossiblyEvaluatedPropertyValue& currentValue) const { if (currentValue.isConstant()) { + auto val = *currentValue.constant(); return typename Attribute::ConstantBinding { - Attribute::value(*currentValue.constant()) + Attribute::value(val, val) }; } else { - return Attributes::allVariableBindings(*vertexBuffer) - .template get(); - } - } - - AttributeBinding maxAttributeBinding(const PossiblyEvaluatedPropertyValue& currentValue) const { - if (currentValue.isConstant()) { - return AttributeBinding(); - } else { - return Attributes::allVariableBindings(*vertexBuffer) - .template get(); + return Attribute::variableBinding(*vertexBuffer, 0); } } @@ -161,24 +144,27 @@ template class PaintPropertyBinder { public: using Type = typename PaintProperty::Type; - using Attribute = typename PaintProperty::Attribute; using PropertyValue = typename PaintProperty::EvaluatedType; + using BaseAttribute = typename PaintProperty::Attribute; + using Attribute = attributes::ZoomInterpolatedAttribute; + using AttributeBinding = typename Attribute::Binding; + using Binder = variant< - ConstantPaintPropertyBinder, - SourceFunctionPaintPropertyBinder, - CompositeFunctionPaintPropertyBinder>; + ConstantPaintPropertyBinder, + SourceFunctionPaintPropertyBinder, + CompositeFunctionPaintPropertyBinder>; PaintPropertyBinder(const PropertyValue& value, float zoom) : binder(value.match( [&] (const Type& constant) -> Binder { - return ConstantPaintPropertyBinder(constant); + return ConstantPaintPropertyBinder(constant); }, [&] (const SourceFunction& function) { - return SourceFunctionPaintPropertyBinder(function, PaintProperty::defaultValue()); + return SourceFunctionPaintPropertyBinder(function, PaintProperty::defaultValue()); }, [&] (const CompositeFunction& function) { - return CompositeFunctionPaintPropertyBinder(function, zoom, PaintProperty::defaultValue()); + return CompositeFunctionPaintPropertyBinder(function, zoom, PaintProperty::defaultValue()); } )) { } @@ -195,19 +181,9 @@ public: }); } - using MinAttribute = attributes::Min; - using MaxAttribute = attributes::Max; - using AttributeBinding = typename Attribute::Binding; - - AttributeBinding minAttributeBinding(const PropertyValue& currentValue) const { - return binder.match([&] (const auto& b) { - return b.minAttributeBinding(currentValue); - }); - } - - AttributeBinding maxAttributeBinding(const PropertyValue& currentValue) const { + AttributeBinding attributeBinding(const PropertyValue& currentValue) const { return binder.match([&] (const auto& b) { - return b.maxAttributeBinding(currentValue); + return b.attributeBinding(currentValue); }); } @@ -252,21 +228,14 @@ public: }); } - using MinAttributes = gl::Attributes::MinAttribute...>; - using MaxAttributes = gl::Attributes::MaxAttribute...>; - - using Attributes = gl::ConcatenateAttributes; + using Attributes = gl::Attributes::Attribute...>; using AttributeBindings = typename Attributes::Bindings; template AttributeBindings attributeBindings(const EvaluatedProperties& currentProperties) const { - const typename MinAttributes::Bindings min { - binders.template get().minAttributeBinding(currentProperties.template get())... - }; - const typename MaxAttributes::Bindings max { - binders.template get().maxAttributeBinding(currentProperties.template get())... + return typename Attributes::Bindings { + binders.template get().attributeBinding(currentProperties.template get())... }; - return min.concat(max); } using Uniforms = gl::Uniforms::InterpolationUniform...>; -- cgit v1.2.1