diff options
author | Molly Lloyd <molly@mapbox.com> | 2017-11-21 20:54:22 -0500 |
---|---|---|
committer | Molly Lloyd <molly@mapbox.com> | 2018-01-17 09:49:31 -0800 |
commit | 831d0ddc95f14a90b426c889453b26d8b9dff6cc (patch) | |
tree | 4472a05112c9802ababd03490bda2b32b337b7e0 /src/mbgl/renderer | |
parent | 1113e6710e249a996c61a69085abe83af1432d35 (diff) | |
download | qtlocation-mapboxgl-831d0ddc95f14a90b426c889453b26d8b9dff6cc.tar.gz |
add raster-dem source and hillshade layer types
Diffstat (limited to 'src/mbgl/renderer')
-rw-r--r-- | src/mbgl/renderer/buckets/hillshade_bucket.cpp | 110 | ||||
-rw-r--r-- | src/mbgl/renderer/buckets/hillshade_bucket.hpp | 48 | ||||
-rw-r--r-- | src/mbgl/renderer/layers/render_hillshade_layer.hpp | 37 | ||||
-rw-r--r-- | src/mbgl/renderer/layers/render_raster_layer.cpp | 1 | ||||
-rw-r--r-- | src/mbgl/renderer/render_layer.cpp | 3 | ||||
-rw-r--r-- | src/mbgl/renderer/render_source.cpp | 3 | ||||
-rw-r--r-- | src/mbgl/renderer/sources/render_raster_dem_source.cpp | 94 | ||||
-rw-r--r-- | src/mbgl/renderer/sources/render_raster_dem_source.hpp | 51 |
8 files changed, 347 insertions, 0 deletions
diff --git a/src/mbgl/renderer/buckets/hillshade_bucket.cpp b/src/mbgl/renderer/buckets/hillshade_bucket.cpp new file mode 100644 index 0000000000..ee92786995 --- /dev/null +++ b/src/mbgl/renderer/buckets/hillshade_bucket.cpp @@ -0,0 +1,110 @@ +#include <mbgl/renderer/buckets/hillshade_bucket.hpp> +#include <mbgl/renderer/layers/render_hillshade_layer.hpp> +#include <mbgl/programs/hillshade_program.hpp> +#include <mbgl/programs/hillshade_prepare_program.hpp> +#include <mbgl/gl/context.hpp> + +namespace mbgl { + +using namespace style; + +HillshadeBucket::HillshadeBucket(PremultipliedImage&& image_) { + pyramid.loadFromImage(image_); +} + +HillshadeBucket::HillshadeBucket(DEMPyramid&& pyramid_) : pyramid(std::move(pyramid_)) { +} + +void HillshadeBucket::upload(gl::Context& context) { + if (!hasData()) { + return; + } + + if (!pyramid.levels.empty()) { + dem = context.createTexture(pyramid.levels.front().image); + for (size_t l = 1; l < pyramid.levels.size(); l++) { + auto& image = pyramid.levels[l].image; + context.updateTexture(*dem, image); + } + } + + if (!segments.empty()) { + vertexBuffer = context.createVertexBuffer(std::move(vertices)); + indexBuffer = context.createIndexBuffer(std::move(indices)); + } + uploaded = true; +} + +void HillshadeBucket::clear() { + vertexBuffer = {}; + indexBuffer = {}; + segments.clear(); + vertices.clear(); + indices.clear(); + + uploaded = false; +} + +void HillshadeBucket::setMask(TileMask&& mask_) { + if (mask == mask_) { + return; + } + + mask = std::move(mask_); + clear(); + + if (mask == TileMask{ { 0, 0, 0 } }) { + // We want to render the full tile, and keeping the segments/vertices/indices empty means + // using the global shared buffers for covering the entire tile. + return; + } + + // Create a new segment so that we will upload (empty) buffers even when there is nothing to + // draw for this tile. + segments.emplace_back(0, 0); + + constexpr const uint16_t vertexLength = 4; + + // Create the vertex buffer for the specified tile mask. + for (const auto& id : mask) { + // Create a quad for every masked tile. + const int32_t vertexExtent = util::EXTENT >> id.z; + + const Point<int16_t> tlVertex = { static_cast<int16_t>(id.x * vertexExtent), + static_cast<int16_t>(id.y * vertexExtent) }; + const Point<int16_t> brVertex = { static_cast<int16_t>(tlVertex.x + vertexExtent), + static_cast<int16_t>(tlVertex.y + vertexExtent) }; + + if (segments.back().vertexLength + vertexLength > std::numeric_limits<uint16_t>::max()) { + // Move to a new segments because the old one can't hold the geometry. + segments.emplace_back(vertices.vertexSize(), indices.indexSize()); + } + + vertices.emplace_back( + HillshadeProgram::layoutVertex({ tlVertex.x, tlVertex.y }, { static_cast<uint16_t>(tlVertex.x), static_cast<uint16_t>(tlVertex.y) })); + vertices.emplace_back( + HillshadeProgram::layoutVertex({ brVertex.x, tlVertex.y }, { static_cast<uint16_t>(brVertex.x), static_cast<uint16_t>(tlVertex.y) })); + vertices.emplace_back( + HillshadeProgram::layoutVertex({ tlVertex.x, brVertex.y }, { static_cast<uint16_t>(tlVertex.x), static_cast<uint16_t>(brVertex.y) })); + vertices.emplace_back( + HillshadeProgram::layoutVertex({ brVertex.x, brVertex.y }, { static_cast<uint16_t>(brVertex.x), static_cast<uint16_t>(brVertex.y) })); + + auto& segment = segments.back(); + assert(segment.vertexLength <= std::numeric_limits<uint16_t>::max()); + const uint16_t offset = segment.vertexLength; + + // 0, 1, 2 + // 1, 2, 3 + indices.emplace_back(offset, offset + 1, offset + 2); + indices.emplace_back(offset + 1, offset + 2, offset + 3); + + segment.vertexLength += vertexLength; + segment.indexLength += 6; + } +} + +bool HillshadeBucket::hasData() const { + return !!pyramid.levels.empty(); +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/buckets/hillshade_bucket.hpp b/src/mbgl/renderer/buckets/hillshade_bucket.hpp new file mode 100644 index 0000000000..d19cdee86c --- /dev/null +++ b/src/mbgl/renderer/buckets/hillshade_bucket.hpp @@ -0,0 +1,48 @@ +#pragma once + +#include <mbgl/gl/index_buffer.hpp> +#include <mbgl/gl/texture.hpp> +#include <mbgl/gl/vertex_buffer.hpp> +#include <mbgl/programs/hillshade_program.hpp> +#include <mbgl/programs/hillshade_prepare_program.hpp> +#include <mbgl/renderer/bucket.hpp> +#include <mbgl/renderer/tile_mask.hpp> +#include <mbgl/geometry/dem_pyramid.hpp> +#include <mbgl/util/image.hpp> +#include <mbgl/util/mat4.hpp> +#include <mbgl/util/optional.hpp> + +namespace mbgl { + +class HillshadeBucket : public Bucket { +public: + HillshadeBucket(PremultipliedImage&&); + HillshadeBucket(std::shared_ptr<PremultipliedImage>); + HillshadeBucket(DEMPyramid&&); + + + void upload(gl::Context&) override; + bool hasData() const override; + + void clear(); + void setMask(TileMask&&); + + optional<gl::Texture> dem; + optional<gl::Texture> texture; + + TileMask mask{ { 0, 0, 0 } }; + bool prepared = false; + + + // Raster-DEM Tile Sources use the default buffers from Painter + gl::VertexVector<HillshadeLayoutVertex> vertices; + gl::IndexVector<gl::Triangles> indices; + SegmentVector<HillshadeAttributes> segments; + + optional<gl::VertexBuffer<HillshadeLayoutVertex>> vertexBuffer; + optional<gl::IndexBuffer<gl::Triangles>> indexBuffer; +private: + DEMPyramid pyramid; +}; + +} // namespace mbgl diff --git a/src/mbgl/renderer/layers/render_hillshade_layer.hpp b/src/mbgl/renderer/layers/render_hillshade_layer.hpp new file mode 100644 index 0000000000..29813a63e8 --- /dev/null +++ b/src/mbgl/renderer/layers/render_hillshade_layer.hpp @@ -0,0 +1,37 @@ +#pragma once + +#include <mbgl/renderer/render_layer.hpp> +#include <mbgl/style/layers/hillshade_layer_impl.hpp> +#include <mbgl/style/layers/hillshade_layer_properties.hpp> +#include <mbgl/tile/tile_id.hpp> + +namespace mbgl { + +class RenderHillshadeLayer: public RenderLayer { +public: + RenderHillshadeLayer(Immutable<style::HillshadeLayer::Impl>); + ~RenderHillshadeLayer() final = default; + + void transition(const TransitionParameters&) override; + void evaluate(const PropertyEvaluationParameters&) override; + bool hasTransition() const override; + + void render(PaintParameters&, RenderSource*) override; + + std::unique_ptr<Bucket> createBucket(const BucketParameters&, const std::vector<const RenderLayer*>&) const override; + + // Paint properties + style::HillshadePaintProperties::Unevaluated unevaluated; + style::HillshadePaintProperties::PossiblyEvaluated evaluated; + + const style::HillshadeLayer::Impl& impl() const; +private: + const std::array<float, 2> getLatRange(const UnwrappedTileID& id); +}; + +template <> +inline bool RenderLayer::is<RenderHillshadeLayer>() const { + return type == style::LayerType::Hillshade; +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/layers/render_raster_layer.cpp b/src/mbgl/renderer/layers/render_raster_layer.cpp index 06616d90e5..e2a9c9f25f 100644 --- a/src/mbgl/renderer/layers/render_raster_layer.cpp +++ b/src/mbgl/renderer/layers/render_raster_layer.cpp @@ -153,3 +153,4 @@ void RenderRasterLayer::render(PaintParameters& parameters, RenderSource* source } } // namespace mbgl + diff --git a/src/mbgl/renderer/render_layer.cpp b/src/mbgl/renderer/render_layer.cpp index eb2b74ffe0..248905f834 100644 --- a/src/mbgl/renderer/render_layer.cpp +++ b/src/mbgl/renderer/render_layer.cpp @@ -4,6 +4,7 @@ #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_hillshade_layer.hpp> #include <mbgl/renderer/layers/render_line_layer.hpp> #include <mbgl/renderer/layers/render_raster_layer.hpp> #include <mbgl/renderer/layers/render_symbol_layer.hpp> @@ -26,6 +27,8 @@ std::unique_ptr<RenderLayer> RenderLayer::create(Immutable<Layer::Impl> impl) { return std::make_unique<RenderSymbolLayer>(staticImmutableCast<SymbolLayer::Impl>(impl)); case LayerType::Raster: return std::make_unique<RenderRasterLayer>(staticImmutableCast<RasterLayer::Impl>(impl)); + case LayerType::Hillshade: + return std::make_unique<RenderHillshadeLayer>(staticImmutableCast<HillshadeLayer::Impl>(impl)); case LayerType::Background: return std::make_unique<RenderBackgroundLayer>(staticImmutableCast<BackgroundLayer::Impl>(impl)); case LayerType::Custom: diff --git a/src/mbgl/renderer/render_source.cpp b/src/mbgl/renderer/render_source.cpp index 6624bb7d96..f75ae5a18b 100644 --- a/src/mbgl/renderer/render_source.cpp +++ b/src/mbgl/renderer/render_source.cpp @@ -2,6 +2,7 @@ #include <mbgl/renderer/render_source_observer.hpp> #include <mbgl/renderer/sources/render_geojson_source.hpp> #include <mbgl/renderer/sources/render_raster_source.hpp> +#include <mbgl/renderer/sources/render_raster_dem_source.hpp> #include <mbgl/renderer/sources/render_vector_source.hpp> #include <mbgl/renderer/tile_parameters.hpp> #include <mbgl/annotation/render_annotation_source.hpp> @@ -19,6 +20,8 @@ std::unique_ptr<RenderSource> RenderSource::create(Immutable<Source::Impl> impl) return std::make_unique<RenderVectorSource>(staticImmutableCast<VectorSource::Impl>(impl)); case SourceType::Raster: return std::make_unique<RenderRasterSource>(staticImmutableCast<RasterSource::Impl>(impl)); + case SourceType::RasterDEM: + return std::make_unique<RenderRasterDEMSource>(staticImmutableCast<RasterDEMSource::Impl>(impl)); case SourceType::GeoJSON: return std::make_unique<RenderGeoJSONSource>(staticImmutableCast<GeoJSONSource::Impl>(impl)); case SourceType::Video: diff --git a/src/mbgl/renderer/sources/render_raster_dem_source.cpp b/src/mbgl/renderer/sources/render_raster_dem_source.cpp new file mode 100644 index 0000000000..2f88c6d5a7 --- /dev/null +++ b/src/mbgl/renderer/sources/render_raster_dem_source.cpp @@ -0,0 +1,94 @@ +#include <mbgl/renderer/sources/render_raster_dem_source.hpp> +#include <mbgl/renderer/render_tile.hpp> +#include <mbgl/tile/raster_dem_tile.hpp> +#include <mbgl/algorithm/update_tile_masks.hpp> + +namespace mbgl { + +using namespace style; + +RenderRasterDEMSource::RenderRasterDEMSource(Immutable<style::RasterDEMSource::Impl> impl_) + : RenderSource(impl_) { + tilePyramid.setObserver(this); +} + +const style::RasterDEMSource::Impl& RenderRasterDEMSource::impl() const { + return static_cast<const style::RasterDEMSource::Impl&>(*baseImpl); +} + +bool RenderRasterDEMSource::isLoaded() const { + return tilePyramid.isLoaded(); +} + +void RenderRasterDEMSource::update(Immutable<style::Source::Impl> baseImpl_, + const std::vector<Immutable<Layer::Impl>>& layers, + const bool needsRendering, + const bool needsRelayout, + const TileParameters& parameters) { + std::swap(baseImpl, baseImpl_); + + enabled = needsRendering; + + optional<Tileset> tileset = impl().getTileset(); + + if (!tileset) { + return; + } + + if (tileURLTemplates != tileset->tiles) { + tileURLTemplates = tileset->tiles; + + // TODO: this removes existing buckets, and will cause flickering. + // Should instead refresh tile data in place. + tilePyramid.tiles.clear(); + tilePyramid.renderTiles.clear(); + tilePyramid.cache.clear(); + } + + tilePyramid.update(layers, + needsRendering, + needsRelayout, + parameters, + SourceType::RasterDEM, + impl().getTileSize(), + tileset->zoomRange, + [&] (const OverscaledTileID& tileID) { + return std::make_unique<RasterDEMTile>(tileID, parameters, *tileset); + }); +} + +void RenderRasterDEMSource::startRender(PaintParameters& parameters) { + algorithm::updateTileMasks(tilePyramid.getRenderTiles()); + tilePyramid.startRender(parameters); +} + +void RenderRasterDEMSource::finishRender(PaintParameters& parameters) { + tilePyramid.finishRender(parameters); +} + +std::vector<std::reference_wrapper<RenderTile>> RenderRasterDEMSource::getRenderTiles() { + return tilePyramid.getRenderTiles(); +} + +std::unordered_map<std::string, std::vector<Feature>> +RenderRasterDEMSource::queryRenderedFeatures(const ScreenLineString&, + const TransformState&, + const std::vector<const RenderLayer*>&, + const RenderedQueryOptions&, + const CollisionIndex& ) const { + return std::unordered_map<std::string, std::vector<Feature>> {}; +} + +std::vector<Feature> RenderRasterDEMSource::querySourceFeatures(const SourceQueryOptions&) const { + return {}; +} + +void RenderRasterDEMSource::onLowMemory() { + tilePyramid.onLowMemory(); +} + +void RenderRasterDEMSource::dumpDebugLogs() const { + tilePyramid.dumpDebugLogs(); +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/sources/render_raster_dem_source.hpp b/src/mbgl/renderer/sources/render_raster_dem_source.hpp new file mode 100644 index 0000000000..ef2348fdd9 --- /dev/null +++ b/src/mbgl/renderer/sources/render_raster_dem_source.hpp @@ -0,0 +1,51 @@ +#pragma once + +#include <mbgl/renderer/render_source.hpp> +#include <mbgl/renderer/tile_pyramid.hpp> +#include <mbgl/style/sources/raster_dem_source_impl.hpp> + +namespace mbgl { + +class RenderRasterDEMSource : public RenderSource { +public: + RenderRasterDEMSource(Immutable<style::RasterDEMSource::Impl>); + + bool isLoaded() const final; + + void update(Immutable<style::Source::Impl>, + const std::vector<Immutable<style::Layer::Impl>>&, + bool needsRendering, + bool needsRelayout, + const TileParameters&) final; + + void startRender(PaintParameters&) final; + void finishRender(PaintParameters&) final; + + std::vector<std::reference_wrapper<RenderTile>> getRenderTiles() final; + + std::unordered_map<std::string, std::vector<Feature>> + queryRenderedFeatures(const ScreenLineString& geometry, + const TransformState& transformState, + const std::vector<const RenderLayer*>& layers, + const RenderedQueryOptions& options, + const CollisionIndex& collisionIndex) const final; + + std::vector<Feature> + querySourceFeatures(const SourceQueryOptions&) const final; + + void onLowMemory() final; + void dumpDebugLogs() const final; + +private: + const style::RasterDEMSource::Impl& impl() const; + + TilePyramid tilePyramid; + optional<std::vector<std::string>> tileURLTemplates; +}; + +template <> +inline bool RenderSource::is<RenderRasterDEMSource>() const { + return baseImpl->type == style::SourceType::RasterDEM; +} + +} // namespace mbgl |