diff options
Diffstat (limited to 'src/mbgl/renderer/painter_fill.cpp')
-rw-r--r-- | src/mbgl/renderer/painter_fill.cpp | 122 |
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); + } +} |