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