summaryrefslogtreecommitdiff
path: root/src/mbgl/renderer
diff options
context:
space:
mode:
Diffstat (limited to 'src/mbgl/renderer')
-rw-r--r--src/mbgl/renderer/circle_bucket.hpp1
-rw-r--r--src/mbgl/renderer/fill_extrusion_bucket.cpp177
-rw-r--r--src/mbgl/renderer/fill_extrusion_bucket.hpp38
-rw-r--r--src/mbgl/renderer/painter.cpp78
-rw-r--r--src/mbgl/renderer/painter.hpp11
-rw-r--r--src/mbgl/renderer/painter_background.cpp4
-rw-r--r--src/mbgl/renderer/painter_clipping.cpp2
-rw-r--r--src/mbgl/renderer/painter_fill_extrusion.cpp87
-rw-r--r--src/mbgl/renderer/painter_raster.cpp2
-rw-r--r--src/mbgl/renderer/render_fill_extrusion_layer.cpp41
-rw-r--r--src/mbgl/renderer/render_fill_extrusion_layer.hpp9
-rw-r--r--src/mbgl/renderer/render_item.hpp8
-rw-r--r--src/mbgl/renderer/render_tile.cpp48
-rw-r--r--src/mbgl/renderer/render_tile.hpp14
14 files changed, 483 insertions, 37 deletions
diff --git a/src/mbgl/renderer/circle_bucket.hpp b/src/mbgl/renderer/circle_bucket.hpp
index 855565ebf4..b048fd7675 100644
--- a/src/mbgl/renderer/circle_bucket.hpp
+++ b/src/mbgl/renderer/circle_bucket.hpp
@@ -22,6 +22,7 @@ public:
bool hasData() const override;
void upload(gl::Context&) override;
+
void render(Painter&, PaintParameters&, const RenderLayer&, const RenderTile&) override;
float getQueryRadius(const RenderLayer&) const override;
diff --git a/src/mbgl/renderer/fill_extrusion_bucket.cpp b/src/mbgl/renderer/fill_extrusion_bucket.cpp
new file mode 100644
index 0000000000..2b352ab66a
--- /dev/null
+++ b/src/mbgl/renderer/fill_extrusion_bucket.cpp
@@ -0,0 +1,177 @@
+#include <mbgl/renderer/fill_extrusion_bucket.hpp>
+#include <mbgl/renderer/painter.hpp>
+#include <mbgl/programs/fill_extrusion_program.hpp>
+#include <mbgl/renderer/bucket_parameters.hpp>
+#include <mbgl/style/layers/fill_extrusion_layer_impl.hpp>
+#include <mbgl/renderer/render_fill_extrusion_layer.hpp>
+#include <mbgl/util/math.hpp>
+#include <mbgl/util/constants.hpp>
+
+#include <mapbox/earcut.hpp>
+
+#include <cassert>
+
+namespace mapbox {
+namespace util {
+template <>
+struct nth<0, mbgl::GeometryCoordinate> {
+ static int64_t get(const mbgl::GeometryCoordinate& t) {
+ return t.x;
+ };
+};
+
+template <>
+struct nth<1, mbgl::GeometryCoordinate> {
+ static int64_t get(const mbgl::GeometryCoordinate& t) {
+ return t.y;
+ };
+};
+} // namespace util
+} // namespace mapbox
+
+namespace mbgl {
+
+using namespace style;
+
+struct GeometryTooLongException : std::exception {};
+
+FillExtrusionBucket::FillExtrusionBucket(const BucketParameters& parameters, const std::vector<const RenderLayer*>& layers) {
+ 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));
+ }
+}
+
+void FillExtrusionBucket::addFeature(const GeometryTileFeature& feature,
+ const GeometryCollection& geometry) {
+ for (auto& polygon : classifyRings(geometry)) {
+ // Optimize polygons with many interior rings for earcut tesselation.
+ limitHoles(polygon, 500);
+
+ std::size_t totalVertices = 0;
+
+ for (const auto& ring : polygon) {
+ totalVertices += ring.size();
+ if (totalVertices > std::numeric_limits<uint16_t>::max())
+ throw GeometryTooLongException();
+ }
+
+ if (totalVertices == 0) continue;
+
+ std::vector<uint32_t> flatIndices;
+ flatIndices.reserve(totalVertices);
+
+ std::size_t startVertices = vertices.vertexSize();
+
+ if (triangleSegments.empty() ||
+ triangleSegments.back().vertexLength + (5 * (totalVertices - 1) + 1) >
+ std::numeric_limits<uint16_t>::max()) {
+ triangleSegments.emplace_back(startVertices, triangles.indexSize());
+ }
+
+ auto& triangleSegment = triangleSegments.back();
+ assert(triangleSegment.vertexLength <= std::numeric_limits<uint16_t>::max());
+ uint16_t triangleIndex = triangleSegment.vertexLength;
+
+ assert(triangleIndex + (5 * (totalVertices - 1) + 1) <=
+ std::numeric_limits<uint16_t>::max());
+
+ for (const auto& ring : polygon) {
+ std::size_t nVertices = ring.size();
+
+ if (nVertices == 0)
+ continue;
+
+ auto edgeDistance = 0;
+
+ for (uint32_t i = 0; i < nVertices; i++) {
+ const auto& p1 = ring[i];
+
+ vertices.emplace_back(
+ FillExtrusionProgram::layoutVertex(p1, 0, 0, 1, 1, edgeDistance));
+ flatIndices.emplace_back(triangleIndex);
+ triangleIndex++;
+
+ if (i != 0) {
+ const auto& p2 = ring[i - 1];
+
+ const auto d1 = convertPoint<double>(p1);
+ const auto d2 = convertPoint<double>(p2);
+
+ const Point<double> perp = util::unit(util::perp(d1 - d2));
+
+ vertices.emplace_back(
+ FillExtrusionProgram::layoutVertex(p1, perp.x, perp.y, 0, 0, edgeDistance));
+ vertices.emplace_back(
+ FillExtrusionProgram::layoutVertex(p1, perp.x, perp.y, 0, 1, edgeDistance));
+
+ edgeDistance += util::dist<int16_t>(d1, d2);
+
+ vertices.emplace_back(
+ FillExtrusionProgram::layoutVertex(p2, perp.x, perp.y, 0, 0, edgeDistance));
+ vertices.emplace_back(
+ FillExtrusionProgram::layoutVertex(p2, perp.x, perp.y, 0, 1, edgeDistance));
+
+ triangles.emplace_back(triangleIndex, triangleIndex + 1, triangleIndex + 2);
+ triangles.emplace_back(triangleIndex + 1, triangleIndex + 2, triangleIndex + 3);
+ triangleIndex += 4;
+ triangleSegment.vertexLength += 4;
+ triangleSegment.indexLength += 6;
+ }
+ }
+ }
+
+ std::vector<uint32_t> indices = mapbox::earcut(polygon);
+
+ std::size_t nIndices = indices.size();
+ assert(nIndices % 3 == 0);
+
+ for (uint32_t i = 0; i < nIndices; i += 3) {
+ triangles.emplace_back(flatIndices[indices[i]], flatIndices[indices[i + 1]],
+ flatIndices[indices[i + 2]]);
+ }
+
+ triangleSegment.vertexLength += totalVertices;
+ triangleSegment.indexLength += nIndices;
+ }
+
+ for (auto& pair : paintPropertyBinders) {
+ pair.second.populateVertexVectors(feature, vertices.vertexSize());
+ }
+}
+
+void FillExtrusionBucket::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 FillExtrusionBucket::render(Painter& painter,
+ PaintParameters& parameters,
+ const RenderLayer& layer,
+ const RenderTile& tile) {
+ painter.renderFillExtrusion(parameters, *this, *layer.as<RenderFillExtrusionLayer>(), tile);
+}
+
+bool FillExtrusionBucket::hasData() const {
+ return !triangleSegments.empty();
+}
+
+float FillExtrusionBucket::getQueryRadius(const RenderLayer& layer) const {
+ if (!layer.is<RenderFillExtrusionLayer>()) {
+ return 0;
+ }
+
+ const std::array<float, 2>& translate = layer.as<RenderFillExtrusionLayer>()->evaluated.get<FillExtrusionTranslate>();
+ return util::length(translate[0], translate[1]);
+}
+
+} // namespace mbgl
diff --git a/src/mbgl/renderer/fill_extrusion_bucket.hpp b/src/mbgl/renderer/fill_extrusion_bucket.hpp
new file mode 100644
index 0000000000..c54805d743
--- /dev/null
+++ b/src/mbgl/renderer/fill_extrusion_bucket.hpp
@@ -0,0 +1,38 @@
+#pragma once
+
+#include <mbgl/renderer/bucket.hpp>
+#include <mbgl/tile/geometry_tile_data.hpp>
+#include <mbgl/gl/vertex_buffer.hpp>
+#include <mbgl/gl/index_buffer.hpp>
+#include <mbgl/gl/segment.hpp>
+#include <mbgl/programs/fill_extrusion_program.hpp>
+#include <mbgl/style/layers/fill_extrusion_layer_properties.hpp>
+
+namespace mbgl {
+
+class BucketParameters;
+
+class FillExtrusionBucket : public Bucket {
+public:
+ FillExtrusionBucket(const BucketParameters&, const std::vector<const RenderLayer*>&);
+
+ void addFeature(const GeometryTileFeature&,
+ const GeometryCollection&) override;
+ bool hasData() const override;
+
+ void upload(gl::Context&) override;
+ void render(Painter&, PaintParameters&, const RenderLayer&, const RenderTile&) override;
+
+ float getQueryRadius(const RenderLayer&) const override;
+
+ gl::VertexVector<FillExtrusionLayoutVertex> vertices;
+ gl::IndexVector<gl::Triangles> triangles;
+ gl::SegmentVector<FillExtrusionAttributes> triangleSegments;
+
+ optional<gl::VertexBuffer<FillExtrusionLayoutVertex>> vertexBuffer;
+ optional<gl::IndexBuffer<gl::Triangles>> indexBuffer;
+
+ std::unordered_map<std::string, FillExtrusionProgram::PaintPropertyBinders> paintPropertyBinders;
+};
+
+} // namespace mbgl
diff --git a/src/mbgl/renderer/painter.cpp b/src/mbgl/renderer/painter.cpp
index 0c4915d3e9..36dd4a793f 100644
--- a/src/mbgl/renderer/painter.cpp
+++ b/src/mbgl/renderer/painter.cpp
@@ -16,6 +16,7 @@
#include <mbgl/renderer/render_background_layer.hpp>
#include <mbgl/renderer/render_custom_layer.hpp>
#include <mbgl/style/layers/custom_layer_impl.hpp>
+#include <mbgl/renderer/render_fill_extrusion_layer.hpp>
#include <mbgl/sprite/sprite_atlas.hpp>
#include <mbgl/geometry/line_atlas.hpp>
@@ -53,7 +54,7 @@ static gl::VertexVector<FillLayoutVertex> tileVertices() {
return result;
}
-static gl::IndexVector<gl::Triangles> tileTriangleIndices() {
+static gl::IndexVector<gl::Triangles> quadTriangleIndices() {
gl::IndexVector<gl::Triangles> result;
result.emplace_back(0, 1, 2);
result.emplace_back(1, 2, 3);
@@ -79,6 +80,16 @@ static gl::VertexVector<RasterLayoutVertex> rasterVertices() {
return result;
}
+static gl::VertexVector<ExtrusionTextureLayoutVertex> extrusionTextureVertices() {
+ gl::VertexVector<ExtrusionTextureLayoutVertex> result;
+ result.emplace_back(ExtrusionTextureProgram::layoutVertex({ 0, 0 }));
+ result.emplace_back(ExtrusionTextureProgram::layoutVertex({ 1, 0 }));
+ result.emplace_back(ExtrusionTextureProgram::layoutVertex({ 0, 1 }));
+ result.emplace_back(ExtrusionTextureProgram::layoutVertex({ 1, 1 }));
+ return result;
+}
+
+
Painter::Painter(gl::Context& context_,
const TransformState& state_,
float pixelRatio,
@@ -87,12 +98,14 @@ Painter::Painter(gl::Context& context_,
state(state_),
tileVertexBuffer(context.createVertexBuffer(tileVertices())),
rasterVertexBuffer(context.createVertexBuffer(rasterVertices())),
- tileTriangleIndexBuffer(context.createIndexBuffer(tileTriangleIndices())),
+ extrusionTextureVertexBuffer(context.createVertexBuffer(extrusionTextureVertices())),
+ quadTriangleIndexBuffer(context.createIndexBuffer(quadTriangleIndices())),
tileBorderIndexBuffer(context.createIndexBuffer(tileLineStripIndices())) {
tileTriangleSegments.emplace_back(0, 0, 4, 6);
tileBorderSegments.emplace_back(0, 0, 4, 5);
rasterSegments.emplace_back(0, 0, 4, 6);
+ extrusionTextureSegments.emplace_back(0, 0, 4, 6);
programs = std::make_unique<Programs>(context,
ProgramParameters{ pixelRatio, false, programCacheDir });
@@ -131,12 +144,18 @@ void Painter::render(const Style& style, const FrameData& frame_, View& view, Sp
spriteAtlas = style.spriteAtlas.get();
lineAtlas = style.lineAtlas.get();
+ evaluatedLight = style.evaluatedLight;
+
RenderData renderData = style.getRenderData(frame.debugOptions, state.getAngle());
const std::vector<RenderItem>& order = renderData.order;
const std::unordered_set<Source*>& sources = renderData.sources;
// Update the default matrices to the current viewport dimensions.
state.getProjMatrix(projMatrix);
+ // Calculate a second projection matrix with the near plane clipped to 100 so as
+ // not to waste lots of depth buffer precision on very close empty space, for layer
+ // types (fill-extrusion) that use the depth buffer to emulate real-world space.
+ state.getProjMatrix(nearClippedProjMatrix, 100);
pixelsToGLUnits = {{ 2.0f / state.getSize().width, -2.0f / state.getSize().height }};
if (state.getViewportMode() == ViewportMode::FlippedY) {
@@ -160,8 +179,11 @@ void Painter::render(const Style& style, const FrameData& frame_, View& view, Sp
annotationSpriteAtlas.upload(context, 0);
for (const auto& item : order) {
- if (item.bucket && item.bucket->needsUpload()) {
- item.bucket->upload(context);
+ for (const auto& tileRef : item.tiles) {
+ const auto& bucket = tileRef.get().tile.getBucket(item.layer);
+ if (bucket && bucket->needsUpload()) {
+ bucket->upload(context);
+ }
}
}
}
@@ -187,7 +209,7 @@ void Painter::render(const Style& style, const FrameData& frame_, View& view, Sp
// Update all clipping IDs.
algorithm::ClipIDGenerator generator;
for (const auto& source : sources) {
- source->baseImpl->startRender(generator, projMatrix, state);
+ source->baseImpl->startRender(generator, projMatrix, nearClippedProjMatrix, state);
}
MBGL_DEBUG_GROUP(context, "clipping masks");
@@ -208,7 +230,6 @@ void Painter::render(const Style& style, const FrameData& frame_, View& view, Sp
// Actually render the layers
if (debug::renderTree) { Log::Info(Event::Render, "{"); indent++; }
- // TODO: Correctly compute the number of layers recursively beforehand.
depthRangeSize = 1 - (order.size() + 2) * numSublayers * depthEpsilon;
// - OPAQUE PASS -------------------------------------------------------------------------------
@@ -302,9 +323,50 @@ void Painter::renderPass(PaintParameters& parameters,
// the viewport or Framebuffer.
parameters.view.bind();
context.setDirtyState();
+ } else if (layer.is<RenderFillExtrusionLayer>()) {
+ const auto size = context.viewport.getCurrentValue().size;
+
+ OffscreenTexture texture(context, size);
+ texture.bindRenderbuffers(1);
+
+ context.setStencilMode(gl::StencilMode::disabled());
+ context.setDepthMode(depthModeForSublayer(0, gl::DepthMode::ReadWrite));
+ context.clear(Color{ 0.0f, 0.0f, 0.0f, 0.0f }, 1.0f, {});
+
+ for (auto& tileRef : item.tiles) {
+ auto& tile = tileRef.get();
+
+ MBGL_DEBUG_GROUP(context, layer.baseImpl.id + " - " + util::toString(tile.id));
+ auto bucket = tile.tile.getBucket(layer);
+ bucket->render(*this, parameters, layer, tile);
+ }
+
+ parameters.view.bind();
+
+ mat4 viewportMat;
+ matrix::ortho(viewportMat, 0, size.width, size.height, 0, 0, 1);
+
+ const PaintProperties<>::Evaluated properties{};
+
+ parameters.programs.extrusionTexture.draw(
+ context, gl::Triangles(), gl::DepthMode::disabled(), gl::StencilMode::disabled(),
+ colorModeForRenderPass(),
+ ExtrusionTextureProgram::UniformValues{
+ uniforms::u_matrix::Value{ viewportMat }, uniforms::u_world::Value{ size },
+ uniforms::u_image::Value{ 1 },
+ uniforms::u_opacity::Value{
+ layer.as<RenderFillExtrusionLayer>()->evaluated.get<FillExtrusionOpacity>() } },
+ extrusionTextureVertexBuffer, quadTriangleIndexBuffer,
+ extrusionTextureSegments,
+ ExtrusionTextureProgram::PaintPropertyBinders{ properties, 0 }, properties,
+ state.getZoom());
} else {
- MBGL_DEBUG_GROUP(context, layer.baseImpl.id + " - " + util::toString(item.tile->id));
- item.bucket->render(*this, parameters, layer, *item.tile);
+ for (auto& tileRef : item.tiles) {
+ auto& tile = tileRef.get();
+ MBGL_DEBUG_GROUP(context, layer.baseImpl.id + " - " + util::toString(tile.id));
+ auto bucket = tile.tile.getBucket(layer);
+ bucket->render(*this, parameters, layer, tile);
+ }
}
}
diff --git a/src/mbgl/renderer/painter.hpp b/src/mbgl/renderer/painter.hpp
index 9c6dd4505f..7706d2d451 100644
--- a/src/mbgl/renderer/painter.hpp
+++ b/src/mbgl/renderer/painter.hpp
@@ -12,6 +12,7 @@
#include <mbgl/programs/debug_program.hpp>
#include <mbgl/programs/program_parameters.hpp>
#include <mbgl/programs/fill_program.hpp>
+#include <mbgl/programs/extrusion_texture_program.hpp>
#include <mbgl/programs/raster_program.hpp>
#include <mbgl/style/style.hpp>
@@ -37,12 +38,14 @@ class Tile;
class DebugBucket;
class FillBucket;
+class FillExtrusionBucket;
class LineBucket;
class CircleBucket;
class SymbolBucket;
class RasterBucket;
class RenderFillLayer;
+class RenderFillExtrusionLayer;
class RenderLineLayer;
class RenderCircleLayer;
class RenderSymbolLayer;
@@ -82,6 +85,7 @@ public:
void renderClippingMask(const UnwrappedTileID&, const ClipID&);
void renderTileDebug(const RenderTile&);
void renderFill(PaintParameters&, FillBucket&, const RenderFillLayer&, const RenderTile&);
+ void renderFillExtrusion(PaintParameters&, FillExtrusionBucket&, const RenderFillExtrusionLayer&, const RenderTile&);
void renderLine(PaintParameters&, LineBucket&, const RenderLineLayer&, const RenderTile&);
void renderCircle(PaintParameters&, CircleBucket&, const RenderCircleLayer&, const RenderTile&);
void renderSymbol(PaintParameters&, SymbolBucket&, const RenderSymbolLayer&, const RenderTile&);
@@ -126,6 +130,7 @@ private:
gl::Context& context;
mat4 projMatrix;
+ mat4 nearClippedProjMatrix;
std::array<float, 2> pixelsToGLUnits;
@@ -152,6 +157,8 @@ private:
GlyphAtlas* glyphAtlas = nullptr;
LineAtlas* lineAtlas = nullptr;
+ style::EvaluatedLight evaluatedLight;
+
FrameHistory frameHistory;
std::unique_ptr<Programs> programs;
@@ -161,13 +168,15 @@ private:
gl::VertexBuffer<FillLayoutVertex> tileVertexBuffer;
gl::VertexBuffer<RasterLayoutVertex> rasterVertexBuffer;
+ gl::VertexBuffer<ExtrusionTextureLayoutVertex> extrusionTextureVertexBuffer;
- gl::IndexBuffer<gl::Triangles> tileTriangleIndexBuffer;
+ gl::IndexBuffer<gl::Triangles> quadTriangleIndexBuffer;
gl::IndexBuffer<gl::LineStrip> tileBorderIndexBuffer;
gl::SegmentVector<FillAttributes> tileTriangleSegments;
gl::SegmentVector<DebugAttributes> tileBorderSegments;
gl::SegmentVector<RasterAttributes> rasterSegments;
+ gl::SegmentVector<ExtrusionTextureAttributes> extrusionTextureSegments;
};
} // namespace mbgl
diff --git a/src/mbgl/renderer/painter_background.cpp b/src/mbgl/renderer/painter_background.cpp
index ac16627246..7cd9cbac5f 100644
--- a/src/mbgl/renderer/painter_background.cpp
+++ b/src/mbgl/renderer/painter_background.cpp
@@ -49,7 +49,7 @@ void Painter::renderBackground(PaintParameters& parameters, const RenderBackgrou
state
),
tileVertexBuffer,
- tileTriangleIndexBuffer,
+ quadTriangleIndexBuffer,
tileTriangleSegments,
paintAttibuteData,
properties,
@@ -69,7 +69,7 @@ void Painter::renderBackground(PaintParameters& parameters, const RenderBackgrou
uniforms::u_world::Value{ context.viewport.getCurrentValue().size },
},
tileVertexBuffer,
- tileTriangleIndexBuffer,
+ quadTriangleIndexBuffer,
tileTriangleSegments,
paintAttibuteData,
properties,
diff --git a/src/mbgl/renderer/painter_clipping.cpp b/src/mbgl/renderer/painter_clipping.cpp
index 70df9837e8..0d3b5f1504 100644
--- a/src/mbgl/renderer/painter_clipping.cpp
+++ b/src/mbgl/renderer/painter_clipping.cpp
@@ -26,7 +26,7 @@ void Painter::renderClippingMask(const UnwrappedTileID& tileID, const ClipID& cl
uniforms::u_world::Value{ context.viewport.getCurrentValue().size },
},
tileVertexBuffer,
- tileTriangleIndexBuffer,
+ quadTriangleIndexBuffer,
tileTriangleSegments,
paintAttibuteData,
properties,
diff --git a/src/mbgl/renderer/painter_fill_extrusion.cpp b/src/mbgl/renderer/painter_fill_extrusion.cpp
new file mode 100644
index 0000000000..af98cae569
--- /dev/null
+++ b/src/mbgl/renderer/painter_fill_extrusion.cpp
@@ -0,0 +1,87 @@
+#include <mbgl/renderer/painter.hpp>
+#include <mbgl/renderer/paint_parameters.hpp>
+#include <mbgl/renderer/fill_extrusion_bucket.hpp>
+#include <mbgl/renderer/render_tile.hpp>
+#include <mbgl/renderer/render_fill_extrusion_layer.hpp>
+#include <mbgl/style/layers/fill_extrusion_layer_impl.hpp>
+#include <mbgl/sprite/sprite_atlas.hpp>
+#include <mbgl/programs/programs.hpp>
+#include <mbgl/programs/fill_extrusion_program.hpp>
+#include <mbgl/util/constants.hpp>
+#include <mbgl/util/convert.hpp>
+
+namespace mbgl {
+
+using namespace style;
+
+void Painter::renderFillExtrusion(PaintParameters& parameters,
+ FillExtrusionBucket& bucket,
+ const RenderFillExtrusionLayer& layer,
+ const RenderTile& tile) {
+ const FillExtrusionPaintProperties::Evaluated& properties = layer.evaluated;
+
+ if (pass == RenderPass::Opaque) {
+ return;
+ }
+
+ if (!properties.get<FillExtrusionPattern>().from.empty()) {
+ optional<SpriteAtlasElement> imagePosA =
+ spriteAtlas->getPattern(properties.get<FillExtrusionPattern>().from);
+ optional<SpriteAtlasElement> imagePosB =
+ spriteAtlas->getPattern(properties.get<FillExtrusionPattern>().to);
+
+ if (!imagePosA || !imagePosB) {
+ return;
+ }
+
+ spriteAtlas->bind(true, context, 0);
+
+ parameters.programs.fillExtrusionPattern.draw(
+ context,
+ gl::Triangles(),
+ depthModeForSublayer(0, gl::DepthMode::ReadWrite),
+ gl::StencilMode::disabled(),
+ colorModeForRenderPass(),
+ FillExtrusionPatternUniforms::values(
+ tile.translatedClipMatrix(properties.get<FillExtrusionTranslate>(),
+ properties.get<FillExtrusionTranslateAnchor>(),
+ state),
+ *imagePosA,
+ *imagePosB,
+ properties.get<FillExtrusionPattern>(),
+ tile.id,
+ state,
+ -std::pow(2, tile.id.canonical.z) / util::tileSize / 8.0f,
+ evaluatedLight
+ ),
+ *bucket.vertexBuffer,
+ *bucket.indexBuffer,
+ bucket.triangleSegments,
+ bucket.paintPropertyBinders.at(layer.getID()),
+ properties,
+ state.getZoom());
+
+ } else {
+ parameters.programs.fillExtrusion.draw(
+ context,
+ gl::Triangles(),
+ depthModeForSublayer(0, gl::DepthMode::ReadWrite),
+ gl::StencilMode::disabled(),
+ colorModeForRenderPass(),
+ FillExtrusionUniforms::values(
+ tile.translatedClipMatrix(properties.get<FillExtrusionTranslate>(),
+ properties.get<FillExtrusionTranslateAnchor>(),
+ state),
+ state,
+ evaluatedLight
+ ),
+ *bucket.vertexBuffer,
+ *bucket.indexBuffer,
+ bucket.triangleSegments,
+ bucket.paintPropertyBinders.at(layer.getID()),
+ properties,
+ state.getZoom());
+ };
+}
+
+} // namespace mbgl
diff --git a/src/mbgl/renderer/painter_raster.cpp b/src/mbgl/renderer/painter_raster.cpp
index 31f10ed3ba..fbe025b5b0 100644
--- a/src/mbgl/renderer/painter_raster.cpp
+++ b/src/mbgl/renderer/painter_raster.cpp
@@ -77,7 +77,7 @@ void Painter::renderRaster(PaintParameters& parameters,
uniforms::u_tl_parent::Value{ std::array<float, 2> {{ 0.0f, 0.0f }} },
},
rasterVertexBuffer,
- tileTriangleIndexBuffer,
+ quadTriangleIndexBuffer,
rasterSegments,
paintAttributeData,
properties,
diff --git a/src/mbgl/renderer/render_fill_extrusion_layer.cpp b/src/mbgl/renderer/render_fill_extrusion_layer.cpp
index a378f12cf0..8df0d36900 100644
--- a/src/mbgl/renderer/render_fill_extrusion_layer.cpp
+++ b/src/mbgl/renderer/render_fill_extrusion_layer.cpp
@@ -1,26 +1,53 @@
#include <mbgl/renderer/render_fill_extrusion_layer.hpp>
-#include <mbgl/renderer/bucket.hpp>
+#include <mbgl/renderer/fill_extrusion_bucket.hpp>
#include <mbgl/style/layers/fill_extrusion_layer_impl.hpp>
+#include <mbgl/geometry/feature_index.hpp>
+#include <mbgl/util/math.hpp>
+#include <mbgl/util/intersection_tests.hpp>
namespace mbgl {
RenderFillExtrusionLayer::RenderFillExtrusionLayer(const style::FillExtrusionLayer::Impl& _impl)
- : RenderLayer(style::LayerType::FillExtrusion, _impl) {
+ : RenderLayer(style::LayerType::FillExtrusion, _impl),
+ impl(&_impl) {
}
std::unique_ptr<RenderLayer> RenderFillExtrusionLayer::clone() const {
return std::make_unique<RenderFillExtrusionLayer>(*this);
}
-std::unique_ptr<Bucket> RenderFillExtrusionLayer::createBucket(const BucketParameters&, const std::vector<const RenderLayer*>&) const {
- return nullptr;
+std::unique_ptr<Bucket> RenderFillExtrusionLayer::createBucket(const BucketParameters& parameters, const std::vector<const RenderLayer*>& layers) const {
+ return std::make_unique<FillExtrusionBucket>(parameters, layers);
}
-void RenderFillExtrusionLayer::cascade(const style::CascadeParameters&) {
+void RenderFillExtrusionLayer::cascade(const style::CascadeParameters& parameters) {
+ unevaluated = impl->cascading.cascade(parameters, std::move(unevaluated));
}
-bool RenderFillExtrusionLayer::evaluate(const style::PropertyEvaluationParameters&) {
- return false;
+bool RenderFillExtrusionLayer::evaluate(const style::PropertyEvaluationParameters& parameters) {
+ evaluated = unevaluated.evaluate(parameters);
+
+ passes = (evaluated.get<style::FillExtrusionOpacity>() > 0) ? RenderPass::Translucent
+ : RenderPass::None;
+
+ return unevaluated.hasTransition();
+}
+
+bool RenderFillExtrusionLayer::queryIntersectsFeature(
+ const GeometryCoordinates& queryGeometry,
+ const GeometryTileFeature& feature,
+ const float,
+ const float bearing,
+ const float pixelsToTileUnits) const {
+
+ auto translatedQueryGeometry = FeatureIndex::translateQueryGeometry(
+ queryGeometry,
+ evaluated.get<style::FillExtrusionTranslate>(),
+ evaluated.get<style::FillExtrusionTranslateAnchor>(),
+ bearing,
+ pixelsToTileUnits);
+
+ return util::polygonIntersectsMultiPolygon(translatedQueryGeometry.value_or(queryGeometry), feature.getGeometries());
}
} // namespace mbgl
diff --git a/src/mbgl/renderer/render_fill_extrusion_layer.hpp b/src/mbgl/renderer/render_fill_extrusion_layer.hpp
index 596ba02fee..87b6ad6071 100644
--- a/src/mbgl/renderer/render_fill_extrusion_layer.hpp
+++ b/src/mbgl/renderer/render_fill_extrusion_layer.hpp
@@ -17,11 +17,20 @@ public:
void cascade(const style::CascadeParameters&) override;
bool evaluate(const style::PropertyEvaluationParameters&) override;
+ bool queryIntersectsFeature(
+ const GeometryCoordinates&,
+ const GeometryTileFeature&,
+ const float,
+ const float,
+ const float) const override;
+
std::unique_ptr<Bucket> createBucket(const BucketParameters&, const std::vector<const RenderLayer*>&) const override;
// Paint properties
style::FillExtrusionPaintProperties::Unevaluated unevaluated;
style::FillExtrusionPaintProperties::Evaluated evaluated;
+
+ const style::FillExtrusionLayer::Impl* const impl;
};
template <>
diff --git a/src/mbgl/renderer/render_item.hpp b/src/mbgl/renderer/render_item.hpp
index 575287d9c6..01bb263d1e 100644
--- a/src/mbgl/renderer/render_item.hpp
+++ b/src/mbgl/renderer/render_item.hpp
@@ -18,14 +18,12 @@ class Source;
class RenderItem {
public:
RenderItem(const RenderLayer& layer_,
- const RenderTile* tile_ = nullptr,
- Bucket* bucket_ = nullptr)
- : tile(tile_), bucket(bucket_), layer(layer_) {
+ std::vector<std::reference_wrapper<RenderTile>> tiles_ = {})
+ : layer(layer_), tiles(std::move(tiles_)) {
}
- const RenderTile* const tile;
- Bucket* const bucket;
const RenderLayer& layer;
+ std::vector<std::reference_wrapper<RenderTile>> tiles;
};
class RenderData {
diff --git a/src/mbgl/renderer/render_tile.cpp b/src/mbgl/renderer/render_tile.cpp
index 5c7c491be0..ce59186e61 100644
--- a/src/mbgl/renderer/render_tile.cpp
+++ b/src/mbgl/renderer/render_tile.cpp
@@ -5,11 +5,12 @@ namespace mbgl {
using namespace style;
-mat4 RenderTile::translatedMatrix(const std::array<float, 2>& translation,
- TranslateAnchorType anchor,
- const TransformState& state) const {
+mat4 RenderTile::translateVtxMatrix(const mat4& tileMatrix,
+ const std::array<float, 2>& translation,
+ TranslateAnchorType anchor,
+ const TransformState& state) const {
if (translation[0] == 0 && translation[1] == 0) {
- return matrix;
+ return tileMatrix;
}
mat4 vtxMatrix;
@@ -17,18 +18,41 @@ mat4 RenderTile::translatedMatrix(const std::array<float, 2>& translation,
if (anchor == TranslateAnchorType::Viewport) {
const double sin_a = std::sin(-state.getAngle());
const double cos_a = std::cos(-state.getAngle());
- matrix::translate(vtxMatrix, matrix,
- id.pixelsToTileUnits(translation[0] * cos_a - translation[1] * sin_a, state.getZoom()),
- id.pixelsToTileUnits(translation[0] * sin_a + translation[1] * cos_a, state.getZoom()),
- 0);
+ matrix::translate(vtxMatrix, tileMatrix,
+ id.pixelsToTileUnits(translation[0] * cos_a - translation[1] * sin_a, state.getZoom()),
+ id.pixelsToTileUnits(translation[0] * sin_a + translation[1] * cos_a, state.getZoom()),
+ 0);
} else {
- matrix::translate(vtxMatrix, matrix,
- id.pixelsToTileUnits(translation[0], state.getZoom()),
- id.pixelsToTileUnits(translation[1], state.getZoom()),
- 0);
+ matrix::translate(vtxMatrix, tileMatrix,
+ id.pixelsToTileUnits(translation[0], state.getZoom()),
+ id.pixelsToTileUnits(translation[1], state.getZoom()),
+ 0);
}
return vtxMatrix;
}
+mat4 RenderTile::translatedMatrix(const std::array<float, 2>& translation,
+ TranslateAnchorType anchor,
+ const TransformState& state) const {
+ return translateVtxMatrix(matrix, translation, anchor, state);
+}
+
+mat4 RenderTile::translatedClipMatrix(const std::array<float, 2>& translation,
+ TranslateAnchorType anchor,
+ const TransformState& state) const {
+ return translateVtxMatrix(nearClippedMatrix, translation, anchor, state);
+}
+
+void RenderTile::calculateMatrices(const mat4& projMatrix,
+ const mat4& projClipMatrix,
+ const TransformState& transform) {
+ // Calculate two matrices for this tile: matrix is the standard tile matrix; nearClippedMatrix
+ // clips the near plane to 100 to save depth buffer precision
+ transform.matrixFor(matrix, id);
+ transform.matrixFor(nearClippedMatrix, id);
+ matrix::multiply(matrix, projMatrix, matrix);
+ matrix::multiply(nearClippedMatrix, projClipMatrix, nearClippedMatrix);
+}
+
} // namespace mbgl
diff --git a/src/mbgl/renderer/render_tile.hpp b/src/mbgl/renderer/render_tile.hpp
index e2e0c3d656..02e8667eec 100644
--- a/src/mbgl/renderer/render_tile.hpp
+++ b/src/mbgl/renderer/render_tile.hpp
@@ -24,11 +24,25 @@ public:
Tile& tile;
ClipID clip;
mat4 matrix;
+ mat4 nearClippedMatrix;
bool used = false;
mat4 translatedMatrix(const std::array<float, 2>& translate,
style::TranslateAnchorType anchor,
const TransformState&) const;
+
+ mat4 translatedClipMatrix(const std::array<float, 2>& translate,
+ style::TranslateAnchorType anchor,
+ const TransformState&) const;
+
+ void calculateMatrices(const mat4& projMatrix,
+ const mat4& projClipMatrix,
+ const TransformState&);
+private:
+ mat4 translateVtxMatrix(const mat4& tileMatrix,
+ const std::array<float, 2>& translation,
+ style::TranslateAnchorType anchor,
+ const TransformState& state) const;
};
} // namespace mbgl