summaryrefslogtreecommitdiff
path: root/src/mbgl/renderer/painter_fill.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mbgl/renderer/painter_fill.cpp')
-rw-r--r--src/mbgl/renderer/painter_fill.cpp122
1 files changed, 122 insertions, 0 deletions
diff --git a/src/mbgl/renderer/painter_fill.cpp b/src/mbgl/renderer/painter_fill.cpp
new file mode 100644
index 0000000000..f2759ffd61
--- /dev/null
+++ b/src/mbgl/renderer/painter_fill.cpp
@@ -0,0 +1,122 @@
+#include <mbgl/renderer/painter.hpp>
+#include <mbgl/renderer/fill_bucket.hpp>
+#include <mbgl/style/style.hpp>
+#include <mbgl/style/style_layer.hpp>
+#include <mbgl/map/map.hpp>
+#include <mbgl/map/sprite.hpp>
+#include <mbgl/geometry/sprite_atlas.hpp>
+#include <mbgl/util/std.hpp>
+#include <mbgl/util/mat3.hpp>
+
+using namespace mbgl;
+
+void Painter::renderFill(FillBucket& bucket, util::ptr<StyleLayer> layer_desc, const Tile::ID& id, const mat4 &matrix) {
+ // Abort early.
+ if (!bucket.hasData()) return;
+
+ const FillProperties &properties = layer_desc->getProperties<FillProperties>();
+ mat4 vtxMatrix = translatedMatrix(matrix, properties.translate, id, properties.translateAnchor);
+
+ Color fill_color = properties.fill_color;
+ fill_color[0] *= properties.opacity;
+ fill_color[1] *= properties.opacity;
+ fill_color[2] *= properties.opacity;
+ fill_color[3] *= properties.opacity;
+
+ Color stroke_color = properties.stroke_color;
+ if (stroke_color[3] < 0) {
+ stroke_color = fill_color;
+ } else {
+ stroke_color[0] *= properties.opacity;
+ stroke_color[1] *= properties.opacity;
+ stroke_color[2] *= properties.opacity;
+ stroke_color[3] *= properties.opacity;
+ }
+
+ const bool pattern = properties.image.size();
+
+ bool outline = properties.antialias && !pattern && properties.stroke_color != properties.fill_color;
+ bool fringeline = properties.antialias && !pattern && properties.stroke_color == properties.fill_color;
+
+ // Because we're drawing top-to-bottom, and we update the stencil mask
+ // below, we have to draw the outline first (!)
+ if (outline && pass == RenderPass::Translucent) {
+ useProgram(outlineShader->program);
+ outlineShader->u_matrix = vtxMatrix;
+ lineWidth(2.0f); // This is always fixed and does not depend on the pixelRatio!
+
+ outlineShader->u_color = stroke_color;
+
+ // Draw the entire line
+ outlineShader->u_world = {{
+ static_cast<float>(state.getFramebufferWidth()),
+ static_cast<float>(state.getFramebufferHeight())
+ }};
+ depthRange(strata, 1.0f);
+ bucket.drawVertices(*outlineShader);
+ }
+
+ if (pattern) {
+ // Image fill.
+ if (pass == RenderPass::Translucent) {
+ const SpriteAtlasPosition pos = spriteAtlas.getPosition(properties.image, true);
+ const float mix = std::fmod(float(state.getZoom()), 1.0f);
+ const float factor = 8.0 / std::pow(2, state.getIntegerZoom() - id.z);
+
+ mat3 patternMatrix;
+ matrix::identity(patternMatrix);
+ matrix::scale(patternMatrix, patternMatrix, 1.0f / (pos.size[0] * factor), 1.0f / (pos.size[1] * factor));
+
+ useProgram(patternShader->program);
+ patternShader->u_matrix = vtxMatrix;
+ patternShader->u_pattern_tl = pos.tl;
+ patternShader->u_pattern_br = pos.br;
+ patternShader->u_opacity = properties.opacity;
+ patternShader->u_image = 0;
+ patternShader->u_mix = mix;
+ patternShader->u_patternmatrix = patternMatrix;
+
+ glActiveTexture(GL_TEXTURE0);
+ spriteAtlas.bind(true);
+
+ // Draw the actual triangles into the color & stencil buffer.
+ depthRange(strata, 1.0f);
+ bucket.drawElements(*patternShader);
+ }
+ }
+ else {
+ // No image fill.
+ if ((fill_color[3] >= 1.0f) == (pass == RenderPass::Opaque)) {
+ // Only draw the fill when it's either opaque and we're drawing opaque
+ // fragments or when it's translucent and we're drawing translucent
+ // fragments
+ // Draw filling rectangle.
+ useProgram(plainShader->program);
+ plainShader->u_matrix = vtxMatrix;
+ plainShader->u_color = fill_color;
+
+ // Draw the actual triangles into the color & stencil buffer.
+ depthRange(strata + strata_epsilon, 1.0f);
+ bucket.drawElements(*plainShader);
+ }
+ }
+
+ // Because we're drawing top-to-bottom, and we update the stencil mask
+ // below, we have to draw the outline first (!)
+ if (fringeline && pass == RenderPass::Translucent) {
+ useProgram(outlineShader->program);
+ outlineShader->u_matrix = vtxMatrix;
+ lineWidth(2.0f); // This is always fixed and does not depend on the pixelRatio!
+
+ outlineShader->u_color = fill_color;
+
+ // Draw the entire line
+ outlineShader->u_world = {{
+ static_cast<float>(state.getFramebufferWidth()),
+ static_cast<float>(state.getFramebufferHeight())
+ }};
+
+ depthRange(strata + strata_epsilon, 1.0f);
+ bucket.drawVertices(*outlineShader);
+ }
+}