diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/mbgl/gl/attribute.hpp | 27 | ||||
-rw-r--r-- | src/mbgl/programs/attributes.hpp | 181 | ||||
-rw-r--r-- | src/mbgl/style/paint_property_binder.hpp | 134 |
3 files changed, 150 insertions, 192 deletions
diff --git a/src/mbgl/gl/attribute.hpp b/src/mbgl/gl/attribute.hpp index 43e2c2d794..ab97ada0f2 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<type_, n_> { static auto name() { return #name_; } } +#define MBGL_DEFINE_ATTRIBUTE(type_, n_, name_) \ + struct name_ { \ + static auto name() { return #name_; } \ + using Type = ::mbgl::gl::Attribute<type_, n_>; \ + } namespace detail { @@ -234,15 +237,15 @@ public: using Types = TypeList<As...>; using Locations = IndexedTuple< TypeList<As...>, - TypeList<typename As::Location...>>; + TypeList<typename As::Type::Location...>>; using Bindings = IndexedTuple< TypeList<As...>, - TypeList<typename As::Binding...>>; + TypeList<typename As::Type::Binding...>>; using VariableBindings = IndexedTuple< TypeList<As...>, - TypeList<optional<typename As::VariableBinding>...>>; + TypeList<optional<typename As::Type::VariableBinding>...>>; - using Vertex = detail::Vertex<As...>; + using Vertex = detail::Vertex<typename As::Type...>; template <class A> static constexpr std::size_t Index = TypeIndex<A, As...>::value; @@ -253,7 +256,7 @@ public: template <class DrawMode> static Bindings allVariableBindings(const VertexBuffer<Vertex, DrawMode>& buffer) { - return Bindings { As::variableBinding(buffer, Index<As>)... }; + return Bindings { As::Type::variableBinding(buffer, Index<As>)... }; } 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<As>(), - oldBindings.template get<As>(), - newBindings.template get<As>(), - vertexOffset), 0)... }); + util::ignore({ (As::Type::bind(context, + locations.template get<As>(), + oldBindings.template get<As>(), + newBindings.template get<As>(), + vertexOffset), 0)... }); } }; diff --git a/src/mbgl/programs/attributes.hpp b/src/mbgl/programs/attributes.hpp index b015c06366..7d39c04395 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 <std::size_t N> -struct a_data : gl::Attribute<uint8_t, N> { +struct a_data { static auto name() { return "a_data"; } + using Type = gl::Attribute<uint8_t, N>; }; template <std::size_t N> -struct a_offset : gl::Attribute<int16_t, N> { +struct a_offset { static auto name() { return "a_offset"; } + using Type = 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 ZoomInterpolatedAttribute : gl::Attribute<typename Attr::ValueType, Attr::Dimensions * 2> { - using Value = typename gl::Attribute<typename Attr::ValueType, Attr::Dimensions * 2>::Value; - - static auto name() { - 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; - } -}; - -template <class Attr> -struct InterpolationUniform : gl::UniformScalar<InterpolationUniform<Attr>, 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<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> { +struct a_color { static auto name() { return "a_color"; } - - static Value value(const Color& color) { - return encodeColor(color); - } + using Type = gl::Attribute<float, 2>; }; -// used in the symbol sdf shader -struct a_fill_color : gl::Attribute<float, 2> { +struct a_fill_color { static auto name() { return "a_fill_color"; } - - static Value value(const Color& color) { - return encodeColor(color); - } + using Type = gl::Attribute<float, 2>; }; -// used in the symbol sdf shader -struct a_halo_color : gl::Attribute<float, 2> { +struct a_halo_color { static auto name() { return "a_halo_color"; } - - static Value value(const Color& color) { - return encodeColor(color); - } + using Type = gl::Attribute<float, 2>; }; -struct a_stroke_color : gl::Attribute<float, 2> { +struct a_stroke_color { static auto name() { return "a_stroke_color"; } - - static Value value(const Color& color) { - return encodeColor(color); - } + using Type = gl::Attribute<float, 2>; }; -struct a_outline_color : gl::Attribute<float, 2> { +struct a_outline_color { static auto name() { return "a_outline_color"; } - - static Value value(const Color& color) { - return encodeColor(color); - } + using Type = gl::Attribute<float, 2>; }; -struct a_opacity : gl::Attribute<float, 1> { +struct a_opacity { static auto name() { return "a_opacity"; } - - static Value value(float opacity) { - return {{ opacity }}; - } + using Type = gl::Attribute<float, 1>; }; -struct a_stroke_opacity : gl::Attribute<float, 1> { +struct a_stroke_opacity { static auto name() { return "a_stroke_opacity"; } - - static Value value(float opacity) { - return {{ opacity }}; - } + using Type = gl::Attribute<float, 1>; }; -struct a_blur : gl::Attribute<float, 1> { +struct a_blur { static auto name() { return "a_blur"; } - - static Value value(float blur) { - return {{ blur }}; - } + using Type = gl::Attribute<float, 1>; }; -struct a_radius : gl::Attribute<float, 1> { +struct a_radius { static auto name() { return "a_radius"; } - - static Value value(float radius) { - return {{ radius }}; - } + using Type = gl::Attribute<float, 1>; }; -struct a_width : gl::Attribute<float, 1> { +struct a_width { static auto name() { return "a_width"; } - - static Value value(float width) { - return {{ width }}; - } + using Type = gl::Attribute<float, 1>; }; -struct a_height : gl::Attribute<float, 1> { +struct a_height { static auto name() { return "a_height"; } - - static Value value(float width) { - return {{ width }}; - } + using Type = gl::Attribute<float, 1>; }; -struct a_base : gl::Attribute<float, 1> { +struct a_base { static auto name() { return "a_base"; } - - static Value value(float width) { - return {{ width }}; - } + using Type = gl::Attribute<float, 1>; }; -struct a_gap_width : gl::Attribute<float, 1> { +struct a_gap_width { static auto name() { return "a_gapwidth"; } - - static Value value(float width) { - return {{ width }}; - } + using Type = gl::Attribute<float, 1>; }; -struct a_stroke_width : gl::Attribute<float, 1> { +struct a_stroke_width { static auto name() { return "a_stroke_width"; } - - static Value value(float width) { - return {{ width }}; - } + using Type = gl::Attribute<float, 1>; }; template <> -struct a_offset<1> : gl::Attribute<float, 1> { +struct a_offset<1> { static auto name() { return "a_offset"; } - - static Value value(float offset) { - return {{ offset }}; - } + using Type = gl::Attribute<float, 1>; }; -struct a_halo_width : gl::Attribute<float, 1> { +struct a_halo_width { static auto name() { return "a_halo_width"; } - - static Value value(float width) { - return {{ width }}; - } + using Type = gl::Attribute<float, 1>; }; -struct a_halo_blur : gl::Attribute<float, 1> { +struct a_halo_blur { static auto name() { return "a_halo_blur"; } - - static Value value(float blur) { - return {{ blur }}; - } + using Type = gl::Attribute<float, 1>; }; - - } // namespace attributes } // namespace mbgl diff --git a/src/mbgl/style/paint_property_binder.hpp b/src/mbgl/style/paint_property_binder.hpp index 630c1104f0..e6e957958c 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<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 A> +using ZoomInterpolatedAttributeType = gl::Attribute<typename A::ValueType, A::Dimensions * 2>; + +inline std::array<float, 1> 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<float, 2> attributeValue(const Color& color) { + return {{ + static_cast<float>(static_cast<uint16_t>(color.r * 255) * 256 + static_cast<uint16_t>(color.g * 255)), + static_cast<float>(static_cast<uint16_t>(color.b * 255) * 256 + static_cast<uint16_t>(color.a * 255)) + }}; +} + +template <size_t N> +std::array<float, N*2> zoomInterpolatedAttributeValue(const std::array<float, N>& min, const std::array<float, N>& max) { + std::array<float, N*2> result; + for (size_t i = 0; i < N; i++) { + result[i] = min[i]; + result[i+N] = max[i]; + } + return result; +} + template <class T, class A> class PaintPropertyBinder { public: - using BaseAttribute = A; - using Attribute = attributes::ZoomInterpolatedAttribute<BaseAttribute>; + using Attribute = ZoomInterpolatedAttributeType<A>; 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<T>& currentValue) const = 0; virtual float interpolationFactor(float currentZoom) const = 0; + + static std::unique_ptr<PaintPropertyBinder> create(const PossiblyEvaluatedPropertyValue<T>& value, float zoom, T defaultValue); }; template <class T, class A> class ConstantPaintPropertyBinder : public PaintPropertyBinder<T, A> { public: - using BaseAttribute = A; - using BaseAttributeValue = typename BaseAttribute::Value; - using BaseAttributeBinding = typename BaseAttribute::Binding; - - using Attribute = attributes::ZoomInterpolatedAttribute<BaseAttribute>; + using Attribute = ZoomInterpolatedAttributeType<A>; using AttributeBinding = typename Attribute::Binding; ConstantPaintPropertyBinder(T constant_) @@ -41,9 +79,9 @@ public: void upload(gl::Context&) override {} AttributeBinding attributeBinding(const PossiblyEvaluatedPropertyValue<T>& 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<T, A> { public: using BaseAttribute = A; using BaseAttributeValue = typename BaseAttribute::Value; - using BaseAttributeBinding = typename BaseAttribute::Binding; - using BaseVertex = typename gl::Attributes<BaseAttribute>::Vertex; + using BaseVertex = gl::detail::Vertex<BaseAttribute>; - using Attribute = attributes::ZoomInterpolatedAttribute<BaseAttribute>; + using Attribute = ZoomInterpolatedAttributeType<A>; using AttributeBinding = typename Attribute::Binding; SourceFunctionPaintPropertyBinder(SourceFunction<T> 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<T>& 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 T, class A> class CompositeFunctionPaintPropertyBinder : public PaintPropertyBinder<T, A> { public: - using Attribute = attributes::ZoomInterpolatedAttribute<A>; + using BaseAttribute = A; + using BaseAttributeValue = typename BaseAttribute::Value; + + using Attribute = ZoomInterpolatedAttributeType<A>; using AttributeValue = typename Attribute::Value; using AttributeBinding = typename Attribute::Binding; - using Vertex = typename gl::Attributes<Attribute>::Vertex; + using Vertex = gl::detail::Vertex<Attribute>; CompositeFunctionPaintPropertyBinder(CompositeFunction<T> 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<T> 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<T>& 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<gl::VertexBuffer<Vertex>> vertexBuffer; }; -template <class PaintProperty> -auto createPaintPropertyBinder(const typename PaintProperty::EvaluatedType& value, float zoom) { - using Type = typename PaintProperty::Type; - using Attribute = typename PaintProperty::Attribute; +template <class T, class A> +std::unique_ptr<PaintPropertyBinder<T, A>> +PaintPropertyBinder<T, A>::create(const PossiblyEvaluatedPropertyValue<T>& value, float zoom, T defaultValue) { return value.match( - [&] (const Type& constant) -> std::unique_ptr<PaintPropertyBinder<Type, Attribute>> { - return std::make_unique<ConstantPaintPropertyBinder<Type, Attribute>>(constant); + [&] (const T& constant) -> std::unique_ptr<PaintPropertyBinder<T, A>> { + return std::make_unique<ConstantPaintPropertyBinder<T, A>>(constant); }, - [&] (const SourceFunction<Type>& function) { - return std::make_unique<SourceFunctionPaintPropertyBinder<Type, Attribute>>(function, PaintProperty::defaultValue()); + [&] (const SourceFunction<T>& function) { + return std::make_unique<SourceFunctionPaintPropertyBinder<T, A>>(function, defaultValue); }, - [&] (const CompositeFunction<Type>& function) { - return std::make_unique<CompositeFunctionPaintPropertyBinder<Type, Attribute>>(function, zoom, PaintProperty::defaultValue()); + [&] (const CompositeFunction<T>& function) { + return std::make_unique<CompositeFunctionPaintPropertyBinder<T, A>>(function, zoom, defaultValue); } ); } +template <class Attr> +struct ZoomInterpolatedAttribute { + static auto name() { return Attr::name(); } + using Type = ZoomInterpolatedAttributeType<typename Attr::Type>; +}; + +template <class Attr> +struct InterpolationUniform : gl::UniformScalar<InterpolationUniform<Attr>, float> { + static auto name() { + static const std::string name = Attr::name() + std::string("_t"); + return name.c_str(); + } +}; + template <class Ps> class PaintPropertyBinders; template <class... Ps> class PaintPropertyBinders<TypeList<Ps...>> { public: + template <class P> + using Binder = PaintPropertyBinder<typename P::Type, typename P::Attribute::Type>; + using Binders = IndexedTuple< TypeList<Ps...>, - TypeList<std::unique_ptr<PaintPropertyBinder<typename Ps::Type, typename Ps::Attribute>>...>>; + TypeList<std::unique_ptr<Binder<Ps>>...>>; template <class EvaluatedProperties> PaintPropertyBinders(const EvaluatedProperties& properties, float z) - : binders(createPaintPropertyBinder<Ps>(properties.template get<Ps>(), z)...) { + : binders(Binder<Ps>::create(properties.template get<Ps>(), 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<typename PaintPropertyBinder<typename Ps::Type, typename Ps::Attribute>::Attribute...>; + template <class P> + using Attribute = ZoomInterpolatedAttribute<typename P::Attribute>; + + using Attributes = gl::Attributes<Attribute<Ps>...>; using AttributeBindings = typename Attributes::Bindings; template <class EvaluatedProperties> @@ -213,13 +273,13 @@ public: }; } - using Uniforms = gl::Uniforms<attributes::InterpolationUniform<typename Ps::Attribute>...>; + using Uniforms = gl::Uniforms<InterpolationUniform<typename Ps::Attribute>...>; 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<typename Ps::Attribute>::Value { + typename InterpolationUniform<typename Ps::Attribute>::Value { binders.template get<Ps>()->interpolationFactor(currentZoom) }... }; |