summaryrefslogtreecommitdiff
path: root/src/mbgl/renderer/painter_fill.cpp
blob: cdce181e1c929606455d484b5d7586758050558d (plain)
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
123
124
125
126
127
128
129
130
131
132
133
134
#include <mbgl/renderer/painter.hpp>
#include <mbgl/renderer/paint_parameters.hpp>
#include <mbgl/renderer/fill_bucket.hpp>
#include <mbgl/renderer/render_tile.hpp>
#include <mbgl/style/layers/fill_layer.hpp>
#include <mbgl/style/layers/fill_layer_impl.hpp>
#include <mbgl/sprite/sprite_atlas.hpp>
#include <mbgl/programs/programs.hpp>
#include <mbgl/programs/fill_program.hpp>
#include <mbgl/util/convert.hpp>

namespace mbgl {

using namespace style;

void Painter::renderFill(PaintParameters& parameters,
                         FillBucket& bucket,
                         const FillLayer& layer,
                         const RenderTile& tile) {
    const FillPaintProperties& properties = layer.impl->paint;

    if (!properties.fillPattern.value.from.empty()) {
        if (pass != RenderPass::Translucent) {
            return;
        }

        optional<SpriteAtlasPosition> imagePosA = spriteAtlas->getPosition(
            properties.fillPattern.value.from, SpritePatternMode::Repeating);
        optional<SpriteAtlasPosition> imagePosB = spriteAtlas->getPosition(
            properties.fillPattern.value.to, SpritePatternMode::Repeating);

        if (!imagePosA || !imagePosB) {
            return;
        }

        spriteAtlas->bind(true, context, 0);

        auto draw = [&] (uint8_t sublayer, auto& program, const auto& subject) {
            context.draw({
                depthModeForSublayer(sublayer, gl::DepthMode::ReadWrite),
                stencilModeForClipping(tile.clip),
                colorModeForRenderPass(),
                program,
                FillPatternUniforms::values(
                    tile.translatedMatrix(properties.fillTranslate.value,
                                          properties.fillTranslateAnchor.value,
                                          state),
                    properties.fillOpacity.value,
                    context.viewport.getCurrentValue().size,
                    *imagePosA,
                    *imagePosB,
                    properties.fillPattern.value,
                    tile.id,
                    state
                ),
                subject
            });
        };

        draw(0,
             parameters.programs.fillPattern,
             gl::Segmented<gl::Triangles>(
                 *bucket.vertexBuffer,
                 *bucket.triangleIndexBuffer,
                 bucket.triangleSegments));

        if (!properties.fillAntialias.value || !properties.fillOutlineColor.isUndefined()) {
            return;
        }

        draw(2,
             parameters.programs.fillOutlinePattern,
             gl::Segmented<gl::Lines>(
                 *bucket.vertexBuffer,
                 *bucket.lineIndexBuffer,
                 bucket.lineSegments,
                 2.0f));
    } else {
        auto draw = [&] (uint8_t sublayer, auto& program, Color outlineColor, const auto& subject) {
            context.draw({
                depthModeForSublayer(sublayer, gl::DepthMode::ReadWrite),
                stencilModeForClipping(tile.clip),
                colorModeForRenderPass(),
                program,
                FillProgram::UniformValues {
                    uniforms::u_matrix::Value{ tile.translatedMatrix(properties.fillTranslate.value,
                                               properties.fillTranslateAnchor.value,
                                               state) },
                    uniforms::u_opacity::Value{ properties.fillOpacity.value },
                    uniforms::u_color::Value{ properties.fillColor.value },
                    uniforms::u_outline_color::Value{ outlineColor },
                    uniforms::u_world::Value{ context.viewport.getCurrentValue().size },
                },
                subject
            });
        };

        if (properties.fillAntialias.value && !properties.fillOutlineColor.isUndefined() && pass == RenderPass::Translucent) {
            draw(2,
                 parameters.programs.fillOutline,
                 properties.fillOutlineColor.value,
                 gl::Segmented<gl::Lines>(
                     *bucket.vertexBuffer,
                     *bucket.lineIndexBuffer,
                     bucket.lineSegments,
                     2.0f));
        }

        // Only draw the fill when it's opaque and we're drawing opaque fragments,
        // or when it's translucent and we're drawing translucent fragments.
        if ((properties.fillColor.value.a >= 1.0f && properties.fillOpacity.value >= 1.0f) == (pass == RenderPass::Opaque)) {
            draw(1,
                 parameters.programs.fill,
                 properties.fillOutlineColor.value,
                 gl::Segmented<gl::Triangles>(
                     *bucket.vertexBuffer,
                     *bucket.triangleIndexBuffer,
                     bucket.triangleSegments));
        }

        if (properties.fillAntialias.value && properties.fillOutlineColor.isUndefined() && pass == RenderPass::Translucent) {
            draw(2,
                 parameters.programs.fillOutline,
                 properties.fillColor.value,
                 gl::Segmented<gl::Lines>(
                     *bucket.vertexBuffer,
                     *bucket.lineIndexBuffer,
                     bucket.lineSegments,
                     2.0f));
        }
    }
}

} // namespace mbgl