summaryrefslogtreecommitdiff
path: root/src/mbgl/renderer
diff options
context:
space:
mode:
authorMolly Lloyd <molly@mapbox.com>2018-06-14 14:35:39 -0700
committerMolly Lloyd <mollymerp@users.noreply.github.com>2018-08-31 13:08:47 -0700
commit4a5dc37245d23805d13865f5ef9c5f26e539a9ca (patch)
treede77bfeff6f7afbe02210c9189bf72da59293083 /src/mbgl/renderer
parentec62e321531b1a836074056e86de8e20018280fb (diff)
downloadqtlocation-mapboxgl-4a5dc37245d23805d13865f5ef9c5f26e539a9ca.tar.gz
[core] Implement CrossFadedDataDrivenProperty to add support for feature expressions in `*-pattern` properties
Diffstat (limited to 'src/mbgl/renderer')
-rw-r--r--src/mbgl/renderer/bucket.hpp12
-rw-r--r--src/mbgl/renderer/buckets/circle_bucket.cpp6
-rw-r--r--src/mbgl/renderer/buckets/circle_bucket.hpp5
-rw-r--r--src/mbgl/renderer/buckets/fill_bucket.cpp25
-rw-r--r--src/mbgl/renderer/buckets/fill_bucket.hpp17
-rw-r--r--src/mbgl/renderer/buckets/fill_extrusion_bucket.cpp30
-rw-r--r--src/mbgl/renderer/buckets/fill_extrusion_bucket.hpp17
-rw-r--r--src/mbgl/renderer/buckets/heatmap_bucket.cpp6
-rw-r--r--src/mbgl/renderer/buckets/heatmap_bucket.hpp4
-rw-r--r--src/mbgl/renderer/buckets/line_bucket.cpp40
-rw-r--r--src/mbgl/renderer/buckets/line_bucket.hpp24
-rw-r--r--src/mbgl/renderer/cross_faded_property_evaluator.cpp11
-rw-r--r--src/mbgl/renderer/cross_faded_property_evaluator.hpp3
-rw-r--r--src/mbgl/renderer/data_driven_property_evaluator.hpp40
-rw-r--r--src/mbgl/renderer/image_atlas.cpp64
-rw-r--r--src/mbgl/renderer/image_atlas.hpp11
-rw-r--r--src/mbgl/renderer/image_manager.cpp11
-rw-r--r--src/mbgl/renderer/image_manager.hpp2
-rw-r--r--src/mbgl/renderer/layers/render_background_layer.cpp13
-rw-r--r--src/mbgl/renderer/layers/render_background_layer.hpp3
-rw-r--r--src/mbgl/renderer/layers/render_circle_layer.cpp18
-rw-r--r--src/mbgl/renderer/layers/render_circle_layer.hpp1
-rw-r--r--src/mbgl/renderer/layers/render_custom_layer.cpp3
-rw-r--r--src/mbgl/renderer/layers/render_custom_layer.hpp1
-rw-r--r--src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp74
-rw-r--r--src/mbgl/renderer/layers/render_fill_extrusion_layer.hpp15
-rw-r--r--src/mbgl/renderer/layers/render_fill_layer.cpp66
-rw-r--r--src/mbgl/renderer/layers/render_fill_layer.hpp14
-rw-r--r--src/mbgl/renderer/layers/render_heatmap_layer.cpp18
-rw-r--r--src/mbgl/renderer/layers/render_heatmap_layer.hpp1
-rw-r--r--src/mbgl/renderer/layers/render_hillshade_layer.cpp28
-rw-r--r--src/mbgl/renderer/layers/render_hillshade_layer.hpp1
-rw-r--r--src/mbgl/renderer/layers/render_line_layer.cpp72
-rw-r--r--src/mbgl/renderer/layers/render_line_layer.hpp17
-rw-r--r--src/mbgl/renderer/layers/render_raster_layer.cpp30
-rw-r--r--src/mbgl/renderer/layers/render_raster_layer.hpp1
-rw-r--r--src/mbgl/renderer/layers/render_symbol_layer.cpp18
-rw-r--r--src/mbgl/renderer/layers/render_symbol_layer.hpp1
-rw-r--r--src/mbgl/renderer/paint_property_binder.hpp314
-rw-r--r--src/mbgl/renderer/possibly_evaluated_property_value.hpp56
-rw-r--r--src/mbgl/renderer/property_evaluation_parameters.hpp19
-rw-r--r--src/mbgl/renderer/render_layer.hpp3
-rw-r--r--src/mbgl/renderer/render_tile.cpp12
-rw-r--r--src/mbgl/renderer/renderer_impl.cpp5
-rw-r--r--src/mbgl/renderer/sources/render_image_source.cpp4
45 files changed, 853 insertions, 283 deletions
diff --git a/src/mbgl/renderer/bucket.hpp b/src/mbgl/renderer/bucket.hpp
index f48593ae49..7ccab8672d 100644
--- a/src/mbgl/renderer/bucket.hpp
+++ b/src/mbgl/renderer/bucket.hpp
@@ -3,7 +3,8 @@
#include <mbgl/util/noncopyable.hpp>
#include <mbgl/tile/geometry_tile_data.hpp>
#include <mbgl/style/layer_type.hpp>
-
+#include <mbgl/style/image_impl.hpp>
+#include <mbgl/renderer/image_atlas.hpp>
#include <atomic>
namespace mbgl {
@@ -13,6 +14,8 @@ class Context;
} // namespace gl
class RenderLayer;
+class PatternDependency;
+using PatternLayerMap = std::unordered_map<std::string, PatternDependency>;
class Bucket : private util::noncopyable {
public:
@@ -41,7 +44,12 @@ public:
// Obtaining these is a costly operation, so we do it only once, and
// pass-by-const-ref the geometries as a second parameter.
virtual void addFeature(const GeometryTileFeature&,
- const GeometryCollection&) {};
+ const GeometryCollection&,
+ const ImagePositions&,
+ const PatternLayerMap&) {};
+
+ virtual void populateFeatureBuffers(const ImagePositions&) {};
+ virtual void addPatternDependencies(const std::vector<const RenderLayer*>&, ImageDependencies&) {};
// As long as this bucket has a Prepare render pass, this function is getting called. Typically,
// this only happens once when the bucket is being rendered for the first time.
diff --git a/src/mbgl/renderer/buckets/circle_bucket.cpp b/src/mbgl/renderer/buckets/circle_bucket.cpp
index d07c1f8dbe..820cf9f525 100644
--- a/src/mbgl/renderer/buckets/circle_bucket.cpp
+++ b/src/mbgl/renderer/buckets/circle_bucket.cpp
@@ -39,7 +39,9 @@ bool CircleBucket::hasData() const {
}
void CircleBucket::addFeature(const GeometryTileFeature& feature,
- const GeometryCollection& geometry) {
+ const GeometryCollection& geometry,
+ const ImagePositions&,
+ const PatternLayerMap&) {
constexpr const uint16_t vertexLength = 4;
for (auto& circle : geometry) {
@@ -87,7 +89,7 @@ void CircleBucket::addFeature(const GeometryTileFeature& feature,
}
for (auto& pair : paintPropertyBinders) {
- pair.second.populateVertexVectors(feature, vertices.vertexSize());
+ pair.second.populateVertexVectors(feature, vertices.vertexSize(), {}, {});
}
}
diff --git a/src/mbgl/renderer/buckets/circle_bucket.hpp b/src/mbgl/renderer/buckets/circle_bucket.hpp
index 3c5f96fb15..db61a0c112 100644
--- a/src/mbgl/renderer/buckets/circle_bucket.hpp
+++ b/src/mbgl/renderer/buckets/circle_bucket.hpp
@@ -18,7 +18,10 @@ public:
CircleBucket(const BucketParameters&, const std::vector<const RenderLayer*>&);
void addFeature(const GeometryTileFeature&,
- const GeometryCollection&) override;
+ const GeometryCollection&,
+ const ImagePositions&,
+ const PatternLayerMap&) override;
+
bool hasData() const override;
void upload(gl::Context&) override;
diff --git a/src/mbgl/renderer/buckets/fill_bucket.cpp b/src/mbgl/renderer/buckets/fill_bucket.cpp
index 14be98c3af..3b1b7ec00f 100644
--- a/src/mbgl/renderer/buckets/fill_bucket.cpp
+++ b/src/mbgl/renderer/buckets/fill_bucket.cpp
@@ -27,20 +27,26 @@ using namespace style;
struct GeometryTooLongException : std::exception {};
-FillBucket::FillBucket(const BucketParameters& parameters, const std::vector<const RenderLayer*>& layers)
+FillBucket::FillBucket(const FillBucket::PossiblyEvaluatedLayoutProperties,
+ std::map<std::string, FillBucket::PossiblyEvaluatedPaintProperties> layerPaintProperties,
+ const float zoom,
+ const uint32_t)
: Bucket(LayerType::Fill) {
- for (const auto& layer : layers) {
+
+ for (const auto& pair : layerPaintProperties) {
paintPropertyBinders.emplace(
std::piecewise_construct,
- std::forward_as_tuple(layer->getID()),
+ std::forward_as_tuple(pair.first),
std::forward_as_tuple(
- layer->as<RenderFillLayer>()->evaluated,
- parameters.tileID.overscaledZ));
+ pair.second,
+ zoom));
}
}
void FillBucket::addFeature(const GeometryTileFeature& feature,
- const GeometryCollection& geometry) {
+ const GeometryCollection& geometry,
+ const ImagePositions& patternPositions,
+ const PatternLayerMap& patternDependencies) {
for (auto& polygon : classifyRings(geometry)) {
// Optimize polygons with many interior rings for earcut tesselation.
limitHoles(polygon, 500);
@@ -105,7 +111,12 @@ void FillBucket::addFeature(const GeometryTileFeature& feature,
}
for (auto& pair : paintPropertyBinders) {
- pair.second.populateVertexVectors(feature, vertices.vertexSize());
+ const auto it = patternDependencies.find(pair.first);
+ if (it != patternDependencies.end()){
+ pair.second.populateVertexVectors(feature, vertices.vertexSize(), patternPositions, it->second);
+ } else {
+ pair.second.populateVertexVectors(feature, vertices.vertexSize(), patternPositions, {});
+ }
}
}
diff --git a/src/mbgl/renderer/buckets/fill_bucket.hpp b/src/mbgl/renderer/buckets/fill_bucket.hpp
index 20b65da39c..47e273d4d2 100644
--- a/src/mbgl/renderer/buckets/fill_bucket.hpp
+++ b/src/mbgl/renderer/buckets/fill_bucket.hpp
@@ -13,13 +13,26 @@
namespace mbgl {
class BucketParameters;
+class RenderFillLayer;
class FillBucket : public Bucket {
public:
- FillBucket(const BucketParameters&, const std::vector<const RenderLayer*>&);
+
+ // These aliases are used by the PatternLayout template
+ using RenderLayerType = RenderFillLayer;
+ using PossiblyEvaluatedPaintProperties = style::FillPaintProperties::PossiblyEvaluated;
+ using PossiblyEvaluatedLayoutProperties = style::Properties<>::PossiblyEvaluated;
+
+ FillBucket(const PossiblyEvaluatedLayoutProperties layout,
+ std::map<std::string, PossiblyEvaluatedPaintProperties> layerPaintProperties,
+ const float zoom,
+ const uint32_t overscaling);
void addFeature(const GeometryTileFeature&,
- const GeometryCollection&) override;
+ const GeometryCollection&,
+ const mbgl::ImagePositions&,
+ const PatternLayerMap&) override;
+
bool hasData() const override;
void upload(gl::Context&) override;
diff --git a/src/mbgl/renderer/buckets/fill_extrusion_bucket.cpp b/src/mbgl/renderer/buckets/fill_extrusion_bucket.cpp
index c6dba38db1..fe742828b8 100644
--- a/src/mbgl/renderer/buckets/fill_extrusion_bucket.cpp
+++ b/src/mbgl/renderer/buckets/fill_extrusion_bucket.cpp
@@ -34,19 +34,26 @@ using namespace style;
struct GeometryTooLongException : std::exception {};
-FillExtrusionBucket::FillExtrusionBucket(const BucketParameters& parameters, const std::vector<const RenderLayer*>& layers)
+FillExtrusionBucket::FillExtrusionBucket(const FillExtrusionBucket::PossiblyEvaluatedLayoutProperties,
+ std::map<std::string, FillExtrusionBucket::PossiblyEvaluatedPaintProperties> layerPaintProperties,
+ const float zoom,
+ const uint32_t)
: Bucket(LayerType::FillExtrusion) {
- for (const auto& layer : layers) {
- paintPropertyBinders.emplace(std::piecewise_construct,
- std::forward_as_tuple(layer->getID()),
- std::forward_as_tuple(
- layer->as<RenderFillExtrusionLayer>()->evaluated,
- parameters.tileID.overscaledZ));
+
+ for (const auto& pair : layerPaintProperties) {
+ paintPropertyBinders.emplace(
+ std::piecewise_construct,
+ std::forward_as_tuple(pair.first),
+ std::forward_as_tuple(
+ pair.second,
+ zoom));
}
}
void FillExtrusionBucket::addFeature(const GeometryTileFeature& feature,
- const GeometryCollection& geometry) {
+ const GeometryCollection& geometry,
+ const ImagePositions& patternPositions,
+ const PatternLayerMap& patternDependencies) {
for (auto& polygon : classifyRings(geometry)) {
// Optimize polygons with many interior rings for earcut tesselation.
limitHoles(polygon, 500);
@@ -143,7 +150,12 @@ void FillExtrusionBucket::addFeature(const GeometryTileFeature& feature,
}
for (auto& pair : paintPropertyBinders) {
- pair.second.populateVertexVectors(feature, vertices.vertexSize());
+ const auto it = patternDependencies.find(pair.first);
+ if (it != patternDependencies.end()){
+ pair.second.populateVertexVectors(feature, vertices.vertexSize(), patternPositions, it->second);
+ } else {
+ pair.second.populateVertexVectors(feature, vertices.vertexSize(), patternPositions, {});
+ }
}
}
diff --git a/src/mbgl/renderer/buckets/fill_extrusion_bucket.hpp b/src/mbgl/renderer/buckets/fill_extrusion_bucket.hpp
index ed98e01292..362a9f4c99 100644
--- a/src/mbgl/renderer/buckets/fill_extrusion_bucket.hpp
+++ b/src/mbgl/renderer/buckets/fill_extrusion_bucket.hpp
@@ -11,13 +11,26 @@
namespace mbgl {
class BucketParameters;
+class RenderFillExtrusionLayer;
class FillExtrusionBucket : public Bucket {
public:
- FillExtrusionBucket(const BucketParameters&, const std::vector<const RenderLayer*>&);
+
+ // These aliases are used by the PatternLayout template
+ using RenderLayerType = RenderFillExtrusionLayer;
+ using PossiblyEvaluatedPaintProperties = style::FillExtrusionPaintProperties::PossiblyEvaluated;
+ using PossiblyEvaluatedLayoutProperties = style::Properties<>::PossiblyEvaluated;
+
+ FillExtrusionBucket(const PossiblyEvaluatedLayoutProperties,
+ std::map<std::string, PossiblyEvaluatedPaintProperties>,
+ const float,
+ const uint32_t);
void addFeature(const GeometryTileFeature&,
- const GeometryCollection&) override;
+ const GeometryCollection&,
+ const mbgl::ImagePositions&,
+ const PatternLayerMap&) override;
+
bool hasData() const override;
void upload(gl::Context&) override;
diff --git a/src/mbgl/renderer/buckets/heatmap_bucket.cpp b/src/mbgl/renderer/buckets/heatmap_bucket.cpp
index eff0c60280..46d5f31599 100644
--- a/src/mbgl/renderer/buckets/heatmap_bucket.cpp
+++ b/src/mbgl/renderer/buckets/heatmap_bucket.cpp
@@ -39,7 +39,9 @@ bool HeatmapBucket::hasData() const {
}
void HeatmapBucket::addFeature(const GeometryTileFeature& feature,
- const GeometryCollection& geometry) {
+ const GeometryCollection& geometry,
+ const ImagePositions&,
+ const PatternLayerMap&) {
constexpr const uint16_t vertexLength = 4;
for (auto& points : geometry) {
@@ -87,7 +89,7 @@ void HeatmapBucket::addFeature(const GeometryTileFeature& feature,
}
for (auto& pair : paintPropertyBinders) {
- pair.second.populateVertexVectors(feature, vertices.vertexSize());
+ pair.second.populateVertexVectors(feature, vertices.vertexSize(), {}, {});
}
}
diff --git a/src/mbgl/renderer/buckets/heatmap_bucket.hpp b/src/mbgl/renderer/buckets/heatmap_bucket.hpp
index 86b6f10296..b2d866d2a2 100644
--- a/src/mbgl/renderer/buckets/heatmap_bucket.hpp
+++ b/src/mbgl/renderer/buckets/heatmap_bucket.hpp
@@ -18,7 +18,9 @@ public:
HeatmapBucket(const BucketParameters&, const std::vector<const RenderLayer*>&);
void addFeature(const GeometryTileFeature&,
- const GeometryCollection&) override;
+ const GeometryCollection&,
+ const ImagePositions&,
+ const PatternLayerMap&) override;
bool hasData() const override;
void upload(gl::Context&) override;
diff --git a/src/mbgl/renderer/buckets/line_bucket.cpp b/src/mbgl/renderer/buckets/line_bucket.cpp
index 80149edafe..2efb60c9ac 100644
--- a/src/mbgl/renderer/buckets/line_bucket.cpp
+++ b/src/mbgl/renderer/buckets/line_bucket.cpp
@@ -1,5 +1,4 @@
#include <mbgl/renderer/buckets/line_bucket.hpp>
-#include <mbgl/renderer/layers/render_line_layer.hpp>
#include <mbgl/renderer/bucket_parameters.hpp>
#include <mbgl/style/layers/line_layer_impl.hpp>
#include <mbgl/util/math.hpp>
@@ -11,34 +10,45 @@ namespace mbgl {
using namespace style;
-LineBucket::LineBucket(const BucketParameters& parameters,
- const std::vector<const RenderLayer*>& layers,
- const style::LineLayoutProperties::Unevaluated& layout_)
+LineBucket::LineBucket(const style::LineLayoutProperties::PossiblyEvaluated layout_,
+ std::map<std::string, RenderLinePaintProperties::PossiblyEvaluated> layerPaintProperties,
+ const float zoom_,
+ const uint32_t overscaling_)
: Bucket(LayerType::Line),
- layout(layout_.evaluate(PropertyEvaluationParameters(parameters.tileID.overscaledZ))),
- overscaling(parameters.tileID.overscaleFactor()),
- zoom(parameters.tileID.overscaledZ) {
- for (const auto& layer : layers) {
+ layout(layout_),
+ zoom(zoom_),
+ overscaling(overscaling_) {
+
+ for (const auto& pair : layerPaintProperties) {
paintPropertyBinders.emplace(
std::piecewise_construct,
- std::forward_as_tuple(layer->getID()),
+ std::forward_as_tuple(pair.first),
std::forward_as_tuple(
- layer->as<RenderLineLayer>()->evaluated,
- parameters.tileID.overscaledZ));
+ pair.second,
+ zoom));
}
}
+
void LineBucket::addFeature(const GeometryTileFeature& feature,
- const GeometryCollection& geometryCollection) {
+ const GeometryCollection& geometryCollection,
+ const ImagePositions& patternPositions,
+ const PatternLayerMap& patternDependencies) {
for (auto& line : geometryCollection) {
addGeometry(line, feature);
}
for (auto& pair : paintPropertyBinders) {
- pair.second.populateVertexVectors(feature, vertices.vertexSize());
+ const auto it = patternDependencies.find(pair.first);
+ if (it != patternDependencies.end()){
+ pair.second.populateVertexVectors(feature, vertices.vertexSize(), patternPositions, it->second);
+ } else {
+ pair.second.populateVertexVectors(feature, vertices.vertexSize(), patternPositions, {});
+ }
}
}
+
/*
* Sharp corners cause dashed lines to tilt because the distance along the line
* is the same at both the inner and outer corners. To improve the appearance of
@@ -130,7 +140,9 @@ void LineBucket::addGeometry(const GeometryCoordinates& coordinates, const Geome
const float miterLimit = joinType == LineJoinType::Bevel ? 1.05f : float(layout.get<LineMiterLimit>());
- const double sharpCornerOffset = SHARP_CORNER_OFFSET * (float(util::EXTENT) / (util::tileSize * overscaling));
+ const double sharpCornerOffset = overscaling == 0 ?
+ SHARP_CORNER_OFFSET * (float(util::EXTENT) / util::tileSize) :
+ SHARP_CORNER_OFFSET * (float(util::EXTENT) / (util::tileSize * overscaling));
const GeometryCoordinate firstCoordinate = coordinates[first];
const LineCapType beginCap = layout.get<LineCap>();
diff --git a/src/mbgl/renderer/buckets/line_bucket.hpp b/src/mbgl/renderer/buckets/line_bucket.hpp
index 23d30ca416..6bd37076de 100644
--- a/src/mbgl/renderer/buckets/line_bucket.hpp
+++ b/src/mbgl/renderer/buckets/line_bucket.hpp
@@ -1,5 +1,4 @@
#pragma once
-
#include <mbgl/renderer/bucket.hpp>
#include <mbgl/tile/geometry_tile_data.hpp>
#include <mbgl/gl/vertex_buffer.hpp>
@@ -7,6 +6,7 @@
#include <mbgl/programs/segment.hpp>
#include <mbgl/programs/line_program.hpp>
#include <mbgl/style/layers/line_layer_properties.hpp>
+#include <mbgl/style/image_impl.hpp>
#include <vector>
@@ -17,19 +17,29 @@ class RenderLineLayer;
class LineBucket : public Bucket {
public:
- LineBucket(const BucketParameters&,
- const std::vector<const RenderLayer*>&,
- const style::LineLayoutProperties::Unevaluated&);
+
+ // These aliases are used by the PatternLayout template
+ using RenderLayerType = RenderLineLayer;
+ using PossiblyEvaluatedPaintProperties = RenderLinePaintProperties::PossiblyEvaluated;
+ using PossiblyEvaluatedLayoutProperties = style::LineLayoutProperties::PossiblyEvaluated;
+
+ LineBucket(const PossiblyEvaluatedLayoutProperties layout,
+ std::map<std::string, PossiblyEvaluatedPaintProperties> layerPaintProperties,
+ const float zoom,
+ const uint32_t overscaling);
void addFeature(const GeometryTileFeature&,
- const GeometryCollection&) override;
+ const GeometryCollection&,
+ const mbgl::ImagePositions& patternPositions,
+ const PatternLayerMap&) override;
+
bool hasData() const override;
void upload(gl::Context&) override;
float getQueryRadius(const RenderLayer&) const override;
- style::LineLayoutProperties::PossiblyEvaluated layout;
+ PossiblyEvaluatedLayoutProperties layout;
gl::VertexVector<LineLayoutVertex> vertices;
gl::IndexVector<gl::Triangles> triangles;
@@ -63,8 +73,8 @@ private:
std::ptrdiff_t e2;
std::ptrdiff_t e3;
- const uint32_t overscaling;
const float zoom;
+ const uint32_t overscaling;
float getLineWidth(const RenderLineLayer& layer) const;
};
diff --git a/src/mbgl/renderer/cross_faded_property_evaluator.cpp b/src/mbgl/renderer/cross_faded_property_evaluator.cpp
index 9a7af8636c..7be9c2bcf5 100644
--- a/src/mbgl/renderer/cross_faded_property_evaluator.cpp
+++ b/src/mbgl/renderer/cross_faded_property_evaluator.cpp
@@ -25,16 +25,9 @@ Faded<T> CrossFadedPropertyEvaluator<T>::operator()(const style::PropertyExpress
template <typename T>
Faded<T> CrossFadedPropertyEvaluator<T>::calculate(const T& min, const T& mid, const T& max) const {
const float z = parameters.z;
- const float fraction = z - std::floor(z);
- const std::chrono::duration<float> d = parameters.defaultFadeDuration;
- const float t =
- d != std::chrono::duration<float>::zero()
- ? std::min((parameters.now - parameters.zoomHistory.lastIntegerZoomTime) / d, 1.0f)
- : 1.0f;
-
return z > parameters.zoomHistory.lastIntegerZoom
- ? Faded<T> { min, mid, 2.0f, 1.0f, fraction + (1.0f - fraction) * t }
- : Faded<T> { max, mid, 0.5f, 1.0f, 1 - (1 - t) * fraction };
+ ? Faded<T> { min, mid }
+ : Faded<T> { max, mid };
}
template class CrossFadedPropertyEvaluator<std::string>;
diff --git a/src/mbgl/renderer/cross_faded_property_evaluator.hpp b/src/mbgl/renderer/cross_faded_property_evaluator.hpp
index 1d17c5eb2f..e925b96fa3 100644
--- a/src/mbgl/renderer/cross_faded_property_evaluator.hpp
+++ b/src/mbgl/renderer/cross_faded_property_evaluator.hpp
@@ -11,9 +11,6 @@ class Faded {
public:
T from;
T to;
- float fromScale;
- float toScale;
- float t;
};
template <typename T>
diff --git a/src/mbgl/renderer/data_driven_property_evaluator.hpp b/src/mbgl/renderer/data_driven_property_evaluator.hpp
index f9452cc572..d65ac36713 100644
--- a/src/mbgl/renderer/data_driven_property_evaluator.hpp
+++ b/src/mbgl/renderer/data_driven_property_evaluator.hpp
@@ -3,6 +3,7 @@
#include <mbgl/style/property_value.hpp>
#include <mbgl/renderer/property_evaluation_parameters.hpp>
#include <mbgl/renderer/possibly_evaluated_property_value.hpp>
+#include <mbgl/renderer/cross_faded_property_evaluator.hpp>
namespace mbgl {
@@ -40,4 +41,43 @@ private:
T defaultValue;
};
+template <typename T>
+class DataDrivenPropertyEvaluator<Faded<T>> {
+public:
+ using ResultType = PossiblyEvaluatedPropertyValue<Faded<T>>;
+
+ DataDrivenPropertyEvaluator(const PropertyEvaluationParameters& parameters_, T defaultValue_)
+ : parameters(parameters_),
+ defaultValue(std::move(defaultValue_)) {}
+
+ ResultType operator()(const T& constant) const {
+ return ResultType(calculate(constant, constant, constant));
+ }
+
+ ResultType operator()(const style::Undefined& ) const {
+ return ResultType(calculate(defaultValue, defaultValue, defaultValue));
+ }
+
+ ResultType operator()(const style::PropertyExpression<T>& expression) const {
+ if (!expression.isFeatureConstant()) {
+ return ResultType(expression);
+ } else {
+ const T evaluated = expression.evaluate(floor(parameters.z));
+ return ResultType(calculate(evaluated, evaluated, evaluated));
+ }
+ }
+
+
+private:
+ Faded<T> calculate(const T& min, const T& mid, const T& max) const {
+ const float z = parameters.z;
+ return z > parameters.zoomHistory.lastIntegerZoom
+ ? Faded<T> { min, mid }
+ : Faded<T> { max, mid };
+ };
+
+ const PropertyEvaluationParameters& parameters;
+ T defaultValue;
+};
+
} // namespace mbgl
diff --git a/src/mbgl/renderer/image_atlas.cpp b/src/mbgl/renderer/image_atlas.cpp
index 8eee7c2095..b39c788ced 100644
--- a/src/mbgl/renderer/image_atlas.cpp
+++ b/src/mbgl/renderer/image_atlas.cpp
@@ -16,36 +16,56 @@ ImagePosition::ImagePosition(const mapbox::Bin& bin, const style::Image::Impl& i
) {
}
-ImageAtlas makeImageAtlas(const ImageMap& images) {
+const mapbox::Bin& _packImage(mapbox::ShelfPack& pack, const style::Image::Impl& image, ImageAtlas& resultImage, ImageType imageType) {
+ const mapbox::Bin& bin = *pack.packOne(-1,
+ image.image.size.width + 2 * padding,
+ image.image.size.height + 2 * padding);
+
+ resultImage.image.resize({
+ static_cast<uint32_t>(pack.width()),
+ static_cast<uint32_t>(pack.height())
+ });
+
+ PremultipliedImage::copy(image.image,
+ resultImage.image,
+ { 0, 0 },
+ {
+ bin.x + padding,
+ bin.y + padding
+ },
+ image.image.size);
+ uint32_t x = bin.x + padding,
+ y = bin.y + padding,
+ w = image.image.size.width,
+ h = image.image.size.height;
+
+ if (imageType == ImageType::Pattern) {
+ // Add 1 pixel wrapped padding on each side of the image.
+ PremultipliedImage::copy(image.image, resultImage.image, { 0, h - 1 }, { x, y - 1 }, { w, 1 }); // T
+ PremultipliedImage::copy(image.image, resultImage.image, { 0, 0 }, { x, y + h }, { w, 1 }); // B
+ PremultipliedImage::copy(image.image, resultImage.image, { w - 1, 0 }, { x - 1, y }, { 1, h }); // L
+ PremultipliedImage::copy(image.image, resultImage.image, { 0, 0 }, { x + w, y }, { 1, h }); // R
+ }
+ return bin;
+}
+
+ImageAtlas makeImageAtlas(const ImageMap& icons, const ImageMap& patterns) {
ImageAtlas result;
mapbox::ShelfPack::ShelfPackOptions options;
options.autoResize = true;
mapbox::ShelfPack pack(0, 0, options);
- for (const auto& entry : images) {
+ for (const auto& entry : icons) {
const style::Image::Impl& image = *entry.second;
+ const mapbox::Bin& bin = _packImage(pack, image, result, ImageType::Icon);
+ result.iconPositions.emplace(image.id, ImagePosition { bin, image });
+ }
- const mapbox::Bin& bin = *pack.packOne(-1,
- image.image.size.width + 2 * padding,
- image.image.size.height + 2 * padding);
-
- result.image.resize({
- static_cast<uint32_t>(pack.width()),
- static_cast<uint32_t>(pack.height())
- });
-
- PremultipliedImage::copy(image.image,
- result.image,
- { 0, 0 },
- {
- bin.x + padding,
- bin.y + padding
- },
- image.image.size);
-
- result.positions.emplace(image.id,
- ImagePosition { bin, image });
+ for (const auto& entry : patterns) {
+ const style::Image::Impl& image = *entry.second;
+ const mapbox::Bin& bin = _packImage(pack, image, result, ImageType::Pattern);
+ result.patternPositions.emplace(image.id, ImagePosition { bin, image });
}
pack.shrink();
diff --git a/src/mbgl/renderer/image_atlas.hpp b/src/mbgl/renderer/image_atlas.hpp
index b3cc166eff..3af31a75f8 100644
--- a/src/mbgl/renderer/image_atlas.hpp
+++ b/src/mbgl/renderer/image_atlas.hpp
@@ -30,6 +30,12 @@ public:
}};
}
+ std::array<uint16_t, 4> tlbr() const {
+ const auto _tl = tl();
+ const auto _br = br();
+ return {{ _tl[0], _tl[1], _br[0], _br[1] }};
+ }
+
std::array<float, 2> displaySize() const {
return {{
textureRect.w / pixelRatio,
@@ -43,9 +49,10 @@ using ImagePositions = std::map<std::string, ImagePosition>;
class ImageAtlas {
public:
PremultipliedImage image;
- ImagePositions positions;
+ ImagePositions iconPositions;
+ ImagePositions patternPositions;
};
-ImageAtlas makeImageAtlas(const ImageMap&);
+ImageAtlas makeImageAtlas(const ImageMap&, const ImageMap&);
} // namespace mbgl
diff --git a/src/mbgl/renderer/image_manager.cpp b/src/mbgl/renderer/image_manager.cpp
index 2ef6be0c4f..fc1f5bb167 100644
--- a/src/mbgl/renderer/image_manager.cpp
+++ b/src/mbgl/renderer/image_manager.cpp
@@ -67,7 +67,7 @@ void ImageManager::getImages(ImageRequestor& requestor, ImageRequestPair&& pair)
bool hasAllDependencies = true;
if (!isLoaded()) {
for (const auto& dependency : pair.first) {
- if (images.find(dependency) == images.end()) {
+ if (images.find(dependency.first) == images.end()) {
hasAllDependencies = false;
}
}
@@ -84,16 +84,17 @@ void ImageManager::removeRequestor(ImageRequestor& requestor) {
}
void ImageManager::notify(ImageRequestor& requestor, const ImageRequestPair& pair) const {
- ImageMap response;
+ ImageMap iconMap;
+ ImageMap patternMap;
for (const auto& dependency : pair.first) {
- auto it = images.find(dependency);
+ auto it = images.find(dependency.first);
if (it != images.end()) {
- response.emplace(*it);
+ dependency.second == ImageType::Pattern ? patternMap.emplace(*it) : iconMap.emplace(*it);
}
}
- requestor.onImagesAvailable(response, pair.second);
+ requestor.onImagesAvailable(iconMap, patternMap, pair.second);
}
void ImageManager::dumpDebugLogs() const {
diff --git a/src/mbgl/renderer/image_manager.hpp b/src/mbgl/renderer/image_manager.hpp
index f72ba9fb53..103491c58b 100644
--- a/src/mbgl/renderer/image_manager.hpp
+++ b/src/mbgl/renderer/image_manager.hpp
@@ -21,7 +21,7 @@ class Context;
class ImageRequestor {
public:
virtual ~ImageRequestor() = default;
- virtual void onImagesAvailable(ImageMap, uint64_t imageCorrelationID) = 0;
+ virtual void onImagesAvailable(ImageMap icons, ImageMap patterns, uint64_t imageCorrelationID) = 0;
};
/*
diff --git a/src/mbgl/renderer/layers/render_background_layer.cpp b/src/mbgl/renderer/layers/render_background_layer.cpp
index 2dc5fe7339..ad85fe0cce 100644
--- a/src/mbgl/renderer/layers/render_background_layer.cpp
+++ b/src/mbgl/renderer/layers/render_background_layer.cpp
@@ -34,6 +34,7 @@ void RenderBackgroundLayer::transition(const TransitionParameters &parameters) {
void RenderBackgroundLayer::evaluate(const PropertyEvaluationParameters &parameters) {
evaluated = unevaluated.evaluate(parameters);
+ crossfade = parameters.getCrossfadeParameters();
passes = evaluated.get<style::BackgroundOpacity>() > 0 ? RenderPass::Translucent
: RenderPass::None;
@@ -43,6 +44,10 @@ bool RenderBackgroundLayer::hasTransition() const {
return unevaluated.hasTransition();
}
+bool RenderBackgroundLayer::hasCrossfade() const {
+ return crossfade.t != 1;
+}
+
void RenderBackgroundLayer::render(PaintParameters& parameters, RenderSource*) {
// Note that for bottommost layers without a pattern, the background color is drawn with
// glClear rather than this method.
@@ -97,7 +102,7 @@ void RenderBackgroundLayer::render(PaintParameters& parameters, RenderSource*) {
parameters.imageManager.getPixelSize(),
*imagePosA,
*imagePosB,
- evaluated.get<BackgroundPattern>(),
+ crossfade,
tileID,
parameters.state
)
@@ -108,9 +113,9 @@ void RenderBackgroundLayer::render(PaintParameters& parameters, RenderSource*) {
draw(
parameters.programs.background,
BackgroundProgram::UniformValues {
- uniforms::u_matrix::Value{ parameters.matrixForTile(tileID) },
- uniforms::u_color::Value{ evaluated.get<BackgroundColor>() },
- uniforms::u_opacity::Value{ evaluated.get<BackgroundOpacity>() },
+ uniforms::u_matrix::Value( parameters.matrixForTile(tileID) ),
+ uniforms::u_color::Value( evaluated.get<BackgroundColor>() ),
+ uniforms::u_opacity::Value( evaluated.get<BackgroundOpacity>() ),
}
);
}
diff --git a/src/mbgl/renderer/layers/render_background_layer.hpp b/src/mbgl/renderer/layers/render_background_layer.hpp
index a619670ee4..854c077a62 100644
--- a/src/mbgl/renderer/layers/render_background_layer.hpp
+++ b/src/mbgl/renderer/layers/render_background_layer.hpp
@@ -14,6 +14,7 @@ public:
void transition(const TransitionParameters&) override;
void evaluate(const PropertyEvaluationParameters&) override;
bool hasTransition() const override;
+ bool hasCrossfade() const override;
void render(PaintParameters&, RenderSource*) override;
std::unique_ptr<Bucket> createBucket(const BucketParameters&, const std::vector<const RenderLayer*>&) const override;
@@ -23,6 +24,8 @@ public:
style::BackgroundPaintProperties::PossiblyEvaluated evaluated;
const style::BackgroundLayer::Impl& impl() const;
+private:
+ CrossfadeParameters crossfade;
};
template <>
diff --git a/src/mbgl/renderer/layers/render_circle_layer.cpp b/src/mbgl/renderer/layers/render_circle_layer.cpp
index ce63ada770..af96e2e991 100644
--- a/src/mbgl/renderer/layers/render_circle_layer.cpp
+++ b/src/mbgl/renderer/layers/render_circle_layer.cpp
@@ -47,6 +47,10 @@ bool RenderCircleLayer::hasTransition() const {
return unevaluated.hasTransition();
}
+bool RenderCircleLayer::hasCrossfade() const {
+ return false;
+}
+
void RenderCircleLayer::render(PaintParameters& parameters, RenderSource*) {
if (parameters.pass == RenderPass::Opaque) {
return;
@@ -68,19 +72,19 @@ void RenderCircleLayer::render(PaintParameters& parameters, RenderSource*) {
const auto allUniformValues = programInstance.computeAllUniformValues(
CircleProgram::UniformValues {
- uniforms::u_matrix::Value{
+ uniforms::u_matrix::Value(
tile.translatedMatrix(evaluated.get<CircleTranslate>(),
evaluated.get<CircleTranslateAnchor>(),
parameters.state)
- },
- uniforms::u_scale_with_map::Value{ scaleWithMap },
- uniforms::u_extrude_scale::Value{ pitchWithMap
+ ),
+ uniforms::u_scale_with_map::Value( scaleWithMap ),
+ uniforms::u_extrude_scale::Value( pitchWithMap
? std::array<float, 2> {{
tile.id.pixelsToTileUnits(1, parameters.state.getZoom()),
tile.id.pixelsToTileUnits(1, parameters.state.getZoom()) }}
- : parameters.pixelsToGLUnits },
- uniforms::u_camera_to_center_distance::Value{ parameters.state.getCameraToCenterDistance() },
- uniforms::u_pitch_with_map::Value{ pitchWithMap }
+ : parameters.pixelsToGLUnits ),
+ uniforms::u_camera_to_center_distance::Value( parameters.state.getCameraToCenterDistance() ),
+ uniforms::u_pitch_with_map::Value( pitchWithMap )
},
paintPropertyBinders,
evaluated,
diff --git a/src/mbgl/renderer/layers/render_circle_layer.hpp b/src/mbgl/renderer/layers/render_circle_layer.hpp
index c9eeae4652..53353fcdcb 100644
--- a/src/mbgl/renderer/layers/render_circle_layer.hpp
+++ b/src/mbgl/renderer/layers/render_circle_layer.hpp
@@ -14,6 +14,7 @@ public:
void transition(const TransitionParameters&) override;
void evaluate(const PropertyEvaluationParameters&) override;
bool hasTransition() const override;
+ bool hasCrossfade() const override;
void render(PaintParameters&, RenderSource*) override;
bool queryIntersectsFeature(
diff --git a/src/mbgl/renderer/layers/render_custom_layer.cpp b/src/mbgl/renderer/layers/render_custom_layer.cpp
index be9f64d9eb..16c18447c5 100644
--- a/src/mbgl/renderer/layers/render_custom_layer.cpp
+++ b/src/mbgl/renderer/layers/render_custom_layer.cpp
@@ -38,6 +38,9 @@ void RenderCustomLayer::evaluate(const PropertyEvaluationParameters&) {
bool RenderCustomLayer::hasTransition() const {
return false;
}
+bool RenderCustomLayer::hasCrossfade() const {
+ return false;
+}
std::unique_ptr<Bucket> RenderCustomLayer::createBucket(const BucketParameters&, const std::vector<const RenderLayer*>&) const {
assert(false);
diff --git a/src/mbgl/renderer/layers/render_custom_layer.hpp b/src/mbgl/renderer/layers/render_custom_layer.hpp
index 971d8d8f42..47d5bb3f40 100644
--- a/src/mbgl/renderer/layers/render_custom_layer.hpp
+++ b/src/mbgl/renderer/layers/render_custom_layer.hpp
@@ -13,6 +13,7 @@ public:
void transition(const TransitionParameters&) final {}
void evaluate(const PropertyEvaluationParameters&) override;
bool hasTransition() const override;
+ bool hasCrossfade() const override;
std::unique_ptr<Bucket> createBucket(const BucketParameters&, const std::vector<const RenderLayer*>&) const final;
void render(PaintParameters&, RenderSource*) final;
diff --git a/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp b/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp
index 2f720284fc..08e9d609cd 100644
--- a/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp
+++ b/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp
@@ -12,6 +12,7 @@
#include <mbgl/geometry/feature_index.hpp>
#include <mbgl/util/math.hpp>
#include <mbgl/util/intersection_tests.hpp>
+#include <mbgl/tile/geometry_tile.hpp>
namespace mbgl {
@@ -26,8 +27,18 @@ const style::FillExtrusionLayer::Impl& RenderFillExtrusionLayer::impl() const {
return static_cast<const style::FillExtrusionLayer::Impl&>(*baseImpl);
}
-std::unique_ptr<Bucket> RenderFillExtrusionLayer::createBucket(const BucketParameters& parameters, const std::vector<const RenderLayer*>& layers) const {
- return std::make_unique<FillExtrusionBucket>(parameters, layers);
+std::unique_ptr<Bucket> RenderFillExtrusionLayer::createBucket(const BucketParameters&, const std::vector<const RenderLayer*>&) const {
+ assert(false); // Should be calling createLayout() instead.
+ return nullptr;
+}
+
+
+std::unique_ptr<PatternLayout<FillExtrusionBucket>>
+RenderFillExtrusionLayer::createLayout(const BucketParameters& parameters,
+ const std::vector<const RenderLayer*>& group,
+ std::unique_ptr<GeometryTileLayer> layer,
+ ImageDependencies& imageDependencies) const {
+ return std::make_unique<PatternLayout<FillExtrusionBucket>>(parameters, group, std::move(layer), imageDependencies);
}
void RenderFillExtrusionLayer::transition(const TransitionParameters& parameters) {
@@ -36,6 +47,7 @@ void RenderFillExtrusionLayer::transition(const TransitionParameters& parameters
void RenderFillExtrusionLayer::evaluate(const PropertyEvaluationParameters& parameters) {
evaluated = unevaluated.evaluate(parameters);
+ crossfade = parameters.getCrossfadeParameters();
passes = (evaluated.get<style::FillExtrusionOpacity>() > 0)
? (RenderPass::Translucent | RenderPass::Pass3D)
@@ -46,6 +58,10 @@ bool RenderFillExtrusionLayer::hasTransition() const {
return unevaluated.hasTransition();
}
+bool RenderFillExtrusionLayer::hasCrossfade() const {
+ return crossfade.t != 1;
+}
+
void RenderFillExtrusionLayer::render(PaintParameters& parameters, RenderSource*) {
if (parameters.pass == RenderPass::Opaque) {
return;
@@ -68,8 +84,10 @@ void RenderFillExtrusionLayer::render(PaintParameters& parameters, RenderSource*
parameters.context.setStencilMode(gl::StencilMode::disabled());
parameters.context.clear(Color{ 0.0f, 0.0f, 0.0f, 0.0f }, depthClearValue, {});
- auto draw = [&](auto& programInstance, const auto& tileBucket, auto&& uniformValues) {
+ auto draw = [&](auto& programInstance, const auto& tileBucket, auto&& uniformValues,
+ const optional<ImagePosition>& patternPositionA, const optional<ImagePosition>& patternPositionB) {
const auto& paintPropertyBinders = tileBucket.paintPropertyBinders.at(getID());
+ paintPropertyBinders.setPatternParameters(patternPositionA, patternPositionB, crossfade);
const auto allUniformValues = programInstance.computeAllUniformValues(
std::move(uniformValues),
@@ -98,7 +116,7 @@ void RenderFillExtrusionLayer::render(PaintParameters& parameters, RenderSource*
getID());
};
- if (evaluated.get<FillExtrusionPattern>().from.empty()) {
+ if (unevaluated.get<FillExtrusionPattern>().isUndefined()) {
for (const RenderTile& tile : renderTiles) {
auto bucket_ = tile.tile.getBucket<FillExtrusionBucket>(*baseImpl);
if (!bucket_) {
@@ -115,26 +133,22 @@ void RenderFillExtrusionLayer::render(PaintParameters& parameters, RenderSource*
parameters.state),
parameters.state,
parameters.evaluatedLight
- )
+ ),
+ {}, {}
);
}
} else {
- optional<ImagePosition> imagePosA =
- parameters.imageManager.getPattern(evaluated.get<FillExtrusionPattern>().from);
- optional<ImagePosition> imagePosB =
- parameters.imageManager.getPattern(evaluated.get<FillExtrusionPattern>().to);
-
- if (!imagePosA || !imagePosB) {
- return;
- }
-
- parameters.imageManager.bind(parameters.context, 0);
-
for (const RenderTile& tile : renderTiles) {
auto bucket_ = tile.tile.getBucket<FillExtrusionBucket>(*baseImpl);
if (!bucket_) {
continue;
}
+ const auto fillPatternValue = evaluated.get<FillExtrusionPattern>().constantOr(mbgl::Faded<std::basic_string<char> >{"", ""});
+ assert(dynamic_cast<GeometryTile*>(&tile.tile));
+ GeometryTile& geometryTile = static_cast<GeometryTile&>(tile.tile);
+ optional<ImagePosition> patternPosA = geometryTile.getPattern(fillPatternValue.from);
+ optional<ImagePosition> patternPosB = geometryTile.getPattern(fillPatternValue.to);
+ parameters.context.bindTexture(*geometryTile.iconAtlasTexture, 0, gl::TextureFilter::Linear);
FillExtrusionBucket& bucket = *bucket_;
draw(
@@ -144,11 +158,16 @@ void RenderFillExtrusionLayer::render(PaintParameters& parameters, RenderSource*
tile.translatedClipMatrix(evaluated.get<FillExtrusionTranslate>(),
evaluated.get<FillExtrusionTranslateAnchor>(),
parameters.state),
- parameters.imageManager.getPixelSize(), *imagePosA, *imagePosB,
- evaluated.get<FillExtrusionPattern>(), tile.id, parameters.state,
+ geometryTile.iconAtlasTexture->size,
+ crossfade,
+ tile.id,
+ parameters.state,
-std::pow(2, tile.id.canonical.z) / util::tileSize / 8.0f,
+ parameters.pixelRatio,
parameters.evaluatedLight
- )
+ ),
+ patternPosA,
+ patternPosB
);
}
}
@@ -168,9 +187,9 @@ void RenderFillExtrusionLayer::render(PaintParameters& parameters, RenderSource*
const auto allUniformValues = programInstance.computeAllUniformValues(
ExtrusionTextureProgram::UniformValues{
- uniforms::u_matrix::Value{ viewportMat }, uniforms::u_world::Value{ size },
- uniforms::u_image::Value{ 0 },
- uniforms::u_opacity::Value{ evaluated.get<FillExtrusionOpacity>() }
+ uniforms::u_matrix::Value( viewportMat ), uniforms::u_world::Value( size ),
+ uniforms::u_image::Value( 0 ),
+ uniforms::u_opacity::Value( evaluated.get<FillExtrusionOpacity>() )
},
paintAttributeData,
properties,
@@ -197,6 +216,17 @@ void RenderFillExtrusionLayer::render(PaintParameters& parameters, RenderSource*
getID());
}
}
+style::FillExtrusionPaintProperties::PossiblyEvaluated RenderFillExtrusionLayer::paintProperties() const {
+ return FillExtrusionPaintProperties::PossiblyEvaluated {
+ evaluated.get<style::FillExtrusionOpacity>(),
+ evaluated.get<style::FillExtrusionColor>(),
+ evaluated.get<style::FillExtrusionTranslate>(),
+ evaluated.get<style::FillExtrusionTranslateAnchor>(),
+ evaluated.get<style::FillExtrusionPattern>(),
+ evaluated.get<style::FillExtrusionHeight>(),
+ evaluated.get<style::FillExtrusionBase>()
+ };
+}
bool RenderFillExtrusionLayer::queryIntersectsFeature(
const GeometryCoordinates& queryGeometry,
diff --git a/src/mbgl/renderer/layers/render_fill_extrusion_layer.hpp b/src/mbgl/renderer/layers/render_fill_extrusion_layer.hpp
index f7ba13c267..1a721d035b 100644
--- a/src/mbgl/renderer/layers/render_fill_extrusion_layer.hpp
+++ b/src/mbgl/renderer/layers/render_fill_extrusion_layer.hpp
@@ -8,15 +8,25 @@
namespace mbgl {
+template <class B>
+class PatternLayout;
+
+class FillExtrusionBucket;
+
class RenderFillExtrusionLayer: public RenderLayer {
public:
+ using StyleLayerImpl = style::FillExtrusionLayer::Impl;
+ using PatternProperty = style::FillExtrusionPattern;
+
RenderFillExtrusionLayer(Immutable<style::FillExtrusionLayer::Impl>);
~RenderFillExtrusionLayer() final = default;
void transition(const TransitionParameters&) override;
void evaluate(const PropertyEvaluationParameters&) override;
bool hasTransition() const override;
+ bool hasCrossfade() const override;
void render(PaintParameters&, RenderSource*) override;
+ style::FillExtrusionPaintProperties::PossiblyEvaluated paintProperties() const;
bool queryIntersectsFeature(
const GeometryCoordinates&,
@@ -28,6 +38,9 @@ public:
std::unique_ptr<Bucket> createBucket(const BucketParameters&, const std::vector<const RenderLayer*>&) const override;
+ std::unique_ptr<PatternLayout<FillExtrusionBucket>>
+ createLayout(const BucketParameters&, const std::vector<const RenderLayer*>&, std::unique_ptr<GeometryTileLayer>, ImageDependencies&) const;
+
// Paint properties
style::FillExtrusionPaintProperties::Unevaluated unevaluated;
style::FillExtrusionPaintProperties::PossiblyEvaluated evaluated;
@@ -35,6 +48,8 @@ public:
const style::FillExtrusionLayer::Impl& impl() const;
optional<OffscreenTexture> renderTexture;
+private:
+ CrossfadeParameters crossfade;
};
template <>
diff --git a/src/mbgl/renderer/layers/render_fill_layer.cpp b/src/mbgl/renderer/layers/render_fill_layer.cpp
index f03eb66c88..5d7ed02da8 100644
--- a/src/mbgl/renderer/layers/render_fill_layer.cpp
+++ b/src/mbgl/renderer/layers/render_fill_layer.cpp
@@ -10,6 +10,7 @@
#include <mbgl/geometry/feature_index.hpp>
#include <mbgl/util/math.hpp>
#include <mbgl/util/intersection_tests.hpp>
+#include <mbgl/tile/geometry_tile.hpp>
namespace mbgl {
@@ -24,8 +25,17 @@ const style::FillLayer::Impl& RenderFillLayer::impl() const {
return static_cast<const style::FillLayer::Impl&>(*baseImpl);
}
-std::unique_ptr<Bucket> RenderFillLayer::createBucket(const BucketParameters& parameters, const std::vector<const RenderLayer*>& layers) const {
- return std::make_unique<FillBucket>(parameters, layers);
+std::unique_ptr<Bucket> RenderFillLayer::createBucket(const BucketParameters&, const std::vector<const RenderLayer*>&) const {
+ assert(false); // Should be calling createLayout() instead.
+ return nullptr;
+}
+
+std::unique_ptr<PatternLayout<FillBucket>>
+RenderFillLayer::createLayout(const BucketParameters& parameters,
+ const std::vector<const RenderLayer*>& group,
+ std::unique_ptr<GeometryTileLayer> layer,
+ ImageDependencies& imageDependencies) const {
+ return std::make_unique<PatternLayout<FillBucket>>(parameters, group, std::move(layer), imageDependencies);
}
void RenderFillLayer::transition(const TransitionParameters& parameters) {
@@ -34,6 +44,7 @@ void RenderFillLayer::transition(const TransitionParameters& parameters) {
void RenderFillLayer::evaluate(const PropertyEvaluationParameters& parameters) {
evaluated = unevaluated.evaluate(parameters);
+ crossfade = parameters.getCrossfadeParameters();
if (unevaluated.get<style::FillOutlineColor>().isUndefined()) {
evaluated.get<style::FillOutlineColor>() = evaluated.get<style::FillColor>();
@@ -58,8 +69,12 @@ bool RenderFillLayer::hasTransition() const {
return unevaluated.hasTransition();
}
+bool RenderFillLayer::hasCrossfade() const {
+ return crossfade.t != 1;
+}
+
void RenderFillLayer::render(PaintParameters& parameters, RenderSource*) {
- if (evaluated.get<FillPattern>().from.empty()) {
+ if (unevaluated.get<FillPattern>().isUndefined()) {
for (const RenderTile& tile : renderTiles) {
auto bucket_ = tile.tile.getBucket<FillBucket>(*baseImpl);
if (!bucket_) {
@@ -78,12 +93,12 @@ void RenderFillLayer::render(PaintParameters& parameters, RenderSource*) {
const auto allUniformValues = programInstance.computeAllUniformValues(
FillProgram::UniformValues {
- uniforms::u_matrix::Value{
+ uniforms::u_matrix::Value(
tile.translatedMatrix(evaluated.get<FillTranslate>(),
evaluated.get<FillTranslateAnchor>(),
parameters.state)
- },
- uniforms::u_world::Value{ parameters.context.viewport.getCurrentValue().size },
+ ),
+ uniforms::u_world::Value( parameters.context.viewport.getCurrentValue().size ),
},
paintPropertyBinders,
evaluated,
@@ -138,17 +153,14 @@ void RenderFillLayer::render(PaintParameters& parameters, RenderSource*) {
if (parameters.pass != RenderPass::Translucent) {
return;
}
-
- optional<ImagePosition> imagePosA = parameters.imageManager.getPattern(evaluated.get<FillPattern>().from);
- optional<ImagePosition> imagePosB = parameters.imageManager.getPattern(evaluated.get<FillPattern>().to);
-
- if (!imagePosA || !imagePosB) {
- return;
- }
-
- parameters.imageManager.bind(parameters.context, 0);
-
+ const auto fillPatternValue = evaluated.get<FillPattern>().constantOr(Faded<std::basic_string<char>>{"", ""});
for (const RenderTile& tile : renderTiles) {
+ assert(dynamic_cast<GeometryTile*>(&tile.tile));
+ GeometryTile& geometryTile = static_cast<GeometryTile&>(tile.tile);
+ optional<ImagePosition> patternPosA = geometryTile.getPattern(fillPatternValue.from);
+ optional<ImagePosition> patternPosB = geometryTile.getPattern(fillPatternValue.to);
+
+ parameters.context.bindTexture(*geometryTile.iconAtlasTexture, 0, gl::TextureFilter::Linear);
auto bucket_ = tile.tile.getBucket<FillBucket>(*baseImpl);
if (!bucket_) {
continue;
@@ -163,6 +175,7 @@ void RenderFillLayer::render(PaintParameters& parameters, RenderSource*) {
auto& programInstance = program.get(evaluated);
const auto& paintPropertyBinders = bucket.paintPropertyBinders.at(getID());
+ paintPropertyBinders.setPatternParameters(patternPosA, patternPosB, crossfade);
const auto allUniformValues = programInstance.computeAllUniformValues(
FillPatternUniforms::values(
@@ -170,12 +183,11 @@ void RenderFillLayer::render(PaintParameters& parameters, RenderSource*) {
evaluated.get<FillTranslateAnchor>(),
parameters.state),
parameters.context.viewport.getCurrentValue().size,
- parameters.imageManager.getPixelSize(),
- *imagePosA,
- *imagePosB,
- evaluated.get<FillPattern>(),
+ geometryTile.iconAtlasTexture->size,
+ crossfade,
tile.id,
- parameters.state
+ parameters.state,
+ parameters.pixelRatio
),
paintPropertyBinders,
evaluated,
@@ -220,6 +232,18 @@ void RenderFillLayer::render(PaintParameters& parameters, RenderSource*) {
}
}
+style::FillPaintProperties::PossiblyEvaluated RenderFillLayer::paintProperties() const {
+ return FillPaintProperties::PossiblyEvaluated {
+ evaluated.get<style::FillAntialias>(),
+ evaluated.get<style::FillOpacity>(),
+ evaluated.get<style::FillColor>(),
+ evaluated.get<style::FillOutlineColor>(),
+ evaluated.get<style::FillTranslate>(),
+ evaluated.get<style::FillTranslateAnchor>(),
+ evaluated.get<style::FillPattern>()
+ };
+}
+
bool RenderFillLayer::queryIntersectsFeature(
const GeometryCoordinates& queryGeometry,
const GeometryTileFeature& feature,
diff --git a/src/mbgl/renderer/layers/render_fill_layer.hpp b/src/mbgl/renderer/layers/render_fill_layer.hpp
index bd195fb828..5a3c05387d 100644
--- a/src/mbgl/renderer/layers/render_fill_layer.hpp
+++ b/src/mbgl/renderer/layers/render_fill_layer.hpp
@@ -3,18 +3,26 @@
#include <mbgl/renderer/render_layer.hpp>
#include <mbgl/style/layers/fill_layer_impl.hpp>
#include <mbgl/style/layers/fill_layer_properties.hpp>
+#include <mbgl/layout/pattern_layout.hpp>
namespace mbgl {
+class FillBucket;
+
class RenderFillLayer: public RenderLayer {
public:
+ using StyleLayerImpl = style::FillLayer::Impl;
+ using PatternProperty = style::FillPattern;
+
RenderFillLayer(Immutable<style::FillLayer::Impl>);
~RenderFillLayer() final = default;
void transition(const TransitionParameters&) override;
void evaluate(const PropertyEvaluationParameters&) override;
bool hasTransition() const override;
+ bool hasCrossfade() const override;
void render(PaintParameters&, RenderSource*) override;
+ style::FillPaintProperties::PossiblyEvaluated paintProperties() const;
bool queryIntersectsFeature(
const GeometryCoordinates&,
@@ -26,11 +34,17 @@ public:
std::unique_ptr<Bucket> createBucket(const BucketParameters&, const std::vector<const RenderLayer*>&) const override;
+ std::unique_ptr<PatternLayout<FillBucket>>
+ createLayout(const BucketParameters&, const std::vector<const RenderLayer*>&, std::unique_ptr<GeometryTileLayer>, ImageDependencies&) const;
+
// Paint properties
style::FillPaintProperties::Unevaluated unevaluated;
style::FillPaintProperties::PossiblyEvaluated evaluated;
const style::FillLayer::Impl& impl() const;
+private:
+ CrossfadeParameters crossfade;
+
};
template <>
diff --git a/src/mbgl/renderer/layers/render_heatmap_layer.cpp b/src/mbgl/renderer/layers/render_heatmap_layer.cpp
index c9ca477cbb..8e24cf8f32 100644
--- a/src/mbgl/renderer/layers/render_heatmap_layer.cpp
+++ b/src/mbgl/renderer/layers/render_heatmap_layer.cpp
@@ -45,6 +45,10 @@ bool RenderHeatmapLayer::hasTransition() const {
return unevaluated.hasTransition();
}
+bool RenderHeatmapLayer::hasCrossfade() const {
+ return false;
+}
+
void RenderHeatmapLayer::render(PaintParameters& parameters, RenderSource*) {
if (parameters.pass == RenderPass::Opaque) {
return;
@@ -101,9 +105,9 @@ void RenderHeatmapLayer::render(PaintParameters& parameters, RenderSource*) {
const auto allUniformValues = programInstance.computeAllUniformValues(
HeatmapProgram::UniformValues {
- uniforms::u_intensity::Value{ evaluated.get<style::HeatmapIntensity>() },
- uniforms::u_matrix::Value{ tile.matrix },
- uniforms::heatmap::u_extrude_scale::Value{ extrudeScale }
+ uniforms::u_intensity::Value( evaluated.get<style::HeatmapIntensity>() ),
+ uniforms::u_matrix::Value( tile.matrix ),
+ uniforms::heatmap::u_extrude_scale::Value( extrudeScale )
},
paintPropertyBinders,
evaluated,
@@ -147,10 +151,10 @@ void RenderHeatmapLayer::render(PaintParameters& parameters, RenderSource*) {
const auto allUniformValues = programInstance.computeAllUniformValues(
HeatmapTextureProgram::UniformValues{
- uniforms::u_matrix::Value{ viewportMat }, uniforms::u_world::Value{ size },
- uniforms::u_image::Value{ 0 },
- uniforms::u_color_ramp::Value{ 1 },
- uniforms::u_opacity::Value{ evaluated.get<HeatmapOpacity>() }
+ uniforms::u_matrix::Value( viewportMat ), uniforms::u_world::Value( size ),
+ uniforms::u_image::Value( 0 ),
+ uniforms::u_color_ramp::Value( 1 ),
+ uniforms::u_opacity::Value( evaluated.get<HeatmapOpacity>() )
},
paintAttributeData,
properties,
diff --git a/src/mbgl/renderer/layers/render_heatmap_layer.hpp b/src/mbgl/renderer/layers/render_heatmap_layer.hpp
index 29fad7d8b8..6f8163ebf1 100644
--- a/src/mbgl/renderer/layers/render_heatmap_layer.hpp
+++ b/src/mbgl/renderer/layers/render_heatmap_layer.hpp
@@ -16,6 +16,7 @@ public:
void transition(const TransitionParameters&) override;
void evaluate(const PropertyEvaluationParameters&) override;
bool hasTransition() const override;
+ bool hasCrossfade() const override;
void render(PaintParameters&, RenderSource*) override;
bool queryIntersectsFeature(
diff --git a/src/mbgl/renderer/layers/render_hillshade_layer.cpp b/src/mbgl/renderer/layers/render_hillshade_layer.cpp
index 8bcd3f1837..b96030f44d 100644
--- a/src/mbgl/renderer/layers/render_hillshade_layer.cpp
+++ b/src/mbgl/renderer/layers/render_hillshade_layer.cpp
@@ -56,6 +56,10 @@ bool RenderHillshadeLayer::hasTransition() const {
return unevaluated.hasTransition();
}
+bool RenderHillshadeLayer::hasCrossfade() const {
+ return false;
+}
+
void RenderHillshadeLayer::render(PaintParameters& parameters, RenderSource* src) {
if (parameters.pass != RenderPass::Translucent && parameters.pass != RenderPass::Pass3D)
return;
@@ -75,13 +79,13 @@ void RenderHillshadeLayer::render(PaintParameters& parameters, RenderSource* src
const auto allUniformValues = programInstance.computeAllUniformValues(
HillshadeProgram::UniformValues {
- uniforms::u_matrix::Value{ matrix },
- uniforms::u_image::Value{ 0 },
- uniforms::u_highlight::Value{ evaluated.get<HillshadeHighlightColor>() },
- uniforms::u_shadow::Value{ evaluated.get<HillshadeShadowColor>() },
- uniforms::u_accent::Value{ evaluated.get<HillshadeAccentColor>() },
- uniforms::u_light::Value{ getLight(parameters) },
- uniforms::u_latrange::Value{ getLatRange(id) },
+ uniforms::u_matrix::Value( matrix ),
+ uniforms::u_image::Value( 0 ),
+ uniforms::u_highlight::Value( evaluated.get<HillshadeHighlightColor>() ),
+ uniforms::u_shadow::Value( evaluated.get<HillshadeShadowColor>() ),
+ uniforms::u_accent::Value( evaluated.get<HillshadeAccentColor>() ),
+ uniforms::u_light::Value( getLight(parameters) ),
+ uniforms::u_latrange::Value( getLatRange(id) ),
},
paintAttributeData,
evaluated,
@@ -137,11 +141,11 @@ void RenderHillshadeLayer::render(PaintParameters& parameters, RenderSource* src
const auto allUniformValues = programInstance.computeAllUniformValues(
HillshadePrepareProgram::UniformValues {
- uniforms::u_matrix::Value { mat },
- uniforms::u_dimension::Value { {{uint16_t(tilesize * 2), uint16_t(tilesize * 2) }} },
- uniforms::u_zoom::Value{ float(tile.id.canonical.z) },
- uniforms::u_maxzoom::Value{ float(maxzoom) },
- uniforms::u_image::Value{ 0 }
+ uniforms::u_matrix::Value( mat ),
+ uniforms::u_dimension::Value( {{uint16_t(tilesize * 2), uint16_t(tilesize * 2)}} ),
+ uniforms::u_zoom::Value( float(tile.id.canonical.z) ),
+ uniforms::u_maxzoom::Value( float(maxzoom) ),
+ uniforms::u_image::Value( 0 )
},
paintAttributeData,
properties,
diff --git a/src/mbgl/renderer/layers/render_hillshade_layer.hpp b/src/mbgl/renderer/layers/render_hillshade_layer.hpp
index 13093ee7ef..f88f1cd12f 100644
--- a/src/mbgl/renderer/layers/render_hillshade_layer.hpp
+++ b/src/mbgl/renderer/layers/render_hillshade_layer.hpp
@@ -15,6 +15,7 @@ public:
void transition(const TransitionParameters&) override;
void evaluate(const PropertyEvaluationParameters&) override;
bool hasTransition() const override;
+ bool hasCrossfade() const override;
void render(PaintParameters&, RenderSource* src) override;
diff --git a/src/mbgl/renderer/layers/render_line_layer.cpp b/src/mbgl/renderer/layers/render_line_layer.cpp
index f204c909e1..ff8a98c950 100644
--- a/src/mbgl/renderer/layers/render_line_layer.cpp
+++ b/src/mbgl/renderer/layers/render_line_layer.cpp
@@ -11,6 +11,7 @@
#include <mbgl/geometry/feature_index.hpp>
#include <mbgl/util/math.hpp>
#include <mbgl/util/intersection_tests.hpp>
+#include <mbgl/tile/geometry_tile.hpp>
namespace mbgl {
@@ -26,8 +27,17 @@ const style::LineLayer::Impl& RenderLineLayer::impl() const {
return static_cast<const style::LineLayer::Impl&>(*baseImpl);
}
-std::unique_ptr<Bucket> RenderLineLayer::createBucket(const BucketParameters& parameters, const std::vector<const RenderLayer*>& layers) const {
- return std::make_unique<LineBucket>(parameters, layers, impl().layout);
+std::unique_ptr<Bucket> RenderLineLayer::createBucket(const BucketParameters&, const std::vector<const RenderLayer*>&) const {
+ assert(false); // Should be calling createLayout() instead.
+ return nullptr;
+}
+
+std::unique_ptr<PatternLayout<LineBucket>>
+RenderLineLayer::createLayout(const BucketParameters& parameters,
+ const std::vector<const RenderLayer*>& group,
+ std::unique_ptr<GeometryTileLayer> layer,
+ ImageDependencies& imageDependencies) const {
+ return std::make_unique<PatternLayout<LineBucket>>(parameters, group, std::move(layer), imageDependencies);
}
void RenderLineLayer::transition(const TransitionParameters& parameters) {
@@ -41,7 +51,9 @@ void RenderLineLayer::evaluate(const PropertyEvaluationParameters& parameters) {
dashArrayParams.useIntegerZoom = true;
evaluated = RenderLinePaintProperties::PossiblyEvaluated(
- unevaluated.evaluate(parameters).concat(extra.evaluate(dashArrayParams)));
+ unevaluated.evaluate(parameters).concat(extra.evaluate(dashArrayParams)));
+
+ crossfade = parameters.getCrossfadeParameters();
passes = (evaluated.get<style::LineOpacity>().constantOr(1.0) > 0
&& evaluated.get<style::LineColor>().constantOr(Color::black()).a > 0
@@ -53,6 +65,10 @@ bool RenderLineLayer::hasTransition() const {
return unevaluated.hasTransition();
}
+bool RenderLineLayer::hasCrossfade() const {
+ return crossfade.t != 1;
+}
+
void RenderLineLayer::render(PaintParameters& parameters, RenderSource*) {
if (parameters.pass == RenderPass::Opaque) {
return;
@@ -65,11 +81,13 @@ void RenderLineLayer::render(PaintParameters& parameters, RenderSource*) {
}
LineBucket& bucket = *bucket_;
- auto draw = [&] (auto& program, auto&& uniformValues) {
+ auto draw = [&] (auto& program, auto&& uniformValues, const optional<ImagePosition>& patternPositionA, const optional<ImagePosition>& patternPositionB) {
auto& programInstance = program.get(evaluated);
const auto& paintPropertyBinders = bucket.paintPropertyBinders.at(getID());
+ paintPropertyBinders.setPatternParameters(patternPositionA, patternPositionB, crossfade);
+
const auto allUniformValues = programInstance.computeAllUniformValues(
std::move(uniformValues),
paintPropertyBinders,
@@ -115,16 +133,18 @@ void RenderLineLayer::render(PaintParameters& parameters, RenderSource*) {
parameters.pixelsToGLUnits,
posA,
posB,
- parameters.lineAtlas.getSize().width));
-
- } else if (!evaluated.get<LinePattern>().from.empty()) {
- optional<ImagePosition> posA = parameters.imageManager.getPattern(evaluated.get<LinePattern>().from);
- optional<ImagePosition> posB = parameters.imageManager.getPattern(evaluated.get<LinePattern>().to);
+ crossfade,
+ parameters.lineAtlas.getSize().width), {}, {});
- if (!posA || !posB)
- return;
+ } else if (!unevaluated.get<LinePattern>().isUndefined()) {
+ const auto linePatternValue = evaluated.get<LinePattern>().constantOr(Faded<std::basic_string<char>>{ "", ""});
+ assert(dynamic_cast<GeometryTile*>(&tile.tile));
+ GeometryTile& geometryTile = static_cast<GeometryTile&>(tile.tile);
+ parameters.context.bindTexture(*geometryTile.iconAtlasTexture, 0, gl::TextureFilter::Linear);
+ const Size texsize = geometryTile.iconAtlasTexture->size;
- parameters.imageManager.bind(parameters.context, 0);
+ optional<ImagePosition> posA = geometryTile.getPattern(linePatternValue.from);
+ optional<ImagePosition> posB = geometryTile.getPattern(linePatternValue.to);
draw(parameters.programs.linePattern,
LinePatternProgram::uniformValues(
@@ -132,9 +152,11 @@ void RenderLineLayer::render(PaintParameters& parameters, RenderSource*) {
tile,
parameters.state,
parameters.pixelsToGLUnits,
- parameters.imageManager.getPixelSize(),
+ texsize,
+ crossfade,
+ parameters.pixelRatio),
*posA,
- *posB));
+ *posB);
} else if (!unevaluated.get<LineGradient>().getValue().isUndefined()) {
if (!colorRampTexture) {
colorRampTexture = parameters.context.createTexture(colorRamp);
@@ -146,14 +168,14 @@ void RenderLineLayer::render(PaintParameters& parameters, RenderSource*) {
evaluated,
tile,
parameters.state,
- parameters.pixelsToGLUnits));
+ parameters.pixelsToGLUnits), {}, {});
} else {
draw(parameters.programs.line,
LineProgram::uniformValues(
evaluated,
tile,
parameters.state,
- parameters.pixelsToGLUnits));
+ parameters.pixelsToGLUnits), {}, {});
}
}
}
@@ -240,6 +262,24 @@ void RenderLineLayer::updateColorRamp() {
}
}
+RenderLinePaintProperties::PossiblyEvaluated RenderLineLayer::paintProperties() const {
+ return RenderLinePaintProperties::PossiblyEvaluated {
+ evaluated.get<style::LineOpacity>(),
+ evaluated.get<style::LineColor>(),
+ evaluated.get<style::LineTranslate>(),
+ evaluated.get<style::LineTranslateAnchor>(),
+ evaluated.get<style::LineWidth>(),
+ evaluated.get<style::LineGapWidth>(),
+ evaluated.get<style::LineOffset>(),
+ evaluated.get<style::LineBlur>(),
+ evaluated.get<style::LineDasharray>(),
+ evaluated.get<style::LinePattern>(),
+ evaluated.get<style::LineGradient>(),
+ evaluated.get<LineFloorwidth>()
+
+ };
+}
+
float RenderLineLayer::getLineWidth(const GeometryTileFeature& feature, const float zoom) const {
float lineWidth = evaluated.get<style::LineWidth>()
.evaluate(feature, zoom, style::LineWidth::defaultValue());
diff --git a/src/mbgl/renderer/layers/render_line_layer.hpp b/src/mbgl/renderer/layers/render_line_layer.hpp
index 1e0100548a..19ccccfb39 100644
--- a/src/mbgl/renderer/layers/render_line_layer.hpp
+++ b/src/mbgl/renderer/layers/render_line_layer.hpp
@@ -4,7 +4,8 @@
#include <mbgl/style/layers/line_layer_impl.hpp>
#include <mbgl/style/layers/line_layer_properties.hpp>
#include <mbgl/programs/uniforms.hpp>
-#include <mbgl/util/image.hpp>
+#include <mbgl/style/image_impl.hpp>
+#include <mbgl/layout/pattern_layout.hpp>
namespace mbgl {
@@ -16,16 +17,24 @@ class RenderLinePaintProperties : public style::ConcatenateProperties<
style::LinePaintProperties,
style::Properties<LineFloorwidth>> {};
+class LineBucket;
+
class RenderLineLayer: public RenderLayer {
public:
+ using StyleLayerImpl = style::LineLayer::Impl;
+ using PatternProperty = style::LinePattern;
+
RenderLineLayer(Immutable<style::LineLayer::Impl>);
~RenderLineLayer() final = default;
void transition(const TransitionParameters&) override;
void evaluate(const PropertyEvaluationParameters&) override;
bool hasTransition() const override;
+ bool hasCrossfade() const override;
void render(PaintParameters&, RenderSource*) override;
+ RenderLinePaintProperties::PossiblyEvaluated paintProperties() const;
+
bool queryIntersectsFeature(
const GeometryCoordinates&,
const GeometryTileFeature&,
@@ -37,7 +46,10 @@ public:
void updateColorRamp();
std::unique_ptr<Bucket> createBucket(const BucketParameters&, const std::vector<const RenderLayer*>&) const override;
-
+ std::unique_ptr<PatternLayout<LineBucket>> createLayout(const BucketParameters&,
+ const std::vector<const RenderLayer*>&,
+ std::unique_ptr<GeometryTileLayer>,
+ ImageDependencies&) const;
// Paint properties
style::LinePaintProperties::Unevaluated unevaluated;
RenderLinePaintProperties::PossiblyEvaluated evaluated;
@@ -46,6 +58,7 @@ public:
private:
float getLineWidth(const GeometryTileFeature&, const float) const;
+ CrossfadeParameters crossfade;
PremultipliedImage colorRamp;
optional<gl::Texture> colorRampTexture;
};
diff --git a/src/mbgl/renderer/layers/render_raster_layer.cpp b/src/mbgl/renderer/layers/render_raster_layer.cpp
index e2524697b5..b8df71b7c1 100644
--- a/src/mbgl/renderer/layers/render_raster_layer.cpp
+++ b/src/mbgl/renderer/layers/render_raster_layer.cpp
@@ -41,6 +41,10 @@ bool RenderRasterLayer::hasTransition() const {
return unevaluated.hasTransition();
}
+bool RenderRasterLayer::hasCrossfade() const {
+ return false;
+}
+
static float saturationFactor(float saturation) {
if (saturation > 0) {
return 1 - 1 / (1.001 - saturation);
@@ -83,19 +87,19 @@ void RenderRasterLayer::render(PaintParameters& parameters, RenderSource* source
const auto allUniformValues = programInstance.computeAllUniformValues(
RasterProgram::UniformValues {
- uniforms::u_matrix::Value{ matrix },
- uniforms::u_image0::Value{ 0 },
- uniforms::u_image1::Value{ 1 },
- uniforms::u_opacity::Value{ evaluated.get<RasterOpacity>() },
- uniforms::u_fade_t::Value{ 1 },
- uniforms::u_brightness_low::Value{ evaluated.get<RasterBrightnessMin>() },
- uniforms::u_brightness_high::Value{ evaluated.get<RasterBrightnessMax>() },
- uniforms::u_saturation_factor::Value{ saturationFactor(evaluated.get<RasterSaturation>()) },
- uniforms::u_contrast_factor::Value{ contrastFactor(evaluated.get<RasterContrast>()) },
- uniforms::u_spin_weights::Value{ spinWeights(evaluated.get<RasterHueRotate>()) },
- uniforms::u_buffer_scale::Value{ 1.0f },
- uniforms::u_scale_parent::Value{ 1.0f },
- uniforms::u_tl_parent::Value{ std::array<float, 2> {{ 0.0f, 0.0f }} },
+ uniforms::u_matrix::Value( matrix ),
+ uniforms::u_image0::Value( 0 ),
+ uniforms::u_image1::Value( 1 ),
+ uniforms::u_opacity::Value( evaluated.get<RasterOpacity>() ),
+ uniforms::u_fade_t::Value( 1 ),
+ uniforms::u_brightness_low::Value( evaluated.get<RasterBrightnessMin>() ),
+ uniforms::u_brightness_high::Value( evaluated.get<RasterBrightnessMax>() ),
+ uniforms::u_saturation_factor::Value( saturationFactor(evaluated.get<RasterSaturation>()) ),
+ uniforms::u_contrast_factor::Value( contrastFactor(evaluated.get<RasterContrast>()) ),
+ uniforms::u_spin_weights::Value( spinWeights(evaluated.get<RasterHueRotate>()) ),
+ uniforms::u_buffer_scale::Value( 1.0f ),
+ uniforms::u_scale_parent::Value( 1.0f ),
+ uniforms::u_tl_parent::Value( std::array<float, 2> {{ 0.0f, 0.0f }} ),
},
paintAttributeData,
evaluated,
diff --git a/src/mbgl/renderer/layers/render_raster_layer.hpp b/src/mbgl/renderer/layers/render_raster_layer.hpp
index 87de316f7c..a8633c4d5e 100644
--- a/src/mbgl/renderer/layers/render_raster_layer.hpp
+++ b/src/mbgl/renderer/layers/render_raster_layer.hpp
@@ -14,6 +14,7 @@ public:
void transition(const TransitionParameters&) override;
void evaluate(const PropertyEvaluationParameters&) override;
bool hasTransition() const override;
+ bool hasCrossfade() const override;
void render(PaintParameters&, RenderSource*) override;
diff --git a/src/mbgl/renderer/layers/render_symbol_layer.cpp b/src/mbgl/renderer/layers/render_symbol_layer.cpp
index f9e4e7c043..cf65e29048 100644
--- a/src/mbgl/renderer/layers/render_symbol_layer.cpp
+++ b/src/mbgl/renderer/layers/render_symbol_layer.cpp
@@ -69,6 +69,10 @@ bool RenderSymbolLayer::hasTransition() const {
return unevaluated.hasTransition();
}
+bool RenderSymbolLayer::hasCrossfade() const {
+ return false;
+}
+
void RenderSymbolLayer::render(PaintParameters& parameters, RenderSource*) {
if (parameters.pass == RenderPass::Opaque) {
return;
@@ -251,9 +255,9 @@ void RenderSymbolLayer::render(PaintParameters& parameters, RenderSource*) {
gl::StencilMode::disabled(),
parameters.colorModeForRenderPass(),
CollisionBoxProgram::UniformValues {
- uniforms::u_matrix::Value{ tile.matrix },
- uniforms::u_extrude_scale::Value{ extrudeScale },
- uniforms::u_camera_to_center_distance::Value{ parameters.state.getCameraToCenterDistance() }
+ uniforms::u_matrix::Value( tile.matrix ),
+ uniforms::u_extrude_scale::Value( extrudeScale ),
+ uniforms::u_camera_to_center_distance::Value( parameters.state.getCameraToCenterDistance() )
},
*bucket.collisionBox.vertexBuffer,
*bucket.collisionBox.dynamicVertexBuffer,
@@ -285,10 +289,10 @@ void RenderSymbolLayer::render(PaintParameters& parameters, RenderSource*) {
gl::StencilMode::disabled(),
parameters.colorModeForRenderPass(),
CollisionCircleProgram::UniformValues {
- uniforms::u_matrix::Value{ tile.matrix },
- uniforms::u_extrude_scale::Value{ extrudeScale },
- uniforms::u_overscale_factor::Value{ float(tile.tile.id.overscaleFactor()) },
- uniforms::u_camera_to_center_distance::Value{ parameters.state.getCameraToCenterDistance() }
+ uniforms::u_matrix::Value( tile.matrix ),
+ uniforms::u_extrude_scale::Value( extrudeScale ),
+ uniforms::u_overscale_factor::Value( float(tile.tile.id.overscaleFactor()) ),
+ uniforms::u_camera_to_center_distance::Value( parameters.state.getCameraToCenterDistance() )
},
*bucket.collisionCircle.vertexBuffer,
*bucket.collisionCircle.dynamicVertexBuffer,
diff --git a/src/mbgl/renderer/layers/render_symbol_layer.hpp b/src/mbgl/renderer/layers/render_symbol_layer.hpp
index 5b73b30294..efdcf0e932 100644
--- a/src/mbgl/renderer/layers/render_symbol_layer.hpp
+++ b/src/mbgl/renderer/layers/render_symbol_layer.hpp
@@ -64,6 +64,7 @@ public:
void transition(const TransitionParameters&) override;
void evaluate(const PropertyEvaluationParameters&) override;
bool hasTransition() const override;
+ bool hasCrossfade() const override;
void render(PaintParameters&, RenderSource*) override;
style::IconPaintProperties::PossiblyEvaluated iconPaintProperties() const;
diff --git a/src/mbgl/renderer/paint_property_binder.hpp b/src/mbgl/renderer/paint_property_binder.hpp
index 29eb716785..dd204743b3 100644
--- a/src/mbgl/renderer/paint_property_binder.hpp
+++ b/src/mbgl/renderer/paint_property_binder.hpp
@@ -7,6 +7,11 @@
#include <mbgl/util/type_list.hpp>
#include <mbgl/renderer/possibly_evaluated_property_value.hpp>
#include <mbgl/renderer/paint_property_statistics.hpp>
+#include <mbgl/renderer/cross_faded_property_evaluator.hpp>
+#include <mbgl/util/variant.hpp>
+#include <mbgl/renderer/image_atlas.hpp>
+#include <mbgl/util/indexed_tuple.hpp>
+#include <mbgl/layout/pattern_layout.hpp>
#include <bitset>
@@ -72,54 +77,92 @@ std::array<float, N*2> zoomInterpolatedAttributeValue(const std::array<float, N>
Note that the shader source varies depending on whether we're using a uniform or
attribute. Like GL JS, we dynamically compile shaders at runtime to accomodate this.
*/
-template <class T, class... As>
+
+template <class T, class UniformValueType, class PossiblyEvaluatedType, class... As>
class PaintPropertyBinder {
public:
virtual ~PaintPropertyBinder() = default;
- virtual void populateVertexVector(const GeometryTileFeature& feature, std::size_t length) = 0;
+ virtual void populateVertexVector(const GeometryTileFeature& feature, std::size_t length, const ImagePositions&, const optional<PatternDependency>&) = 0;
virtual void upload(gl::Context& context) = 0;
- virtual optional<gl::AttributeBinding> attributeBinding(const PossiblyEvaluatedPropertyValue<T>& currentValue) const = 0;
- virtual float interpolationFactor(float currentZoom) const = 0;
- virtual T uniformValue(const PossiblyEvaluatedPropertyValue<T>& currentValue) const = 0;
+ virtual void setPatternParameters(const optional<ImagePosition>&, const optional<ImagePosition>&, CrossfadeParameters&) = 0;
+ virtual std::tuple<ExpandToType<As, optional<gl::AttributeBinding>>...> attributeBinding(const PossiblyEvaluatedType& currentValue) const = 0;
+ virtual std::tuple<ExpandToType<As, float>...> interpolationFactor(float currentZoom) const = 0;
+ virtual std::tuple<ExpandToType<As, UniformValueType>...> uniformValue(const PossiblyEvaluatedType& currentValue) const = 0;
- static std::unique_ptr<PaintPropertyBinder> create(const PossiblyEvaluatedPropertyValue<T>& value, float zoom, T defaultValue);
+ static std::unique_ptr<PaintPropertyBinder> create(const PossiblyEvaluatedType& value, float zoom, T defaultValue);
PaintPropertyStatistics<T> statistics;
};
template <class T, class A>
-class ConstantPaintPropertyBinder : public PaintPropertyBinder<T, A> {
+class ConstantPaintPropertyBinder : public PaintPropertyBinder<T, T, PossiblyEvaluatedPropertyValue<T>, A> {
public:
ConstantPaintPropertyBinder(T constant_)
: constant(std::move(constant_)) {
}
- void populateVertexVector(const GeometryTileFeature&, std::size_t) override {}
+ void populateVertexVector(const GeometryTileFeature&, std::size_t, const ImagePositions&, const optional<PatternDependency>&) override {}
void upload(gl::Context&) override {}
+ void setPatternParameters(const optional<ImagePosition>&, const optional<ImagePosition>&, CrossfadeParameters&) override {};
- optional<gl::AttributeBinding> attributeBinding(const PossiblyEvaluatedPropertyValue<T>&) const override {
- return {};
+ std::tuple<optional<gl::AttributeBinding>> attributeBinding(const PossiblyEvaluatedPropertyValue<T>&) const override {
+ return std::tuple<optional<gl::AttributeBinding>> {};
}
- float interpolationFactor(float) const override {
- return 0.0f;
+ std::tuple<float> interpolationFactor(float) const override {
+ return std::tuple<float> { 0.0f };
}
- T uniformValue(const PossiblyEvaluatedPropertyValue<T>& currentValue) const override {
- return currentValue.constantOr(constant);
+ std::tuple<T> uniformValue(const PossiblyEvaluatedPropertyValue<T>& currentValue) const override {
+ return std::tuple<T> { currentValue.constantOr(constant) };
}
private:
T constant;
};
+template <class T, class... As>
+class ConstantCrossFadedPaintPropertyBinder : public PaintPropertyBinder<T, std::array<uint16_t, 4>,PossiblyEvaluatedPropertyValue<Faded<T>>, As...> {
+public:
+ ConstantCrossFadedPaintPropertyBinder(Faded<T> constant_)
+ : constant(std::move(constant_)), constantPatternPositions({}) {
+ }
+
+ void populateVertexVector(const GeometryTileFeature&, std::size_t, const ImagePositions&, const optional<PatternDependency>&) override {}
+ void upload(gl::Context&) override {}
+
+ void setPatternParameters(const optional<ImagePosition>& posA, const optional<ImagePosition>& posB, CrossfadeParameters&) override {
+ if (!posA && !posB) {
+ return;
+ } else {
+ constantPatternPositions = std::tuple<std::array<uint16_t, 4>, std::array<uint16_t, 4>> { posB->tlbr(), posA->tlbr() };
+ }
+ }
+
+ std::tuple<optional<gl::AttributeBinding>, optional<gl::AttributeBinding>>
+ attributeBinding(const PossiblyEvaluatedPropertyValue<Faded<T>>&) const override {
+ return std::tuple<optional<gl::AttributeBinding>, optional<gl::AttributeBinding>> {};
+ }
+
+ std::tuple<float, float> interpolationFactor(float) const override {
+ return std::tuple<float, float> { 0.0f, 0.0f };
+ }
+
+ std::tuple<std::array<uint16_t, 4>, std::array<uint16_t, 4>> uniformValue(const PossiblyEvaluatedPropertyValue<Faded<T>>&) const override {
+ return constantPatternPositions;
+ }
+
+private:
+ Faded<T> constant;
+ std::tuple<std::array<uint16_t, 4>, std::array<uint16_t, 4>> constantPatternPositions;
+};
+
template <class T, class A>
-class SourceFunctionPaintPropertyBinder : public PaintPropertyBinder<T, A> {
+class SourceFunctionPaintPropertyBinder : public PaintPropertyBinder<T, T, PossiblyEvaluatedPropertyValue<T>, A> {
public:
using BaseAttribute = A;
- using BaseAttributeValue = typename BaseAttribute::Value;
using BaseVertex = gl::detail::Vertex<BaseAttribute>;
using AttributeType = ZoomInterpolatedAttributeType<A>;
@@ -128,8 +171,8 @@ public:
: expression(std::move(expression_)),
defaultValue(std::move(defaultValue_)) {
}
-
- void populateVertexVector(const GeometryTileFeature& feature, std::size_t length) override {
+ void setPatternParameters(const optional<ImagePosition>&, const optional<ImagePosition>&, CrossfadeParameters&) override {};
+ void populateVertexVector(const GeometryTileFeature& feature, std::size_t length, const ImagePositions&, const optional<PatternDependency>&) override {
auto evaluated = expression.evaluate(feature, defaultValue);
this->statistics.add(evaluated);
auto value = attributeValue(evaluated);
@@ -142,21 +185,21 @@ public:
vertexBuffer = context.createVertexBuffer(std::move(vertexVector));
}
- optional<gl::AttributeBinding> attributeBinding(const PossiblyEvaluatedPropertyValue<T>& currentValue) const override {
+ std::tuple<optional<gl::AttributeBinding>> attributeBinding(const PossiblyEvaluatedPropertyValue<T>& currentValue) const override {
if (currentValue.isConstant()) {
return {};
} else {
- return AttributeType::binding(*vertexBuffer, 0, BaseAttribute::Dimensions);
+ return std::tuple<optional<gl::AttributeBinding>> { AttributeType::binding(*vertexBuffer, 0, BaseAttribute::Dimensions) };
}
}
- float interpolationFactor(float) const override {
- return 0.0f;
+ std::tuple<float> interpolationFactor(float) const override {
+ return std::tuple<float> { 0.0f };
}
- T uniformValue(const PossiblyEvaluatedPropertyValue<T>& currentValue) const override {
+ std::tuple<T> uniformValue(const PossiblyEvaluatedPropertyValue<T>& currentValue) const override {
if (currentValue.isConstant()) {
- return *currentValue.constant();
+ return std::tuple<T>{ *currentValue.constant() };
} else {
// Uniform values for vertex attribute arrays are unused.
return {};
@@ -171,7 +214,7 @@ private:
};
template <class T, class A>
-class CompositeFunctionPaintPropertyBinder : public PaintPropertyBinder<T, A> {
+class CompositeFunctionPaintPropertyBinder : public PaintPropertyBinder<T, T, PossiblyEvaluatedPropertyValue<T>, A> {
public:
using AttributeType = ZoomInterpolatedAttributeType<A>;
@@ -183,8 +226,8 @@ public:
defaultValue(std::move(defaultValue_)),
zoomRange({zoom, zoom + 1}) {
}
-
- void populateVertexVector(const GeometryTileFeature& feature, std::size_t length) override {
+ void setPatternParameters(const optional<ImagePosition>&, const optional<ImagePosition>&, CrossfadeParameters&) override {};
+ void populateVertexVector(const GeometryTileFeature& feature, std::size_t length, const ImagePositions&, const optional<PatternDependency>&) override {
Range<T> range = expression.evaluate(zoomRange, feature, defaultValue);
this->statistics.add(range.min);
this->statistics.add(range.max);
@@ -200,25 +243,25 @@ public:
vertexBuffer = context.createVertexBuffer(std::move(vertexVector));
}
- optional<gl::AttributeBinding> attributeBinding(const PossiblyEvaluatedPropertyValue<T>& currentValue) const override {
+ std::tuple<optional<gl::AttributeBinding>> attributeBinding(const PossiblyEvaluatedPropertyValue<T>& currentValue) const override {
if (currentValue.isConstant()) {
return {};
} else {
- return AttributeType::binding(*vertexBuffer, 0);
+ return std::tuple<optional<gl::AttributeBinding>> { AttributeType::binding(*vertexBuffer, 0) };
}
}
- float interpolationFactor(float currentZoom) const override {
+ std::tuple<float> interpolationFactor(float currentZoom) const override {
if (expression.useIntegerZoom) {
- return expression.interpolationFactor(zoomRange, std::floor(currentZoom));
+ return std::tuple<float> { expression.interpolationFactor(zoomRange, std::floor(currentZoom)) };
} else {
- return expression.interpolationFactor(zoomRange, currentZoom);
+ return std::tuple<float> { expression.interpolationFactor(zoomRange, currentZoom) };
}
}
- T uniformValue(const PossiblyEvaluatedPropertyValue<T>& currentValue) const override {
+ std::tuple<T> uniformValue(const PossiblyEvaluatedPropertyValue<T>& currentValue) const override {
if (currentValue.isConstant()) {
- return *currentValue.constant();
+ return std::tuple<T> { *currentValue.constant() };
} else {
// Uniform values for vertex attribute arrays are unused.
return {};
@@ -233,21 +276,131 @@ private:
optional<gl::VertexBuffer<Vertex>> vertexBuffer;
};
-template <class T, class... As>
-std::unique_ptr<PaintPropertyBinder<T, As...>>
-PaintPropertyBinder<T, As...>::create(const PossiblyEvaluatedPropertyValue<T>& value, float zoom, T defaultValue) {
- return value.match(
- [&] (const T& constant) -> std::unique_ptr<PaintPropertyBinder<T, As...>> {
- return std::make_unique<ConstantPaintPropertyBinder<T, As...>>(constant);
- },
- [&] (const style::PropertyExpression<T>& expression) -> std::unique_ptr<PaintPropertyBinder<T, As...>> {
- if (expression.isZoomConstant()) {
- return std::make_unique<SourceFunctionPaintPropertyBinder<T, As...>>(expression, defaultValue);
- } else {
- return std::make_unique<CompositeFunctionPaintPropertyBinder<T, As...>>(expression, zoom, defaultValue);
+template <class T, class A1, class A2>
+class CompositeCrossFadedPaintPropertyBinder : public PaintPropertyBinder<T, std::array<uint16_t, 4>, PossiblyEvaluatedPropertyValue<Faded<T>>, A1, A2> {
+public:
+ using AttributeType = ZoomInterpolatedAttributeType<A1>;
+ using AttributeType2 = ZoomInterpolatedAttributeType<A2>;
+
+ using BaseAttribute = A1;
+ using BaseAttributeValue = typename BaseAttribute::Value;
+
+ using BaseAttribute2 = A2;
+ using BaseAttributeValue2 = typename BaseAttribute2::Value;
+
+ using Vertex = gl::detail::Vertex<BaseAttribute>;
+ using Vertex2 = gl::detail::Vertex<BaseAttribute2>;
+
+ CompositeCrossFadedPaintPropertyBinder(style::PropertyExpression<T> expression_, float zoom, T defaultValue_)
+ : expression(std::move(expression_)),
+ defaultValue(std::move(defaultValue_)),
+ zoomRange({zoom, zoom + 1}) {
+ }
+
+ void setPatternParameters(const optional<ImagePosition>&, const optional<ImagePosition>&, CrossfadeParameters& crossfade_) override {
+ crossfade = crossfade_;
+ };
+
+ void populateVertexVector(const GeometryTileFeature&, std::size_t length, const ImagePositions& patternPositions, const optional<PatternDependency>& patternDependencies) override {
+ if (!patternDependencies) return;
+ if (!patternPositions.empty()) {
+ const auto min = patternPositions.find(patternDependencies->min);
+ const auto mid = patternPositions.find(patternDependencies->mid);
+ const auto max = patternPositions.find(patternDependencies->max);
+
+ const auto end = patternPositions.end();
+ if (min == end || mid == end || max == end) return;
+
+ const ImagePosition imageMin = min->second;
+ const ImagePosition imageMid = mid->second;
+ const ImagePosition imageMax = max->second;
+
+ for (std::size_t i = zoomInVertexVector.vertexSize(); i < length; ++i) {
+ patternToVertexVector.emplace_back(Vertex { imageMid.tlbr() });
+ zoomInVertexVector.emplace_back(Vertex2 { imageMin.tlbr() });
+ zoomOutVertexVector.emplace_back(Vertex2 { imageMax.tlbr() });
}
}
- );
+ }
+
+ void upload(gl::Context& context) override {
+ patternToVertexBuffer = context.createVertexBuffer(std::move(patternToVertexVector));
+ zoomInVertexBuffer = context.createVertexBuffer(std::move(zoomInVertexVector));
+ zoomOutVertexBuffer = context.createVertexBuffer(std::move(zoomOutVertexVector));
+ }
+
+ std::tuple<optional<gl::AttributeBinding>, optional<gl::AttributeBinding>> attributeBinding(const PossiblyEvaluatedPropertyValue<Faded<T>>& currentValue) const override {
+ if (currentValue.isConstant()) {
+ return {};
+ } else {
+ return std::tuple<optional<gl::AttributeBinding>, optional<gl::AttributeBinding>> {
+ AttributeType::binding(*patternToVertexBuffer, 0, BaseAttribute::Dimensions),
+ AttributeType2::binding(
+ crossfade.fromScale == 2 ? *zoomInVertexBuffer : *zoomOutVertexBuffer,
+ 0, BaseAttribute2::Dimensions) };
+ }
+ }
+
+ std::tuple<float, float> interpolationFactor(float) const override {
+ return std::tuple<float, float> { 0.0f, 0.0f };
+ }
+
+ std::tuple<std::array<uint16_t, 4>, std::array<uint16_t, 4>> uniformValue(const PossiblyEvaluatedPropertyValue<Faded<T>>& ) const override {
+ // Uniform values for vertex attribute arrays are unused.
+ return {};
+ }
+
+private:
+ style::PropertyExpression<T> expression;
+ T defaultValue;
+ Range<float> zoomRange;
+ gl::VertexVector<Vertex> patternToVertexVector;
+ gl::VertexVector<Vertex2> zoomInVertexVector;
+ gl::VertexVector<Vertex2> zoomOutVertexVector;
+ optional<gl::VertexBuffer<Vertex>> patternToVertexBuffer;
+ optional<gl::VertexBuffer<Vertex2>> zoomInVertexBuffer;
+ optional<gl::VertexBuffer<Vertex2>> zoomOutVertexBuffer;
+ CrossfadeParameters crossfade;
+};
+
+template <class T, class PossiblyEvaluatedType>
+struct CreateBinder {
+ template <class A>
+ static std::unique_ptr<PaintPropertyBinder<T, T, PossiblyEvaluatedType, A>> create(const PossiblyEvaluatedType& value, float zoom, T defaultValue) {
+ return value.match(
+ [&] (const T& constant) -> std::unique_ptr<PaintPropertyBinder<T, T, PossiblyEvaluatedType, A>> {
+ return std::make_unique<ConstantPaintPropertyBinder<T, A>>(constant);
+ },
+ [&] (const style::PropertyExpression<T>& expression) -> std::unique_ptr<PaintPropertyBinder<T, T, PossiblyEvaluatedType, A>> {
+ if (expression.isZoomConstant()) {
+ return std::make_unique<SourceFunctionPaintPropertyBinder<T, A>>(expression, defaultValue);
+ } else {
+ return std::make_unique<CompositeFunctionPaintPropertyBinder<T, A>>(expression, zoom, defaultValue);
+ }
+ }
+ );
+ }
+};
+
+template <class T>
+struct CreateBinder<T, PossiblyEvaluatedPropertyValue<Faded<T>>> {
+ template <class A1, class A2>
+ static std::unique_ptr<PaintPropertyBinder<T, std::array<uint16_t, 4>, PossiblyEvaluatedPropertyValue<Faded<T>>, A1, A2>> create(const PossiblyEvaluatedPropertyValue<Faded<T>>& value, float zoom, T defaultValue) {
+ return value.match(
+ [&] (const Faded<T>& constant) -> std::unique_ptr<PaintPropertyBinder<T, std::array<uint16_t, 4>, PossiblyEvaluatedPropertyValue<Faded<T>>, A1, A2>> {
+ return std::make_unique<ConstantCrossFadedPaintPropertyBinder<T, A1, A2>>(constant);
+ },
+ [&] (const style::PropertyExpression<T>& expression) -> std::unique_ptr<PaintPropertyBinder<T, std::array<uint16_t, 4>, PossiblyEvaluatedPropertyValue<Faded<T>>, A1, A2>> {
+ return std::make_unique<CompositeCrossFadedPaintPropertyBinder<T, A1, A2>>(expression, zoom, defaultValue);
+ }
+ );
+ }
+};
+
+template <class T, class UniformValueType, class PossiblyEvaluatedType, class... As>
+std::unique_ptr<PaintPropertyBinder<T, UniformValueType, PossiblyEvaluatedType, As... >>
+PaintPropertyBinder<T, UniformValueType, PossiblyEvaluatedType, As...>::create(const PossiblyEvaluatedType& value, float zoom, T defaultValue) {
+ return CreateBinder<T, PossiblyEvaluatedType>::template create<As...>(value, zoom, defaultValue);
}
template <class Attr>
@@ -270,17 +423,18 @@ class PaintPropertyBinders;
template <class... Ps>
class PaintPropertyBinders<TypeList<Ps...>> {
private:
- template <class T, class... As>
+ template <class T, class PossiblyEvaluatedType, class... As>
struct Detail;
- template <class T, class... As>
- struct Detail<T, TypeList<As...>> {
- using Binder = PaintPropertyBinder<T, typename As::Type...>;
+ template <class T, class UniformValueType, class PossiblyEvaluatedType, class... As>
+ struct Detail<T, UniformValueType, PossiblyEvaluatedType, TypeList<As...>> {
+ using Binder = PaintPropertyBinder<T, UniformValueType, PossiblyEvaluatedType, typename As::Type...>;
using ZoomInterpolatedAttributeList = TypeList<ZoomInterpolatedAttribute<As>...>;
+ using InterpolationUniformList = TypeList<InterpolationUniform<As>...>;
};
template <class P>
- using Property = Detail<typename P::Type, typename P::Attributes>;
+ using Property = Detail<typename P::Type, typename P::Uniform::Type, typename P::PossiblyEvaluatedType, typename P::Attributes>;
public:
template <class P>
@@ -299,9 +453,15 @@ public:
PaintPropertyBinders(PaintPropertyBinders&&) = default;
PaintPropertyBinders(const PaintPropertyBinders&) = delete;
- void populateVertexVectors(const GeometryTileFeature& feature, std::size_t length) {
+ void populateVertexVectors(const GeometryTileFeature& feature, std::size_t length, const ImagePositions& patternPositions, const optional<PatternDependency>& patternDependencies) {
util::ignore({
- (binders.template get<Ps>()->populateVertexVector(feature, length), 0)...
+ (binders.template get<Ps>()->populateVertexVector(feature, length, patternPositions, patternDependencies), 0)...
+ });
+ }
+
+ void setPatternParameters(const optional<ImagePosition>& posA, const optional<ImagePosition>& posB, CrossfadeParameters& crossfade) const {
+ util::ignore({
+ (binders.template get<Ps>()->setPatternParameters(posA, posB, crossfade), 0)...
});
}
@@ -313,31 +473,32 @@ public:
template <class P>
using ZoomInterpolatedAttributeList = typename Property<P>::ZoomInterpolatedAttributeList;
+ template <class P>
+ using InterpolationUniformList = typename Property<P>::InterpolationUniformList;
using Attributes = typename TypeListConcat<ZoomInterpolatedAttributeList<Ps>...>::template ExpandInto<gl::Attributes>;
using AttributeBindings = typename Attributes::Bindings;
template <class EvaluatedProperties>
AttributeBindings attributeBindings(const EvaluatedProperties& currentProperties) const {
- return AttributeBindings {
- binders.template get<Ps>()->attributeBinding(currentProperties.template get<Ps>())...
- };
+ return AttributeBindings { std::tuple_cat(
+ binders.template get<Ps>()->attributeBinding(currentProperties.template get<Ps>())...
+ ) };
}
- using Uniforms = gl::Uniforms<InterpolationUniform<typename Ps::Attribute>..., typename Ps::Uniform...>;
+ using Uniforms = typename TypeListConcat<InterpolationUniformList<Ps>..., typename Ps::Uniforms...>::template ExpandInto<gl::Uniforms>;
using UniformValues = typename Uniforms::Values;
template <class EvaluatedProperties>
- UniformValues uniformValues(float currentZoom, const EvaluatedProperties& currentProperties) const {
+ UniformValues uniformValues(float currentZoom, EvaluatedProperties& currentProperties) const {
(void)currentZoom; // Workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56958
- return UniformValues {
- typename InterpolationUniform<typename Ps::Attribute>::Value {
- binders.template get<Ps>()->interpolationFactor(currentZoom)
- }...,
- typename Ps::Uniform::Value {
- binders.template get<Ps>()->uniformValue(currentProperties.template get<Ps>())
- }...
- };
+ return UniformValues (
+ std::tuple_cat(
+ // interpolation uniform values
+ binders.template get<Ps>()->interpolationFactor(currentZoom)...,
+ // uniform values
+ binders.template get<Ps>()->uniformValue(currentProperties.template get<Ps>())...)
+ );
}
template <class P>
@@ -345,7 +506,6 @@ public:
return binders.template get<P>()->statistics;
}
-
using Bitset = std::bitset<sizeof...(Ps)>;
template <class EvaluatedProperties>
@@ -358,13 +518,25 @@ public:
return result;
}
+ template <class>
+ struct UniformDefines;
+
+ template <class... Us>
+ struct UniformDefines<TypeList<Us...>> {
+ static void appendDefines(std::vector<std::string>& defines) {
+ util::ignore({
+ (defines.push_back(std::string("#define HAS_UNIFORM_") + Us::name()), 0)...
+ });
+ }
+ };
+
template <class EvaluatedProperties>
static std::vector<std::string> defines(const EvaluatedProperties& currentProperties) {
std::vector<std::string> result;
util::ignore({
- (result.push_back(currentProperties.template get<Ps>().isConstant()
- ? std::string("#define HAS_UNIFORM_") + Ps::Uniform::name()
- : std::string()), 0)...
+ (currentProperties.template get<Ps>().isConstant()
+ ? UniformDefines<typename Ps::Uniforms>::appendDefines(result)
+ : (void) 0, 0)...
});
return result;
}
diff --git a/src/mbgl/renderer/possibly_evaluated_property_value.hpp b/src/mbgl/renderer/possibly_evaluated_property_value.hpp
index f2d265f2f7..353df2ab90 100644
--- a/src/mbgl/renderer/possibly_evaluated_property_value.hpp
+++ b/src/mbgl/renderer/possibly_evaluated_property_value.hpp
@@ -1,6 +1,7 @@
#pragma once
#include <mbgl/style/property_expression.hpp>
+#include <mbgl/renderer/cross_faded_property_evaluator.hpp>
#include <mbgl/util/interpolate.hpp>
#include <mbgl/util/variant.hpp>
@@ -57,6 +58,61 @@ public:
bool useIntegerZoom;
};
+template <class T>
+class PossiblyEvaluatedPropertyValue<Faded<T>> {
+private:
+ using Value = variant<
+ Faded<T>,
+ style::PropertyExpression<T>>;
+
+ Value value;
+
+public:
+ PossiblyEvaluatedPropertyValue() = default;
+ PossiblyEvaluatedPropertyValue(Value v, bool useIntegerZoom_ = false)
+ : value(std::move(v)),
+ useIntegerZoom(useIntegerZoom_) {}
+
+ bool isConstant() const {
+ return value.template is<Faded<T>>();
+ }
+
+ optional<Faded<T>> constant() const {
+ return value.match(
+ [&] (const Faded<T>& t) { return optional<Faded<T>>(t); },
+ [&] (const auto&) { return optional<Faded<T>>(); });
+ }
+
+ Faded<T> constantOr(const Faded<T>& t) const {
+ return constant().value_or(t);
+ }
+
+ template <class... Ts>
+ auto match(Ts&&... ts) const {
+ return value.match(std::forward<Ts>(ts)...);
+ }
+
+ template <class Feature>
+ Faded<T> evaluate(const Feature& feature, float zoom, T defaultValue) const {
+ return this->match(
+ [&] (const Faded<T>& constant_) { return constant_; },
+ [&] (const style::PropertyExpression<T>& expression) {
+ if (!expression.isZoomConstant()) {
+ const T min = expression.evaluate(floor(zoom), feature, defaultValue);
+ const T max = expression.evaluate(floor(zoom) + 1, feature, defaultValue);
+ return Faded<T> {min, max};
+ } else {
+ const T evaluated = expression.evaluate(feature, defaultValue);
+ return Faded<T> {evaluated, evaluated};
+ }
+ }
+ );
+ }
+
+ bool useIntegerZoom;
+};
+
+
namespace util {
template <typename T>
diff --git a/src/mbgl/renderer/property_evaluation_parameters.hpp b/src/mbgl/renderer/property_evaluation_parameters.hpp
index da6a4a0892..0e1c317294 100644
--- a/src/mbgl/renderer/property_evaluation_parameters.hpp
+++ b/src/mbgl/renderer/property_evaluation_parameters.hpp
@@ -5,6 +5,13 @@
namespace mbgl {
+class CrossfadeParameters {
+public:
+ float fromScale;
+ float toScale;
+ float t;
+};
+
class PropertyEvaluationParameters {
public:
explicit PropertyEvaluationParameters(float z_)
@@ -24,6 +31,18 @@ public:
defaultFadeDuration(std::move(defaultFadeDuration_)),
useIntegerZoom(useIntegerZoom_) {}
+ CrossfadeParameters getCrossfadeParameters() const {
+ const float fraction = z - std::floor(z);
+ const std::chrono::duration<float> d = defaultFadeDuration;
+ const float t = d != std::chrono::duration<float>::zero()
+ ? std::min((now - zoomHistory.lastIntegerZoomTime) / d, 1.0f)
+ : 1.0f;
+
+ return z > zoomHistory.lastIntegerZoom
+ ? CrossfadeParameters { 2.0f, 1.0f, fraction + (1.0f - fraction) * t }
+ : CrossfadeParameters { 0.5f, 1.0f, 1 - (1 - t) * fraction };
+ }
+
float z;
TimePoint now;
ZoomHistory zoomHistory;
diff --git a/src/mbgl/renderer/render_layer.hpp b/src/mbgl/renderer/render_layer.hpp
index 3e2f1d7525..9f327c63e5 100644
--- a/src/mbgl/renderer/render_layer.hpp
+++ b/src/mbgl/renderer/render_layer.hpp
@@ -40,6 +40,9 @@ public:
// Returns true if any paint properties have active transitions.
virtual bool hasTransition() const = 0;
+ // Returns true if the layer has a pattern property and is actively crossfading.
+ virtual bool hasCrossfade() const = 0;
+
// Check whether this layer is of the given subtype.
template <class T>
bool is() const;
diff --git a/src/mbgl/renderer/render_tile.cpp b/src/mbgl/renderer/render_tile.cpp
index 64790938ef..fcd8b77771 100644
--- a/src/mbgl/renderer/render_tile.cpp
+++ b/src/mbgl/renderer/render_tile.cpp
@@ -103,8 +103,8 @@ void RenderTile::finishRender(PaintParameters& parameters) {
tile.debugBucket->segments,
program.computeAllUniformValues(
DebugProgram::UniformValues {
- uniforms::u_matrix::Value{ matrix },
- uniforms::u_color::Value{ Color::white() }
+ uniforms::u_matrix::Value( matrix ),
+ uniforms::u_color::Value( Color::white() )
},
paintAttributeData,
properties,
@@ -124,8 +124,8 @@ void RenderTile::finishRender(PaintParameters& parameters) {
tile.debugBucket->segments,
program.computeAllUniformValues(
DebugProgram::UniformValues {
- uniforms::u_matrix::Value{ matrix },
- uniforms::u_color::Value{ Color::black() }
+ uniforms::u_matrix::Value( matrix ),
+ uniforms::u_color::Value( Color::black() )
},
paintAttributeData,
properties,
@@ -147,8 +147,8 @@ void RenderTile::finishRender(PaintParameters& parameters) {
parameters.staticData.tileBorderSegments,
program.computeAllUniformValues(
DebugProgram::UniformValues {
- uniforms::u_matrix::Value{ matrix },
- uniforms::u_color::Value{ Color::red() }
+ uniforms::u_matrix::Value( matrix ),
+ uniforms::u_color::Value( Color::red() )
},
paintAttributeData,
properties,
diff --git a/src/mbgl/renderer/renderer_impl.cpp b/src/mbgl/renderer/renderer_impl.cpp
index bc39c40796..92d04063ca 100644
--- a/src/mbgl/renderer/renderer_impl.cpp
+++ b/src/mbgl/renderer/renderer_impl.cpp
@@ -14,6 +14,7 @@
#include <mbgl/renderer/layers/render_background_layer.hpp>
#include <mbgl/renderer/layers/render_custom_layer.hpp>
#include <mbgl/renderer/layers/render_fill_extrusion_layer.hpp>
+#include <mbgl/renderer/layers/render_fill_layer.hpp>
#include <mbgl/renderer/layers/render_heatmap_layer.hpp>
#include <mbgl/renderer/layers/render_hillshade_layer.hpp>
#include <mbgl/renderer/style_diff.hpp>
@@ -195,7 +196,7 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) {
}
}
- if (layerAdded || layerChanged || zoomChanged || layer.hasTransition()) {
+ if (layerAdded || layerChanged || zoomChanged || layer.hasTransition() || layer.hasCrossfade()) {
layer.evaluate(evaluationParameters);
}
}
@@ -512,7 +513,7 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) {
parameters.staticData.tileTriangleSegments,
program.computeAllUniformValues(
ClippingMaskProgram::UniformValues {
- uniforms::u_matrix::Value{ parameters.matrixForTile(clipID.first) },
+ uniforms::u_matrix::Value( parameters.matrixForTile(clipID.first) ),
},
paintAttributeData,
properties,
diff --git a/src/mbgl/renderer/sources/render_image_source.cpp b/src/mbgl/renderer/sources/render_image_source.cpp
index 2ce046a7a0..d4577e787a 100644
--- a/src/mbgl/renderer/sources/render_image_source.cpp
+++ b/src/mbgl/renderer/sources/render_image_source.cpp
@@ -71,8 +71,8 @@ void RenderImageSource::finishRender(PaintParameters& parameters) {
parameters.staticData.tileBorderSegments,
programInstance.computeAllUniformValues(
DebugProgram::UniformValues {
- uniforms::u_matrix::Value{ matrix },
- uniforms::u_color::Value{ Color::red() }
+ uniforms::u_matrix::Value( matrix ),
+ uniforms::u_color::Value( Color::red() )
},
paintAttributeData,
properties,