Skip to content

Commit eb4f6aa

Browse files
VectorLayer - simplify styles
- remove styles that do not contribute anything (removes ~3700 draw instructions from problematic qwant styled tile in vienna)
1 parent ea8c255 commit eb4f6aa

File tree

4 files changed

+372
-326
lines changed

4 files changed

+372
-326
lines changed

nucleus/vector_layer/Preprocessor.cpp

+38-4
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,39 @@ GpuVectorLayerTile preprocess(tile::Id id, const QByteArray& vector_tile_data, c
6262
} // namespace nucleus::vector_layer
6363
namespace nucleus::vector_layer::details {
6464

65+
std::vector<std::pair<uint32_t, uint32_t>> simplify_styles(std::vector<std::pair<uint32_t, uint32_t>> style_indices, const std::vector<glm::u32vec4> style_buffer)
66+
{
67+
// we get multiple styles that may have full opacity and the same width
68+
// creating render calls for both does not make sense -> we only want to draw the top layer
69+
// this function simplifys all the styles so that only the styles which actually have a change to be rendered will remain
70+
71+
// order the styles so that we look at layer in descending order
72+
std::sort(style_indices.begin(), style_indices.end(), [](std::pair<uint32_t, uint32_t> a, std::pair<uint32_t, uint32_t> b) { return a.second > b.second; });
73+
74+
std::vector<std::pair<uint32_t, uint32_t>> out_styles;
75+
int accummulative_opacity = 0;
76+
float width = 0.0;
77+
78+
for (const auto& indices : style_indices) {
79+
const auto style_data = style_buffer[indices.first];
80+
const float current_width = float(style_data.z) / float(constants::style_precision);
81+
const int current_opacity = style_data.x & 255;
82+
83+
if (width < current_width) {
84+
// reset opacity
85+
accummulative_opacity = 0;
86+
width = current_width;
87+
}
88+
89+
if (accummulative_opacity < 255) {
90+
accummulative_opacity += current_opacity;
91+
out_styles.push_back(indices);
92+
}
93+
}
94+
95+
return out_styles;
96+
}
97+
6598
std::vector<GeometryData> parse_tile(tile::Id id, const QByteArray& vector_tile_data, const Style& style)
6699
{
67100
const auto d = vector_tile_data.toStdString();
@@ -93,9 +126,10 @@ std::vector<GeometryData> parse_tile(tile::Id id, const QByteArray& vector_tile_
93126
const auto feature = mapbox::vector_tile::feature(layer.getFeature(i), layer);
94127

95128
const auto type = (feature.getType() == mapbox::vector_tile::GeomType::LINESTRING) ? "line" : "fill";
96-
auto styles = style.indices(layer_name, type, id.zoom_level, feature);
129+
auto style_indices = style.indices(layer_name, type, id.zoom_level, feature);
130+
style_indices = simplify_styles(style_indices, style_buffer);
97131

98-
if (styles.size() == 0) // no styles found -> we do not visualize it
132+
if (style_indices.size() == 0) // no styles found -> we do not visualize it
99133
continue;
100134

101135
if (feature.getType() == mapbox::vector_tile::GeomType::POLYGON) {
@@ -114,7 +148,7 @@ std::vector<GeometryData> parse_tile(tile::Id id, const QByteArray& vector_tile_
114148

115149
// TODO performance -> might be more efficient to find out if the style is the same and the alpha is full -> only visualize the higher layer_index
116150

117-
for (const auto& style : styles)
151+
for (const auto& style : style_indices)
118152
data.emplace_back(vertices, extent, style.first, style.second, true, all_edges, 0);
119153
// data.emplace_back(std::vector<glm::vec2>(vertices), extent, styles[0].first, styles[0].second, true, std::vector<glm::ivec2>(edges), 0);
120154
// data.push_back({ vertices, extent, styles[0].first, styles[0].second, true, all_edges, 0 });
@@ -131,7 +165,7 @@ std::vector<GeometryData> parse_tile(tile::Id id, const QByteArray& vector_tile_
131165

132166
// TODO performance -> instead of duplicating the vertice data we only want to duplicate the index data
133167

134-
for (const auto& style : styles) {
168+
for (const auto& style : style_indices) {
135169
const auto line_width = float(style_buffer[style.first].z) / float(constants::style_precision);
136170
data.emplace_back(vertices, extent, style.first, style.second, false, no_edges, line_width);
137171
}

nucleus/vector_layer/Preprocessor.h

+2
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,8 @@ namespace details {
108108

109109
std::vector<GeometryData> parse_tile(tile::Id id, const QByteArray& vector_tile_data, const Style& style);
110110

111+
std::vector<std::pair<uint32_t, uint32_t>> simplify_styles(std::vector<std::pair<uint32_t, uint32_t>> styles, const std::vector<glm::u32vec4> style_buffer);
112+
111113
/**
112114
* 96 bits -> rgb32UI
113115
* 2*3*13=78 bits for all coordinate values

unittests/nucleus/vector_preprocess.cpp

+32
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,38 @@ TEST_CASE("nucleus/vector_preprocess")
314314
// // DEBUG: save image (image saved to build/Desktop-Profile/unittests/nucleus)
315315
image.save(QString("vector_layer_grid_lines.png"));
316316
}
317+
SECTION("Simplify styles")
318+
{
319+
{
320+
// only draw second style
321+
std::vector<glm::u32vec4> style_buffer { { 200, 0, 0, 0 }, { 255, 0, 0, 0 } };
322+
std::vector<std::pair<uint32_t, uint32_t>> style_indices { { 0, 0 }, { 1, 1 } };
323+
const auto simplified = nucleus::vector_layer::details::simplify_styles(style_indices, style_buffer);
324+
325+
CHECK(simplified.size() == 1);
326+
CHECK(simplified[0].first == 1);
327+
}
328+
{
329+
// draw both styles
330+
std::vector<glm::u32vec4> style_buffer { { 200, 0, 0, 0 }, { 200, 0, 0, 0 } };
331+
std::vector<std::pair<uint32_t, uint32_t>> style_indices { { 0, 0 }, { 1, 1 } };
332+
const auto simplified = nucleus::vector_layer::details::simplify_styles(style_indices, style_buffer);
333+
334+
CHECK(simplified.size() == 2);
335+
CHECK(simplified[0].first == 1); // but layer 1 first
336+
}
337+
338+
{
339+
// width changed -> draw 3 than 1
340+
std::vector<glm::u32vec4> style_buffer { { 200, 0, 10, 0 }, { 255, 0, 0, 0 }, { 255, 0, 0, 0 } };
341+
std::vector<std::pair<uint32_t, uint32_t>> style_indices { { 0, 0 }, { 1, 1 }, { 2, 2 } };
342+
const auto simplified = nucleus::vector_layer::details::simplify_styles(style_indices, style_buffer);
343+
344+
CHECK(simplified.size() == 2);
345+
CHECK(simplified[0].first == 2);
346+
CHECK(simplified[1].first == 0);
347+
}
348+
}
317349

318350
// SECTION("Tile exploration") // section mostly used for tile debugging -> not a real test
319351
// {

0 commit comments

Comments
 (0)