diff --git a/include/llmr/map/source.hpp b/include/llmr/map/source.hpp index 7ce6aa632..4a506ecac 100644 --- a/include/llmr/map/source.hpp +++ b/include/llmr/map/source.hpp @@ -37,6 +37,7 @@ public: bool update(); void updateMatrices(const TransformState &transform); + bool viewportTileParsed(); void drawClippingMasks(); size_t getTileCount() const; void render(const LayerDescription& layer_desc, const BucketDescription &bucket_desc); diff --git a/src/map/source.cpp b/src/map/source.cpp index 2491e083e..e8a2fb4a7 100644 --- a/src/map/source.cpp +++ b/src/map/source.cpp @@ -57,6 +57,19 @@ size_t Source::getTileCount() const { return tiles.size(); } +bool Source::viewportTileParsed() { + bool parsed = false; + + for (auto &pair : tiles) { + Tile::ID id = pair.first; + if (hasTile(id) == TileData::State::parsed) { + parsed = true; + } + } + + return parsed; +} + void Source::drawClippingMasks() { for (std::pair> &pair : tiles) { Tile &tile = *pair.second; diff --git a/src/renderer/painter_clipping.cpp b/src/renderer/painter_clipping.cpp index 3a4a24b11..5a28befb6 100644 --- a/src/renderer/painter_clipping.cpp +++ b/src/renderer/painter_clipping.cpp @@ -9,22 +9,64 @@ using namespace llmr; void Painter::drawClippingMasks(const Sources &sources) { gl::group group("clipping masks"); - useProgram(plainShader->program); glDisable(GL_DEPTH_TEST); depthMask(false); glDepthRange(1.0f, 1.0f); glStencilMask(0xFF); - const BackgroundProperties &properties = map.getStyle()->computed.background; - Color background = properties.color; - const float opacity = properties.opacity; - background[0] *= opacity; - background[1] *= opacity; - background[2] *= opacity; - background[3] *= opacity; - plainShader->setColor(background); + bool ready = false; - coveringPlainArray.bind(*plainShader, tileStencilBuffer, BUFFER_OFFSET(0)); + for (const auto &pair : sources) { + Source &source = *pair.second; + if (source.viewportTileParsed()) { + ready = true; + } + } + + if (ready) { + // At least one viewport tile is parsed. Draw the background. + useProgram(plainShader->program); + + const BackgroundProperties &properties = map.getStyle()->computed.background; + Color background = properties.color; + const float opacity = properties.opacity; + background[0] *= opacity; + background[1] *= opacity; + background[2] *= opacity; + background[3] *= opacity; + plainShader->setColor(background); + + coveringPlainArray.bind(*plainShader, tileStencilBuffer, BUFFER_OFFSET(0)); + } else { + // No viewport tiles are parsed. Draw the grid pattern. + const std::shared_ptr &sprite = map.getStyle()->sprite; + if (sprite) { + SpriteAtlas &spriteAtlas = *map.getSpriteAtlas(); + Rect imagePos = spriteAtlas.getImage("matte-256", *sprite); + + std::array imageSize = {{ + (float)(imagePos.w * 0.5), + (float)(imagePos.h * 0.5) + } + }; + + useProgram(patternShader->program); + patternShader->setPatternSize(imageSize); + patternShader->setPatternTopLeft({{ + float(imagePos.x) / spriteAtlas.getWidth(), + float(imagePos.y) / spriteAtlas.getHeight(), + }}); + patternShader->setPatternBottomRight({{ + float(imagePos.x + imagePos.w) / spriteAtlas.getWidth(), + float(imagePos.y + imagePos.h) / spriteAtlas.getHeight(), + }}); + std::array color = {{ 1, 1, 1, 1 }}; + patternShader->setColor(color); + spriteAtlas.bind(true); + + coveringPatternArray.bind(*patternShader, tileStencilBuffer, BUFFER_OFFSET(0)); + } + } for (const auto &pair : sources) { Source &source = *pair.second;