diff --git a/src/mbgl/gl/attribute.hpp b/src/mbgl/gl/attribute.hpp index 43e2c2d79..ab97ada0f 100644 --- a/src/mbgl/gl/attribute.hpp +++ b/src/mbgl/gl/attribute.hpp @@ -113,8 +113,11 @@ public: } }; -#define MBGL_DEFINE_ATTRIBUTE(type_, n_, name_) \ - struct name_ : ::mbgl::gl::Attribute { static auto name() { return #name_; } } +#define MBGL_DEFINE_ATTRIBUTE(type_, n_, name_) \ + struct name_ { \ + static auto name() { return #name_; } \ + using Type = ::mbgl::gl::Attribute; \ + } namespace detail { @@ -234,15 +237,15 @@ public: using Types = TypeList; using Locations = IndexedTuple< TypeList, - TypeList>; + TypeList>; using Bindings = IndexedTuple< TypeList, - TypeList>; + TypeList>; using VariableBindings = IndexedTuple< TypeList, - TypeList...>>; + TypeList...>>; - using Vertex = detail::Vertex; + using Vertex = detail::Vertex; template static constexpr std::size_t Index = TypeIndex::value; @@ -253,7 +256,7 @@ public: template static Bindings allVariableBindings(const VertexBuffer& buffer) { - return Bindings { As::variableBinding(buffer, Index)... }; + return Bindings { As::Type::variableBinding(buffer, Index)... }; } static void bind(Context& context, @@ -261,11 +264,11 @@ public: VariableBindings& oldBindings, const Bindings& newBindings, std::size_t vertexOffset) { - util::ignore({ (As::bind(context, - locations.template get(), - oldBindings.template get(), - newBindings.template get(), - vertexOffset), 0)... }); + util::ignore({ (As::Type::bind(context, + locations.template get(), + oldBindings.template get(), + newBindings.template get(), + vertexOffset), 0)... }); } }; diff --git a/src/mbgl/programs/attributes.hpp b/src/mbgl/programs/attributes.hpp index b015c0636..7d39c0439 100644 --- a/src/mbgl/programs/attributes.hpp +++ b/src/mbgl/programs/attributes.hpp @@ -16,209 +16,104 @@ MBGL_DEFINE_ATTRIBUTE(int16_t, 4, a_pos_offset); MBGL_DEFINE_ATTRIBUTE(uint16_t, 2, a_texture_pos); template -struct a_data : gl::Attribute { +struct a_data { static auto name() { return "a_data"; } + using Type = gl::Attribute; }; template -struct a_offset : gl::Attribute { +struct a_offset { static auto name() { return "a_offset"; } + using Type = 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 ZoomInterpolatedAttribute : gl::Attribute { - using Value = typename gl::Attribute::Value; - - static auto name() { - 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; - } -}; - -template -struct InterpolationUniform : gl::UniformScalar, float> { - static auto name() { - static const std::string name = Attr::name() + std::string("_t"); - return name.c_str(); - } -}; - -/* - 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 { +struct a_color { static auto name() { return "a_color"; } - - static Value value(const Color& color) { - return encodeColor(color); - } + using Type = gl::Attribute; }; -// used in the symbol sdf shader -struct a_fill_color : gl::Attribute { +struct a_fill_color { static auto name() { return "a_fill_color"; } - - static Value value(const Color& color) { - return encodeColor(color); - } + using Type = gl::Attribute; }; -// used in the symbol sdf shader -struct a_halo_color : gl::Attribute { +struct a_halo_color { static auto name() { return "a_halo_color"; } - - static Value value(const Color& color) { - return encodeColor(color); - } + using Type = gl::Attribute; }; -struct a_stroke_color : gl::Attribute { +struct a_stroke_color { static auto name() { return "a_stroke_color"; } - - static Value value(const Color& color) { - return encodeColor(color); - } + using Type = gl::Attribute; }; -struct a_outline_color : gl::Attribute { +struct a_outline_color { static auto name() { return "a_outline_color"; } - - static Value value(const Color& color) { - return encodeColor(color); - } + using Type = gl::Attribute; }; -struct a_opacity : gl::Attribute { +struct a_opacity { static auto name() { return "a_opacity"; } - - static Value value(float opacity) { - return {{ opacity }}; - } + using Type = gl::Attribute; }; -struct a_stroke_opacity : gl::Attribute { +struct a_stroke_opacity { static auto name() { return "a_stroke_opacity"; } - - static Value value(float opacity) { - return {{ opacity }}; - } + using Type = gl::Attribute; }; -struct a_blur : gl::Attribute { +struct a_blur { static auto name() { return "a_blur"; } - - static Value value(float blur) { - return {{ blur }}; - } + using Type = gl::Attribute; }; -struct a_radius : gl::Attribute { +struct a_radius { static auto name() { return "a_radius"; } - - static Value value(float radius) { - return {{ radius }}; - } + using Type = gl::Attribute; }; -struct a_width : gl::Attribute { +struct a_width { static auto name() { return "a_width"; } - - static Value value(float width) { - return {{ width }}; - } + using Type = gl::Attribute; }; -struct a_height : gl::Attribute { +struct a_height { static auto name() { return "a_height"; } - - static Value value(float width) { - return {{ width }}; - } + using Type = gl::Attribute; }; -struct a_base : gl::Attribute { +struct a_base { static auto name() { return "a_base"; } - - static Value value(float width) { - return {{ width }}; - } + using Type = gl::Attribute; }; -struct a_gap_width : gl::Attribute { +struct a_gap_width { static auto name() { return "a_gapwidth"; } - - static Value value(float width) { - return {{ width }}; - } + using Type = gl::Attribute; }; -struct a_stroke_width : gl::Attribute { +struct a_stroke_width { static auto name() { return "a_stroke_width"; } - - static Value value(float width) { - return {{ width }}; - } + using Type = gl::Attribute; }; template <> -struct a_offset<1> : gl::Attribute { +struct a_offset<1> { static auto name() { return "a_offset"; } - - static Value value(float offset) { - return {{ offset }}; - } + using Type = gl::Attribute; }; -struct a_halo_width : gl::Attribute { +struct a_halo_width { static auto name() { return "a_halo_width"; } - - static Value value(float width) { - return {{ width }}; - } + using Type = gl::Attribute; }; -struct a_halo_blur : gl::Attribute { +struct a_halo_blur { static auto name() { return "a_halo_blur"; } - - static Value value(float blur) { - return {{ blur }}; - } + using Type = gl::Attribute; }; - - } // namespace attributes } // namespace mbgl diff --git a/src/mbgl/style/paint_property_binder.hpp b/src/mbgl/style/paint_property_binder.hpp index 630c1104f..e6e957958 100644 --- a/src/mbgl/style/paint_property_binder.hpp +++ b/src/mbgl/style/paint_property_binder.hpp @@ -8,11 +8,51 @@ namespace mbgl { namespace style { +/* + 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 +using ZoomInterpolatedAttributeType = gl::Attribute; + +inline std::array attributeValue(float v) { + return {{ v }}; +} + +/* + 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. +*/ +inline std::array attributeValue(const Color& color) { + return {{ + static_cast(static_cast(color.r * 255) * 256 + static_cast(color.g * 255)), + static_cast(static_cast(color.b * 255) * 256 + static_cast(color.a * 255)) + }}; +} + +template +std::array zoomInterpolatedAttributeValue(const std::array& min, const std::array& max) { + std::array result; + for (size_t i = 0; i < N; i++) { + result[i] = min[i]; + result[i+N] = max[i]; + } + return result; +} + template class PaintPropertyBinder { public: - using BaseAttribute = A; - using Attribute = attributes::ZoomInterpolatedAttribute; + using Attribute = ZoomInterpolatedAttributeType; using AttributeBinding = typename Attribute::Binding; virtual ~PaintPropertyBinder() = default; @@ -21,16 +61,14 @@ public: virtual void upload(gl::Context& context) = 0; virtual AttributeBinding attributeBinding(const PossiblyEvaluatedPropertyValue& currentValue) const = 0; virtual float interpolationFactor(float currentZoom) const = 0; + + static std::unique_ptr create(const PossiblyEvaluatedPropertyValue& value, float zoom, T defaultValue); }; template class ConstantPaintPropertyBinder : public PaintPropertyBinder { public: - using BaseAttribute = A; - using BaseAttributeValue = typename BaseAttribute::Value; - using BaseAttributeBinding = typename BaseAttribute::Binding; - - using Attribute = attributes::ZoomInterpolatedAttribute; + using Attribute = ZoomInterpolatedAttributeType; using AttributeBinding = typename Attribute::Binding; ConstantPaintPropertyBinder(T constant_) @@ -41,9 +79,9 @@ public: void upload(gl::Context&) override {} AttributeBinding attributeBinding(const PossiblyEvaluatedPropertyValue& currentValue) const override { - auto val = currentValue.constantOr(constant); + auto value = attributeValue(currentValue.constantOr(constant)); return typename Attribute::ConstantBinding { - Attribute::value(val, val) + zoomInterpolatedAttributeValue(value, value) }; } @@ -60,10 +98,9 @@ class SourceFunctionPaintPropertyBinder : public PaintPropertyBinder { public: using BaseAttribute = A; using BaseAttributeValue = typename BaseAttribute::Value; - using BaseAttributeBinding = typename BaseAttribute::Binding; - using BaseVertex = typename gl::Attributes::Vertex; + using BaseVertex = gl::detail::Vertex; - using Attribute = attributes::ZoomInterpolatedAttribute; + using Attribute = ZoomInterpolatedAttributeType; using AttributeBinding = typename Attribute::Binding; SourceFunctionPaintPropertyBinder(SourceFunction function_, T defaultValue_) @@ -72,8 +109,7 @@ public: } void populateVertexVector(const GeometryTileFeature& feature, std::size_t length) override { - auto val = function.evaluate(feature, defaultValue); - BaseAttributeValue value = BaseAttribute::value(val); + auto value = attributeValue(function.evaluate(feature, defaultValue)); for (std::size_t i = vertexVector.vertexSize(); i < length; ++i) { vertexVector.emplace_back(BaseVertex { value }); } @@ -85,9 +121,9 @@ public: AttributeBinding attributeBinding(const PossiblyEvaluatedPropertyValue& currentValue) const override { if (currentValue.isConstant()) { - auto val = *currentValue.constant(); + BaseAttributeValue value = attributeValue(*currentValue.constant()); return typename Attribute::ConstantBinding { - Attribute::value(val, val) + zoomInterpolatedAttributeValue(value, value) }; } else { return Attribute::variableBinding(*vertexBuffer, 0, BaseAttribute::Dimensions); @@ -108,10 +144,13 @@ private: template class CompositeFunctionPaintPropertyBinder : public PaintPropertyBinder { public: - using Attribute = attributes::ZoomInterpolatedAttribute; + using BaseAttribute = A; + using BaseAttributeValue = typename BaseAttribute::Value; + + using Attribute = ZoomInterpolatedAttributeType; using AttributeValue = typename Attribute::Value; using AttributeBinding = typename Attribute::Binding; - using Vertex = typename gl::Attributes::Vertex; + using Vertex = gl::detail::Vertex; CompositeFunctionPaintPropertyBinder(CompositeFunction function_, float zoom, T defaultValue_) : function(std::move(function_)), @@ -121,9 +160,11 @@ public: void populateVertexVector(const GeometryTileFeature& feature, std::size_t length) override { Range range = function.evaluate(std::get<1>(coveringRanges), feature, defaultValue); - AttributeValue minMax = Attribute::value(range.min, range.max); + AttributeValue value = zoomInterpolatedAttributeValue( + attributeValue(range.min), + attributeValue(range.max)); for (std::size_t i = vertexVector.vertexSize(); i < length; ++i) { - vertexVector.emplace_back(Vertex { minMax }); + vertexVector.emplace_back(Vertex { value }); } } @@ -133,9 +174,9 @@ public: AttributeBinding attributeBinding(const PossiblyEvaluatedPropertyValue& currentValue) const override { if (currentValue.isConstant()) { - auto val = *currentValue.constant(); + BaseAttributeValue value = attributeValue(*currentValue.constant()); return typename Attribute::ConstantBinding { - Attribute::value(val, val) + zoomInterpolatedAttributeValue(value, value) }; } else { return Attribute::variableBinding(*vertexBuffer, 0); @@ -155,36 +196,52 @@ private: optional> vertexBuffer; }; -template -auto createPaintPropertyBinder(const typename PaintProperty::EvaluatedType& value, float zoom) { - using Type = typename PaintProperty::Type; - using Attribute = typename PaintProperty::Attribute; +template +std::unique_ptr> +PaintPropertyBinder::create(const PossiblyEvaluatedPropertyValue& value, float zoom, T defaultValue) { return value.match( - [&] (const Type& constant) -> std::unique_ptr> { - return std::make_unique>(constant); + [&] (const T& constant) -> std::unique_ptr> { + return std::make_unique>(constant); }, - [&] (const SourceFunction& function) { - return std::make_unique>(function, PaintProperty::defaultValue()); + [&] (const SourceFunction& function) { + return std::make_unique>(function, defaultValue); }, - [&] (const CompositeFunction& function) { - return std::make_unique>(function, zoom, PaintProperty::defaultValue()); + [&] (const CompositeFunction& function) { + return std::make_unique>(function, zoom, defaultValue); } ); } +template +struct ZoomInterpolatedAttribute { + static auto name() { return Attr::name(); } + using Type = ZoomInterpolatedAttributeType; +}; + +template +struct InterpolationUniform : gl::UniformScalar, float> { + static auto name() { + static const std::string name = Attr::name() + std::string("_t"); + return name.c_str(); + } +}; + template class PaintPropertyBinders; template class PaintPropertyBinders> { public: + template + using Binder = PaintPropertyBinder; + using Binders = IndexedTuple< TypeList, - TypeList>...>>; + TypeList>...>>; template PaintPropertyBinders(const EvaluatedProperties& properties, float z) - : binders(createPaintPropertyBinder(properties.template get(), z)...) { + : binders(Binder::create(properties.template get(), z, Ps::defaultValue())...) { (void)z; // Workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56958 } @@ -203,7 +260,10 @@ public: }); } - using Attributes = gl::Attributes::Attribute...>; + template + using Attribute = ZoomInterpolatedAttribute; + + using Attributes = gl::Attributes...>; using AttributeBindings = typename Attributes::Bindings; template @@ -213,13 +273,13 @@ public: }; } - using Uniforms = gl::Uniforms...>; + using Uniforms = gl::Uniforms...>; using UniformValues = typename Uniforms::Values; UniformValues uniformValues(float currentZoom) const { (void)currentZoom; // Workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56958 return UniformValues { - typename attributes::InterpolationUniform::Value { + typename InterpolationUniform::Value { binders.template get()->interpolationFactor(currentZoom) }... };