summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLeith Bade <leith@mapbox.com>2015-01-23 11:11:04 +1100
committerLeith Bade <leith@mapbox.com>2015-01-23 11:11:04 +1100
commit42d1972732a2f8cc59cf3c3041944b7831b4c97b (patch)
tree0b28f7476f805f55b67a621552c73b15dc7a358e /src
parent5234cd9f79d7aa1ac7843693f1f28f9d358edf2c (diff)
parent0c2ffc251c519af76a0ed6dd1925621ebe393e7b (diff)
downloadqtlocation-mapboxgl-42d1972732a2f8cc59cf3c3041944b7831b4c97b.tar.gz
Merge branch 'master' of github.com:mapbox/mapbox-gl-native into android-mason
Conflicts: src/mbgl/renderer/painter_prerender.cpp src/mbgl/renderer/prerendered_texture.cpp src/mbgl/renderer/prerendered_texture.hpp
Diffstat (limited to 'src')
-rw-r--r--src/mbgl/geometry/line_atlas.cpp171
-rw-r--r--src/mbgl/geometry/line_atlas.hpp41
-rw-r--r--src/mbgl/map/map.cpp12
-rw-r--r--src/mbgl/map/tile_parser.cpp8
-rw-r--r--src/mbgl/renderer/line_bucket.cpp14
-rw-r--r--src/mbgl/renderer/line_bucket.hpp4
-rw-r--r--src/mbgl/renderer/painter.cpp4
-rw-r--r--src/mbgl/renderer/painter.hpp6
-rw-r--r--src/mbgl/renderer/painter_line.cpp32
-rw-r--r--src/mbgl/renderer/painter_prerender.cpp45
-rw-r--r--src/mbgl/renderer/painter_raster.cpp45
-rw-r--r--src/mbgl/renderer/prerendered_texture.cpp185
-rw-r--r--src/mbgl/renderer/prerendered_texture.hpp38
-rw-r--r--src/mbgl/renderer/raster_bucket.cpp1
-rw-r--r--src/mbgl/renderer/raster_bucket.hpp2
-rw-r--r--src/mbgl/shader/line.fragment.glsl8
-rw-r--r--src/mbgl/shader/line.vertex.glsl3
-rw-r--r--src/mbgl/shader/line_shader.hpp1
-rw-r--r--src/mbgl/shader/linesdf.fragment.glsl23
-rw-r--r--src/mbgl/shader/linesdf.vertex.glsl49
-rw-r--r--src/mbgl/shader/linesdf_shader.cpp30
-rw-r--r--src/mbgl/shader/linesdf_shader.hpp34
-rw-r--r--src/mbgl/style/function_properties.cpp2
-rw-r--r--src/mbgl/style/property_fallback.cpp2
-rw-r--r--src/mbgl/style/property_key.hpp2
-rw-r--r--src/mbgl/style/property_value.hpp5
-rw-r--r--src/mbgl/style/style_bucket.hpp4
-rw-r--r--src/mbgl/style/style_layer.cpp15
-rw-r--r--src/mbgl/style/style_layer.hpp3
-rw-r--r--src/mbgl/style/style_parser.cpp99
-rw-r--r--src/mbgl/style/style_parser.hpp6
-rw-r--r--src/mbgl/style/style_properties.hpp4
-rw-r--r--src/mbgl/util/interpolate.hpp5
-rw-r--r--src/mbgl/util/raster.hpp1
34 files changed, 465 insertions, 439 deletions
diff --git a/src/mbgl/geometry/line_atlas.cpp b/src/mbgl/geometry/line_atlas.cpp
new file mode 100644
index 0000000000..b396d93259
--- /dev/null
+++ b/src/mbgl/geometry/line_atlas.cpp
@@ -0,0 +1,171 @@
+#include <mbgl/geometry/line_atlas.hpp>
+#include <mbgl/platform/gl.hpp>
+#include <mbgl/platform/platform.hpp>
+
+#include <sstream>
+#include <cmath>
+
+using namespace mbgl;
+
+LineAtlas::LineAtlas(uint16_t w, uint16_t h)
+ : width(w),
+ height(h),
+ data(new char[w * h]),
+ dirty(true) {
+}
+
+LineAtlas::~LineAtlas() {
+ std::lock_guard<std::recursive_mutex> lock(mtx);
+
+ MBGL_CHECK_ERROR(glDeleteTextures(1, &texture));
+ texture = 0;
+}
+
+LinePatternPos LineAtlas::getDashPosition(const std::vector<float> &dasharray, bool round) {
+ std::lock_guard<std::recursive_mutex> lock(mtx);
+
+ std::ostringstream sskey;
+
+ for (const float &part : dasharray) {
+ sskey << part << "-";
+ }
+ sskey << round;
+ std::string key = sskey.str();
+
+ if (positions.find(key) == positions.end()) {
+ positions[key] = addDash(dasharray, round);
+ }
+
+ return positions[key];
+}
+
+LinePatternPos LineAtlas::addDash(const std::vector<float> &dasharray, bool round) {
+
+ int n = round ? 7 : 0;
+ int dashheight = 2 * n + 1;
+ const uint8_t offset = 128;
+
+ if (nextRow + dashheight > height) {
+ fprintf(stderr, "[WARNING] line atlas bitmap overflow\n");
+ return LinePatternPos();
+ }
+
+ float length = 0;
+ for (const float &part : dasharray) {
+ length += part;
+ }
+
+ float stretch = width / length;
+ float halfWidth = stretch * 0.5;
+ // If dasharray has an odd length, both the first and last parts
+ // are dashes and should be joined seamlessly.
+ bool oddLength = dasharray.size() % 2 == 1;
+
+ for (int y = -n; y <= n; y++) {
+ int row = nextRow + n + y;
+ int index = width * row;
+
+ float left = 0;
+ float right = dasharray[0];
+ unsigned int partIndex = 1;
+
+ if (oddLength) {
+ left -= dasharray.back();
+ }
+
+ for (int x = 0; x < width; x++) {
+
+ while (right < x / stretch) {
+ left = right;
+ right = right + dasharray[partIndex];
+
+ if (oddLength && partIndex == dasharray.size() - 1) {
+ right += dasharray.front();
+ }
+
+ partIndex++;
+ }
+
+ float distLeft = fabs(x - left * stretch);
+ float distRight = fabs(x - right * stretch);
+ float dist = fmin(distLeft, distRight);
+ bool inside = (partIndex % 2) == 1;
+ int signedDistance;
+
+ if (round) {
+ float distMiddle = n ? (float)y / n * (halfWidth + 1) : 0;
+ if (inside) {
+ float distEdge = halfWidth - fabs(distMiddle);
+ signedDistance = sqrt(dist * dist + distEdge * distEdge);
+ } else {
+ signedDistance = halfWidth - sqrt(dist * dist + distMiddle * distMiddle);
+ }
+
+ } else {
+ signedDistance = int((inside ? 1 : -1) * dist);
+ }
+
+ data[index + x] = fmax(0, fmin(255, signedDistance + offset));
+ }
+ }
+
+ LinePatternPos position;
+ position.y = (0.5 + nextRow + n) / height;
+ position.height = (2.0 * n) / height;
+ position.width = length;
+
+ nextRow += dashheight;
+
+ dirty = true;
+ bind();
+
+ return position;
+};
+
+void LineAtlas::bind() {
+ std::lock_guard<std::recursive_mutex> lock(mtx);
+
+ bool first = false;
+ if (!texture) {
+ MBGL_CHECK_ERROR(glGenTextures(1, &texture));
+ MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, texture));
+ MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
+ MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
+ MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT));
+ MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
+ first = true;
+ } else {
+ MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, texture));
+ }
+
+ if (dirty) {
+ if (first) {
+ glTexImage2D(
+ GL_TEXTURE_2D, // GLenum target
+ 0, // GLint level
+ GL_ALPHA, // GLint internalformat
+ width, // GLsizei width
+ height, // GLsizei height
+ 0, // GLint border
+ GL_ALPHA, // GLenum format
+ GL_UNSIGNED_BYTE, // GLenum type
+ data // const GLvoid * data
+ );
+ } else {
+ glTexSubImage2D(
+ GL_TEXTURE_2D, // GLenum target
+ 0, // GLint level
+ 0, // GLint xoffset
+ 0, // GLint yoffset
+ width, // GLsizei width
+ height, // GLsizei height
+ GL_ALPHA, // GLenum format
+ GL_UNSIGNED_BYTE, // GLenum type
+ data // const GLvoid *pixels
+ );
+ }
+
+
+ dirty = false;
+ }
+};
diff --git a/src/mbgl/geometry/line_atlas.hpp b/src/mbgl/geometry/line_atlas.hpp
new file mode 100644
index 0000000000..191dc0c4d4
--- /dev/null
+++ b/src/mbgl/geometry/line_atlas.hpp
@@ -0,0 +1,41 @@
+#ifndef MBGL_GEOMETRY_LINE_ATLAS
+#define MBGL_GEOMETRY_LINE_ATLAS
+
+#include <vector>
+#include <map>
+#include <mutex>
+#include <atomic>
+
+namespace mbgl {
+
+typedef struct {
+ float width;
+ float height;
+ float y;
+} LinePatternPos;
+
+class LineAtlas {
+public:
+ LineAtlas(uint16_t width, uint16_t height);
+ ~LineAtlas();
+
+ void bind();
+
+ LinePatternPos getDashPosition(const std::vector<float>&, bool);
+ LinePatternPos addDash(const std::vector<float> &dasharray, bool round);
+
+ const int width;
+ const int height;
+
+private:
+ std::recursive_mutex mtx;
+ char *const data = nullptr;
+ std::atomic<bool> dirty;
+ uint32_t texture = 0;
+ int nextRow = 0;
+ std::map<std::string, LinePatternPos> positions;
+};
+
+};
+
+#endif
diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp
index 923ce326a2..ff584c54ba 100644
--- a/src/mbgl/map/map.cpp
+++ b/src/mbgl/map/map.cpp
@@ -20,6 +20,7 @@
#include <mbgl/style/style_bucket.hpp>
#include <mbgl/util/texture_pool.hpp>
#include <mbgl/geometry/sprite_atlas.hpp>
+#include <mbgl/geometry/line_atlas.hpp>
#include <mbgl/storage/file_source.hpp>
#include <mbgl/platform/log.hpp>
#include <mbgl/util/string.hpp>
@@ -99,8 +100,9 @@ Map::Map(View& view_, FileSource& fileSource_)
glyphAtlas(util::make_unique<GlyphAtlas>(1024, 1024)),
glyphStore(std::make_shared<GlyphStore>(fileSource)),
spriteAtlas(util::make_unique<SpriteAtlas>(512, 512)),
+ lineAtlas(util::make_unique<LineAtlas>(512, 512)),
texturePool(std::make_shared<TexturePool>()),
- painter(util::make_unique<Painter>(*spriteAtlas, *glyphAtlas))
+ painter(util::make_unique<Painter>(*spriteAtlas, *glyphAtlas, *lineAtlas))
{
view.initialize(this);
// Make sure that we're doing an initial drawing in all cases.
@@ -662,12 +664,8 @@ void Map::updateSources(const util::ptr<StyleLayerGroup> &group) {
}
for (const util::ptr<StyleLayer> &layer : group->layers) {
if (!layer) continue;
- if (layer->bucket) {
- if (layer->bucket->style_source) {
- (*activeSources.emplace(layer->bucket->style_source).first)->enabled = true;
- }
- } else if (layer->layers) {
- updateSources(layer->layers);
+ if (layer->bucket && layer->bucket->style_source) {
+ (*activeSources.emplace(layer->bucket->style_source).first)->enabled = true;
}
}
}
diff --git a/src/mbgl/map/tile_parser.cpp b/src/mbgl/map/tile_parser.cpp
index 1e12e5fc16..e72bb79dcf 100644
--- a/src/mbgl/map/tile_parser.cpp
+++ b/src/mbgl/map/tile_parser.cpp
@@ -70,10 +70,8 @@ void TileParser::parseStyleLayers(util::ptr<StyleLayerGroup> group) {
if (layer_desc->isBackground()) {
// background is a special, fake bucket
continue;
- } else if (layer_desc->layers) {
- // This is a layer group.
- parseStyleLayers(layer_desc->layers);
}
+
if (layer_desc->bucket) {
// This is a singular layer. Check if this bucket already exists. If not,
// parse this bucket.
@@ -88,7 +86,7 @@ void TileParser::parseStyleLayers(util::ptr<StyleLayerGroup> group) {
}
}
} else {
- fprintf(stderr, "[WARNING] layer '%s' does not have child layers or buckets\n", layer_desc->id.c_str());
+ fprintf(stderr, "[WARNING] layer '%s' does not have buckets\n", layer_desc->id.c_str());
}
}
}
@@ -117,8 +115,6 @@ std::unique_ptr<Bucket> TileParser::createBucket(util::ptr<StyleBucket> bucket_d
} else {
fprintf(stderr, "[WARNING] unknown bucket render type for layer '%s' (source layer '%s')\n", bucket_desc->name.c_str(), bucket_desc->source_layer.c_str());
}
- } else if (bucket_desc->render.is<StyleBucketRaster>() && bucket_desc->render.get<StyleBucketRaster>().prerendered == true) {
- return createRasterBucket(bucket_desc->render.get<StyleBucketRaster>());
} else {
// The layer specified in the bucket does not exist. Do nothing.
if (debug::tileParseWarnings) {
diff --git a/src/mbgl/renderer/line_bucket.cpp b/src/mbgl/renderer/line_bucket.cpp
index e88b771eef..4937c8ac63 100644
--- a/src/mbgl/renderer/line_bucket.cpp
+++ b/src/mbgl/renderer/line_bucket.cpp
@@ -374,6 +374,20 @@ void LineBucket::drawLines(LineShader& shader) {
}
}
+void LineBucket::drawLineSDF(LineSDFShader& shader) {
+ char *vertex_index = BUFFER_OFFSET(vertex_start * vertexBuffer.itemSize);
+ char *elements_index = BUFFER_OFFSET(triangle_elements_start * triangleElementsBuffer.itemSize);
+ for (triangle_group_type& group : triangleGroups) {
+ if (!group.elements_length) {
+ continue;
+ }
+ group.array[2].bind(shader, vertexBuffer, triangleElementsBuffer, vertex_index);
+ MBGL_CHECK_ERROR(glDrawElements(GL_TRIANGLES, group.elements_length * 3, GL_UNSIGNED_SHORT, elements_index));
+ vertex_index += group.vertex_length * vertexBuffer.itemSize;
+ elements_index += group.elements_length * triangleElementsBuffer.itemSize;
+ }
+}
+
void LineBucket::drawLinePatterns(LinepatternShader& shader) {
char *vertex_index = BUFFER_OFFSET(vertex_start * vertexBuffer.itemSize);
char *elements_index = BUFFER_OFFSET(triangle_elements_start * triangleElementsBuffer.itemSize);
diff --git a/src/mbgl/renderer/line_bucket.hpp b/src/mbgl/renderer/line_bucket.hpp
index 7337ca80ad..c4d0d4a050 100644
--- a/src/mbgl/renderer/line_bucket.hpp
+++ b/src/mbgl/renderer/line_bucket.hpp
@@ -16,11 +16,12 @@ class LineVertexBuffer;
class TriangleElementsBuffer;
class LineShader;
class LinejoinShader;
+class LineSDFShader;
class LinepatternShader;
struct pbf;
class LineBucket : public Bucket {
- typedef ElementGroup<2> triangle_group_type;
+ typedef ElementGroup<3> triangle_group_type;
typedef ElementGroup<1> point_group_type;
public:
@@ -38,6 +39,7 @@ public:
bool hasPoints() const;
void drawLines(LineShader& shader);
+ void drawLineSDF(LineSDFShader& shader);
void drawLinePatterns(LinepatternShader& shader);
void drawPoints(LinejoinShader& shader);
diff --git a/src/mbgl/renderer/painter.cpp b/src/mbgl/renderer/painter.cpp
index 1af33c4130..0c17d52b5d 100644
--- a/src/mbgl/renderer/painter.cpp
+++ b/src/mbgl/renderer/painter.cpp
@@ -24,9 +24,10 @@ using namespace mbgl;
#define BUFFER_OFFSET(i) ((char *)nullptr + (i))
-Painter::Painter(SpriteAtlas& spriteAtlas_, GlyphAtlas& glyphAtlas_)
+Painter::Painter(SpriteAtlas& spriteAtlas_, GlyphAtlas& glyphAtlas_, LineAtlas& lineAtlas_)
: spriteAtlas(spriteAtlas_)
, glyphAtlas(glyphAtlas_)
+ , lineAtlas(lineAtlas_)
{
}
@@ -93,6 +94,7 @@ void Painter::setupShaders() {
if (!outlineShader) outlineShader = util::make_unique<OutlineShader>();
if (!lineShader) lineShader = util::make_unique<LineShader>();
if (!linejoinShader) linejoinShader = util::make_unique<LinejoinShader>();
+ if (!linesdfShader) linesdfShader = util::make_unique<LineSDFShader>();
if (!linepatternShader) linepatternShader = util::make_unique<LinepatternShader>();
if (!patternShader) patternShader = util::make_unique<PatternShader>();
if (!iconShader) iconShader = util::make_unique<IconShader>();
diff --git a/src/mbgl/renderer/painter.hpp b/src/mbgl/renderer/painter.hpp
index a39a368acb..4d4876a6f1 100644
--- a/src/mbgl/renderer/painter.hpp
+++ b/src/mbgl/renderer/painter.hpp
@@ -14,6 +14,7 @@
#include <mbgl/shader/pattern_shader.hpp>
#include <mbgl/shader/line_shader.hpp>
#include <mbgl/shader/linejoin_shader.hpp>
+#include <mbgl/shader/linesdf_shader.hpp>
#include <mbgl/shader/linepattern_shader.hpp>
#include <mbgl/shader/icon_shader.hpp>
#include <mbgl/shader/raster_shader.hpp>
@@ -38,6 +39,7 @@ class Tile;
class Sprite;
class SpriteAtlas;
class GlyphAtlas;
+class LineAtlas;
class Source;
class StyleSource;
class StyleLayerGroup;
@@ -56,7 +58,7 @@ class RasterTileData;
class Painter : private util::noncopyable {
public:
- Painter(SpriteAtlas&, GlyphAtlas&);
+ Painter(SpriteAtlas&, GlyphAtlas&, LineAtlas&);
~Painter();
void setup();
@@ -194,11 +196,13 @@ public:
SpriteAtlas& spriteAtlas;
GlyphAtlas& glyphAtlas;
+ LineAtlas& lineAtlas;
std::unique_ptr<PlainShader> plainShader;
std::unique_ptr<OutlineShader> outlineShader;
std::unique_ptr<LineShader> lineShader;
std::unique_ptr<LinejoinShader> linejoinShader;
+ std::unique_ptr<LineSDFShader> linesdfShader;
std::unique_ptr<LinepatternShader> linepatternShader;
std::unique_ptr<PatternShader> patternShader;
std::unique_ptr<IconShader> iconShader;
diff --git a/src/mbgl/renderer/painter_line.cpp b/src/mbgl/renderer/painter_line.cpp
index 71364f40c4..2d57bb26ea 100644
--- a/src/mbgl/renderer/painter_line.cpp
+++ b/src/mbgl/renderer/painter_line.cpp
@@ -4,6 +4,7 @@
#include <mbgl/style/style_layer.hpp>
#include <mbgl/map/sprite.hpp>
#include <mbgl/geometry/sprite_atlas.hpp>
+#include <mbgl/geometry/line_atlas.hpp>
#include <mbgl/map/map.hpp>
using namespace mbgl;
@@ -41,9 +42,6 @@ void Painter::renderLine(LineBucket& bucket, util::ptr<StyleLayer> layer_desc, c
color[2] *= properties.opacity;
color[3] *= properties.opacity;
- float dash_length = properties.dash_array[0];
- float dash_gap = properties.dash_array[1];
-
float ratio = state.getPixelRatio();
mat4 vtxMatrix = translatedMatrix(matrix, properties.translate, id, properties.translateAnchor);
@@ -72,7 +70,32 @@ void Painter::renderLine(LineBucket& bucket, util::ptr<StyleLayer> layer_desc, c
bucket.drawPoints(*linejoinShader);
}
- if (properties.image.size()) {
+ if (properties.dash_array.size()) {
+
+ useProgram(linesdfShader->program);
+
+ linesdfShader->u_matrix = vtxMatrix;
+ linesdfShader->u_exmatrix = extrudeMatrix;
+ linesdfShader->u_linewidth = {{ outset, inset }};
+ linesdfShader->u_ratio = ratio;
+ linesdfShader->u_blur = blur;
+ linesdfShader->u_color = color;
+
+ LinePatternPos pos = lineAtlas.getDashPosition(properties.dash_array, bucket.properties.cap == CapType::Round);
+ lineAtlas.bind();
+
+ float patternratio = std::pow(2.0, std::floor(std::log2(state.getScale())) - id.z) / 8.0;
+ float scaleX = patternratio / pos.width / properties.dash_line_width;
+ float scaleY = -pos.height / 2.0;
+
+ linesdfShader->u_patternscale = {{ scaleX, scaleY }};
+ linesdfShader->u_tex_y = pos.y;
+ linesdfShader->u_image = 0;
+ linesdfShader->u_sdfgamma = lineAtlas.width / (properties.dash_line_width * pos.width * 256.0 * state.getPixelRatio());
+
+ bucket.drawLineSDF(*linesdfShader);
+
+ } else if (properties.image.size()) {
SpriteAtlasPosition imagePos = spriteAtlas.getPosition(properties.image, true);
float factor = 8.0 / std::pow(2, state.getIntegerZoom() - id.z);
@@ -107,7 +130,6 @@ void Painter::renderLine(LineBucket& bucket, util::ptr<StyleLayer> layer_desc, c
lineShader->u_blur = blur;
lineShader->u_color = color;
- lineShader->u_dasharray = {{ dash_length, dash_gap }};
bucket.drawLines(*lineShader);
}
diff --git a/src/mbgl/renderer/painter_prerender.cpp b/src/mbgl/renderer/painter_prerender.cpp
deleted file mode 100644
index 4f07331a86..0000000000
--- a/src/mbgl/renderer/painter_prerender.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-#include <mbgl/renderer/painter.hpp>
-#include <mbgl/style/style_properties.hpp>
-#include <mbgl/renderer/prerendered_texture.hpp>
-#include <mbgl/renderer/raster_bucket.hpp>
-
-using namespace mbgl;
-
-void Painter::preparePrerender(RasterBucket &bucket) {
- MBGL_CHECK_ERROR(glDisable(GL_DEPTH_TEST));
- MBGL_CHECK_ERROR(glDisable(GL_STENCIL_TEST));
-
-// Render the actual tile.
-#if GL_EXT_discard_framebuffer && !__ANDROID__
- const GLenum discards[] = {GL_COLOR_ATTACHMENT0};
- MBGL_CHECK_ERROR(glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, discards));
-#endif
- MBGL_CHECK_ERROR(glClearColor(0.0, 0.0, 0.0, 0.0));
- MBGL_CHECK_ERROR(glClear(GL_COLOR_BUFFER_BIT));
-
- MBGL_CHECK_ERROR(glViewport(0, 0, bucket.properties.size, bucket.properties.size));
-}
-
-void Painter::renderPrerenderedTexture(RasterBucket &bucket, const mat4 &matrix, const RasterProperties& properties) {
- const int buffer = bucket.properties.buffer * 4096.0f;
-
- // draw the texture on a quad
- useProgram(rasterShader->program);
- rasterShader->u_matrix = matrix;
- rasterShader->u_opacity = 1;
-
- depthRange(strata, 1.0f);
-
- MBGL_CHECK_ERROR(glActiveTexture(GL_TEXTURE0));
- rasterShader->u_image = 0;
- rasterShader->u_buffer = buffer;
- rasterShader->u_opacity = properties.opacity;
- rasterShader->u_brightness_low = properties.brightness[0];
- rasterShader->u_brightness_high = properties.brightness[1];
- rasterShader->u_saturation_factor = saturationFactor(properties.saturation);
- rasterShader->u_contrast_factor = contrastFactor(properties.contrast);
- rasterShader->u_spin_weights = spinWeights(properties.hue_rotate);
- bucket.texture.bindTexture();
- coveringRasterArray.bind(*rasterShader, tileStencilBuffer, BUFFER_OFFSET(0));
- MBGL_CHECK_ERROR(glDrawArrays(GL_TRIANGLES, 0, (GLsizei)tileStencilBuffer.index()));
-}
diff --git a/src/mbgl/renderer/painter_raster.cpp b/src/mbgl/renderer/painter_raster.cpp
index 4c98a5e65b..a85b773788 100644
--- a/src/mbgl/renderer/painter_raster.cpp
+++ b/src/mbgl/renderer/painter_raster.cpp
@@ -9,53 +9,11 @@
using namespace mbgl;
-void Painter::renderRaster(RasterBucket& bucket, util::ptr<StyleLayer> layer_desc, const Tile::ID& id, const mat4 &matrix) {
+void Painter::renderRaster(RasterBucket& bucket, util::ptr<StyleLayer> layer_desc, const Tile::ID&, const mat4 &matrix) {
if (pass != RenderPass::Translucent) return;
const RasterProperties &properties = layer_desc->getProperties<RasterProperties>();
- if (layer_desc->layers) {
-
- if (!bucket.texture.getTexture()) {
-
- bucket.texture.bindFramebuffer();
-
- preparePrerender(bucket);
-
- const int buffer = bucket.properties.buffer * 4096.0f;
-
- const mat4 preMatrix = [&]{
- mat4 vtxMatrix;
- matrix::ortho(vtxMatrix, -buffer, 4096 + buffer, -4096 - buffer, buffer, 0, 1);
- matrix::translate(vtxMatrix, vtxMatrix, 0, -4096, 0);
- return vtxMatrix;
- }();
-
- for (const util::ptr<StyleLayer> &layer : layer_desc->layers->layers) {
- setOpaque();
- renderLayer(layer, &id, &preMatrix);
- setTranslucent();
- renderLayer(layer, &id, &preMatrix);
- }
-
- if (bucket.properties.blur > 0) {
- bucket.texture.blur(*this, bucket.properties.blur);
- }
-
- bucket.texture.unbindFramebuffer();
-
- MBGL_CHECK_ERROR(glEnable(GL_DEPTH_TEST));
- MBGL_CHECK_ERROR(glEnable(GL_STENCIL_TEST));
-
- MBGL_CHECK_ERROR(glViewport(0, 0, gl_viewport[0], gl_viewport[1]));
-
- }
-
- renderPrerenderedTexture(bucket, matrix, properties);
-
- }
-
- // Only draw non-prerendered raster here
if (bucket.hasData()) {
depthMask(false);
@@ -75,7 +33,6 @@ void Painter::renderRaster(RasterBucket& bucket, util::ptr<StyleLayer> layer_des
depthMask(true);
}
-
}
float Painter::saturationFactor(float saturation) {
diff --git a/src/mbgl/renderer/prerendered_texture.cpp b/src/mbgl/renderer/prerendered_texture.cpp
deleted file mode 100644
index 6d8af3c3be..0000000000
--- a/src/mbgl/renderer/prerendered_texture.cpp
+++ /dev/null
@@ -1,185 +0,0 @@
-#include <mbgl/renderer/prerendered_texture.hpp>
-
-#include <mbgl/renderer/painter.hpp>
-#include <mbgl/style/style_bucket.hpp>
-
-#include <mbgl/platform/log.hpp>
-
-using namespace mbgl;
-
-PrerenderedTexture::PrerenderedTexture(const StyleBucketRaster &properties_)
- : properties(properties_) {
-}
-
-PrerenderedTexture::~PrerenderedTexture() {
- if (texture != 0) {
- MBGL_CHECK_ERROR(glDeleteTextures(1, &texture));
- texture = 0;
- }
-
- if (fboDepth != 0) {
- MBGL_CHECK_ERROR(glDeleteRenderbuffers(1, &fboDepth));
- fboDepth = 0;
- }
-
- if (fboStencil != 0) {
- MBGL_CHECK_ERROR(glDeleteRenderbuffers(1, &fboStencil));
- fboStencil = 0;
- }
-
- if (fbo != 0) {
- MBGL_CHECK_ERROR(glDeleteFramebuffers(1, &fbo));
- fbo = 0;
- }
-}
-
-
-void PrerenderedTexture::bindTexture() {
- if (texture == 0) {
- bindFramebuffer();
- unbindFramebuffer();
- }
-
- MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, texture));
-}
-
-void PrerenderedTexture::bindFramebuffer() {
- MBGL_CHECK_ERROR(glGetIntegerv(GL_FRAMEBUFFER_BINDING, &previousFbo));
-
- if (texture == 0) {
- MBGL_CHECK_ERROR(glGenTextures(1, &texture));
- MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, texture));
-#ifndef GL_ES_VERSION_2_0
- MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0));
-#endif
- MBGL_CHECK_ERROR(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
- MBGL_CHECK_ERROR(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
- MBGL_CHECK_ERROR(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
- MBGL_CHECK_ERROR(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
- MBGL_CHECK_ERROR(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, properties.size, properties.size, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0));
- MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, 0));
- }
-
- if (fboDepth == 0) {
- // Create depth buffer
- MBGL_CHECK_ERROR(glGenRenderbuffers(1, &fboDepth));
- MBGL_CHECK_ERROR(glBindRenderbuffer(GL_RENDERBUFFER, fboDepth));
- if (gl::isPackedDepthStencilSupported) {
- MBGL_CHECK_ERROR(glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, properties.size, properties.size));
- } else {
- if (gl::isDepth24Supported) {
- MBGL_CHECK_ERROR(glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, properties.size, properties.size));
- } else {
- MBGL_CHECK_ERROR(glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, properties.size, properties.size));
- }
- }
-
- MBGL_CHECK_ERROR(glBindRenderbuffer(GL_RENDERBUFFER, 0));
- }
-
- if (!gl::isPackedDepthStencilSupported && (fboStencil == 0)) {
- // Create stencil buffer
- MBGL_CHECK_ERROR(glGenRenderbuffers(1, &fboStencil));
- MBGL_CHECK_ERROR(glBindRenderbuffer(GL_RENDERBUFFER, fboStencil));
- MBGL_CHECK_ERROR(glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, properties.size, properties.size));
-
- MBGL_CHECK_ERROR(glBindRenderbuffer(GL_RENDERBUFFER, 0));
- }
-
- if (fbo == 0) {
- MBGL_CHECK_ERROR(glGenFramebuffers(1, &fbo));
- MBGL_CHECK_ERROR(glBindFramebuffer(GL_FRAMEBUFFER, fbo));
- MBGL_CHECK_ERROR(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0));
-
- if (gl::isPackedDepthStencilSupported) {
-#ifdef GL_ES_VERSION_2_0
- MBGL_CHECK_ERROR(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fboDepth));
- MBGL_CHECK_ERROR(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fboDepth));
-#else
- MBGL_CHECK_ERROR(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fboDepth));
-#endif
- } else {
- MBGL_CHECK_ERROR(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fboDepth));
- MBGL_CHECK_ERROR(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fboStencil));
- }
-
- GLenum status = MBGL_CHECK_ERROR(glCheckFramebufferStatus(GL_FRAMEBUFFER));
- if (status != GL_FRAMEBUFFER_COMPLETE) {
- mbgl::Log::Error(mbgl::Event::OpenGL, "Couldn't create framebuffer: ");
- switch (status) {
- case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: mbgl::Log::Error(mbgl::Event::OpenGL, "incomplete attachment\n"); break;
- case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: mbgl::Log::Error(mbgl::Event::OpenGL, "incomplete missing attachment\n"); break;
-#ifdef GL_ES_VERSION_2_0
- case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: mbgl::Log::Error(mbgl::Event::OpenGL, "incomplete dimensions\n"); break;
-#else
- case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: mbgl::Log::Error(mbgl::Event::OpenGL, "incomplete draw buffer\n"); break;
-#endif
- case GL_FRAMEBUFFER_UNSUPPORTED: mbgl::Log::Error(mbgl::Event::OpenGL, "unsupported\n"); break;
- default: mbgl::Log::Error(mbgl::Event::OpenGL, "other\n"); break;
- }
- return;
- }
- } else {
- MBGL_CHECK_ERROR(glBindFramebuffer(GL_FRAMEBUFFER, fbo));
- }
-}
-
-void PrerenderedTexture::unbindFramebuffer() {
- MBGL_CHECK_ERROR(glBindFramebuffer(GL_FRAMEBUFFER, previousFbo));
-
- if (fbo != 0) {
- MBGL_CHECK_ERROR(glDeleteFramebuffers(1, &fbo));
- fbo = 0;
- }
-}
-
-void PrerenderedTexture::blur(Painter& painter, uint16_t passes) {
- const GLuint originalTexture = texture;
-
- // Create a secondary texture
- GLuint secondaryTexture;
- MBGL_CHECK_ERROR(glGenTextures(1, &secondaryTexture));
- MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, secondaryTexture));
- MBGL_CHECK_ERROR(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
- MBGL_CHECK_ERROR(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
- MBGL_CHECK_ERROR(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
- MBGL_CHECK_ERROR(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
- MBGL_CHECK_ERROR(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, properties.size, properties.size, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0));
- MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, 0));
-
- painter.useProgram(painter.gaussianShader->program);
- painter.gaussianShader->u_matrix = painter.flipMatrix;
- painter.gaussianShader->u_image = 0;
- MBGL_CHECK_ERROR(glActiveTexture(GL_TEXTURE0));
-
- for (int i = 0; i < passes; i++) {
- // Render horizontal
- MBGL_CHECK_ERROR(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, secondaryTexture, 0));
-#if GL_EXT_discard_framebuffer
- const GLenum discards[] = { GL_COLOR_ATTACHMENT0 };
- MBGL_CHECK_ERROR(glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, discards));
-#endif
- MBGL_CHECK_ERROR(glClear(GL_COLOR_BUFFER_BIT));
-
- painter.gaussianShader->u_offset = {{ 1.0f / float(properties.size), 0 }};
- MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, originalTexture));
- painter.coveringGaussianArray.bind(*painter.gaussianShader, painter.tileStencilBuffer, BUFFER_OFFSET(0));
- MBGL_CHECK_ERROR(glDrawArrays(GL_TRIANGLES, 0, (GLsizei)painter.tileStencilBuffer.index()));
-
-
-
- // Render vertical
- MBGL_CHECK_ERROR(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, originalTexture, 0));
-#if GL_EXT_discard_framebuffer
- MBGL_CHECK_ERROR(glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, discards));
-#endif
- MBGL_CHECK_ERROR(glClear(GL_COLOR_BUFFER_BIT));
-
- painter.gaussianShader->u_offset = {{ 0, 1.0f / float(properties.size) }};
- MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, secondaryTexture));
- painter.coveringGaussianArray.bind(*painter.gaussianShader, painter.tileStencilBuffer, BUFFER_OFFSET(0));
- MBGL_CHECK_ERROR(glDrawArrays(GL_TRIANGLES, 0, (GLsizei)painter.tileStencilBuffer.index()));
- }
-
- MBGL_CHECK_ERROR(glDeleteTextures(1, &secondaryTexture));
-}
diff --git a/src/mbgl/renderer/prerendered_texture.hpp b/src/mbgl/renderer/prerendered_texture.hpp
deleted file mode 100644
index 3ccd24038d..0000000000
--- a/src/mbgl/renderer/prerendered_texture.hpp
+++ /dev/null
@@ -1,38 +0,0 @@
-#ifndef MBGL_RENDERER_PRERENDERED_TEXTURE
-#define MBGL_RENDERER_PRERENDERED_TEXTURE
-
-#include <mbgl/util/noncopyable.hpp>
-#include <mbgl/platform/gl.hpp>
-
-namespace mbgl {
-
-class StyleBucketRaster;
-class Painter;
-
-class PrerenderedTexture : private util::noncopyable {
-public:
- PrerenderedTexture(const StyleBucketRaster &properties);
- ~PrerenderedTexture();
-
- void bindTexture();
- void bindFramebuffer();
- void unbindFramebuffer();
-
- inline GLuint getTexture() const { return texture; }
-
- void blur(Painter& painter, uint16_t passes);
-
-public:
- const StyleBucketRaster &properties;
-
-private:
- GLint previousFbo = 0;
- GLuint fbo = 0;
- GLuint texture = 0;
- GLuint fboDepth= 0;
- GLuint fboStencil = 0;
-};
-
-}
-
-#endif
diff --git a/src/mbgl/renderer/raster_bucket.cpp b/src/mbgl/renderer/raster_bucket.cpp
index dfba8cee22..6d09e41fdd 100644
--- a/src/mbgl/renderer/raster_bucket.cpp
+++ b/src/mbgl/renderer/raster_bucket.cpp
@@ -5,7 +5,6 @@ using namespace mbgl;
RasterBucket::RasterBucket(TexturePool& texturePool, const StyleBucketRaster& properties_)
: properties(properties_),
- texture(properties_),
raster(texturePool) {
}
diff --git a/src/mbgl/renderer/raster_bucket.hpp b/src/mbgl/renderer/raster_bucket.hpp
index 0a7651d7cc..e03b08aa5f 100644
--- a/src/mbgl/renderer/raster_bucket.hpp
+++ b/src/mbgl/renderer/raster_bucket.hpp
@@ -3,7 +3,6 @@
#include <mbgl/renderer/bucket.hpp>
#include <mbgl/util/raster.hpp>
-#include <mbgl/renderer/prerendered_texture.hpp>
#include <mbgl/style/style_bucket.hpp>
@@ -24,7 +23,6 @@ public:
bool setImage(const std::string &data);
const StyleBucketRaster &properties;
- PrerenderedTexture texture;
void drawRaster(RasterShader& shader, StaticVertexBuffer &vertices, VertexArrayObject &array);
diff --git a/src/mbgl/shader/line.fragment.glsl b/src/mbgl/shader/line.fragment.glsl
index f4ac1458b3..717c46e10d 100644
--- a/src/mbgl/shader/line.fragment.glsl
+++ b/src/mbgl/shader/line.fragment.glsl
@@ -2,10 +2,7 @@ uniform vec2 u_linewidth;
uniform vec4 u_color;
uniform float u_blur;
-uniform vec2 u_dasharray;
-
varying vec2 v_normal;
-varying float v_linesofar;
void main() {
// Calculate the distance of the pixel from the line in pixels.
@@ -16,10 +13,5 @@ void main() {
// (v_linewidth.s)
float alpha = clamp(min(dist - (u_linewidth.t - u_blur), u_linewidth.s - dist) / u_blur, 0.0, 1.0);
- // Calculate the antialiasing fade factor based on distance to the dash.
- // Only affects alpha when line is dashed
- float pos = mod(v_linesofar, u_dasharray.x + u_dasharray.y);
- alpha *= max(step(0.0, -u_dasharray.y), clamp(min(pos, u_dasharray.x - pos), 0.0, 1.0));
-
gl_FragColor = u_color * alpha;
}
diff --git a/src/mbgl/shader/line.vertex.glsl b/src/mbgl/shader/line.vertex.glsl
index bf0b537e83..1f5432991c 100644
--- a/src/mbgl/shader/line.vertex.glsl
+++ b/src/mbgl/shader/line.vertex.glsl
@@ -20,11 +20,9 @@ uniform vec2 u_linewidth;
uniform vec4 u_color;
varying vec2 v_normal;
-varying float v_linesofar;
void main() {
vec2 a_extrude = a_data.xy;
- float a_linesofar = a_data.z * 128.0 + a_data.w;
// We store the texture normals in the most insignificant bit
// transform y so that 0 => -1 and 1 => 1
@@ -43,5 +41,4 @@ void main() {
// because we're extruding the line in pixel space, regardless of the current
// tile's zoom level.
gl_Position = u_matrix * vec4(floor(a_pos * 0.5), 0.0, 1.0) + u_exmatrix * dist;
- v_linesofar = a_linesofar * u_ratio;
}
diff --git a/src/mbgl/shader/line_shader.hpp b/src/mbgl/shader/line_shader.hpp
index c6adc0ff8d..85152d6e0c 100644
--- a/src/mbgl/shader/line_shader.hpp
+++ b/src/mbgl/shader/line_shader.hpp
@@ -16,7 +16,6 @@ public:
UniformMatrix<4> u_exmatrix = {"u_exmatrix", *this};
Uniform<std::array<float, 4>> u_color = {"u_color", *this};
Uniform<std::array<float, 2>> u_linewidth = {"u_linewidth", *this};
- Uniform<std::array<float, 2>> u_dasharray = {"u_dasharray", *this};
Uniform<float> u_ratio = {"u_ratio", *this};
Uniform<float> u_blur = {"u_blur", *this};
diff --git a/src/mbgl/shader/linesdf.fragment.glsl b/src/mbgl/shader/linesdf.fragment.glsl
new file mode 100644
index 0000000000..90a5eac3e2
--- /dev/null
+++ b/src/mbgl/shader/linesdf.fragment.glsl
@@ -0,0 +1,23 @@
+uniform vec2 u_linewidth;
+uniform vec4 u_color;
+uniform float u_blur;
+uniform sampler2D u_image;
+uniform float u_sdfgamma;
+
+varying vec2 v_normal;
+varying vec2 v_tex;
+
+void main() {
+ // Calculate the distance of the pixel from the line in pixels.
+ float dist = length(v_normal) * u_linewidth.s;
+
+ // Calculate the antialiasing fade factor. This is either when fading in
+ // the line in case of an offset line (v_linewidth.t) or when fading out
+ // (v_linewidth.s)
+ float alpha = clamp(min(dist - (u_linewidth.t - u_blur), u_linewidth.s - dist) / u_blur, 0.0, 1.0);
+
+ float sdfdist = texture2D(u_image, v_tex).a;
+ alpha *= smoothstep(0.5 - u_sdfgamma, 0.5 + u_sdfgamma, sdfdist);
+
+ gl_FragColor = u_color * alpha;
+}
diff --git a/src/mbgl/shader/linesdf.vertex.glsl b/src/mbgl/shader/linesdf.vertex.glsl
new file mode 100644
index 0000000000..0ab6804ab5
--- /dev/null
+++ b/src/mbgl/shader/linesdf.vertex.glsl
@@ -0,0 +1,49 @@
+// floor(127 / 2) == 63.0
+// the maximum allowed miter limit is 2.0 at the moment. the extrude normal is
+// stored in a byte (-128..127). we scale regular normals up to length 63, but
+// there are also "special" normals that have a bigger length (of up to 126 in
+// this case).
+// #define scale 63.0
+#define scale 0.015873016
+
+attribute vec2 a_pos;
+attribute vec4 a_data;
+
+// matrix is for the vertex position, exmatrix is for rotating and projecting
+// the extrusion vector.
+uniform mat4 u_matrix;
+uniform mat4 u_exmatrix;
+
+// shared
+uniform float u_ratio;
+uniform vec2 u_linewidth;
+uniform vec2 u_patternscale;
+uniform float u_tex_y;
+
+varying vec2 v_normal;
+varying vec2 v_tex;
+
+void main() {
+ vec2 a_extrude = a_data.xy;
+ float a_linesofar = a_data.z * 128.0 + a_data.w;
+
+ // We store the texture normals in the most insignificant bit
+ // transform y so that 0 => -1 and 1 => 1
+ // In the texture normal, x is 0 if the normal points straight up/down and 1 if it's a round cap
+ // y is 1 if the normal points up, and -1 if it points down
+ vec2 normal = mod(a_pos, 2.0);
+ normal.y = sign(normal.y - 0.5);
+ v_normal = normal;
+
+ // Scale the extrusion vector down to a normal and then up by the line width
+ // of this vertex.
+ vec4 dist = vec4(u_linewidth.s * a_extrude * scale, 0.0, 0.0);
+
+ // Remove the texture normal bit of the position before scaling it with the
+ // model/view matrix. Add the extrusion vector *after* the model/view matrix
+ // because we're extruding the line in pixel space, regardless of the current
+ // tile's zoom level.
+ gl_Position = u_matrix * vec4(floor(a_pos * 0.5), 0.0, 1.0) + u_exmatrix * dist;
+
+ v_tex = vec2(a_linesofar * u_patternscale.x, normal.y * u_patternscale.y + u_tex_y);
+}
diff --git a/src/mbgl/shader/linesdf_shader.cpp b/src/mbgl/shader/linesdf_shader.cpp
new file mode 100644
index 0000000000..9802afb532
--- /dev/null
+++ b/src/mbgl/shader/linesdf_shader.cpp
@@ -0,0 +1,30 @@
+#include <mbgl/shader/linesdf_shader.hpp>
+#include <mbgl/shader/shaders.hpp>
+#include <mbgl/platform/gl.hpp>
+
+#include <cstdio>
+
+using namespace mbgl;
+
+LineSDFShader::LineSDFShader()
+ : Shader(
+ "line",
+ shaders[LINESDF_SHADER].vertex,
+ shaders[LINESDF_SHADER].fragment
+ ) {
+ if (!valid) {
+ fprintf(stderr, "invalid line shader\n");
+ return;
+ }
+
+ a_pos = MBGL_CHECK_ERROR(glGetAttribLocation(program, "a_pos"));
+ a_data = MBGL_CHECK_ERROR(glGetAttribLocation(program, "a_data"));
+}
+
+void LineSDFShader::bind(char *offset) {
+ MBGL_CHECK_ERROR(glEnableVertexAttribArray(a_pos));
+ MBGL_CHECK_ERROR(glVertexAttribPointer(a_pos, 2, GL_SHORT, false, 8, offset + 0));
+
+ MBGL_CHECK_ERROR(glEnableVertexAttribArray(a_data));
+ MBGL_CHECK_ERROR(glVertexAttribPointer(a_data, 4, GL_BYTE, false, 8, offset + 4));
+}
diff --git a/src/mbgl/shader/linesdf_shader.hpp b/src/mbgl/shader/linesdf_shader.hpp
new file mode 100644
index 0000000000..918ed5cbab
--- /dev/null
+++ b/src/mbgl/shader/linesdf_shader.hpp
@@ -0,0 +1,34 @@
+#ifndef MBGL_SHADER_SHADER_LINESDF
+#define MBGL_SHADER_SHADER_LINESDF
+
+#include <mbgl/shader/shader.hpp>
+#include <mbgl/shader/uniform.hpp>
+
+namespace mbgl {
+
+class LineSDFShader : public Shader {
+public:
+ LineSDFShader();
+
+ void bind(char *offset);
+
+ UniformMatrix<4> u_matrix = {"u_matrix", *this};
+ UniformMatrix<4> u_exmatrix = {"u_exmatrix", *this};
+ Uniform<std::array<float, 4>> u_color = {"u_color", *this};
+ Uniform<std::array<float, 2>> u_linewidth = {"u_linewidth", *this};
+ Uniform<float> u_ratio = {"u_ratio", *this};
+ Uniform<float> u_blur = {"u_blur", *this};
+ Uniform<std::array<float, 2>> u_patternscale = { "u_patternscale", *this };
+ Uniform<float> u_tex_y = {"u_tex_y", *this};
+ Uniform<int32_t> u_image = {"u_image", *this};
+ Uniform<float> u_sdfgamma = {"u_sdfgamma", *this};
+
+private:
+ int32_t a_pos = -1;
+ int32_t a_data = -1;
+};
+
+
+}
+
+#endif
diff --git a/src/mbgl/style/function_properties.cpp b/src/mbgl/style/function_properties.cpp
index 69466c1f64..81b1c85c72 100644
--- a/src/mbgl/style/function_properties.cpp
+++ b/src/mbgl/style/function_properties.cpp
@@ -12,6 +12,7 @@ inline T defaultStopsValue();
template <> inline bool defaultStopsValue() { return true; }
template <> inline float defaultStopsValue() { return 1.0f; }
template <> inline Color defaultStopsValue() { return {{ 0, 0, 0, 1 }}; }
+template <> inline std::vector<float> defaultStopsValue() { return {{ 1, 0 }}; }
template <typename T>
@@ -64,5 +65,6 @@ T StopsFunction<T>::evaluate(float z) const {
template bool StopsFunction<bool>::evaluate(float z) const;
template float StopsFunction<float>::evaluate(float z) const;
template Color StopsFunction<Color>::evaluate(float z) const;
+template std::vector<float> StopsFunction<std::vector<float>>::evaluate(float z) const;
}
diff --git a/src/mbgl/style/property_fallback.cpp b/src/mbgl/style/property_fallback.cpp
index 965baf6c4b..dc747b37e6 100644
--- a/src/mbgl/style/property_fallback.cpp
+++ b/src/mbgl/style/property_fallback.cpp
@@ -20,8 +20,6 @@ const std::map<PropertyKey, PropertyValue> PropertyFallbackValue::properties = {
{ PropertyKey::LineWidth, defaultStyleProperties<LineProperties>().width },
{ PropertyKey::LineGapWidth, defaultStyleProperties<LineProperties>().gap_width },
{ PropertyKey::LineBlur, defaultStyleProperties<LineProperties>().blur },
- { PropertyKey::LineDashLand, defaultStyleProperties<LineProperties>().dash_array[0] },
- { PropertyKey::LineDashGap, defaultStyleProperties<LineProperties>().dash_array[1] },
{ PropertyKey::IconOpacity, defaultStyleProperties<SymbolProperties>().icon.opacity },
{ PropertyKey::IconRotate, defaultStyleProperties<SymbolProperties>().icon.rotate },
diff --git a/src/mbgl/style/property_key.hpp b/src/mbgl/style/property_key.hpp
index efeebf0242..e283f11579 100644
--- a/src/mbgl/style/property_key.hpp
+++ b/src/mbgl/style/property_key.hpp
@@ -24,8 +24,6 @@ enum class PropertyKey {
LineGapWidth,
LineBlur,
LineDashArray, // for transitions only
- LineDashLand,
- LineDashGap,
LineImage,
IconOpacity,
diff --git a/src/mbgl/style/property_value.hpp b/src/mbgl/style/property_value.hpp
index 1b22b31177..e017981dee 100644
--- a/src/mbgl/style/property_value.hpp
+++ b/src/mbgl/style/property_value.hpp
@@ -5,6 +5,8 @@
#include <mbgl/style/function_properties.hpp>
#include <mbgl/style/types.hpp>
+#include <vector>
+
namespace mbgl {
typedef mapbox::util::variant<
@@ -13,7 +15,8 @@ typedef mapbox::util::variant<
RotateAnchorType,
Function<bool>,
Function<float>,
- Function<Color>
+ Function<Color>,
+ Function<std::vector<float>>
> PropertyValue;
}
diff --git a/src/mbgl/style/style_bucket.hpp b/src/mbgl/style/style_bucket.hpp
index d84d35d5b2..cc71ea99f7 100644
--- a/src/mbgl/style/style_bucket.hpp
+++ b/src/mbgl/style/style_bucket.hpp
@@ -80,10 +80,6 @@ public:
class StyleBucketRaster {
public:
- bool prerendered = false;
- uint16_t size = 256;
- float blur = 0.0f;
- float buffer = 0.03125f;
};
typedef mapbox::util::variant<StyleBucketFill, StyleBucketLine, StyleBucketSymbol,
diff --git a/src/mbgl/style/style_layer.cpp b/src/mbgl/style/style_layer.cpp
index e58756afa4..262ca23af8 100644
--- a/src/mbgl/style/style_layer.cpp
+++ b/src/mbgl/style/style_layer.cpp
@@ -51,11 +51,6 @@ void StyleLayer::setClasses(const std::vector<std::string> &class_names, const t
appliedProperties.add(ClassID::Fallback, begin, end, value);
}
}
-
- // Update all child layers as well.
- if (layers) {
- layers->setClasses(class_names, now, defaultTransition);
- }
}
// Helper function for applying all properties of a a single class that haven't been applied yet.
@@ -185,9 +180,11 @@ void StyleLayer::applyStyleProperties<LineProperties>(const float z, const times
applyTransitionedStyleProperty(PropertyKey::LineWidth, line.width, z, now);
applyTransitionedStyleProperty(PropertyKey::LineGapWidth, line.gap_width, z, now);
applyTransitionedStyleProperty(PropertyKey::LineBlur, line.blur, z, now);
- applyTransitionedStyleProperty(PropertyKey::LineDashLand, line.dash_array[0], z, now);
- applyTransitionedStyleProperty(PropertyKey::LineDashGap, line.dash_array[1], z, now);
+ applyStyleProperty(PropertyKey::LineDashArray, line.dash_array, z, now);
applyStyleProperty(PropertyKey::LineImage, line.image, z, now);
+
+ // for scaling dasharrays
+ applyStyleProperty(PropertyKey::LineWidth, line.dash_line_width, std::floor(z), now + 10000);
}
template <>
@@ -239,10 +236,6 @@ void StyleLayer::applyStyleProperties<BackgroundProperties>(const float z, const
}
void StyleLayer::updateProperties(float z, const timestamp now) {
- if (layers) {
- layers->updateProperties(z, now);
- }
-
cleanupAppliedStyleProperties(now);
switch (type) {
diff --git a/src/mbgl/style/style_layer.hpp b/src/mbgl/style/style_layer.hpp
index 641dc1e71c..7cf661ca33 100644
--- a/src/mbgl/style/style_layer.hpp
+++ b/src/mbgl/style/style_layer.hpp
@@ -79,9 +79,6 @@ public:
// Stores the evaluated, and cascaded styling information, specific to this
// layer's type.
StyleProperties properties;
-
- // Child layer array (if this layer has child layers).
- util::ptr<StyleLayerGroup> layers;
};
}
diff --git a/src/mbgl/style/style_parser.cpp b/src/mbgl/style/style_parser.cpp
index 2dec648aff..cdec991a16 100644
--- a/src/mbgl/style/style_parser.cpp
+++ b/src/mbgl/style/style_parser.cpp
@@ -209,6 +209,24 @@ Color parseColor(JSVal value) {
css_color.a}};
}
+std::tuple<bool,std::vector<float>> parseFloatArray(JSVal value) {
+ if (!value.IsArray()) {
+ Log::Warning(Event::ParseStyle, "dasharray value must be an array of numbers");
+ return std::tuple<bool, std::vector<float>> { false, std::vector<float>() };
+ }
+
+ std::vector<float> vec;
+ for (rapidjson::SizeType i = 0; i < value.Size(); ++i) {
+ JSVal part = value[i];
+ if (!part.IsNumber()) {
+ Log::Warning(Event::ParseStyle, "dasharray value must be an array of numbers");
+ return std::tuple<bool, std::vector<float>> { false, std::vector<float>() };
+ }
+ vec.push_back(part.GetDouble());
+ }
+ return std::tuple<bool, std::vector<float>> { true, vec };
+}
+
template <>
bool StyleParser::parseFunctionArgument(JSVal value) {
JSVal rvalue = replaceConstant(value);
@@ -239,6 +257,12 @@ Color StyleParser::parseFunctionArgument(JSVal value) {
return parseColor(rvalue);
}
+template <>
+std::vector<float> StyleParser::parseFunctionArgument(JSVal value) {
+ JSVal rvalue = replaceConstant(value);
+ return std::get<1>(parseFloatArray(rvalue));
+}
+
template <typename T> inline float defaultBaseValue() { return 1.75; }
template <> inline float defaultBaseValue<Color>() { return 1.0; }
@@ -293,17 +317,6 @@ std::tuple<bool, Function<T>> StyleParser::parseFunction(JSVal value) {
template <typename T>
-bool StyleParser::parseFunction(PropertyKey key, ClassProperties &klass, JSVal value) {
- bool parsed;
- Function<T> function;
- std::tie(parsed, function) = parseFunction<T>(value);
- if (parsed) {
- klass.set(key, function);
- }
- return parsed;
-}
-
-template <typename T>
bool StyleParser::setProperty(JSVal value, const char *property_name, PropertyKey key, ClassProperties &klass) {
bool parsed;
T result;
@@ -314,18 +327,6 @@ bool StyleParser::setProperty(JSVal value, const char *property_name, PropertyKe
return parsed;
}
-template <typename T>
-bool StyleParser::setProperty(JSVal value, const char *property_name, T &target) {
- bool parsed;
- T result;
- std::tie(parsed, result) = parseProperty<T>(value, property_name);
- if (parsed) {
- target = std::move(result);
- }
- return parsed;
-}
-
-
template<typename T>
bool StyleParser::parseOptionalProperty(const char *property_name, PropertyKey key, ClassProperties &klass, JSVal value) {
if (!value.HasMember(property_name)) {
@@ -335,15 +336,6 @@ bool StyleParser::parseOptionalProperty(const char *property_name, PropertyKey k
}
}
-template <typename T>
-bool StyleParser::parseOptionalProperty(const char *property_name, T &target, JSVal value) {
- if (!value.HasMember(property_name)) {
- return false;
- } else {
- return setProperty<T>(replaceConstant(value[property_name]), property_name, target);
- }
-}
-
template<> std::tuple<bool, std::string> StyleParser::parseProperty(JSVal value, const char *property_name) {
if (!value.IsString()) {
Log::Warning(Event::ParseStyle, "value of '%s' must be a string", property_name);
@@ -426,6 +418,18 @@ template<> std::tuple<bool, Function<Color>> StyleParser::parseProperty(JSVal va
}
}
+template<> std::tuple<bool, Function<std::vector<float>>> StyleParser::parseProperty(JSVal value, const char *property_name) {
+ if (value.IsObject()) {
+ return parseFunction<std::vector<float>>(value);
+ } else if (value.IsArray()) {
+ std::tuple<bool, std::vector<float>> parsed = parseFloatArray(value);
+ return std::tuple<bool, Function<std::vector<float>>> { std::get<0>(parsed), ConstantFunction<std::vector<float>>(std::get<1>(parsed)) };
+ } else {
+ Log::Warning(Event::ParseStyle, "value of '%s' must be an array of numbers, or a number array function", property_name);
+ return std::tuple<bool, Function<std::vector<float>>> { false, ConstantFunction<std::vector<float>>(std::vector<float>()) };
+ }
+}
+
template <typename T>
bool StyleParser::parseOptionalProperty(const char *property_name, const std::vector<PropertyKey> &keys, ClassProperties &klass, JSVal value) {
if (value.HasMember(property_name)) {
@@ -490,10 +494,6 @@ util::ptr<StyleLayer> StyleParser::createLayer(JSVal value) {
util::ptr<StyleLayer> layer = std::make_shared<StyleLayer>(
layer_id, std::move(paints));
- if (value.HasMember("layers")) {
- layer->layers = createLayers(value["layers"]);
- }
-
// Store the layer ID so we can reference it later.
layers.emplace(layer_id, std::pair<JSVal, util::ptr<StyleLayer>> { value, layer });
@@ -523,7 +523,7 @@ void StyleParser::parseLayer(std::pair<JSVal, util::ptr<StyleLayer>> &pair) {
}
}
- if (layer->bucket || (layer->layers && layer->type != StyleLayerType::Raster)) {
+ if (layer->bucket) {
// Skip parsing this again. We already have a valid layer definition.
return;
}
@@ -588,8 +588,7 @@ void StyleParser::parsePaint(JSVal value, ClassProperties &klass) {
parseOptionalProperty<PropertyTransition>("line-gap-width-transition", Key::LineGapWidth, klass, value);
parseOptionalProperty<Function<float>>("line-blur", Key::LineBlur, klass, value);
parseOptionalProperty<PropertyTransition>("line-blur-transition", Key::LineBlur, klass, value);
- parseOptionalProperty<Function<float>>("line-dasharray", { Key::LineDashLand, Key::LineDashGap }, klass, value);
- parseOptionalProperty<PropertyTransition>("line-dasharray-transition", Key::LineDashArray, klass, value);
+ parseOptionalProperty<Function<std::vector<float>>>("line-dasharray", Key::LineDashArray, klass, value);
parseOptionalProperty<std::string>("line-image", Key::LineImage, klass, value);
parseOptionalProperty<Function<float>>("icon-opacity", Key::IconOpacity, klass, value);
@@ -661,18 +660,9 @@ void StyleParser::parseReference(JSVal value, util::ptr<StyleLayer> &layer) {
parseLayer(it->second);
stack.pop_front();
-
util::ptr<StyleLayer> reference = it->second.second;
-
layer->type = reference->type;
-
- if (reference->layers) {
- Log::Warning(Event::ParseStyle, "layer '%s' references composite layer", layer->id.c_str());
- // We cannot parse this layer further.
- return;
- } else {
- layer->bucket = reference->bucket;
- }
+ layer->bucket = reference->bucket;
}
#pragma mark - Parse Bucket
@@ -812,17 +802,6 @@ void StyleParser::parseLayout(JSVal value, util::ptr<StyleLayer> &layer) {
parseRenderProperty(value, render.text.optional, "text-optional");
} break;
- case StyleLayerType::Raster: {
- StyleBucketRaster &render = bucket.render.get<StyleBucketRaster>();
-
- parseRenderProperty(value, render.size, "raster-size");
- parseRenderProperty(value, render.blur, "raster-blur");
- parseRenderProperty(value, render.buffer, "raster-buffer");
- if (layer->layers) {
- render.prerendered = true;
- }
- } break;
-
default:
// There are no render properties for these layer types.
break;
diff --git a/src/mbgl/style/style_parser.hpp b/src/mbgl/style/style_parser.hpp
index c37e856034..42e22f9458 100644
--- a/src/mbgl/style/style_parser.hpp
+++ b/src/mbgl/style/style_parser.hpp
@@ -69,18 +69,12 @@ private:
template <typename T>
bool parseOptionalProperty(const char *property_name, const std::vector<PropertyKey> &keys, ClassProperties &klass, JSVal value);
template <typename T>
- bool parseOptionalProperty(const char *property_name, T &target, JSVal value);
- template <typename T>
bool setProperty(JSVal value, const char *property_name, PropertyKey key, ClassProperties &klass);
- template <typename T>
- bool setProperty(JSVal value, const char *property_name, T &target);
template <typename T>
std::tuple<bool, T> parseProperty(JSVal value, const char *property_name);
template <typename T>
- bool parseFunction(PropertyKey key, ClassProperties &klass, JSVal value);
- template <typename T>
std::tuple<bool, Function<T>> parseFunction(JSVal value);
template <typename T>
T parseFunctionArgument(JSVal value);
diff --git a/src/mbgl/style/style_properties.hpp b/src/mbgl/style/style_properties.hpp
index c44b7c34c8..c5149b2d1c 100644
--- a/src/mbgl/style/style_properties.hpp
+++ b/src/mbgl/style/style_properties.hpp
@@ -9,6 +9,7 @@
#include <string>
#include <type_traits>
#include <memory>
+#include <vector>
namespace mbgl {
@@ -36,7 +37,8 @@ struct LineProperties {
float width = 1;
float gap_width = 0;
float blur = 0;
- std::array<float, 2> dash_array = {{ 1, -1 }};
+ std::vector<float> dash_array;
+ float dash_line_width = 1;
std::string image;
inline bool isVisible() const {
diff --git a/src/mbgl/util/interpolate.hpp b/src/mbgl/util/interpolate.hpp
index c9232db4eb..952d7b9c10 100644
--- a/src/mbgl/util/interpolate.hpp
+++ b/src/mbgl/util/interpolate.hpp
@@ -2,6 +2,7 @@
#define MBGL_UTIL_INTERPOLATE
#include <array>
+#include <vector>
namespace mbgl {
namespace util {
@@ -21,6 +22,10 @@ inline std::array<T, 4> interpolate(const std::array<T, 4>& a, const std::array<
}};
}
+inline std::vector<float> interpolate(const std::vector<float> &a, const std::vector<float>, const double) {
+ return a;
+}
+
}
}
diff --git a/src/mbgl/util/raster.hpp b/src/mbgl/util/raster.hpp
index ff27f509f4..bbdfc5321d 100644
--- a/src/mbgl/util/raster.hpp
+++ b/src/mbgl/util/raster.hpp
@@ -5,7 +5,6 @@
#include <mbgl/util/texture_pool.hpp>
#include <mbgl/util/image.hpp>
#include <mbgl/util/ptr.hpp>
-#include <mbgl/renderer/prerendered_texture.hpp>
#include <string>
#include <mutex>