summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
m---------mapbox-gl-js0
-rwxr-xr-xscripts/generate-shaders.js7
-rw-r--r--src/mbgl/gl/attribute.cpp2
-rw-r--r--src/mbgl/gl/attribute.hpp46
-rw-r--r--src/mbgl/programs/attributes.hpp96
-rw-r--r--src/mbgl/programs/symbol_program.hpp8
-rw-r--r--src/mbgl/shaders/circle.cpp35
-rw-r--r--src/mbgl/shaders/fill.cpp10
-rw-r--r--src/mbgl/shaders/fill_outline.cpp10
-rw-r--r--src/mbgl/shaders/fill_outline_pattern.cpp5
-rw-r--r--src/mbgl/shaders/fill_pattern.cpp5
-rw-r--r--src/mbgl/shaders/line.cpp25
-rw-r--r--src/mbgl/shaders/line_pattern.cpp20
-rw-r--r--src/mbgl/shaders/line_sdf.cpp25
-rw-r--r--src/mbgl/shaders/preludes.cpp25
-rw-r--r--src/mbgl/shaders/symbol_icon.cpp12
-rw-r--r--src/mbgl/shaders/symbol_sdf.cpp31
-rw-r--r--src/mbgl/style/paint_property_binder.hpp123
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...>;