diff options
author | John Firebaugh <john.firebaugh@gmail.com> | 2016-10-28 18:17:33 -0700 |
---|---|---|
committer | John Firebaugh <john.firebaugh@gmail.com> | 2016-11-08 08:09:29 -0800 |
commit | 66bdbc3b969083b9d647abdf72784be64a125949 (patch) | |
tree | 9f2f1c6eb3d0569926420459c2c9afda50c66fd0 /src/mbgl/programs | |
parent | 36210fe4e9c68a52dedc90548d90e77cf39a2228 (diff) | |
download | qtlocation-mapboxgl-66bdbc3b969083b9d647abdf72784be64a125949.tar.gz |
[core] Introduce gl::Program template
Diffstat (limited to 'src/mbgl/programs')
-rw-r--r-- | src/mbgl/programs/attributes.hpp | 23 | ||||
-rw-r--r-- | src/mbgl/programs/circle_program.cpp | 7 | ||||
-rw-r--r-- | src/mbgl/programs/circle_program.hpp | 52 | ||||
-rw-r--r-- | src/mbgl/programs/collision_box_program.cpp | 7 | ||||
-rw-r--r-- | src/mbgl/programs/collision_box_program.hpp | 53 | ||||
-rw-r--r-- | src/mbgl/programs/fill_program.cpp | 47 | ||||
-rw-r--r-- | src/mbgl/programs/fill_program.hpp | 119 | ||||
-rw-r--r-- | src/mbgl/programs/line_program.cpp | 135 | ||||
-rw-r--r-- | src/mbgl/programs/line_program.hpp | 184 | ||||
-rw-r--r-- | src/mbgl/programs/program.hpp | 31 | ||||
-rw-r--r-- | src/mbgl/programs/programs.hpp | 46 | ||||
-rw-r--r-- | src/mbgl/programs/raster_program.cpp | 7 | ||||
-rw-r--r-- | src/mbgl/programs/raster_program.hpp | 65 | ||||
-rw-r--r-- | src/mbgl/programs/symbol_program.cpp | 145 | ||||
-rw-r--r-- | src/mbgl/programs/symbol_program.hpp | 134 | ||||
-rw-r--r-- | src/mbgl/programs/uniforms.hpp | 33 |
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 |