1 #include <mbgl/programs/symbol_program.hpp>
2 #include <mbgl/renderer/render_tile.hpp>
3 #include <mbgl/map/transform_state.hpp>
4 #include <mbgl/style/layers/symbol_layer_impl.hpp>
5 #include <mbgl/layout/symbol_projection.hpp>
6 #include <mbgl/tile/tile.hpp>
7 #include <mbgl/util/enum.hpp>
8 #include <mbgl/math/clamp.hpp>
9 
10 namespace mbgl {
11 
12 using namespace style;
13 
14 static_assert(sizeof(SymbolLayoutVertex) == 16, "expected SymbolLayoutVertex size");
15 
create(const float tileZoom,const style::DataDrivenPropertyValue<float> & sizeProperty,const float defaultValue)16 std::unique_ptr<SymbolSizeBinder> SymbolSizeBinder::create(const float tileZoom,
17                                                     const style::DataDrivenPropertyValue<float>& sizeProperty,
18                                                     const float defaultValue) {
19     return sizeProperty.match(
20         [&] (const Undefined& value) -> std::unique_ptr<SymbolSizeBinder> {
21             return std::make_unique<ConstantSymbolSizeBinder>(tileZoom, value, defaultValue);
22         },
23         [&] (float value) -> std::unique_ptr<SymbolSizeBinder> {
24             return std::make_unique<ConstantSymbolSizeBinder>(tileZoom, value, defaultValue);
25         },
26         [&] (const style::PropertyExpression<float>& expression) -> std::unique_ptr<SymbolSizeBinder> {
27             if (expression.isFeatureConstant()) {
28                 return std::make_unique<ConstantSymbolSizeBinder>(tileZoom, expression, defaultValue);
29             } else if (expression.isZoomConstant()) {
30                 return std::make_unique<SourceFunctionSymbolSizeBinder>(tileZoom, expression, defaultValue);
31             } else {
32                 return std::make_unique<CompositeFunctionSymbolSizeBinder>(tileZoom, expression, defaultValue);
33             }
34         }
35     );
36 }
37 
38 template <class Values, class...Args>
makeValues(const bool isText,const style::SymbolPropertyValues & values,const Size & texsize,const std::array<float,2> & pixelsToGLUnits,const bool alongLine,const RenderTile & tile,const TransformState & state,const float symbolFadeChange,Args &&...args)39 Values makeValues(const bool isText,
40                   const style::SymbolPropertyValues& values,
41                   const Size& texsize,
42                   const std::array<float, 2>& pixelsToGLUnits,
43                   const bool alongLine,
44                   const RenderTile& tile,
45                   const TransformState& state,
46                   const float symbolFadeChange,
47                   Args&&... args) {
48     std::array<float, 2> extrudeScale;
49 
50     if (values.pitchAlignment == AlignmentType::Map) {
51         extrudeScale.fill(tile.id.pixelsToTileUnits(1, state.getZoom()));
52     } else {
53         extrudeScale = {{
54             pixelsToGLUnits[0] * state.getCameraToCenterDistance(),
55             pixelsToGLUnits[1] * state.getCameraToCenterDistance()
56         }};
57     }
58 
59     const float pixelsToTileUnits = tile.id.pixelsToTileUnits(1.0, state.getZoom());
60     const bool pitchWithMap = values.pitchAlignment == style::AlignmentType::Map;
61     const bool rotateWithMap = values.rotationAlignment == style::AlignmentType::Map;
62 
63     // Line label rotation happens in `updateLineLabels`
64     // Pitched point labels are automatically rotated by the labelPlaneMatrix projection
65     // Unpitched point labels need to have their rotation applied after projection
66     const bool rotateInShader = rotateWithMap && !pitchWithMap && !alongLine;
67 
68     mat4 labelPlaneMatrix;
69     if (alongLine) {
70         // For labels that follow lines the first part of the projection is handled on the cpu.
71         // Pass an identity matrix because no transformation needs to be done in the vertex shader.
72         matrix::identity(labelPlaneMatrix);
73     } else {
74         labelPlaneMatrix = getLabelPlaneMatrix(tile.matrix, pitchWithMap, rotateWithMap, state, pixelsToTileUnits);
75     }
76 
77     mat4 glCoordMatrix = getGlCoordMatrix(tile.matrix, pitchWithMap, rotateWithMap, state, pixelsToTileUnits);
78 
79     return Values {
80         uniforms::u_matrix::Value{ tile.translatedMatrix(values.translate,
81                                    values.translateAnchor,
82                                    state) },
83         uniforms::u_label_plane_matrix::Value{labelPlaneMatrix},
84         uniforms::u_gl_coord_matrix::Value{ tile.translateVtxMatrix(glCoordMatrix,
85                                             values.translate,
86                                             values.translateAnchor,
87                                             state,
88                                             true) },
89         uniforms::u_extrude_scale::Value{ extrudeScale },
90         uniforms::u_texsize::Value{ texsize },
91         uniforms::u_texture::Value{ 0 },
92         uniforms::u_fade_change::Value{ symbolFadeChange },
93         uniforms::u_is_text::Value{ isText },
94         uniforms::u_camera_to_center_distance::Value{ state.getCameraToCenterDistance() },
95         uniforms::u_pitch::Value{ state.getPitch() },
96         uniforms::u_pitch_with_map::Value{ pitchWithMap },
97         uniforms::u_rotate_symbol::Value{ rotateInShader },
98         uniforms::u_aspect_ratio::Value{ state.getSize().aspectRatio() },
99         std::forward<Args>(args)...
100     };
101 }
102 
103 SymbolIconProgram::UniformValues
uniformValues(const bool isText,const style::SymbolPropertyValues & values,const Size & texsize,const std::array<float,2> & pixelsToGLUnits,const bool alongLine,const RenderTile & tile,const TransformState & state,const float symbolFadeChange)104 SymbolIconProgram::uniformValues(const bool isText,
105                                  const style::SymbolPropertyValues& values,
106                                  const Size& texsize,
107                                  const std::array<float, 2>& pixelsToGLUnits,
108                                  const bool alongLine,
109                                  const RenderTile& tile,
110                                  const TransformState& state,
111                                  const float symbolFadeChange)
112 {
113     return makeValues<SymbolIconProgram::UniformValues>(
114         isText,
115         values,
116         texsize,
117         pixelsToGLUnits,
118         alongLine,
119         tile,
120         state,
121         symbolFadeChange
122     );
123 }
124 
125 template <class PaintProperties>
uniformValues(const bool isText,const style::SymbolPropertyValues & values,const Size & texsize,const std::array<float,2> & pixelsToGLUnits,const bool alongLine,const RenderTile & tile,const TransformState & state,const float symbolFadeChange,const SymbolSDFPart part)126 typename SymbolSDFProgram<PaintProperties>::UniformValues SymbolSDFProgram<PaintProperties>::uniformValues(
127       const bool isText,
128       const style::SymbolPropertyValues& values,
129       const Size& texsize,
130       const std::array<float, 2>& pixelsToGLUnits,
131       const bool alongLine,
132       const RenderTile& tile,
133       const TransformState& state,
134       const float symbolFadeChange,
135       const SymbolSDFPart part)
136 {
137     const float gammaScale = (values.pitchAlignment == AlignmentType::Map
138                               ? std::cos(state.getPitch()) * state.getCameraToCenterDistance()
139                               : 1.0);
140 
141     return makeValues<SymbolSDFProgram<PaintProperties>::UniformValues>(
142         isText,
143         values,
144         texsize,
145         pixelsToGLUnits,
146         alongLine,
147         tile,
148         state,
149         symbolFadeChange,
150         uniforms::u_gamma_scale::Value{ gammaScale },
151         uniforms::u_is_halo::Value{ part == SymbolSDFPart::Halo }
152     );
153 }
154 
155 template class SymbolSDFProgram<style::IconPaintProperties>;
156 template class SymbolSDFProgram<style::TextPaintProperties>;
157 
158 } // namespace mbgl
159