diff options
m--------- | mapbox-gl-js | 0 | ||||
-rwxr-xr-x | scripts/generate-shaders.js | 7 | ||||
-rw-r--r-- | src/mbgl/gl/attribute.cpp | 2 | ||||
-rw-r--r-- | src/mbgl/gl/attribute.hpp | 46 | ||||
-rw-r--r-- | src/mbgl/programs/attributes.hpp | 96 | ||||
-rw-r--r-- | src/mbgl/programs/symbol_program.hpp | 8 | ||||
-rw-r--r-- | src/mbgl/shaders/circle.cpp | 35 | ||||
-rw-r--r-- | src/mbgl/shaders/fill.cpp | 10 | ||||
-rw-r--r-- | src/mbgl/shaders/fill_outline.cpp | 10 | ||||
-rw-r--r-- | src/mbgl/shaders/fill_outline_pattern.cpp | 5 | ||||
-rw-r--r-- | src/mbgl/shaders/fill_pattern.cpp | 5 | ||||
-rw-r--r-- | src/mbgl/shaders/line.cpp | 25 | ||||
-rw-r--r-- | src/mbgl/shaders/line_pattern.cpp | 20 | ||||
-rw-r--r-- | src/mbgl/shaders/line_sdf.cpp | 25 | ||||
-rw-r--r-- | src/mbgl/shaders/preludes.cpp | 25 | ||||
-rw-r--r-- | src/mbgl/shaders/symbol_icon.cpp | 12 | ||||
-rw-r--r-- | src/mbgl/shaders/symbol_sdf.cpp | 31 | ||||
-rw-r--r-- | src/mbgl/style/paint_property_binder.hpp | 123 |
18 files changed, 238 insertions, 247 deletions
diff --git a/mapbox-gl-js b/mapbox-gl-js -Subproject f9c5c175926278a24f1b0d958867632023773ed +Subproject 69bb05cef27c99722f6616867032d64b5f12ee5 diff --git a/scripts/generate-shaders.js b/scripts/generate-shaders.js index 892620cf21..cffe9d3854 100755 --- a/scripts/generate-shaders.js +++ b/scripts/generate-shaders.js @@ -60,9 +60,11 @@ ${fragmentPrelude} ].forEach(function (shaderName) { function applyPragmas(source, pragmas) { return source.replace(/#pragma mapbox: ([\w]+) ([\w]+) ([\w]+) ([\w]+)/g, (match, operation, precision, type, name) => { + const a_type = type === "float" ? "vec2" : "vec4"; return pragmas[operation] .join("\n") .replace(/\{type\}/g, type) + .replace(/\{a_type}/g, a_type) .replace(/\{precision\}/g, precision) .replace(/\{name\}/g, name); }); @@ -73,12 +75,11 @@ ${fragmentPrelude} return applyPragmas(source, { define: [ "uniform lowp float a_{name}_t;", - "attribute {precision} {type} a_{name}_min;", - "attribute {precision} {type} a_{name}_max;", + "attribute {precision} {a_type} a_{name};", "varying {precision} {type} {name};" ], initialize: [ - "{name} = mix(a_{name}_min, a_{name}_max, a_{name}_t);" + "{name} = unpack_mix_{a_type}(a_{name}, a_{name}_t);" ] }); } 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<T, N>::bind(Context& context, MBGL_CHECK_ERROR(glEnableVertexAttribArray(location)); MBGL_CHECK_ERROR(glVertexAttribPointer( location, - static_cast<GLint>(N), + static_cast<GLint>(attributeSize), static_cast<GLenum>(DataTypeOf<T>), static_cast<GLboolean>(IsNormalized<T>), static_cast<GLsizei>(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<VariableAttributeBinding<T, N>>&, 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 <class T, std::size_t N> @@ -58,9 +62,16 @@ private: std::array<T, N> value; }; +/* + gl::Attribute<T,N> manages the binding of a constant value or vertex buffer to a GL program attribute. + - T is the underlying primitive type (exposed as Attribute<T,N>::ValueType) + - N is the number of components in the attribute declared in the shader (exposed as Attribute<T,N>::Dimensions) +*/ template <class T, std::size_t N> class Attribute { public: + using ValueType = T; + static constexpr size_t Dimensions = N; using Value = std::array<T, N>; using VariableBinding = VariableAttributeBinding<T, N>; @@ -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 <class Vertex, class DrawMode> + static VariableBinding variableBinding(const VertexBuffer<Vertex, DrawMode>& buffer, + std::size_t attributeIndex, + std::size_t attributeSize = N) { + static_assert(std::is_standard_layout<Vertex>::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<VariableBinding>& oldBinding, @@ -223,15 +253,7 @@ public: template <class DrawMode> static Bindings allVariableBindings(const VertexBuffer<Vertex, DrawMode>& buffer) { - static_assert(std::is_standard_layout<Vertex>::value, "vertex type must use standard layout"); - - return Bindings { - typename As::VariableBinding { - buffer.buffer, - sizeof(Vertex), - Vertex::attributeOffsets[Index<As>] - }... - }; + return Bindings { As::variableBinding(buffer, Index<As>)... }; } 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 <std::size_t N> @@ -27,19 +28,30 @@ struct a_offset : gl::Attribute<int16_t, N> { // Paint attributes +/* + ZoomInterpolatedAttribute<Attr> 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 <class Attr> -struct Min : Attr { - static auto name() { - static const std::string name = Attr::name() + std::string("_min"); - return name.c_str(); - } -}; +struct ZoomInterpolatedAttribute : gl::Attribute<typename Attr::ValueType, Attr::Dimensions * 2> { + using Value = typename gl::Attribute<typename Attr::ValueType, Attr::Dimensions * 2>::Value; -template <class Attr> -struct Max : Attr { static auto name() { - static const std::string name = Attr::name() + std::string("_max"); - return name.c_str(); + return Attr::name(); + } + + template <class InputType> + 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<InterpolationUniform<Attr>, floa } }; -struct a_color : gl::Attribute<gl::Normalized<uint8_t>, 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<float, 2> encodeColor (const Color& color) { + const auto v1 = static_cast<uint16_t>( static_cast<uint16_t>(color.r*255)*256 + color.g*255); + const auto v2 = static_cast<uint16_t>( static_cast<uint16_t>(color.b*255)*256 + color.a*255); + return {{ static_cast<float>(v1), static_cast<float>(v2) }}; +} + +struct a_color : gl::Attribute<float, 2> { static auto name() { return "a_color"; } static Value value(const Color& color) { - return {{ - gl::Normalized<uint8_t>(color.r), - gl::Normalized<uint8_t>(color.g), - gl::Normalized<uint8_t>(color.b), - gl::Normalized<uint8_t>(color.a) - }}; + return encodeColor(color); } }; // used in the symbol sdf shader -struct a_fill_color : gl::Attribute<gl::Normalized<uint8_t>, 4> { +struct a_fill_color : gl::Attribute<float, 2> { static auto name() { return "a_fill_color"; } static Value value(const Color& color) { - return {{ - gl::Normalized<uint8_t>(color.r), - gl::Normalized<uint8_t>(color.g), - gl::Normalized<uint8_t>(color.b), - gl::Normalized<uint8_t>(color.a) - }}; + return encodeColor(color); } }; // used in the symbol sdf shader -struct a_halo_color : gl::Attribute<gl::Normalized<uint8_t>, 4> { +struct a_halo_color : gl::Attribute<float, 2> { static auto name() { return "a_halo_color"; } - static Value value(const Color& color) { - return {{ - gl::Normalized<uint8_t>(color.r), - gl::Normalized<uint8_t>(color.g), - gl::Normalized<uint8_t>(color.b), - gl::Normalized<uint8_t>(color.a) - }}; + static Value value(const Color& color) { + return encodeColor(color); } }; -struct a_stroke_color : gl::Attribute<gl::Normalized<uint8_t>, 4> { +struct a_stroke_color : gl::Attribute<float, 2> { static auto name() { return "a_stroke_color"; } static Value value(const Color& color) { - return {{ - gl::Normalized<uint8_t>(color.r), - gl::Normalized<uint8_t>(color.g), - gl::Normalized<uint8_t>(color.b), - gl::Normalized<uint8_t>(color.a) - }}; + return encodeColor(color); } }; -struct a_outline_color : gl::Attribute<gl::Normalized<uint8_t>, 4> { +struct a_outline_color : gl::Attribute<float, 2> { static auto name() { return "a_outline_color"; } static Value value(const Color& color) { - return {{ - gl::Normalized<uint8_t>(color.r), - gl::Normalized<uint8_t>(color.g), - gl::Normalized<uint8_t>(color.b), - gl::Normalized<uint8_t>(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<int16_t>(a.x), - static_cast<int16_t>(a.y) - }}, - {{ + static_cast<int16_t>(a.y), static_cast<int16_t>(::round(o.x * 64)), // use 1/64 pixels for placement static_cast<int16_t>(::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 T, class A> 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<BaseAttribute>; 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<T>& currentValue) const { + AttributeBinding attributeBinding(const PossiblyEvaluatedPropertyValue<T>& currentValue) const { + auto val = currentValue.constantOr(constant); return typename Attribute::ConstantBinding { - Attribute::value(currentValue.constantOr(constant)) + Attribute::value(val, val) }; } - AttributeBinding maxAttributeBinding(const PossiblyEvaluatedPropertyValue<T>&) const { - return AttributeBinding(); - } - float interpolationFactor(float) const { return 0.0f; } @@ -43,12 +43,13 @@ private: template <class T, class A> 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<BaseAttribute>::Vertex; - using Attributes = gl::Attributes<Attribute>; - using Vertex = typename Attributes::Vertex; + using Attribute = attributes::ZoomInterpolatedAttribute<BaseAttribute>; + using AttributeBinding = typename Attribute::Binding; SourceFunctionPaintPropertyBinder(SourceFunction<T> 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<T>& currentValue) const { + AttributeBinding attributeBinding(const PossiblyEvaluatedPropertyValue<T>& 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<Attribute>(); + return Attribute::variableBinding(*vertexBuffer, 0, BaseAttribute::Dimensions); } } - AttributeBinding maxAttributeBinding(const PossiblyEvaluatedPropertyValue<T>&) const { - return AttributeBinding(); - } - float interpolationFactor(float) const { return 0.0f; } @@ -88,22 +86,17 @@ public: private: SourceFunction<T> function; T defaultValue; - gl::VertexVector<Vertex> vertexVector; - optional<gl::VertexBuffer<Vertex>> vertexBuffer; + gl::VertexVector<BaseVertex> vertexVector; + optional<gl::VertexBuffer<BaseVertex>> vertexBuffer; }; template <class T, class A> class CompositeFunctionPaintPropertyBinder { public: - using Attribute = A; + using Attribute = attributes::ZoomInterpolatedAttribute<A>; using AttributeValue = typename Attribute::Value; using AttributeBinding = typename Attribute::Binding; - - using MinAttribute = attributes::Min<Attribute>; - using MaxAttribute = attributes::Max<Attribute>; - - using Attributes = gl::Attributes<MinAttribute, MaxAttribute>; - using Vertex = typename Attributes::Vertex; + using Vertex = typename gl::Attributes<Attribute>::Vertex; CompositeFunctionPaintPropertyBinder(CompositeFunction<T> function_, float zoom, T defaultValue_) : function(std::move(function_)), @@ -113,10 +106,9 @@ public: void populateVertexVector(const GeometryTileFeature& feature, std::size_t length) { Range<T> 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<T>& currentValue) const { + AttributeBinding attributeBinding(const PossiblyEvaluatedPropertyValue<T>& 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<MinAttribute>(); - } - } - - AttributeBinding maxAttributeBinding(const PossiblyEvaluatedPropertyValue<T>& currentValue) const { - if (currentValue.isConstant()) { - return AttributeBinding(); - } else { - return Attributes::allVariableBindings(*vertexBuffer) - .template get<MaxAttribute>(); + return Attribute::variableBinding(*vertexBuffer, 0); } } @@ -161,24 +144,27 @@ template <class PaintProperty> 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<BaseAttribute>; + using AttributeBinding = typename Attribute::Binding; + using Binder = variant< - ConstantPaintPropertyBinder<Type, Attribute>, - SourceFunctionPaintPropertyBinder<Type, Attribute>, - CompositeFunctionPaintPropertyBinder<Type, Attribute>>; + ConstantPaintPropertyBinder<Type, BaseAttribute>, + SourceFunctionPaintPropertyBinder<Type, BaseAttribute>, + CompositeFunctionPaintPropertyBinder<Type, BaseAttribute>>; PaintPropertyBinder(const PropertyValue& value, float zoom) : binder(value.match( [&] (const Type& constant) -> Binder { - return ConstantPaintPropertyBinder<Type, Attribute>(constant); + return ConstantPaintPropertyBinder<Type, BaseAttribute>(constant); }, [&] (const SourceFunction<Type>& function) { - return SourceFunctionPaintPropertyBinder<Type, Attribute>(function, PaintProperty::defaultValue()); + return SourceFunctionPaintPropertyBinder<Type, BaseAttribute>(function, PaintProperty::defaultValue()); }, [&] (const CompositeFunction<Type>& function) { - return CompositeFunctionPaintPropertyBinder<Type, Attribute>(function, zoom, PaintProperty::defaultValue()); + return CompositeFunctionPaintPropertyBinder<Type, BaseAttribute>(function, zoom, PaintProperty::defaultValue()); } )) { } @@ -195,19 +181,9 @@ public: }); } - using MinAttribute = attributes::Min<Attribute>; - using MaxAttribute = attributes::Max<Attribute>; - 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<typename PaintPropertyBinder<Ps>::MinAttribute...>; - using MaxAttributes = gl::Attributes<typename PaintPropertyBinder<Ps>::MaxAttribute...>; - - using Attributes = gl::ConcatenateAttributes<MinAttributes, MaxAttributes>; + using Attributes = gl::Attributes<typename PaintPropertyBinder<Ps>::Attribute...>; using AttributeBindings = typename Attributes::Bindings; template <class EvaluatedProperties> AttributeBindings attributeBindings(const EvaluatedProperties& currentProperties) const { - const typename MinAttributes::Bindings min { - binders.template get<Ps>().minAttributeBinding(currentProperties.template get<Ps>())... - }; - const typename MaxAttributes::Bindings max { - binders.template get<Ps>().maxAttributeBinding(currentProperties.template get<Ps>())... + return typename Attributes::Bindings { + binders.template get<Ps>().attributeBinding(currentProperties.template get<Ps>())... }; - return min.concat(max); } using Uniforms = gl::Uniforms<typename PaintPropertyBinder<Ps>::InterpolationUniform...>; |