From 831d0ddc95f14a90b426c889453b26d8b9dff6cc Mon Sep 17 00:00:00 2001 From: Molly Lloyd Date: Tue, 21 Nov 2017 20:54:22 -0500 Subject: add raster-dem source and hillshade layer types --- src/mbgl/renderer/buckets/hillshade_bucket.cpp | 110 +++++++++++++++++++++ src/mbgl/renderer/buckets/hillshade_bucket.hpp | 48 +++++++++ .../renderer/layers/render_hillshade_layer.hpp | 37 +++++++ src/mbgl/renderer/layers/render_raster_layer.cpp | 1 + src/mbgl/renderer/render_layer.cpp | 3 + src/mbgl/renderer/render_source.cpp | 3 + .../renderer/sources/render_raster_dem_source.cpp | 94 ++++++++++++++++++ .../renderer/sources/render_raster_dem_source.hpp | 51 ++++++++++ 8 files changed, 347 insertions(+) create mode 100644 src/mbgl/renderer/buckets/hillshade_bucket.cpp create mode 100644 src/mbgl/renderer/buckets/hillshade_bucket.hpp create mode 100644 src/mbgl/renderer/layers/render_hillshade_layer.hpp create mode 100644 src/mbgl/renderer/sources/render_raster_dem_source.cpp create mode 100644 src/mbgl/renderer/sources/render_raster_dem_source.hpp (limited to 'src/mbgl/renderer') 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 +#include +#include +#include +#include + +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 tlVertex = { static_cast(id.x * vertexExtent), + static_cast(id.y * vertexExtent) }; + const Point brVertex = { static_cast(tlVertex.x + vertexExtent), + static_cast(tlVertex.y + vertexExtent) }; + + if (segments.back().vertexLength + vertexLength > std::numeric_limits::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(tlVertex.x), static_cast(tlVertex.y) })); + vertices.emplace_back( + HillshadeProgram::layoutVertex({ brVertex.x, tlVertex.y }, { static_cast(brVertex.x), static_cast(tlVertex.y) })); + vertices.emplace_back( + HillshadeProgram::layoutVertex({ tlVertex.x, brVertex.y }, { static_cast(tlVertex.x), static_cast(brVertex.y) })); + vertices.emplace_back( + HillshadeProgram::layoutVertex({ brVertex.x, brVertex.y }, { static_cast(brVertex.x), static_cast(brVertex.y) })); + + auto& segment = segments.back(); + assert(segment.vertexLength <= std::numeric_limits::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace mbgl { + +class HillshadeBucket : public Bucket { +public: + HillshadeBucket(PremultipliedImage&&); + HillshadeBucket(std::shared_ptr); + HillshadeBucket(DEMPyramid&&); + + + void upload(gl::Context&) override; + bool hasData() const override; + + void clear(); + void setMask(TileMask&&); + + optional dem; + optional texture; + + TileMask mask{ { 0, 0, 0 } }; + bool prepared = false; + + + // Raster-DEM Tile Sources use the default buffers from Painter + gl::VertexVector vertices; + gl::IndexVector indices; + SegmentVector segments; + + optional> vertexBuffer; + optional> 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 +#include +#include +#include + +namespace mbgl { + +class RenderHillshadeLayer: public RenderLayer { +public: + RenderHillshadeLayer(Immutable); + ~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 createBucket(const BucketParameters&, const std::vector&) const override; + + // Paint properties + style::HillshadePaintProperties::Unevaluated unevaluated; + style::HillshadePaintProperties::PossiblyEvaluated evaluated; + + const style::HillshadeLayer::Impl& impl() const; +private: + const std::array getLatRange(const UnwrappedTileID& id); +}; + +template <> +inline bool RenderLayer::is() 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 #include #include +#include #include #include #include @@ -26,6 +27,8 @@ std::unique_ptr RenderLayer::create(Immutable impl) { return std::make_unique(staticImmutableCast(impl)); case LayerType::Raster: return std::make_unique(staticImmutableCast(impl)); + case LayerType::Hillshade: + return std::make_unique(staticImmutableCast(impl)); case LayerType::Background: return std::make_unique(staticImmutableCast(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 #include #include +#include #include #include #include @@ -19,6 +20,8 @@ std::unique_ptr RenderSource::create(Immutable impl) return std::make_unique(staticImmutableCast(impl)); case SourceType::Raster: return std::make_unique(staticImmutableCast(impl)); + case SourceType::RasterDEM: + return std::make_unique(staticImmutableCast(impl)); case SourceType::GeoJSON: return std::make_unique(staticImmutableCast(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 +#include +#include +#include + +namespace mbgl { + +using namespace style; + +RenderRasterDEMSource::RenderRasterDEMSource(Immutable impl_) + : RenderSource(impl_) { + tilePyramid.setObserver(this); +} + +const style::RasterDEMSource::Impl& RenderRasterDEMSource::impl() const { + return static_cast(*baseImpl); +} + +bool RenderRasterDEMSource::isLoaded() const { + return tilePyramid.isLoaded(); +} + +void RenderRasterDEMSource::update(Immutable baseImpl_, + const std::vector>& layers, + const bool needsRendering, + const bool needsRelayout, + const TileParameters& parameters) { + std::swap(baseImpl, baseImpl_); + + enabled = needsRendering; + + optional 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(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> RenderRasterDEMSource::getRenderTiles() { + return tilePyramid.getRenderTiles(); +} + +std::unordered_map> +RenderRasterDEMSource::queryRenderedFeatures(const ScreenLineString&, + const TransformState&, + const std::vector&, + const RenderedQueryOptions&, + const CollisionIndex& ) const { + return std::unordered_map> {}; +} + +std::vector 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 +#include +#include + +namespace mbgl { + +class RenderRasterDEMSource : public RenderSource { +public: + RenderRasterDEMSource(Immutable); + + bool isLoaded() const final; + + void update(Immutable, + const std::vector>&, + bool needsRendering, + bool needsRelayout, + const TileParameters&) final; + + void startRender(PaintParameters&) final; + void finishRender(PaintParameters&) final; + + std::vector> getRenderTiles() final; + + std::unordered_map> + queryRenderedFeatures(const ScreenLineString& geometry, + const TransformState& transformState, + const std::vector& layers, + const RenderedQueryOptions& options, + const CollisionIndex& collisionIndex) const final; + + std::vector + querySourceFeatures(const SourceQueryOptions&) const final; + + void onLowMemory() final; + void dumpDebugLogs() const final; + +private: + const style::RasterDEMSource::Impl& impl() const; + + TilePyramid tilePyramid; + optional> tileURLTemplates; +}; + +template <> +inline bool RenderSource::is() const { + return baseImpl->type == style::SourceType::RasterDEM; +} + +} // namespace mbgl -- cgit v1.2.1