1 #include <mbgl/renderer/buckets/hillshade_bucket.hpp>
2 #include <mbgl/renderer/layers/render_hillshade_layer.hpp>
3 #include <mbgl/programs/hillshade_program.hpp>
4 #include <mbgl/programs/hillshade_prepare_program.hpp>
5 #include <mbgl/gl/context.hpp>
6 
7 namespace mbgl {
8 
9 using namespace style;
10 
HillshadeBucket(PremultipliedImage && image_,Tileset::DEMEncoding encoding)11 HillshadeBucket::HillshadeBucket(PremultipliedImage&& image_, Tileset::DEMEncoding encoding)
12     : Bucket(LayerType::Hillshade),
13       demdata(image_, encoding) {
14 }
15 
HillshadeBucket(DEMData && demdata_)16 HillshadeBucket::HillshadeBucket(DEMData&& demdata_)
17     : Bucket(LayerType::Hillshade),
18       demdata(std::move(demdata_)) {
19 }
20 
getDEMData() const21 const DEMData& HillshadeBucket::getDEMData() const {
22     return demdata;
23 }
24 
getDEMData()25 DEMData& HillshadeBucket::getDEMData() {
26     return demdata;
27 }
28 
upload(gl::Context & context)29 void HillshadeBucket::upload(gl::Context& context) {
30     if (!hasData()) {
31         return;
32     }
33 
34 
35     const PremultipliedImage* image = demdata.getImage();
36     dem = context.createTexture(*image);
37 
38     if (!segments.empty()) {
39         vertexBuffer = context.createVertexBuffer(std::move(vertices));
40         indexBuffer = context.createIndexBuffer(std::move(indices));
41     }
42     uploaded = true;
43 }
44 
clear()45 void HillshadeBucket::clear() {
46     vertexBuffer = {};
47     indexBuffer = {};
48     segments.clear();
49     vertices.clear();
50     indices.clear();
51 
52     uploaded = false;
53 }
54 
setMask(TileMask && mask_)55 void HillshadeBucket::setMask(TileMask&& mask_) {
56     if (mask == mask_) {
57         return;
58     }
59 
60     mask = std::move(mask_);
61     clear();
62 
63     if (mask == TileMask{ { 0, 0, 0 } }) {
64         // We want to render the full tile, and keeping the segments/vertices/indices empty means
65         // using the global shared buffers for covering the entire tile.
66         return;
67     }
68 
69     // Create a new segment so that we will upload (empty) buffers even when there is nothing to
70     // draw for this tile.
71     segments.emplace_back(0, 0);
72 
73     constexpr const uint16_t vertexLength = 4;
74 
75     // Create the vertex buffer for the specified tile mask.
76     for (const auto& id : mask) {
77         // Create a quad for every masked tile.
78         const int32_t vertexExtent = util::EXTENT >> id.z;
79 
80         const Point<int16_t> tlVertex = { static_cast<int16_t>(id.x * vertexExtent),
81                                           static_cast<int16_t>(id.y * vertexExtent) };
82         const Point<int16_t> brVertex = { static_cast<int16_t>(tlVertex.x + vertexExtent),
83                                           static_cast<int16_t>(tlVertex.y + vertexExtent) };
84 
85         if (segments.back().vertexLength + vertexLength > std::numeric_limits<uint16_t>::max()) {
86             // Move to a new segments because the old one can't hold the geometry.
87             segments.emplace_back(vertices.vertexSize(), indices.indexSize());
88         }
89 
90         vertices.emplace_back(
91             HillshadeProgram::layoutVertex({ tlVertex.x, tlVertex.y }, { static_cast<uint16_t>(tlVertex.x), static_cast<uint16_t>(tlVertex.y) }));
92         vertices.emplace_back(
93             HillshadeProgram::layoutVertex({ brVertex.x, tlVertex.y }, { static_cast<uint16_t>(brVertex.x), static_cast<uint16_t>(tlVertex.y) }));
94         vertices.emplace_back(
95             HillshadeProgram::layoutVertex({ tlVertex.x, brVertex.y }, { static_cast<uint16_t>(tlVertex.x), static_cast<uint16_t>(brVertex.y) }));
96         vertices.emplace_back(
97             HillshadeProgram::layoutVertex({ brVertex.x, brVertex.y }, { static_cast<uint16_t>(brVertex.x), static_cast<uint16_t>(brVertex.y) }));
98 
99         auto& segment = segments.back();
100         assert(segment.vertexLength <= std::numeric_limits<uint16_t>::max());
101         const uint16_t offset = segment.vertexLength;
102 
103         // 0, 1, 2
104         // 1, 2, 3
105         indices.emplace_back(offset, offset + 1, offset + 2);
106         indices.emplace_back(offset + 1, offset + 2, offset + 3);
107 
108         segment.vertexLength += vertexLength;
109         segment.indexLength += 6;
110     }
111 }
112 
hasData() const113 bool HillshadeBucket::hasData() const {
114     return demdata.getImage()->valid();
115 }
116 
117 } // namespace mbgl
118