1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
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);
}
}
|