summaryrefslogtreecommitdiff
path: root/src/mbgl/programs
diff options
context:
space:
mode:
authorJohn Firebaugh <john.firebaugh@gmail.com>2016-10-28 18:17:33 -0700
committerJohn Firebaugh <john.firebaugh@gmail.com>2016-11-08 08:09:29 -0800
commit66bdbc3b969083b9d647abdf72784be64a125949 (patch)
tree9f2f1c6eb3d0569926420459c2c9afda50c66fd0 /src/mbgl/programs
parent36210fe4e9c68a52dedc90548d90e77cf39a2228 (diff)
downloadqtlocation-mapboxgl-66bdbc3b969083b9d647abdf72784be64a125949.tar.gz
[core] Introduce gl::Program template
Diffstat (limited to 'src/mbgl/programs')
-rw-r--r--src/mbgl/programs/attributes.hpp23
-rw-r--r--src/mbgl/programs/circle_program.cpp7
-rw-r--r--src/mbgl/programs/circle_program.hpp52
-rw-r--r--src/mbgl/programs/collision_box_program.cpp7
-rw-r--r--src/mbgl/programs/collision_box_program.hpp53
-rw-r--r--src/mbgl/programs/fill_program.cpp47
-rw-r--r--src/mbgl/programs/fill_program.hpp119
-rw-r--r--src/mbgl/programs/line_program.cpp135
-rw-r--r--src/mbgl/programs/line_program.hpp184
-rw-r--r--src/mbgl/programs/program.hpp31
-rw-r--r--src/mbgl/programs/programs.hpp46
-rw-r--r--src/mbgl/programs/raster_program.cpp7
-rw-r--r--src/mbgl/programs/raster_program.hpp65
-rw-r--r--src/mbgl/programs/symbol_program.cpp145
-rw-r--r--src/mbgl/programs/symbol_program.hpp134
-rw-r--r--src/mbgl/programs/uniforms.hpp33
16 files changed, 1088 insertions, 0 deletions
diff --git a/src/mbgl/programs/attributes.hpp b/src/mbgl/programs/attributes.hpp
new file mode 100644
index 0000000000..38bbe89377
--- /dev/null
+++ b/src/mbgl/programs/attributes.hpp
@@ -0,0 +1,23 @@
+#pragma once
+
+#include <mbgl/gl/attribute.hpp>
+
+#include <cstdint>
+
+namespace mbgl {
+namespace attributes {
+
+// Attributes common to several shaders.
+
+MBGL_DEFINE_ATTRIBUTE(int16_t, 2, a_pos);
+MBGL_DEFINE_ATTRIBUTE(int16_t, 2, a_offset);
+MBGL_DEFINE_ATTRIBUTE(int16_t, 2, a_extrude);
+MBGL_DEFINE_ATTRIBUTE(uint16_t, 2, a_texture_pos);
+
+template <std::size_t N>
+struct a_data : gl::Attribute<a_data<N>, uint8_t, N> {
+ static constexpr auto name = "a_data";
+};
+
+} // namespace attributes
+} // namespace mbgl
diff --git a/src/mbgl/programs/circle_program.cpp b/src/mbgl/programs/circle_program.cpp
new file mode 100644
index 0000000000..d6bc439feb
--- /dev/null
+++ b/src/mbgl/programs/circle_program.cpp
@@ -0,0 +1,7 @@
+#include <mbgl/programs/circle_program.hpp>
+
+namespace mbgl {
+
+static_assert(sizeof(CircleProgram::Vertex) == 4, "expected CircleVertex size");
+
+} // namespace mbgl
diff --git a/src/mbgl/programs/circle_program.hpp b/src/mbgl/programs/circle_program.hpp
new file mode 100644
index 0000000000..690608a438
--- /dev/null
+++ b/src/mbgl/programs/circle_program.hpp
@@ -0,0 +1,52 @@
+#pragma once
+
+#include <mbgl/programs/program.hpp>
+#include <mbgl/programs/attributes.hpp>
+#include <mbgl/programs/uniforms.hpp>
+#include <mbgl/shader/circle.hpp>
+#include <mbgl/util/geometry.hpp>
+
+namespace mbgl {
+
+namespace uniforms {
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_radius);
+MBGL_DEFINE_UNIFORM_SCALAR(bool, u_scale_with_map);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_devicepixelratio);
+} // namespace uniforms
+
+class CircleProgram : public Program<
+ shaders::circle,
+ gl::Attributes<
+ attributes::a_pos>,
+ gl::Uniforms<
+ uniforms::u_matrix,
+ uniforms::u_opacity,
+ uniforms::u_color,
+ uniforms::u_radius,
+ uniforms::u_blur,
+ uniforms::u_scale_with_map,
+ uniforms::u_extrude_scale,
+ uniforms::u_devicepixelratio>>
+{
+public:
+ using Program::Program;
+
+ /*
+ * @param {number} x vertex position
+ * @param {number} y vertex position
+ * @param {number} ex extrude normal
+ * @param {number} ey extrude normal
+ */
+ static Vertex vertex(Point<int16_t> p, float ex, float ey) {
+ return Vertex {
+ {
+ static_cast<int16_t>((p.x * 2) + ((ex + 1) / 2)),
+ static_cast<int16_t>((p.y * 2) + ((ey + 1) / 2))
+ }
+ };
+ }
+};
+
+using CircleVertex = CircleProgram::Vertex;
+
+} // namespace mbgl
diff --git a/src/mbgl/programs/collision_box_program.cpp b/src/mbgl/programs/collision_box_program.cpp
new file mode 100644
index 0000000000..d6a36e54a1
--- /dev/null
+++ b/src/mbgl/programs/collision_box_program.cpp
@@ -0,0 +1,7 @@
+#include <mbgl/programs/collision_box_program.hpp>
+
+namespace mbgl {
+
+static_assert(sizeof(CollisionBoxProgram::Vertex) == 10, "expected CollisionBoxVertex size");
+
+} // namespace mbgl
diff --git a/src/mbgl/programs/collision_box_program.hpp b/src/mbgl/programs/collision_box_program.hpp
new file mode 100644
index 0000000000..66b1284621
--- /dev/null
+++ b/src/mbgl/programs/collision_box_program.hpp
@@ -0,0 +1,53 @@
+#pragma once
+
+#include <mbgl/programs/program.hpp>
+#include <mbgl/programs/attributes.hpp>
+#include <mbgl/programs/uniforms.hpp>
+#include <mbgl/shader/collision_box.hpp>
+#include <mbgl/util/geometry.hpp>
+
+#include <cmath>
+
+namespace mbgl {
+
+namespace uniforms {
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_scale);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_maxzoom);
+} // namespace uniforms
+
+class CollisionBoxProgram : public Program<
+ shaders::collision_box,
+ gl::Attributes<
+ attributes::a_pos,
+ attributes::a_extrude,
+ attributes::a_data<2>>,
+ gl::Uniforms<
+ uniforms::u_matrix,
+ uniforms::u_scale,
+ uniforms::u_zoom,
+ uniforms::u_maxzoom>>
+{
+public:
+ using Program::Program;
+
+ static Vertex vertex(Point<float> a, Point<float> o, float maxzoom, float placementZoom) {
+ return Vertex {
+ {
+ static_cast<int16_t>(a.x),
+ static_cast<int16_t>(a.y)
+ },
+ {
+ static_cast<int16_t>(::round(o.x)),
+ static_cast<int16_t>(::round(o.y))
+ },
+ {
+ static_cast<uint8_t>(maxzoom * 10),
+ static_cast<uint8_t>(placementZoom * 10)
+ }
+ };
+ }
+};
+
+using CollisionBoxVertex = CollisionBoxProgram::Vertex;
+
+} // namespace mbgl
diff --git a/src/mbgl/programs/fill_program.cpp b/src/mbgl/programs/fill_program.cpp
new file mode 100644
index 0000000000..90c09a995c
--- /dev/null
+++ b/src/mbgl/programs/fill_program.cpp
@@ -0,0 +1,47 @@
+#include <mbgl/programs/fill_program.hpp>
+#include <mbgl/sprite/sprite_atlas.hpp>
+#include <mbgl/style/property_evaluator.hpp>
+#include <mbgl/tile/tile_id.hpp>
+#include <mbgl/map/transform_state.hpp>
+
+namespace mbgl {
+
+using namespace style;
+
+static_assert(sizeof(FillAttributes::Vertex) == 4, "expected FillVertex size");
+
+FillPatternUniforms::Values
+FillPatternUniforms::values(mat4 matrix,
+ float opacity,
+ Size framebufferSize,
+ const SpriteAtlasPosition& a,
+ const SpriteAtlasPosition& b,
+ const Faded<std::string>& fading,
+ const UnwrappedTileID& tileID,
+ const TransformState& state)
+{
+ int32_t tileSizeAtNearestZoom = util::tileSize * state.zoomScale(state.getIntegerZoom() - tileID.canonical.z);
+ int32_t pixelX = tileSizeAtNearestZoom * (tileID.canonical.x + tileID.wrap * state.zoomScale(tileID.canonical.z));
+ int32_t pixelY = tileSizeAtNearestZoom * tileID.canonical.y;
+
+ return FillPatternUniforms::Values {
+ uniforms::u_matrix::Value{ matrix },
+ uniforms::u_opacity::Value{ opacity },
+ uniforms::u_world::Value{ framebufferSize },
+ uniforms::u_pattern_tl_a::Value{ a.tl },
+ uniforms::u_pattern_br_a::Value{ a.br },
+ uniforms::u_pattern_tl_b::Value{ b.tl },
+ uniforms::u_pattern_br_b::Value{ b.br },
+ uniforms::u_pattern_size_a::Value{ a.size },
+ uniforms::u_pattern_size_b::Value{ b.size },
+ uniforms::u_scale_a::Value{ fading.fromScale },
+ uniforms::u_scale_b::Value{ fading.toScale },
+ uniforms::u_mix::Value{ fading.t },
+ uniforms::u_image::Value{ 0 },
+ uniforms::u_pixel_coord_upper::Value{ std::array<float, 2> {{ float(pixelX >> 16), float(pixelY >> 16) }} },
+ uniforms::u_pixel_coord_lower::Value{ std::array<float, 2> {{ float(pixelX & 0xFFFF), float(pixelY & 0xFFFF) }} },
+ uniforms::u_tile_units_to_pixels::Value{ 1.0f / tileID.pixelsToTileUnits(1.0f, state.getIntegerZoom()) },
+ };
+}
+
+} // namespace mbgl
diff --git a/src/mbgl/programs/fill_program.hpp b/src/mbgl/programs/fill_program.hpp
new file mode 100644
index 0000000000..3f738527c8
--- /dev/null
+++ b/src/mbgl/programs/fill_program.hpp
@@ -0,0 +1,119 @@
+#pragma once
+
+#include <mbgl/programs/program.hpp>
+#include <mbgl/programs/attributes.hpp>
+#include <mbgl/programs/uniforms.hpp>
+#include <mbgl/shader/fill.hpp>
+#include <mbgl/shader/fill_pattern.hpp>
+#include <mbgl/shader/fill_outline.hpp>
+#include <mbgl/shader/fill_outline_pattern.hpp>
+#include <mbgl/util/geometry.hpp>
+#include <mbgl/util/mat4.hpp>
+#include <mbgl/util/size.hpp>
+
+#include <string>
+
+namespace mbgl {
+
+class SpriteAtlasPosition;
+class UnwrappedTileID;
+class TransformState;
+
+namespace style {
+template <class> class Faded;
+} // namespace style
+
+namespace uniforms {
+MBGL_DEFINE_UNIFORM_SCALAR(Size, u_world);
+MBGL_DEFINE_UNIFORM_SCALAR(Color, u_outline_color);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_scale_a);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_scale_b);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_tile_units_to_pixels);
+MBGL_DEFINE_UNIFORM_VECTOR(float, 2, u_pixel_coord_upper);
+MBGL_DEFINE_UNIFORM_VECTOR(float, 2, u_pixel_coord_lower);
+} // namespace uniforms
+
+struct FillAttributes : gl::Attributes<
+ attributes::a_pos>
+{
+ static Vertex vertex(Point<int16_t> p) {
+ return Vertex {
+ {
+ p.x,
+ p.y
+ }
+ };
+ }
+};
+
+using FillVertex = FillAttributes::Vertex;
+
+struct FillUniforms : gl::Uniforms<
+ uniforms::u_matrix,
+ uniforms::u_opacity,
+ uniforms::u_color,
+ uniforms::u_outline_color,
+ uniforms::u_world>
+{};
+
+struct FillPatternUniforms : gl::Uniforms<
+ uniforms::u_matrix,
+ uniforms::u_opacity,
+ uniforms::u_world,
+ uniforms::u_pattern_tl_a,
+ uniforms::u_pattern_br_a,
+ uniforms::u_pattern_tl_b,
+ uniforms::u_pattern_br_b,
+ uniforms::u_pattern_size_a,
+ uniforms::u_pattern_size_b,
+ uniforms::u_scale_a,
+ uniforms::u_scale_b,
+ uniforms::u_mix,
+ uniforms::u_image,
+ uniforms::u_pixel_coord_upper,
+ uniforms::u_pixel_coord_lower,
+ uniforms::u_tile_units_to_pixels>
+{
+ static Values values(mat4 matrix,
+ float opacity,
+ Size framebufferSize,
+ const SpriteAtlasPosition&,
+ const SpriteAtlasPosition&,
+ const style::Faded<std::string>&,
+ const UnwrappedTileID&,
+ const TransformState&);
+};
+
+class FillProgram : public Program<
+ shaders::fill,
+ FillAttributes,
+ FillUniforms>
+{
+ using Program::Program;
+};
+
+class FillPatternProgram : public Program<
+ shaders::fill_pattern,
+ FillAttributes,
+ FillPatternUniforms>
+{
+ using Program::Program;
+};
+
+class FillOutlineProgram : public Program<
+ shaders::fill_outline,
+ FillAttributes,
+ FillUniforms>
+{
+ using Program::Program;
+};
+
+class FillOutlinePatternProgram : public Program<
+ shaders::fill_outline_pattern,
+ FillAttributes,
+ FillPatternUniforms>
+{
+ using Program::Program;
+};
+
+} // namespace mbgl
diff --git a/src/mbgl/programs/line_program.cpp b/src/mbgl/programs/line_program.cpp
new file mode 100644
index 0000000000..07af464eb3
--- /dev/null
+++ b/src/mbgl/programs/line_program.cpp
@@ -0,0 +1,135 @@
+#include <mbgl/programs/line_program.hpp>
+#include <mbgl/style/layers/line_layer_properties.hpp>
+#include <mbgl/renderer/render_tile.hpp>
+#include <mbgl/map/transform_state.hpp>
+#include <mbgl/util/mat2.hpp>
+#include <mbgl/sprite/sprite_atlas.hpp>
+#include <mbgl/geometry/line_atlas.hpp>
+
+namespace mbgl {
+
+static_assert(sizeof(LineAttributes::Vertex) == 8, "expected LineVertex size");
+
+template <class Values, class...Args>
+Values makeValues(const style::LinePaintProperties& properties,
+ float pixelRatio,
+ const RenderTile& tile,
+ const TransformState& state,
+ Args&&... args) {
+ // the distance over which the line edge fades out.
+ // Retina devices need a smaller distance to avoid aliasing.
+ float antialiasing = 1.0 / pixelRatio;
+
+ mat2 antialiasingMatrix;
+ matrix::identity(antialiasingMatrix);
+ matrix::scale(antialiasingMatrix, antialiasingMatrix, 1.0, std::cos(state.getPitch()));
+ matrix::rotate(antialiasingMatrix, antialiasingMatrix, state.getAngle());
+
+ // calculate how much longer the real world distance is at the top of the screen
+ // than at the middle of the screen.
+ float topedgelength = std::sqrt(std::pow(state.getSize().height, 2.0f) / 4.0f * (1.0f + std::pow(state.getAltitude(), 2.0f)));
+ float x = state.getSize().height / 2.0f * std::tan(state.getPitch());
+
+ return Values {
+ uniforms::u_matrix::Value{ tile.translatedMatrix(properties.lineTranslate.value,
+ properties.lineTranslateAnchor.value,
+ state) },
+ uniforms::u_opacity::Value{ properties.lineOpacity.value },
+ uniforms::u_linewidth::Value{ properties.lineWidth.value / 2 },
+ uniforms::u_gapwidth::Value{ properties.lineGapWidth.value / 2 },
+ uniforms::u_blur::Value{ properties.lineBlur.value + antialiasing },
+ uniforms::u_offset::Value{ -properties.lineOffset.value },
+ uniforms::u_antialiasing::Value{ antialiasing / 2 },
+ uniforms::u_antialiasingmatrix::Value{ antialiasingMatrix },
+ uniforms::u_ratio::Value{ 1.0f / tile.id.pixelsToTileUnits(1.0, state.getZoom()) },
+ uniforms::u_extra::Value{ (topedgelength + x) / topedgelength - 1.0f },
+ std::forward<Args>(args)...
+ };
+}
+
+LineProgram::UniformValues
+LineProgram::uniformValues(const style::LinePaintProperties& properties,
+ float pixelRatio,
+ const RenderTile& tile,
+ const TransformState& state) {
+ return makeValues<LineProgram::UniformValues>(
+ properties,
+ pixelRatio,
+ tile,
+ state,
+ uniforms::u_color::Value{ properties.lineColor.value }
+ );
+}
+
+LineSDFProgram::UniformValues
+LineSDFProgram::uniformValues(const style::LinePaintProperties& properties,
+ float pixelRatio,
+ const RenderTile& tile,
+ const TransformState& state,
+ const LinePatternPos& posA,
+ const LinePatternPos& posB,
+ float dashLineWidth,
+ float atlasWidth) {
+ const float widthA = posA.width * properties.lineDasharray.value.fromScale * dashLineWidth;
+ const float widthB = posB.width * properties.lineDasharray.value.toScale * dashLineWidth;
+
+ std::array<float, 2> scaleA {{
+ 1.0f / tile.id.pixelsToTileUnits(widthA, state.getIntegerZoom()),
+ -posA.height / 2.0f
+ }};
+
+ std::array<float, 2> scaleB {{
+ 1.0f / tile.id.pixelsToTileUnits(widthB, state.getIntegerZoom()),
+ -posB.height / 2.0f
+ }};
+
+ return makeValues<LineSDFProgram::UniformValues>(
+ properties,
+ pixelRatio,
+ tile,
+ state,
+ uniforms::u_color::Value{ properties.lineColor.value },
+ uniforms::u_patternscale_a::Value{ scaleA },
+ uniforms::u_patternscale_b::Value{ scaleB },
+ uniforms::u_tex_y_a::Value{ posA.y },
+ uniforms::u_tex_y_b::Value{ posB.y },
+ uniforms::u_mix::Value{ properties.lineDasharray.value.t },
+ uniforms::u_sdfgamma::Value{ atlasWidth / (std::min(widthA, widthB) * 256.0f * pixelRatio) / 2.0f },
+ uniforms::u_image::Value{ 0 }
+ );
+}
+
+LinePatternProgram::UniformValues
+LinePatternProgram::uniformValues(const style::LinePaintProperties& properties,
+ float pixelRatio,
+ const RenderTile& tile,
+ const TransformState& state,
+ const SpriteAtlasPosition& posA,
+ const SpriteAtlasPosition& posB) {
+ std::array<float, 2> sizeA {{
+ tile.id.pixelsToTileUnits(posA.size[0] * properties.linePattern.value.fromScale, state.getIntegerZoom()),
+ posA.size[1]
+ }};
+
+ std::array<float, 2> sizeB {{
+ tile.id.pixelsToTileUnits(posB.size[0] * properties.linePattern.value.toScale, state.getIntegerZoom()),
+ posB.size[1]
+ }};
+
+ return makeValues<LinePatternProgram::UniformValues>(
+ properties,
+ pixelRatio,
+ tile,
+ state,
+ uniforms::u_pattern_tl_a::Value{ posA.tl },
+ uniforms::u_pattern_br_a::Value{ posA.br },
+ uniforms::u_pattern_tl_b::Value{ posB.tl },
+ uniforms::u_pattern_br_b::Value{ posB.br },
+ uniforms::u_pattern_size_a::Value{ sizeA },
+ uniforms::u_pattern_size_b::Value{ sizeB },
+ uniforms::u_fade::Value{ properties.linePattern.value.t },
+ uniforms::u_image::Value{ 0 }
+ );
+}
+
+} // namespace mbgl
diff --git a/src/mbgl/programs/line_program.hpp b/src/mbgl/programs/line_program.hpp
new file mode 100644
index 0000000000..960438f4cd
--- /dev/null
+++ b/src/mbgl/programs/line_program.hpp
@@ -0,0 +1,184 @@
+#pragma once
+
+#include <mbgl/programs/program.hpp>
+#include <mbgl/programs/attributes.hpp>
+#include <mbgl/programs/uniforms.hpp>
+#include <mbgl/shader/line.hpp>
+#include <mbgl/shader/line_pattern.hpp>
+#include <mbgl/shader/line_sdf.hpp>
+#include <mbgl/util/geometry.hpp>
+
+#include <cmath>
+
+namespace mbgl {
+
+namespace style {
+class LinePaintProperties;
+} // namespace style
+
+class RenderTile;
+class TransformState;
+class LinePatternPos;
+class SpriteAtlasPosition;
+
+namespace uniforms {
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_ratio);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_linewidth);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_gapwidth);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_antialiasing);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_extra);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_offset);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_tex_y_a);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_tex_y_b);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_sdfgamma);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_fade);
+MBGL_DEFINE_UNIFORM_VECTOR(float, 2, u_patternscale_a);
+MBGL_DEFINE_UNIFORM_VECTOR(float, 2, u_patternscale_b);
+MBGL_DEFINE_UNIFORM_MATRIX(double, 2, u_antialiasingmatrix);
+} // namespace uniforms
+
+struct LineAttributes : gl::Attributes<
+ attributes::a_pos,
+ attributes::a_data<4>>
+{
+ /*
+ * @param p vertex position
+ * @param e extrude normal
+ * @param t texture normal
+ * @param dir direction of the line cap (-1/0/1)
+ */
+ static Vertex vertex(Point<int16_t> p, Point<double> e, Point<bool> t, int8_t dir, int32_t linesofar = 0) {
+ return Vertex {
+ {
+ static_cast<int16_t>((p.x * 2) | t.x),
+ static_cast<int16_t>((p.y * 2) | t.y)
+ },
+ {
+ // add 128 to store an byte in an unsigned byte
+ static_cast<uint8_t>(::round(extrudeScale * e.x) + 128),
+ static_cast<uint8_t>(::round(extrudeScale * e.y) + 128),
+
+ // Encode the -1/0/1 direction value into the first two bits of .z of a_data.
+ // Combine it with the lower 6 bits of `linesofar` (shifted by 2 bites to make
+ // room for the direction value). The upper 8 bits of `linesofar` are placed in
+ // the `w` component. `linesofar` is scaled down by `LINE_DISTANCE_SCALE` so that
+ // we can store longer distances while sacrificing precision.
+
+ // Encode the -1/0/1 direction value into .zw coordinates of a_data, which is normally covered
+ // by linesofar, so we need to merge them.
+ // The z component's first bit, as well as the sign bit is reserved for the direction,
+ // so we need to shift the linesofar.
+ static_cast<uint8_t>(((dir == 0 ? 0 : (dir < 0 ? -1 : 1 )) + 1) | ((linesofar & 0x3F) << 2)),
+ static_cast<uint8_t>(linesofar >> 6)
+ }
+ };
+ }
+
+ /*
+ * Scale the extrusion vector so that the normal length is this value.
+ * Contains the "texture" normals (-1..1). This is distinct from the extrude
+ * normals for line joins, because the x-value remains 0 for the texture
+ * normal array, while the extrude normal actually moves the vertex to create
+ * the acute/bevelled line join.
+ */
+ static const int8_t extrudeScale = 63;
+};
+
+using LineVertex = LineAttributes::Vertex;
+
+class LineProgram : public Program<
+ shaders::line,
+ LineAttributes,
+ gl::Uniforms<
+ uniforms::u_matrix,
+ uniforms::u_opacity,
+ uniforms::u_linewidth,
+ uniforms::u_gapwidth,
+ uniforms::u_blur,
+ uniforms::u_offset,
+ uniforms::u_antialiasing,
+ uniforms::u_antialiasingmatrix,
+ uniforms::u_ratio,
+ uniforms::u_extra,
+ uniforms::u_color>>
+{
+public:
+ using Program::Program;
+
+ static UniformValues uniformValues(const style::LinePaintProperties&,
+ float pixelRatio,
+ const RenderTile&,
+ const TransformState&);
+};
+
+class LinePatternProgram : public Program<
+ shaders::line_pattern,
+ LineAttributes,
+ gl::Uniforms<
+ uniforms::u_matrix,
+ uniforms::u_opacity,
+ uniforms::u_linewidth,
+ uniforms::u_gapwidth,
+ uniforms::u_blur,
+ uniforms::u_offset,
+ uniforms::u_antialiasing,
+ uniforms::u_antialiasingmatrix,
+ uniforms::u_ratio,
+ uniforms::u_extra,
+ uniforms::u_pattern_tl_a,
+ uniforms::u_pattern_br_a,
+ uniforms::u_pattern_tl_b,
+ uniforms::u_pattern_br_b,
+ uniforms::u_pattern_size_a,
+ uniforms::u_pattern_size_b,
+ uniforms::u_fade,
+ uniforms::u_image>>
+{
+public:
+ using Program::Program;
+
+ static UniformValues uniformValues(const style::LinePaintProperties&,
+ float pixelRatio,
+ const RenderTile&,
+ const TransformState&,
+ const SpriteAtlasPosition& posA,
+ const SpriteAtlasPosition& posB);
+};
+
+class LineSDFProgram : public Program<
+ shaders::line_sdf,
+ LineAttributes,
+ gl::Uniforms<
+ uniforms::u_matrix,
+ uniforms::u_opacity,
+ uniforms::u_linewidth,
+ uniforms::u_gapwidth,
+ uniforms::u_blur,
+ uniforms::u_offset,
+ uniforms::u_antialiasing,
+ uniforms::u_antialiasingmatrix,
+ uniforms::u_ratio,
+ uniforms::u_extra,
+ uniforms::u_color,
+ uniforms::u_patternscale_a,
+ uniforms::u_patternscale_b,
+ uniforms::u_tex_y_a,
+ uniforms::u_tex_y_b,
+ uniforms::u_mix,
+ uniforms::u_sdfgamma,
+ uniforms::u_image>>
+{
+public:
+ using Program::Program;
+
+ static UniformValues uniformValues(const style::LinePaintProperties&,
+ float pixelRatio,
+ const RenderTile&,
+ const TransformState&,
+ const LinePatternPos& posA,
+ const LinePatternPos& posB,
+ float dashLineWidth,
+ float atlasWidth);
+};
+
+} // namespace mbgl
diff --git a/src/mbgl/programs/program.hpp b/src/mbgl/programs/program.hpp
new file mode 100644
index 0000000000..9f154b051a
--- /dev/null
+++ b/src/mbgl/programs/program.hpp
@@ -0,0 +1,31 @@
+#pragma once
+
+#include <mbgl/gl/program.hpp>
+
+#include <cassert>
+
+namespace mbgl {
+
+enum class ProgramDefines : bool {
+ None = false,
+ Overdraw = true,
+};
+
+template <class Shaders, class As, class Us>
+class Program : public gl::Program<As, Us> {
+public:
+ Program(gl::Context& context, ProgramDefines defines)
+ : gl::Program<As, Us>(context, Shaders::vertexSource, fragmentSource(defines))
+ {}
+
+ static std::string fragmentSource(ProgramDefines defines) {
+ std::string fragment = Shaders::fragmentSource;
+ if (defines == ProgramDefines::Overdraw) {
+ assert(fragment.find("#ifdef OVERDRAW_INSPECTOR") != std::string::npos);
+ fragment.replace(fragment.find_first_of('\n'), 1, "\n#define OVERDRAW_INSPECTOR\n");
+ }
+ return fragment;
+ }
+};
+
+} // namespace mbgl
diff --git a/src/mbgl/programs/programs.hpp b/src/mbgl/programs/programs.hpp
new file mode 100644
index 0000000000..aebafaec62
--- /dev/null
+++ b/src/mbgl/programs/programs.hpp
@@ -0,0 +1,46 @@
+#pragma once
+
+#include <mbgl/programs/circle_program.hpp>
+#include <mbgl/programs/fill_program.hpp>
+#include <mbgl/programs/line_program.hpp>
+#include <mbgl/programs/raster_program.hpp>
+#include <mbgl/programs/symbol_program.hpp>
+#include <mbgl/programs/collision_box_program.hpp>
+
+namespace mbgl {
+
+class Programs {
+public:
+ Programs(gl::Context& context, ProgramDefines defines = ProgramDefines::None)
+ : circle(context, defines),
+ fill(context, defines),
+ fillPattern(context, defines),
+ fillOutline(context, defines),
+ fillOutlinePattern(context, defines),
+ line(context, defines),
+ lineSDF(context, defines),
+ linePattern(context, defines),
+ raster(context, defines),
+ symbolIcon(context, defines),
+ symbolIconSDF(context, defines),
+ symbolGlyph(context, defines),
+ collisionBox(context, ProgramDefines::None) {
+ }
+
+ CircleProgram circle;
+ FillProgram fill;
+ FillPatternProgram fillPattern;
+ FillOutlineProgram fillOutline;
+ FillOutlinePatternProgram fillOutlinePattern;
+ LineProgram line;
+ LineSDFProgram lineSDF;
+ LinePatternProgram linePattern;
+ RasterProgram raster;
+ SymbolIconProgram symbolIcon;
+ SymbolSDFProgram symbolIconSDF;
+ SymbolSDFProgram symbolGlyph;
+
+ CollisionBoxProgram collisionBox;
+};
+
+} // namespace mbgl
diff --git a/src/mbgl/programs/raster_program.cpp b/src/mbgl/programs/raster_program.cpp
new file mode 100644
index 0000000000..ebec4c68cc
--- /dev/null
+++ b/src/mbgl/programs/raster_program.cpp
@@ -0,0 +1,7 @@
+#include <mbgl/programs/raster_program.hpp>
+
+namespace mbgl {
+
+static_assert(sizeof(RasterProgram::Vertex) == 8, "expected RasterVertex size");
+
+} // namespace mbgl
diff --git a/src/mbgl/programs/raster_program.hpp b/src/mbgl/programs/raster_program.hpp
new file mode 100644
index 0000000000..1e9a0cdb6a
--- /dev/null
+++ b/src/mbgl/programs/raster_program.hpp
@@ -0,0 +1,65 @@
+#pragma once
+
+#include <mbgl/programs/program.hpp>
+#include <mbgl/programs/attributes.hpp>
+#include <mbgl/programs/uniforms.hpp>
+#include <mbgl/shader/raster.hpp>
+#include <mbgl/util/geometry.hpp>
+
+namespace mbgl {
+
+namespace uniforms {
+MBGL_DEFINE_UNIFORM_SCALAR(gl::TextureUnit, u_image0);
+MBGL_DEFINE_UNIFORM_SCALAR(gl::TextureUnit, u_image1);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_opacity0);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_opacity1);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_buffer_scale);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_brightness_low);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_brightness_high);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_saturation_factor);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_contrast_factor);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_scale_parent);
+MBGL_DEFINE_UNIFORM_VECTOR(float, 3, u_spin_weights);
+MBGL_DEFINE_UNIFORM_VECTOR(float, 2, u_tl_parent);
+} // namespace uniforms
+
+class RasterProgram : public Program<
+ shaders::raster,
+ gl::Attributes<
+ attributes::a_pos,
+ attributes::a_texture_pos>,
+ gl::Uniforms<
+ uniforms::u_matrix,
+ uniforms::u_image0,
+ uniforms::u_image1,
+ uniforms::u_opacity0,
+ uniforms::u_opacity1,
+ uniforms::u_brightness_low,
+ uniforms::u_brightness_high,
+ uniforms::u_saturation_factor,
+ uniforms::u_contrast_factor,
+ uniforms::u_spin_weights,
+ uniforms::u_buffer_scale,
+ uniforms::u_scale_parent,
+ uniforms::u_tl_parent>>
+{
+public:
+ using Program::Program;
+
+ static Vertex vertex(Point<int16_t> p, Point<uint16_t> t) {
+ return Vertex {
+ {
+ p.x,
+ p.y
+ },
+ {
+ t.x,
+ t.y
+ }
+ };
+ }
+};
+
+using RasterVertex = RasterProgram::Vertex;
+
+} // namespace mbgl
diff --git a/src/mbgl/programs/symbol_program.cpp b/src/mbgl/programs/symbol_program.cpp
new file mode 100644
index 0000000000..8c9c34210c
--- /dev/null
+++ b/src/mbgl/programs/symbol_program.cpp
@@ -0,0 +1,145 @@
+#include <mbgl/programs/symbol_program.hpp>
+#include <mbgl/renderer/render_tile.hpp>
+#include <mbgl/map/transform_state.hpp>
+#include <mbgl/style/layers/symbol_layer_impl.hpp>
+
+namespace mbgl {
+
+using namespace style;
+
+static_assert(sizeof(SymbolAttributes::Vertex) == 16, "expected SymbolVertex size");
+
+template <class Values, class...Args>
+Values makeValues(const style::SymbolPropertyValues& values,
+ const Size& texsize,
+ const std::array<float, 2>& pixelsToGLUnits,
+ const RenderTile& tile,
+ const TransformState& state,
+ Args&&... args) {
+ std::array<float, 2> extrudeScale;
+
+ const float scale = values.paintSize / values.sdfScale;
+ if (values.pitchAlignment == AlignmentType::Map) {
+ extrudeScale.fill(tile.id.pixelsToTileUnits(1, state.getZoom()) * scale);
+ } else {
+ extrudeScale = {{
+ pixelsToGLUnits[0] * scale * state.getAltitude(),
+ pixelsToGLUnits[1] * scale * state.getAltitude()
+ }};
+ }
+
+ // adjust min/max zooms for variable font sies
+ float zoomAdjust = std::log(values.paintSize / values.layoutSize) / std::log(2);
+
+ return Values {
+ uniforms::u_matrix::Value{ tile.translatedMatrix(values.translate,
+ values.translateAnchor,
+ state) },
+ uniforms::u_opacity::Value{ values.opacity },
+ uniforms::u_extrude_scale::Value{ extrudeScale },
+ uniforms::u_texsize::Value{ std::array<float, 2> {{ float(texsize.width) / 4, float(texsize.height) / 4 }} },
+ uniforms::u_zoom::Value{ float((state.getZoom() - zoomAdjust) * 10) },
+ uniforms::u_rotate_with_map::Value{ values.rotationAlignment == AlignmentType::Map },
+ uniforms::u_texture::Value{ 0 },
+ uniforms::u_fadetexture::Value{ 1 },
+ std::forward<Args>(args)...
+ };
+}
+
+SymbolIconProgram::UniformValues
+SymbolIconProgram::uniformValues(const style::SymbolPropertyValues& values,
+ const Size& texsize,
+ const std::array<float, 2>& pixelsToGLUnits,
+ const RenderTile& tile,
+ const TransformState& state)
+{
+ return makeValues<SymbolIconProgram::UniformValues>(
+ values,
+ texsize,
+ pixelsToGLUnits,
+ tile,
+ state
+ );
+}
+
+static SymbolSDFProgram::UniformValues makeSDFValues(const style::SymbolPropertyValues& values,
+ const Size& texsize,
+ const std::array<float, 2>& pixelsToGLUnits,
+ const RenderTile& tile,
+ const TransformState& state,
+ float pixelRatio,
+ Color color,
+ float buffer,
+ float gammaAdjust)
+{
+ // The default gamma value has to be adjust for the current pixelratio so that we're not
+ // drawing blurry font on retina screens.
+ const float gammaBase = 0.105 * values.sdfScale / values.paintSize / pixelRatio;
+ const float gammaScale = values.pitchAlignment == AlignmentType::Map
+ ? 1.0 / std::cos(state.getPitch())
+ : 1.0;
+
+ return makeValues<SymbolSDFProgram::UniformValues>(
+ values,
+ texsize,
+ pixelsToGLUnits,
+ tile,
+ state,
+ uniforms::u_color::Value{ color },
+ uniforms::u_buffer::Value{ buffer },
+ uniforms::u_gamma::Value{ (gammaBase + gammaAdjust) * gammaScale },
+ uniforms::u_pitch::Value{ state.getPitch() },
+ uniforms::u_bearing::Value{ -1.0f * state.getAngle() },
+ uniforms::u_aspect_ratio::Value{ (state.getSize().width * 1.0f) / (state.getSize().height * 1.0f) },
+ uniforms::u_pitch_with_map::Value{ values.pitchAlignment == AlignmentType::Map }
+ );
+}
+
+SymbolSDFProgram::UniformValues
+SymbolSDFProgram::haloUniformValues(const style::SymbolPropertyValues& values,
+ const Size& texsize,
+ const std::array<float, 2>& pixelsToGLUnits,
+ const RenderTile& tile,
+ const TransformState& state,
+ float pixelRatio)
+{
+ const float scale = values.paintSize / values.sdfScale;
+ const float sdfPx = 8.0f;
+ const float blurOffset = 1.19f;
+ const float haloOffset = 6.0f;
+
+ return makeSDFValues(
+ values,
+ texsize,
+ pixelsToGLUnits,
+ tile,
+ state,
+ pixelRatio,
+ values.haloColor,
+ (haloOffset - values.haloWidth / scale) / sdfPx,
+ values.haloBlur * blurOffset / scale / sdfPx
+ );
+}
+
+SymbolSDFProgram::UniformValues
+SymbolSDFProgram::foregroundUniformValues(const style::SymbolPropertyValues& values,
+ const Size& texsize,
+ const std::array<float, 2>& pixelsToGLUnits,
+ const RenderTile& tile,
+ const TransformState& state,
+ float pixelRatio)
+{
+ return makeSDFValues(
+ values,
+ texsize,
+ pixelsToGLUnits,
+ tile,
+ state,
+ pixelRatio,
+ values.color,
+ (256.0f - 64.0f) / 256.0f,
+ 0
+ );
+}
+
+} // namespace mbgl
diff --git a/src/mbgl/programs/symbol_program.hpp b/src/mbgl/programs/symbol_program.hpp
new file mode 100644
index 0000000000..eb8c56b326
--- /dev/null
+++ b/src/mbgl/programs/symbol_program.hpp
@@ -0,0 +1,134 @@
+#pragma once
+
+#include <mbgl/programs/program.hpp>
+#include <mbgl/programs/attributes.hpp>
+#include <mbgl/programs/uniforms.hpp>
+#include <mbgl/shader/symbol_icon.hpp>
+#include <mbgl/shader/symbol_sdf.hpp>
+#include <mbgl/util/geometry.hpp>
+#include <mbgl/util/size.hpp>
+
+#include <cmath>
+#include <array>
+
+namespace mbgl {
+
+namespace style {
+class SymbolPropertyValues;
+} // namespace style
+
+class RenderTile;
+class TransformState;
+
+namespace uniforms {
+MBGL_DEFINE_UNIFORM_VECTOR(float, 2, u_texsize);
+MBGL_DEFINE_UNIFORM_SCALAR(bool, u_rotate_with_map);
+MBGL_DEFINE_UNIFORM_SCALAR(bool, u_pitch_with_map);
+MBGL_DEFINE_UNIFORM_SCALAR(gl::TextureUnit, u_texture);
+MBGL_DEFINE_UNIFORM_SCALAR(gl::TextureUnit, u_fadetexture);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_buffer);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_gamma);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_aspect_ratio);
+} // namespace uniforms
+
+struct SymbolAttributes : gl::Attributes<
+ attributes::a_pos,
+ attributes::a_offset,
+ attributes::a_texture_pos,
+ attributes::a_data<4>>
+{
+ static Vertex vertex(Point<float> a,
+ Point<float> o,
+ uint16_t tx,
+ uint16_t ty,
+ float minzoom,
+ float maxzoom,
+ float labelminzoom,
+ uint8_t labelangle) {
+ return Vertex {
+ {
+ static_cast<int16_t>(a.x),
+ static_cast<int16_t>(a.y)
+ },
+ {
+ static_cast<int16_t>(::round(o.x * 64)), // use 1/64 pixels for placement
+ static_cast<int16_t>(::round(o.y * 64))
+ },
+ {
+ static_cast<uint16_t>(tx / 4),
+ static_cast<uint16_t>(ty / 4)
+ },
+ {
+ static_cast<uint8_t>(labelminzoom * 10), // 1/10 zoom levels: z16 == 160
+ static_cast<uint8_t>(labelangle),
+ static_cast<uint8_t>(minzoom * 10),
+ static_cast<uint8_t>(::fmin(maxzoom, 25) * 10)
+ }
+ };
+ }
+};
+
+using SymbolVertex = SymbolAttributes::Vertex;
+
+class SymbolIconProgram : public Program<
+ shaders::symbol_icon,
+ SymbolAttributes,
+ gl::Uniforms<
+ uniforms::u_matrix,
+ uniforms::u_opacity,
+ uniforms::u_extrude_scale,
+ uniforms::u_texsize,
+ uniforms::u_zoom,
+ uniforms::u_rotate_with_map,
+ uniforms::u_texture,
+ uniforms::u_fadetexture>>
+{
+public:
+ using Program::Program;
+
+ static UniformValues uniformValues(const style::SymbolPropertyValues&,
+ const Size& texsize,
+ const std::array<float, 2>& pixelsToGLUnits,
+ const RenderTile&,
+ const TransformState&);
+};
+
+class SymbolSDFProgram : public Program<
+ shaders::symbol_sdf,
+ SymbolAttributes,
+ gl::Uniforms<
+ uniforms::u_matrix,
+ uniforms::u_opacity,
+ uniforms::u_extrude_scale,
+ uniforms::u_texsize,
+ uniforms::u_zoom,
+ uniforms::u_rotate_with_map,
+ uniforms::u_texture,
+ uniforms::u_fadetexture,
+ uniforms::u_color,
+ uniforms::u_buffer,
+ uniforms::u_gamma,
+ uniforms::u_pitch,
+ uniforms::u_bearing,
+ uniforms::u_aspect_ratio,
+ uniforms::u_pitch_with_map>>
+{
+public:
+ using Program::Program;
+
+ static UniformValues haloUniformValues(const style::SymbolPropertyValues&,
+ const Size& texsize,
+ const std::array<float, 2>& pixelsToGLUnits,
+ const RenderTile&,
+ const TransformState&,
+ float pixelRatio);
+
+ static UniformValues foregroundUniformValues(const style::SymbolPropertyValues&,
+ const Size& texsize,
+ const std::array<float, 2>& pixelsToGLUnits,
+ const RenderTile&,
+ const TransformState&,
+ float pixelRatio);
+};
+
+} // namespace mbgl
diff --git a/src/mbgl/programs/uniforms.hpp b/src/mbgl/programs/uniforms.hpp
new file mode 100644
index 0000000000..e0c5a0d361
--- /dev/null
+++ b/src/mbgl/programs/uniforms.hpp
@@ -0,0 +1,33 @@
+#pragma once
+
+#include <mbgl/gl/uniform.hpp>
+#include <mbgl/util/color.hpp>
+
+namespace mbgl {
+namespace uniforms {
+
+// Uniforms common to several shaders.
+
+MBGL_DEFINE_UNIFORM_MATRIX(double, 4, u_matrix);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_opacity);
+MBGL_DEFINE_UNIFORM_SCALAR(Color, u_color);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_blur);
+
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_zoom);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_pitch);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_bearing);
+
+MBGL_DEFINE_UNIFORM_VECTOR(float, 2, u_extrude_scale);
+
+MBGL_DEFINE_UNIFORM_VECTOR(float, 2, u_pattern_tl_a);
+MBGL_DEFINE_UNIFORM_VECTOR(float, 2, u_pattern_br_a);
+MBGL_DEFINE_UNIFORM_VECTOR(float, 2, u_pattern_tl_b);
+MBGL_DEFINE_UNIFORM_VECTOR(float, 2, u_pattern_br_b);
+MBGL_DEFINE_UNIFORM_VECTOR(float, 2, u_pattern_size_a);
+MBGL_DEFINE_UNIFORM_VECTOR(float, 2, u_pattern_size_b);
+
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_mix);
+MBGL_DEFINE_UNIFORM_SCALAR(gl::TextureUnit, u_image);
+
+} // namespace uniforms
+} // namespace mbgl