diff options
Diffstat (limited to 'src/mbgl/renderer')
23 files changed, 296 insertions, 157 deletions
diff --git a/src/mbgl/renderer/bucket.hpp b/src/mbgl/renderer/bucket.hpp index 49619c14f7..294e50dd8c 100644 --- a/src/mbgl/renderer/bucket.hpp +++ b/src/mbgl/renderer/bucket.hpp @@ -2,6 +2,7 @@ #include <mbgl/renderer/render_pass.hpp> #include <mbgl/util/noncopyable.hpp> +#include <mbgl/tile/geometry_tile_data.hpp> #include <atomic> @@ -22,6 +23,10 @@ class Layer; class Bucket : private util::noncopyable { public: Bucket() = default; + virtual ~Bucket() = default; + + virtual void addFeature(const GeometryTileFeature&, + const GeometryCollection&) {}; // 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. @@ -31,8 +36,6 @@ public: // once or twice (for Opaque and Transparent render passes). virtual void render(Painter&, PaintParameters&, const style::Layer&, const RenderTile&) = 0; - virtual ~Bucket() = default; - virtual bool hasData() const = 0; bool needsUpload() const { diff --git a/src/mbgl/renderer/circle_bucket.cpp b/src/mbgl/renderer/circle_bucket.cpp index ba2285c4eb..6722d04497 100644 --- a/src/mbgl/renderer/circle_bucket.cpp +++ b/src/mbgl/renderer/circle_bucket.cpp @@ -1,26 +1,38 @@ #include <mbgl/renderer/circle_bucket.hpp> #include <mbgl/renderer/painter.hpp> -#include <mbgl/gl/context.hpp> - #include <mbgl/programs/circle_program.hpp> +#include <mbgl/style/bucket_parameters.hpp> #include <mbgl/style/layers/circle_layer.hpp> +#include <mbgl/style/layers/circle_layer_impl.hpp> #include <mbgl/util/constants.hpp> namespace mbgl { using namespace style; -CircleBucket::CircleBucket(MapMode mode_) : mode(mode_) { +CircleBucket::CircleBucket(const BucketParameters& parameters, const std::vector<const Layer*>& layers) + : mode(parameters.mode) { + for (const auto& layer : layers) { + paintPropertyBinders.emplace(layer->getID(), + CircleProgram::PaintPropertyBinders( + layer->as<CircleLayer>()->impl->paint.evaluated, + parameters.tileID.overscaledZ)); + } } void CircleBucket::upload(gl::Context& context) { vertexBuffer = context.createVertexBuffer(std::move(vertices)); indexBuffer = context.createIndexBuffer(std::move(triangles)); + + for (auto& pair : paintPropertyBinders) { + pair.second.upload(context); + } + uploaded = true; } void CircleBucket::render(Painter& painter, - PaintParameters& parameters, + PaintParameters& parameters, const Layer& layer, const RenderTile& tile) { painter.renderCircle(parameters, *this, *layer.as<CircleLayer>(), tile); @@ -30,10 +42,11 @@ bool CircleBucket::hasData() const { return !segments.empty(); } -void CircleBucket::addGeometry(const GeometryCollection& geometryCollection) { +void CircleBucket::addFeature(const GeometryTileFeature& feature, + const GeometryCollection& geometry) { constexpr const uint16_t vertexLength = 4; - for (auto& circle : geometryCollection) { + for (auto& circle : geometry) { for(auto& point : circle) { auto x = point.x; auto y = point.y; @@ -76,6 +89,10 @@ void CircleBucket::addGeometry(const GeometryCollection& geometryCollection) { segment.indexLength += 6; } } + + for (auto& pair : paintPropertyBinders) { + pair.second.populateVertexVectors(feature, vertices.vertexSize()); + } } } // namespace mbgl diff --git a/src/mbgl/renderer/circle_bucket.hpp b/src/mbgl/renderer/circle_bucket.hpp index af7041a238..412db53f65 100644 --- a/src/mbgl/renderer/circle_bucket.hpp +++ b/src/mbgl/renderer/circle_bucket.hpp @@ -7,26 +7,34 @@ #include <mbgl/gl/index_buffer.hpp> #include <mbgl/gl/segment.hpp> #include <mbgl/programs/circle_program.hpp> +#include <mbgl/style/layers/circle_layer_properties.hpp> namespace mbgl { +namespace style { +class BucketParameters; +} // namespace style + class CircleBucket : public Bucket { public: - CircleBucket(const MapMode); + CircleBucket(const style::BucketParameters&, const std::vector<const style::Layer*>&); + + void addFeature(const GeometryTileFeature&, + const GeometryCollection&) override; + bool hasData() const override; void upload(gl::Context&) override; void render(Painter&, PaintParameters&, const style::Layer&, const RenderTile&) override; - bool hasData() const override; - void addGeometry(const GeometryCollection&); - - gl::VertexVector<CircleVertex> vertices; + gl::VertexVector<CircleLayoutVertex> vertices; gl::IndexVector<gl::Triangles> triangles; gl::SegmentVector<CircleAttributes> segments; - optional<gl::VertexBuffer<CircleVertex>> vertexBuffer; + optional<gl::VertexBuffer<CircleLayoutVertex>> vertexBuffer; optional<gl::IndexBuffer<gl::Triangles>> indexBuffer; + std::unordered_map<std::string, CircleProgram::PaintPropertyBinders> paintPropertyBinders; + const MapMode mode; }; diff --git a/src/mbgl/renderer/debug_bucket.cpp b/src/mbgl/renderer/debug_bucket.cpp index 167df4376f..2a514989cf 100644 --- a/src/mbgl/renderer/debug_bucket.cpp +++ b/src/mbgl/renderer/debug_bucket.cpp @@ -23,7 +23,7 @@ DebugBucket::DebugBucket(const OverscaledTileID& id, expires(std::move(expires_)), debugMode(debugMode_) { - gl::VertexVector<FillVertex> vertices; + gl::VertexVector<FillLayoutVertex> vertices; gl::IndexVector<gl::Lines> indices; auto addText = [&] (const std::string& text, double left, double baseline, double scale) { @@ -43,7 +43,7 @@ DebugBucket::DebugBucket(const OverscaledTileID& id, int16_t(::round(baseline - glyph.data[j + 1] * scale)) }; - vertices.emplace_back(FillAttributes::vertex(p)); + vertices.emplace_back(FillProgram::layoutVertex(p)); if (prev) { indices.emplace_back(vertices.vertexSize() - 2, diff --git a/src/mbgl/renderer/debug_bucket.hpp b/src/mbgl/renderer/debug_bucket.hpp index 4676381789..756e58a6de 100644 --- a/src/mbgl/renderer/debug_bucket.hpp +++ b/src/mbgl/renderer/debug_bucket.hpp @@ -34,7 +34,7 @@ public: const MapDebugOptions debugMode; gl::SegmentVector<DebugAttributes> segments; - optional<gl::VertexBuffer<DebugVertex>> vertexBuffer; + optional<gl::VertexBuffer<DebugLayoutVertex>> vertexBuffer; optional<gl::IndexBuffer<gl::Lines>> indexBuffer; }; diff --git a/src/mbgl/renderer/fill_bucket.cpp b/src/mbgl/renderer/fill_bucket.cpp index b89e982057..64efafb108 100644 --- a/src/mbgl/renderer/fill_bucket.cpp +++ b/src/mbgl/renderer/fill_bucket.cpp @@ -1,8 +1,9 @@ #include <mbgl/renderer/fill_bucket.hpp> -#include <mbgl/style/layers/fill_layer.hpp> #include <mbgl/renderer/painter.hpp> #include <mbgl/programs/fill_program.hpp> -#include <mbgl/util/logging.hpp> +#include <mbgl/style/bucket_parameters.hpp> +#include <mbgl/style/layers/fill_layer.hpp> +#include <mbgl/style/layers/fill_layer_impl.hpp> #include <mapbox/earcut.hpp> @@ -26,7 +27,17 @@ using namespace style; struct GeometryTooLongException : std::exception {}; -void FillBucket::addGeometry(const GeometryCollection& geometry) { +FillBucket::FillBucket(const BucketParameters& parameters, const std::vector<const Layer*>& layers) { + for (const auto& layer : layers) { + paintPropertyBinders.emplace(layer->getID(), + FillProgram::PaintPropertyBinders( + layer->as<FillLayer>()->impl->paint.evaluated, + parameters.tileID.overscaledZ)); + } +} + +void FillBucket::addFeature(const GeometryTileFeature& feature, + const GeometryCollection& geometry) { for (auto& polygon : classifyRings(geometry)) { // Optimize polygons with many interior rings for earcut tesselation. limitHoles(polygon, 500); @@ -55,11 +66,11 @@ void FillBucket::addGeometry(const GeometryCollection& geometry) { assert(lineSegment.vertexLength <= std::numeric_limits<uint16_t>::max()); uint16_t lineIndex = lineSegment.vertexLength; - vertices.emplace_back(FillAttributes::vertex(ring[0])); + vertices.emplace_back(FillProgram::layoutVertex(ring[0])); lines.emplace_back(lineIndex + nVertices - 1, lineIndex); for (uint32_t i = 1; i < nVertices; i++) { - vertices.emplace_back(FillAttributes::vertex(ring[i])); + vertices.emplace_back(FillProgram::layoutVertex(ring[i])); lines.emplace_back(lineIndex + i - 1, lineIndex + i); } @@ -89,6 +100,10 @@ void FillBucket::addGeometry(const GeometryCollection& geometry) { triangleSegment.vertexLength += totalVertices; triangleSegment.indexLength += nIndicies; } + + for (auto& pair : paintPropertyBinders) { + pair.second.populateVertexVectors(feature, vertices.vertexSize()); + } } void FillBucket::upload(gl::Context& context) { @@ -96,7 +111,10 @@ void FillBucket::upload(gl::Context& context) { lineIndexBuffer = context.createIndexBuffer(std::move(lines)); triangleIndexBuffer = context.createIndexBuffer(std::move(triangles)); - // From now on, we're going to render during the opaque and translucent pass. + for (auto& pair : paintPropertyBinders) { + pair.second.upload(context); + } + uploaded = true; } diff --git a/src/mbgl/renderer/fill_bucket.hpp b/src/mbgl/renderer/fill_bucket.hpp index edb1521c1d..b403e1053b 100644 --- a/src/mbgl/renderer/fill_bucket.hpp +++ b/src/mbgl/renderer/fill_bucket.hpp @@ -6,28 +6,38 @@ #include <mbgl/gl/index_buffer.hpp> #include <mbgl/gl/segment.hpp> #include <mbgl/programs/fill_program.hpp> +#include <mbgl/style/layers/fill_layer_properties.hpp> #include <vector> namespace mbgl { +namespace style { +class BucketParameters; +} // namespace style + class FillBucket : public Bucket { public: - void upload(gl::Context&) override; - void render(Painter&, PaintParameters&, const style::Layer&, const RenderTile&) override; + FillBucket(const style::BucketParameters&, const std::vector<const style::Layer*>&); + + void addFeature(const GeometryTileFeature&, + const GeometryCollection&) override; bool hasData() const override; - void addGeometry(const GeometryCollection&); + void upload(gl::Context&) override; + void render(Painter&, PaintParameters&, const style::Layer&, const RenderTile&) override; - gl::VertexVector<FillVertex> vertices; + gl::VertexVector<FillLayoutVertex> vertices; gl::IndexVector<gl::Lines> lines; gl::IndexVector<gl::Triangles> triangles; gl::SegmentVector<FillAttributes> lineSegments; gl::SegmentVector<FillAttributes> triangleSegments; - optional<gl::VertexBuffer<FillVertex>> vertexBuffer; + optional<gl::VertexBuffer<FillLayoutVertex>> vertexBuffer; optional<gl::IndexBuffer<gl::Lines>> lineIndexBuffer; optional<gl::IndexBuffer<gl::Triangles>> triangleIndexBuffer; + + std::unordered_map<std::string, FillProgram::PaintPropertyBinders> paintPropertyBinders; }; } // namespace mbgl diff --git a/src/mbgl/renderer/frame_history.cpp b/src/mbgl/renderer/frame_history.cpp index 1ee53d87b2..a933a9004a 100644 --- a/src/mbgl/renderer/frame_history.cpp +++ b/src/mbgl/renderer/frame_history.cpp @@ -8,7 +8,7 @@ namespace mbgl { FrameHistory::FrameHistory() { changeOpacities.fill(0); - std::fill(opacities.data.get(), opacities.data.get() + opacities.bytes(), 0); + opacities.fill(0); } void FrameHistory::record(const TimePoint& now, float zoom, const Duration& duration) { diff --git a/src/mbgl/renderer/frame_history.hpp b/src/mbgl/renderer/frame_history.hpp index fffbd113ed..f2b11f5f41 100644 --- a/src/mbgl/renderer/frame_history.hpp +++ b/src/mbgl/renderer/frame_history.hpp @@ -26,7 +26,7 @@ public: private: std::array<TimePoint, 256> changeTimes; std::array<uint8_t, 256> changeOpacities; - const AlphaImage opacities{ { 256, 1 } }; + AlphaImage opacities{ { 256, 1 } }; int16_t previousZoomIndex = 0; TimePoint previousTime; diff --git a/src/mbgl/renderer/line_bucket.cpp b/src/mbgl/renderer/line_bucket.cpp index 007060bd1b..50a70c0fd4 100644 --- a/src/mbgl/renderer/line_bucket.cpp +++ b/src/mbgl/renderer/line_bucket.cpp @@ -1,6 +1,8 @@ #include <mbgl/renderer/line_bucket.hpp> -#include <mbgl/style/layers/line_layer.hpp> #include <mbgl/renderer/painter.hpp> +#include <mbgl/style/layers/line_layer.hpp> +#include <mbgl/style/bucket_parameters.hpp> +#include <mbgl/style/layers/line_layer_impl.hpp> #include <mbgl/util/math.hpp> #include <mbgl/util/constants.hpp> @@ -10,19 +12,29 @@ namespace mbgl { using namespace style; -LineBucket::LineBucket(uint32_t overscaling_) : overscaling(overscaling_) { -} - -LineBucket::~LineBucket() { - // Do not remove. header file only contains forward definitions to unique pointers. +LineBucket::LineBucket(const BucketParameters& parameters, + const std::vector<const Layer*>& layers, + const style::LineLayoutProperties& layout_) + : layout(layout_.evaluate(PropertyEvaluationParameters(parameters.tileID.overscaledZ))), + overscaling(parameters.tileID.overscaleFactor()) { + for (const auto& layer : layers) { + paintPropertyBinders.emplace(layer->getID(), + LineProgram::PaintPropertyBinders( + layer->as<LineLayer>()->impl->paint.evaluated, + parameters.tileID.overscaledZ)); + } } -void LineBucket::addGeometry(const GeometryCollection& geometryCollection) { +void LineBucket::addFeature(const GeometryTileFeature& feature, + const GeometryCollection& geometryCollection) { for (auto& line : geometryCollection) { addGeometry(line); } -} + for (auto& pair : paintPropertyBinders) { + pair.second.populateVertexVectors(feature, vertices.vertexSize()); + } +} /* * Sharp corners cause dashed lines to tilt because the distance along the line @@ -139,7 +151,14 @@ void LineBucket::addGeometry(const GeometryCoordinates& coordinates) { // Determine the normal of the join extrusion. It is the angle bisector // of the segments between the previous line and the next line. - Point<double> joinNormal = util::unit(*prevNormal + *nextNormal); + // In the case of 180° angles, the prev and next normals cancel each other out: + // prevNormal + nextNormal = (0, 0), its magnitude is 0, so the unit vector would be + // undefined. In that case, we're keeping the joinNormal at (0, 0), so that the cosHalfAngle + // below will also become 0 and miterLength will become Infinity. + Point<double> joinNormal = *prevNormal + *nextNormal; + if (joinNormal.x != 0 || joinNormal.y != 0) { + joinNormal = util::unit(joinNormal); + } /* joinNormal prevNormal * ↖ ↑ @@ -155,7 +174,8 @@ void LineBucket::addGeometry(const GeometryCoordinates& coordinates) { // Find the cosine of the angle between the next and join normals // using dot product. The inverse of that is the miter length. const double cosHalfAngle = joinNormal.x * nextNormal->x + joinNormal.y * nextNormal->y; - const double miterLength = cosHalfAngle != 0 ? 1 / cosHalfAngle: 1; + const double miterLength = + cosHalfAngle != 0 ? 1 / cosHalfAngle : std::numeric_limits<double>::infinity(); const bool isSharpCorner = cosHalfAngle < COS_HALF_SHARP_CORNER && prevCoordinate && nextCoordinate; @@ -189,7 +209,7 @@ void LineBucket::addGeometry(const GeometryCoordinates& coordinates) { if (currentJoin == LineJoinType::Bevel) { // The maximum extrude length is 128 / 63 = 2 times the width of the line - // so if miterLength >= 2 we need to draw a different type of bevel where. + // so if miterLength >= 2 we need to draw a different type of bevel here. if (miterLength > 2) { currentJoin = LineJoinType::FlipBevel; } @@ -216,7 +236,7 @@ void LineBucket::addGeometry(const GeometryCoordinates& coordinates) { if (miterLength > 100) { // Almost parallel lines - joinNormal = *nextNormal; + joinNormal = *nextNormal * -1.0; } else { const double direction = prevNormal->x * nextNormal->y - prevNormal->y * nextNormal->x > 0 ? -1 : 1; const double bevelLength = miterLength * util::mag(*prevNormal + *nextNormal) / @@ -375,7 +395,7 @@ void LineBucket::addCurrentVertex(const GeometryCoordinate& currentCoordinate, Point<double> extrude = normal; if (endLeft) extrude = extrude - (util::perp(normal) * endLeft); - vertices.emplace_back(LineAttributes::vertex(currentCoordinate, extrude, { round, false }, endLeft, distance * LINE_DISTANCE_SCALE)); + vertices.emplace_back(LineProgram::layoutVertex(currentCoordinate, extrude, { round, false }, endLeft, distance * LINE_DISTANCE_SCALE)); e3 = vertices.vertexSize() - 1 - startVertex; if (e1 >= 0 && e2 >= 0) { triangleStore.emplace_back(e1, e2, e3); @@ -386,7 +406,7 @@ void LineBucket::addCurrentVertex(const GeometryCoordinate& currentCoordinate, extrude = normal * -1.0; if (endRight) extrude = extrude - (util::perp(normal) * endRight); - vertices.emplace_back(LineAttributes::vertex(currentCoordinate, extrude, { round, true }, -endRight, distance * LINE_DISTANCE_SCALE)); + vertices.emplace_back(LineProgram::layoutVertex(currentCoordinate, extrude, { round, true }, -endRight, distance * LINE_DISTANCE_SCALE)); e3 = vertices.vertexSize() - 1 - startVertex; if (e1 >= 0 && e2 >= 0) { triangleStore.emplace_back(e1, e2, e3); @@ -411,7 +431,7 @@ void LineBucket::addPieSliceVertex(const GeometryCoordinate& currentVertex, std::size_t startVertex, std::vector<TriangleElement>& triangleStore) { Point<double> flippedExtrude = extrude * (lineTurnsLeft ? -1.0 : 1.0); - vertices.emplace_back(LineAttributes::vertex(currentVertex, flippedExtrude, { false, lineTurnsLeft }, 0, distance * LINE_DISTANCE_SCALE)); + vertices.emplace_back(LineProgram::layoutVertex(currentVertex, flippedExtrude, { false, lineTurnsLeft }, 0, distance * LINE_DISTANCE_SCALE)); e3 = vertices.vertexSize() - 1 - startVertex; if (e1 >= 0 && e2 >= 0) { triangleStore.emplace_back(e1, e2, e3); @@ -428,7 +448,10 @@ void LineBucket::upload(gl::Context& context) { vertexBuffer = context.createVertexBuffer(std::move(vertices)); indexBuffer = context.createIndexBuffer(std::move(triangles)); - // From now on, we're only going to render during the translucent pass. + for (auto& pair : paintPropertyBinders) { + pair.second.upload(context); + } + uploaded = true; } diff --git a/src/mbgl/renderer/line_bucket.hpp b/src/mbgl/renderer/line_bucket.hpp index d11d78ff69..78293d75f9 100644 --- a/src/mbgl/renderer/line_bucket.hpp +++ b/src/mbgl/renderer/line_bucket.hpp @@ -12,28 +12,37 @@ namespace mbgl { +namespace style { +class BucketParameters; +} // namespace style + class LineBucket : public Bucket { public: - LineBucket(uint32_t overscaling); - ~LineBucket() override; + LineBucket(const style::BucketParameters&, + const std::vector<const style::Layer*>&, + const style::LineLayoutProperties&); - void upload(gl::Context&) override; - void render(Painter&, PaintParameters&, const style::Layer&, const RenderTile&) override; + void addFeature(const GeometryTileFeature&, + const GeometryCollection&) override; bool hasData() const override; - void addGeometry(const GeometryCollection&); - void addGeometry(const GeometryCoordinates& line); + void upload(gl::Context&) override; + void render(Painter&, PaintParameters&, const style::Layer&, const RenderTile&) override; style::LineLayoutProperties::Evaluated layout; - gl::VertexVector<LineVertex> vertices; + gl::VertexVector<LineLayoutVertex> vertices; gl::IndexVector<gl::Triangles> triangles; gl::SegmentVector<LineAttributes> segments; - optional<gl::VertexBuffer<LineVertex>> vertexBuffer; + optional<gl::VertexBuffer<LineLayoutVertex>> vertexBuffer; optional<gl::IndexBuffer<gl::Triangles>> indexBuffer; + std::unordered_map<std::string, LineProgram::PaintPropertyBinders> paintPropertyBinders; + private: + void addGeometry(const GeometryCoordinates& line); + struct TriangleElement { TriangleElement(uint16_t a_, uint16_t b_, uint16_t c_) : a(a_), b(b_), c(c_) {} uint16_t a, b, c; diff --git a/src/mbgl/renderer/painter.cpp b/src/mbgl/renderer/painter.cpp index 505007304d..27d24d14a9 100644 --- a/src/mbgl/renderer/painter.cpp +++ b/src/mbgl/renderer/painter.cpp @@ -42,12 +42,12 @@ namespace mbgl { using namespace style; -static gl::VertexVector<FillVertex> tileVertices() { - gl::VertexVector<FillVertex> result; - result.emplace_back(FillAttributes::vertex({ 0, 0 })); - result.emplace_back(FillAttributes::vertex({ util::EXTENT, 0 })); - result.emplace_back(FillAttributes::vertex({ 0, util::EXTENT })); - result.emplace_back(FillAttributes::vertex({ util::EXTENT, util::EXTENT })); +static gl::VertexVector<FillLayoutVertex> tileVertices() { + gl::VertexVector<FillLayoutVertex> result; + result.emplace_back(FillProgram::layoutVertex({ 0, 0 })); + result.emplace_back(FillProgram::layoutVertex({ util::EXTENT, 0 })); + result.emplace_back(FillProgram::layoutVertex({ 0, util::EXTENT })); + result.emplace_back(FillProgram::layoutVertex({ util::EXTENT, util::EXTENT })); return result; } @@ -68,12 +68,12 @@ static gl::IndexVector<gl::LineStrip> tileLineStripIndices() { return result; } -static gl::VertexVector<RasterVertex> rasterVertices() { - gl::VertexVector<RasterVertex> result; - result.emplace_back(RasterProgram::vertex({ 0, 0 }, { 0, 0 })); - result.emplace_back(RasterProgram::vertex({ util::EXTENT, 0 }, { 32767, 0 })); - result.emplace_back(RasterProgram::vertex({ 0, util::EXTENT }, { 0, 32767 })); - result.emplace_back(RasterProgram::vertex({ util::EXTENT, util::EXTENT }, { 32767, 32767 })); +static gl::VertexVector<RasterLayoutVertex> rasterVertices() { + gl::VertexVector<RasterLayoutVertex> result; + result.emplace_back(RasterProgram::layoutVertex({ 0, 0 }, { 0, 0 })); + result.emplace_back(RasterProgram::layoutVertex({ util::EXTENT, 0 }, { 32767, 0 })); + result.emplace_back(RasterProgram::layoutVertex({ 0, util::EXTENT }, { 0, 32767 })); + result.emplace_back(RasterProgram::layoutVertex({ util::EXTENT, util::EXTENT }, { 32767, 32767 })); return result; } @@ -94,7 +94,7 @@ Painter::Painter(gl::Context& context_, const TransformState& state_, float pixe ProgramParameters programParameters{ pixelRatio, false }; programs = std::make_unique<Programs>(context, programParameters); #ifndef NDEBUG - + ProgramParameters programParametersOverdraw{ pixelRatio, true }; overdrawPrograms = std::make_unique<Programs>(context, programParametersOverdraw); #endif diff --git a/src/mbgl/renderer/painter.hpp b/src/mbgl/renderer/painter.hpp index dec7fa57fd..91f329a6eb 100644 --- a/src/mbgl/renderer/painter.hpp +++ b/src/mbgl/renderer/painter.hpp @@ -158,8 +158,8 @@ private: std::unique_ptr<Programs> overdrawPrograms; #endif - gl::VertexBuffer<FillVertex> tileVertexBuffer; - gl::VertexBuffer<RasterVertex> rasterVertexBuffer; + gl::VertexBuffer<FillLayoutVertex> tileVertexBuffer; + gl::VertexBuffer<RasterLayoutVertex> rasterVertexBuffer; gl::IndexBuffer<gl::Triangles> tileTriangleIndexBuffer; gl::IndexBuffer<gl::LineStrip> tileBorderIndexBuffer; diff --git a/src/mbgl/renderer/painter_background.cpp b/src/mbgl/renderer/painter_background.cpp index 4a3e41701d..4ac414335b 100644 --- a/src/mbgl/renderer/painter_background.cpp +++ b/src/mbgl/renderer/painter_background.cpp @@ -14,13 +14,18 @@ using namespace style; void Painter::renderBackground(PaintParameters& parameters, const BackgroundLayer& layer) { // Note that for bottommost layers without a pattern, the background color is drawn with // glClear rather than this method. - const BackgroundPaintProperties::Evaluated& properties = layer.impl->paint.evaluated; + const BackgroundPaintProperties::Evaluated& background = layer.impl->paint.evaluated; - if (!properties.get<BackgroundPattern>().to.empty()) { - optional<SpriteAtlasPosition> imagePosA = spriteAtlas->getPosition( - properties.get<BackgroundPattern>().from, SpritePatternMode::Repeating); - optional<SpriteAtlasPosition> imagePosB = spriteAtlas->getPosition( - properties.get<BackgroundPattern>().to, SpritePatternMode::Repeating); + style::FillPaintProperties::Evaluated properties; + properties.get<FillPattern>() = background.get<BackgroundPattern>(); + properties.get<FillOpacity>() = { background.get<BackgroundOpacity>() }; + properties.get<FillColor>() = { background.get<BackgroundColor>() }; + + const FillProgram::PaintPropertyBinders paintAttibuteData(properties, 0); + + if (!background.get<BackgroundPattern>().to.empty()) { + optional<SpriteAtlasElement> imagePosA = spriteAtlas->getPattern(background.get<BackgroundPattern>().from); + optional<SpriteAtlasElement> imagePosB = spriteAtlas->getPattern(background.get<BackgroundPattern>().to); if (!imagePosA || !imagePosB) return; @@ -36,17 +41,19 @@ void Painter::renderBackground(PaintParameters& parameters, const BackgroundLaye colorModeForRenderPass(), FillPatternUniforms::values( matrixForTile(tileID), - properties.get<BackgroundOpacity>(), context.viewport.getCurrentValue().size, *imagePosA, *imagePosB, - properties.get<BackgroundPattern>(), + background.get<BackgroundPattern>(), tileID, state ), tileVertexBuffer, tileTriangleIndexBuffer, - tileTriangleSegments + tileTriangleSegments, + paintAttibuteData, + properties, + state.getZoom() ); } } else { @@ -59,14 +66,14 @@ void Painter::renderBackground(PaintParameters& parameters, const BackgroundLaye colorModeForRenderPass(), FillProgram::UniformValues { uniforms::u_matrix::Value{ matrixForTile(tileID) }, - uniforms::u_opacity::Value{ properties.get<BackgroundOpacity>() }, - uniforms::u_color::Value{ properties.get<BackgroundColor>() }, - uniforms::u_outline_color::Value{ properties.get<BackgroundColor>() }, uniforms::u_world::Value{ context.viewport.getCurrentValue().size }, }, tileVertexBuffer, tileTriangleIndexBuffer, - tileTriangleSegments + tileTriangleSegments, + paintAttibuteData, + properties, + state.getZoom() ); } } diff --git a/src/mbgl/renderer/painter_circle.cpp b/src/mbgl/renderer/painter_circle.cpp index 966d58b59b..8d47e75f71 100644 --- a/src/mbgl/renderer/painter_circle.cpp +++ b/src/mbgl/renderer/painter_circle.cpp @@ -37,13 +37,6 @@ void Painter::renderCircle(PaintParameters& parameters, properties.get<CircleTranslateAnchor>(), state) }, - uniforms::u_opacity::Value{ properties.get<CircleOpacity>() }, - uniforms::u_color::Value{ properties.get<CircleColor>() }, - uniforms::u_radius::Value{ properties.get<CircleRadius>() }, - uniforms::u_blur::Value{ properties.get<CircleBlur>() }, - uniforms::u_stroke_color::Value{ properties.get<CircleStrokeColor>() }, - uniforms::u_stroke_width::Value{ properties.get<CircleStrokeWidth>() }, - uniforms::u_stroke_opacity::Value{ properties.get<CircleStrokeOpacity>() }, uniforms::u_scale_with_map::Value{ scaleWithMap }, uniforms::u_extrude_scale::Value{ scaleWithMap ? std::array<float, 2> {{ @@ -54,7 +47,10 @@ void Painter::renderCircle(PaintParameters& parameters, }, *bucket.vertexBuffer, *bucket.indexBuffer, - bucket.segments + bucket.segments, + bucket.paintPropertyBinders.at(layer.getID()), + properties, + state.getZoom() ); } diff --git a/src/mbgl/renderer/painter_clipping.cpp b/src/mbgl/renderer/painter_clipping.cpp index a2529561fe..70df9837e8 100644 --- a/src/mbgl/renderer/painter_clipping.cpp +++ b/src/mbgl/renderer/painter_clipping.cpp @@ -6,6 +6,8 @@ namespace mbgl { void Painter::renderClippingMask(const UnwrappedTileID& tileID, const ClipID& clip) { + static const style::FillPaintProperties::Evaluated properties {}; + static const FillProgram::PaintPropertyBinders paintAttibuteData(properties, 0); programs->fill.draw( context, gl::Triangles(), @@ -21,14 +23,14 @@ void Painter::renderClippingMask(const UnwrappedTileID& tileID, const ClipID& cl gl::ColorMode::disabled(), FillProgram::UniformValues { uniforms::u_matrix::Value{ matrixForTile(tileID) }, - uniforms::u_opacity::Value{ 0.0f }, - uniforms::u_color::Value{ Color {} }, - uniforms::u_outline_color::Value{ Color {} }, uniforms::u_world::Value{ context.viewport.getCurrentValue().size }, }, tileVertexBuffer, tileTriangleIndexBuffer, - tileTriangleSegments + tileTriangleSegments, + paintAttibuteData, + properties, + state.getZoom() ); } diff --git a/src/mbgl/renderer/painter_debug.cpp b/src/mbgl/renderer/painter_debug.cpp index 2b838dec0e..5b347884bf 100644 --- a/src/mbgl/renderer/painter_debug.cpp +++ b/src/mbgl/renderer/painter_debug.cpp @@ -12,12 +12,17 @@ namespace mbgl { +using namespace style; + void Painter::renderTileDebug(const RenderTile& renderTile) { if (frame.debugOptions == MapDebugOptions::NoDebug) return; MBGL_DEBUG_GROUP(std::string { "debug " } + util::toString(renderTile.id)); + static const style::PaintProperties<>::Evaluated properties {}; + static const DebugProgram::PaintPropertyBinders paintAttibuteData(properties, 0); + auto draw = [&] (Color color, const auto& vertexBuffer, const auto& indexBuffer, const auto& segments, auto drawMode) { programs->debug.draw( context, @@ -31,7 +36,10 @@ void Painter::renderTileDebug(const RenderTile& renderTile) { }, vertexBuffer, indexBuffer, - segments + segments, + paintAttibuteData, + properties, + state.getZoom() ); }; diff --git a/src/mbgl/renderer/painter_fill.cpp b/src/mbgl/renderer/painter_fill.cpp index 356ccfc0b2..4276bd06ed 100644 --- a/src/mbgl/renderer/painter_fill.cpp +++ b/src/mbgl/renderer/painter_fill.cpp @@ -24,10 +24,8 @@ void Painter::renderFill(PaintParameters& parameters, return; } - optional<SpriteAtlasPosition> imagePosA = spriteAtlas->getPosition( - properties.get<FillPattern>().from, SpritePatternMode::Repeating); - optional<SpriteAtlasPosition> imagePosB = spriteAtlas->getPosition( - properties.get<FillPattern>().to, SpritePatternMode::Repeating); + optional<SpriteAtlasElement> imagePosA = spriteAtlas->getPattern(properties.get<FillPattern>().from); + optional<SpriteAtlasElement> imagePosB = spriteAtlas->getPattern(properties.get<FillPattern>().to); if (!imagePosA || !imagePosB) { return; @@ -38,7 +36,6 @@ void Painter::renderFill(PaintParameters& parameters, auto draw = [&] (uint8_t sublayer, auto& program, const auto& drawMode, - const auto& vertexBuffer, const auto& indexBuffer, const auto& segments) { program.draw( @@ -51,7 +48,6 @@ void Painter::renderFill(PaintParameters& parameters, tile.translatedMatrix(properties.get<FillTranslate>(), properties.get<FillTranslateAnchor>(), state), - properties.get<FillOpacity>(), context.viewport.getCurrentValue().size, *imagePosA, *imagePosB, @@ -59,16 +55,18 @@ void Painter::renderFill(PaintParameters& parameters, tile.id, state ), - vertexBuffer, + *bucket.vertexBuffer, indexBuffer, - segments + segments, + bucket.paintPropertyBinders.at(layer.getID()), + properties, + state.getZoom() ); }; draw(0, parameters.programs.fillPattern, gl::Triangles(), - *bucket.vertexBuffer, *bucket.triangleIndexBuffer, bucket.triangleSegments); @@ -79,15 +77,12 @@ void Painter::renderFill(PaintParameters& parameters, draw(2, parameters.programs.fillOutlinePattern, gl::Lines { 2.0f }, - *bucket.vertexBuffer, *bucket.lineIndexBuffer, bucket.lineSegments); } else { auto draw = [&] (uint8_t sublayer, auto& program, - Color outlineColor, const auto& drawMode, - const auto& vertexBuffer, const auto& indexBuffer, const auto& segments) { program.draw( @@ -97,38 +92,37 @@ void Painter::renderFill(PaintParameters& parameters, stencilModeForClipping(tile.clip), colorModeForRenderPass(), FillProgram::UniformValues { - uniforms::u_matrix::Value{ tile.translatedMatrix(properties.get<FillTranslate>(), - properties.get<FillTranslateAnchor>(), - state) }, - uniforms::u_opacity::Value{ properties.get<FillOpacity>() }, - uniforms::u_color::Value{ properties.get<FillColor>() }, - uniforms::u_outline_color::Value{ outlineColor }, + uniforms::u_matrix::Value{ + tile.translatedMatrix(properties.get<FillTranslate>(), + properties.get<FillTranslateAnchor>(), + state) + }, uniforms::u_world::Value{ context.viewport.getCurrentValue().size }, }, - vertexBuffer, + *bucket.vertexBuffer, indexBuffer, - segments + segments, + bucket.paintPropertyBinders.at(layer.getID()), + properties, + state.getZoom() ); }; if (properties.get<FillAntialias>() && !layer.impl->paint.unevaluated.get<FillOutlineColor>().isUndefined() && pass == RenderPass::Translucent) { draw(2, parameters.programs.fillOutline, - properties.get<FillOutlineColor>(), gl::Lines { 2.0f }, - *bucket.vertexBuffer, *bucket.lineIndexBuffer, bucket.lineSegments); } // Only draw the fill when it's opaque and we're drawing opaque fragments, // or when it's translucent and we're drawing translucent fragments. - if ((properties.get<FillColor>().a >= 1.0f && properties.get<FillOpacity>() >= 1.0f) == (pass == RenderPass::Opaque)) { + if ((properties.get<FillColor>().constantOr(Color()).a >= 1.0f + && properties.get<FillOpacity>().constantOr(0) >= 1.0f) == (pass == RenderPass::Opaque)) { draw(1, parameters.programs.fill, - properties.get<FillOutlineColor>(), gl::Triangles(), - *bucket.vertexBuffer, *bucket.triangleIndexBuffer, bucket.triangleSegments); } @@ -136,9 +130,7 @@ void Painter::renderFill(PaintParameters& parameters, if (properties.get<FillAntialias>() && layer.impl->paint.unevaluated.get<FillOutlineColor>().isUndefined() && pass == RenderPass::Translucent) { draw(2, parameters.programs.fillOutline, - properties.get<FillColor>(), gl::Lines { 2.0f }, - *bucket.vertexBuffer, *bucket.lineIndexBuffer, bucket.lineSegments); } diff --git a/src/mbgl/renderer/painter_line.cpp b/src/mbgl/renderer/painter_line.cpp index 012746d2f2..4e19f841b1 100644 --- a/src/mbgl/renderer/painter_line.cpp +++ b/src/mbgl/renderer/painter_line.cpp @@ -33,7 +33,10 @@ void Painter::renderLine(PaintParameters& parameters, std::move(uniformValues), *bucket.vertexBuffer, *bucket.indexBuffer, - bucket.segments + bucket.segments, + bucket.paintPropertyBinders.at(layer.getID()), + properties, + state.getZoom() ); }; @@ -58,10 +61,8 @@ void Painter::renderLine(PaintParameters& parameters, lineAtlas->getSize().width)); } else if (!properties.get<LinePattern>().from.empty()) { - optional<SpriteAtlasPosition> posA = spriteAtlas->getPosition( - properties.get<LinePattern>().from, SpritePatternMode::Repeating); - optional<SpriteAtlasPosition> posB = spriteAtlas->getPosition( - properties.get<LinePattern>().to, SpritePatternMode::Repeating); + optional<SpriteAtlasElement> posA = spriteAtlas->getPattern(properties.get<LinePattern>().from); + optional<SpriteAtlasElement> posB = spriteAtlas->getPattern(properties.get<LinePattern>().to); if (!posA || !posB) return; diff --git a/src/mbgl/renderer/painter_raster.cpp b/src/mbgl/renderer/painter_raster.cpp index dcf2644140..c216955db8 100644 --- a/src/mbgl/renderer/painter_raster.cpp +++ b/src/mbgl/renderer/painter_raster.cpp @@ -49,6 +49,7 @@ void Painter::renderRaster(PaintParameters& parameters, return; const RasterPaintProperties::Evaluated& properties = layer.impl->paint.evaluated; + const RasterProgram::PaintPropertyBinders paintAttributeData(properties, 0); assert(bucket.texture); context.bindTexture(*bucket.texture, 0, gl::TextureFilter::Linear); @@ -77,7 +78,10 @@ void Painter::renderRaster(PaintParameters& parameters, }, rasterVertexBuffer, tileTriangleIndexBuffer, - rasterSegments + rasterSegments, + paintAttributeData, + properties, + state.getZoom() ); } diff --git a/src/mbgl/renderer/painter_symbol.cpp b/src/mbgl/renderer/painter_symbol.cpp index 39075976a0..48c2e7ff66 100644 --- a/src/mbgl/renderer/painter_symbol.cpp +++ b/src/mbgl/renderer/painter_symbol.cpp @@ -33,7 +33,9 @@ void Painter::renderSymbol(PaintParameters& parameters, auto draw = [&] (auto& program, auto&& uniformValues, const auto& buffers, - const SymbolPropertyValues& values_) + const SymbolPropertyValues& values_, + const auto& binders, + const auto& paintProperties) { // We clip symbols to their tile extent in still mode. const bool needsClipping = frame.mapMode == MapMode::Still; @@ -51,12 +53,16 @@ void Painter::renderSymbol(PaintParameters& parameters, std::move(uniformValues), *buffers.vertexBuffer, *buffers.indexBuffer, - buffers.segments + buffers.segments, + binders, + paintProperties, + state.getZoom() ); }; if (bucket.hasIconData()) { auto values = layer.impl->iconPropertyValues(layout); + auto paintPropertyValues = layer.impl->iconPaintProperties(); SpriteAtlas& atlas = *layer.impl->spriteAtlas; const bool iconScaled = values.paintSize != 1.0f || frame.pixelRatio != atlas.getPixelRatio() || bucket.iconsNeedLinear; @@ -66,24 +72,30 @@ void Painter::renderSymbol(PaintParameters& parameters, const Size texsize = atlas.getSize(); if (bucket.sdfIcons) { - if (values.hasHalo()) { + if (values.hasHalo) { draw(parameters.programs.symbolIconSDF, - SymbolSDFProgram::haloUniformValues(values, texsize, pixelsToGLUnits, tile, state, frame.pixelRatio), + SymbolSDFIconProgram::uniformValues(values, texsize, pixelsToGLUnits, tile, state, SymbolSDFPart::Halo), bucket.icon, - values); + values, + bucket.paintPropertyBinders.at(layer.getID()).first, + paintPropertyValues); } - if (values.hasForeground()) { + if (values.hasFill) { draw(parameters.programs.symbolIconSDF, - SymbolSDFProgram::foregroundUniformValues(values, texsize, pixelsToGLUnits, tile, state, frame.pixelRatio), + SymbolSDFIconProgram::uniformValues(values, texsize, pixelsToGLUnits, tile, state, SymbolSDFPart::Fill), bucket.icon, - values); + values, + bucket.paintPropertyBinders.at(layer.getID()).first, + paintPropertyValues); } } else { draw(parameters.programs.symbolIcon, SymbolIconProgram::uniformValues(values, texsize, pixelsToGLUnits, tile, state), bucket.icon, - values); + values, + bucket.paintPropertyBinders.at(layer.getID()).first, + paintPropertyValues); } } @@ -91,25 +103,33 @@ void Painter::renderSymbol(PaintParameters& parameters, glyphAtlas->bind(context, 0); auto values = layer.impl->textPropertyValues(layout); + auto paintPropertyValues = layer.impl->textPaintProperties(); const Size texsize = glyphAtlas->getSize(); - if (values.hasHalo()) { + if (values.hasHalo) { draw(parameters.programs.symbolGlyph, - SymbolSDFProgram::haloUniformValues(values, texsize, pixelsToGLUnits, tile, state, frame.pixelRatio), + SymbolSDFTextProgram::uniformValues(values, texsize, pixelsToGLUnits, tile, state, SymbolSDFPart::Halo), bucket.text, - values); + values, + bucket.paintPropertyBinders.at(layer.getID()).second, + paintPropertyValues); } - if (values.hasForeground()) { + if (values.hasFill) { draw(parameters.programs.symbolGlyph, - SymbolSDFProgram::foregroundUniformValues(values, texsize, pixelsToGLUnits, tile, state, frame.pixelRatio), + SymbolSDFTextProgram::uniformValues(values, texsize, pixelsToGLUnits, tile, state, SymbolSDFPart::Fill), bucket.text, - values); + values, + bucket.paintPropertyBinders.at(layer.getID()).second, + paintPropertyValues); } } if (bucket.hasCollisionBoxData()) { + static const style::PaintProperties<>::Evaluated properties {}; + static const CollisionBoxProgram::PaintPropertyBinders paintAttributeData(properties, 0); + programs->collisionBox.draw( context, gl::Lines { 1.0f }, @@ -124,7 +144,10 @@ void Painter::renderSymbol(PaintParameters& parameters, }, *bucket.collisionBox.vertexBuffer, *bucket.collisionBox.indexBuffer, - bucket.collisionBox.segments + bucket.collisionBox.segments, + paintAttributeData, + properties, + state.getZoom() ); } } diff --git a/src/mbgl/renderer/symbol_bucket.cpp b/src/mbgl/renderer/symbol_bucket.cpp index 0f2c89339f..fa4178dda1 100644 --- a/src/mbgl/renderer/symbol_bucket.cpp +++ b/src/mbgl/renderer/symbol_bucket.cpp @@ -1,19 +1,28 @@ #include <mbgl/renderer/symbol_bucket.hpp> #include <mbgl/renderer/painter.hpp> +#include <mbgl/style/bucket_parameters.hpp> #include <mbgl/style/layers/symbol_layer.hpp> +#include <mbgl/style/layers/symbol_layer_impl.hpp> namespace mbgl { using namespace style; -SymbolBucket::SymbolBucket(const MapMode mode_, - style::SymbolLayoutProperties::Evaluated layout_, +SymbolBucket::SymbolBucket(style::SymbolLayoutProperties::Evaluated layout_, + const std::unordered_map<std::string, std::pair< + style::IconPaintProperties::Evaluated, style::TextPaintProperties::Evaluated>>& layerPaintProperties, + float zoom, bool sdfIcons_, bool iconsNeedLinear_) - : mode(mode_), - layout(std::move(layout_)), + : layout(std::move(layout_)), sdfIcons(sdfIcons_), iconsNeedLinear(iconsNeedLinear_) { + for (const auto& pair : layerPaintProperties) { + paintPropertyBinders.emplace(pair.first, std::make_pair( + SymbolIconProgram::PaintPropertyBinders(pair.second.first, zoom), + SymbolSDFTextProgram::PaintPropertyBinders(pair.second.second, zoom) + )); + } } void SymbolBucket::upload(gl::Context& context) { @@ -32,6 +41,11 @@ void SymbolBucket::upload(gl::Context& context) { collisionBox.indexBuffer = context.createIndexBuffer(std::move(collisionBox.lines)); } + for (auto& pair : paintPropertyBinders) { + pair.second.first.upload(context); + pair.second.second.upload(context); + } + uploaded = true; } diff --git a/src/mbgl/renderer/symbol_bucket.hpp b/src/mbgl/renderer/symbol_bucket.hpp index d62a61aab7..dcf3f5f495 100644 --- a/src/mbgl/renderer/symbol_bucket.hpp +++ b/src/mbgl/renderer/symbol_bucket.hpp @@ -16,8 +16,9 @@ namespace mbgl { class SymbolBucket : public Bucket { public: - SymbolBucket(const MapMode, - style::SymbolLayoutProperties::Evaluated, + SymbolBucket(style::SymbolLayoutProperties::Evaluated, + const std::unordered_map<std::string, std::pair<style::IconPaintProperties::Evaluated, style::TextPaintProperties::Evaluated>>&, + float zoom, bool sdfIcons, bool iconsNeedLinear); @@ -28,26 +29,29 @@ public: bool hasIconData() const; bool hasCollisionBoxData() const; - const MapMode mode; const style::SymbolLayoutProperties::Evaluated layout; const bool sdfIcons; const bool iconsNeedLinear; + std::unordered_map<std::string, std::pair< + SymbolIconProgram::PaintPropertyBinders, + SymbolSDFTextProgram::PaintPropertyBinders>> paintPropertyBinders; + struct TextBuffer { - gl::VertexVector<SymbolVertex> vertices; + gl::VertexVector<SymbolLayoutVertex> vertices; gl::IndexVector<gl::Triangles> triangles; - gl::SegmentVector<SymbolAttributes> segments; + gl::SegmentVector<SymbolTextAttributes> segments; - optional<gl::VertexBuffer<SymbolVertex>> vertexBuffer; + optional<gl::VertexBuffer<SymbolLayoutVertex>> vertexBuffer; optional<gl::IndexBuffer<gl::Triangles>> indexBuffer; } text; struct IconBuffer { - gl::VertexVector<SymbolVertex> vertices; + gl::VertexVector<SymbolLayoutVertex> vertices; gl::IndexVector<gl::Triangles> triangles; - gl::SegmentVector<SymbolAttributes> segments; + gl::SegmentVector<SymbolIconAttributes> segments; - optional<gl::VertexBuffer<SymbolVertex>> vertexBuffer; + optional<gl::VertexBuffer<SymbolLayoutVertex>> vertexBuffer; optional<gl::IndexBuffer<gl::Triangles>> indexBuffer; } icon; |