#include #include #include #include #include namespace mbgl { using namespace style; HillshadeBucket::HillshadeBucket(PremultipliedImage&& image_, Tileset::DEMEncoding encoding) : demdata(image_, encoding) { } HillshadeBucket::HillshadeBucket(DEMData&& demdata_) : demdata(std::move(demdata_)) { } HillshadeBucket::~HillshadeBucket() = default; const DEMData& HillshadeBucket::getDEMData() const { return demdata; } DEMData& HillshadeBucket::getDEMData() { return demdata; } void HillshadeBucket::upload(gfx::Context& context) { if (!hasData()) { return; } const PremultipliedImage* image = demdata.getImage(); dem = context.createTexture(*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.elements(), indices.elements()); } 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 demdata.getImage()->valid(); } bool HillshadeBucket::supportsLayer(const style::Layer::Impl& impl) const { return style::HillshadeLayer::Impl::staticTypeInfo() == impl.getTypeInfo(); } } // namespace mbgl