summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xbin/convert-style.js4
-rw-r--r--bin/style.js3
-rw-r--r--include/llmr/map/map.hpp2
-rw-r--r--include/llmr/renderer/bucket.hpp3
-rw-r--r--include/llmr/renderer/fill_bucket.hpp2
-rw-r--r--include/llmr/renderer/line_bucket.hpp2
-rw-r--r--include/llmr/renderer/painter.hpp6
-rw-r--r--include/llmr/renderer/shader-pattern.hpp25
-rw-r--r--include/llmr/shader/shaders.hpp1
-rw-r--r--include/llmr/style/properties.hpp3
-rw-r--r--include/llmr/style/style.hpp3
-rw-r--r--proto/style.proto1
-rw-r--r--resources/style.pbfbin1027 -> 1033 bytes
-rw-r--r--src/CMakeLists.txt2
-rw-r--r--src/map/map.cpp5
-rw-r--r--src/renderer/fill_bucket.cpp4
-rw-r--r--src/renderer/line_bucket.cpp4
-rw-r--r--src/renderer/painter.cpp74
-rw-r--r--src/renderer/shader-pattern.cpp27
-rw-r--r--src/shader/pattern.fragment.glsl26
-rw-r--r--src/shader/pattern.vertex.glsl10
-rw-r--r--src/shader/shaders.cpp6
-rw-r--r--src/style/resources.cpp44
-rw-r--r--src/style/style.cpp3
24 files changed, 189 insertions, 71 deletions
diff --git a/bin/convert-style.js b/bin/convert-style.js
index 74501ad8e3..549732c001 100755
--- a/bin/convert-style.js
+++ b/bin/convert-style.js
@@ -140,6 +140,10 @@ function createFillClass(layer, name) {
pbf.writeMessage(7 /* opacity */, convertProperty(layer.opacity));
}
+ if ('image' in layer) {
+ pbf.writeTaggedString(8 /* image */, layer.image);
+ }
+
return pbf;
}
diff --git a/bin/style.js b/bin/style.js
index 26b7bc6544..10f5501660 100644
--- a/bin/style.js
+++ b/bin/style.js
@@ -82,7 +82,8 @@ module.exports = {
"park": {
"type": "fill",
"color": "#c8df9f",
- "antialias": true
+ "antialias": true,
+ "image": "park"
},
"wood": {
"type": "fill",
diff --git a/include/llmr/map/map.hpp b/include/llmr/map/map.hpp
index 2d950afe47..0cae687302 100644
--- a/include/llmr/map/map.hpp
+++ b/include/llmr/map/map.hpp
@@ -69,8 +69,6 @@ private:
int32_t min_zoom;
int32_t max_zoom;
- std::shared_ptr<Sprite> sprite;
-
std::forward_list<Tile::Ptr> tiles;
std::forward_list<Tile::Ptr> historic_tiles;
};
diff --git a/include/llmr/renderer/bucket.hpp b/include/llmr/renderer/bucket.hpp
index 95db9e017d..7ae0d2d008 100644
--- a/include/llmr/renderer/bucket.hpp
+++ b/include/llmr/renderer/bucket.hpp
@@ -2,6 +2,7 @@
#define LLMR_RENDERER_BUCKET
#include <string>
+#include <llmr/map/tile.hpp>
namespace llmr {
@@ -10,7 +11,7 @@ class Painter;
class Bucket {
public:
Bucket() = default;
- virtual void render(Painter& painter, const std::string& layer_name) = 0;
+ virtual void render(Painter& painter, const std::string& layer_name, const Tile::ID& id) = 0;
private:
// Make noncopyable
diff --git a/include/llmr/renderer/fill_bucket.hpp b/include/llmr/renderer/fill_bucket.hpp
index 32d8bc3218..bf1dd47cb4 100644
--- a/include/llmr/renderer/fill_bucket.hpp
+++ b/include/llmr/renderer/fill_bucket.hpp
@@ -18,7 +18,7 @@ class FillBucket : public Bucket {
public:
FillBucket(const std::shared_ptr<FillBuffer>& buffer, const BucketDescription& bucket_desc);
- virtual void render(Painter& painter, const std::string& layer_name);
+ virtual void render(Painter& painter, const std::string& layer_name, const Tile::ID& id);
void addGeometry(pbf& data);
void addGeometry(const std::vector<Coordinate>& line);
diff --git a/include/llmr/renderer/line_bucket.hpp b/include/llmr/renderer/line_bucket.hpp
index 8350dc4b22..4c75fd38f6 100644
--- a/include/llmr/renderer/line_bucket.hpp
+++ b/include/llmr/renderer/line_bucket.hpp
@@ -17,7 +17,7 @@ class LineBucket : public Bucket {
public:
LineBucket(const std::shared_ptr<LineBuffer>& buffer, const BucketDescription& bucket_desc);
- virtual void render(Painter& painter, const std::string& layer_name);
+ virtual void render(Painter& painter, const std::string& layer_name, const Tile::ID& id);
void addGeometry(pbf& data);
void addGeometry(const std::vector<Coordinate>& line);
diff --git a/include/llmr/renderer/painter.hpp b/include/llmr/renderer/painter.hpp
index 86d53c1637..dafa61c11d 100644
--- a/include/llmr/renderer/painter.hpp
+++ b/include/llmr/renderer/painter.hpp
@@ -5,6 +5,7 @@
#include "shader-plain.hpp"
#include "shader-outline.hpp"
#include "shader-line.hpp"
+#include "shader-pattern.hpp"
#include "../map/tile.hpp"
#include "../geometry/vertex_buffer.hpp"
@@ -42,8 +43,8 @@ public:
void renderMatte();
void renderBackground();
- void renderFill(FillBucket& bucket, const std::string& layer_name);
- void renderLine(LineBucket& bucket, const std::string& layer_name);
+ void renderFill(FillBucket& bucket, const std::string& layer_name, const Tile::ID& id);
+ void renderLine(LineBucket& bucket, const std::string& layer_name, const Tile::ID& id);
void drawClippingMask();
@@ -68,6 +69,7 @@ private:
std::shared_ptr<PlainShader> plainShader;
std::shared_ptr<OutlineShader> outlineShader;
std::shared_ptr<LineShader> lineShader;
+ std::shared_ptr<PatternShader> patternShader;
// Set up the stencil quad we're using to generate the stencil mask.
VertexBuffer tileStencilBuffer = {
diff --git a/include/llmr/renderer/shader-pattern.hpp b/include/llmr/renderer/shader-pattern.hpp
new file mode 100644
index 0000000000..5b295cfffb
--- /dev/null
+++ b/include/llmr/renderer/shader-pattern.hpp
@@ -0,0 +1,25 @@
+#ifndef LLMR_RENDERER_SHADER_PATTERN
+#define LLMR_RENDERER_SHADER_PATTERN
+
+#include "shader.hpp"
+
+namespace llmr {
+
+class PatternShader : public Shader {
+public:
+ PatternShader();
+
+ int32_t a_pos;
+ int32_t u_matrix;
+ int32_t u_color;
+ int32_t u_offset;
+ int32_t u_pattern_size;
+ int32_t u_pattern_tl;
+ int32_t u_pattern_br;
+ int32_t u_mix;
+
+};
+
+}
+
+#endif
diff --git a/include/llmr/shader/shaders.hpp b/include/llmr/shader/shaders.hpp
index 885f81813e..065b8d47f1 100644
--- a/include/llmr/shader/shaders.hpp
+++ b/include/llmr/shader/shaders.hpp
@@ -14,6 +14,7 @@ enum {
FILL_SHADER,
LINE_SHADER,
OUTLINE_SHADER,
+ PATTERN_SHADER,
PLAIN_SHADER,
SHADER_COUNT
};
diff --git a/include/llmr/style/properties.hpp b/include/llmr/style/properties.hpp
index f0e3cf5079..572ca61acd 100644
--- a/include/llmr/style/properties.hpp
+++ b/include/llmr/style/properties.hpp
@@ -3,6 +3,7 @@
#include <array>
#include <vector>
+#include <string>
namespace llmr {
@@ -87,6 +88,7 @@ struct FillClass {
Color fill_color = {{ 0, 0, 0, 1 }};
Color stroke_color = {{ 0, 0, 0, std::numeric_limits<float>::infinity() }};
FunctionProperty<float> opacity = 1;
+ std::string image;
};
struct FillProperties {
@@ -96,6 +98,7 @@ struct FillProperties {
Color fill_color = {{ 0, 0, 0, 1 }};
Color stroke_color = {{ 0, 0, 0, 1 }};
float opacity = 1.0;
+ std::string image;
};
}
diff --git a/include/llmr/style/style.hpp b/include/llmr/style/style.hpp
index 80834fa44f..f2acbd1eea 100644
--- a/include/llmr/style/style.hpp
+++ b/include/llmr/style/style.hpp
@@ -11,6 +11,7 @@
#include "bucket_description.hpp"
#include "layer_description.hpp"
#include "class_description.hpp"
+#include "sprite.hpp"
namespace llmr {
@@ -37,6 +38,8 @@ private:
static Color parseColor(pbf& data);
public:
+ std::shared_ptr<Sprite> sprite;
+
// This is static information parsed from the stylesheet.
std::map<std::string, BucketDescription> buckets;
std::vector<LayerDescription> layers;
diff --git a/proto/style.proto b/proto/style.proto
index 281749c903..8459477bf7 100644
--- a/proto/style.proto
+++ b/proto/style.proto
@@ -79,6 +79,7 @@ message fill_style {
optional fixed32 fill_color = 5 [ default = 0x000000FF ]; // rgba (=> rgb << 8 | 0xFF for opaque!)
optional fixed32 stroke_color = 6; // if none is specified, no stroke will be painted
optional property opacity = 7; // values from 0..1
+ optional string image = 8;
// TODO: translate x/y
}
diff --git a/resources/style.pbf b/resources/style.pbf
index 2157505641..e70b6ae2bb 100644
--- a/resources/style.pbf
+++ b/resources/style.pbf
Binary files differ
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 66fea4cd14..3d805ab3d5 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -14,6 +14,7 @@ SET(llmr_SOURCES
renderer/shader-plain.cpp
renderer/shader-outline.cpp
renderer/shader-line.cpp
+ renderer/shader-pattern.cpp
renderer/shader.cpp
renderer/fill_bucket.cpp
renderer/line_bucket.cpp
@@ -46,6 +47,7 @@ SET(llmr_HEADERS
../include/llmr/renderer/shader-plain.hpp
../include/llmr/renderer/shader-outline.hpp
../include/llmr/renderer/shader-line.hpp
+ ../include/llmr/renderer/shader-pattern.hpp
../include/llmr/renderer/shader.hpp
../include/llmr/shader/shaders.hpp
../include/llmr/util/animation.hpp
diff --git a/src/map/map.cpp b/src/map/map.cpp
index db48054624..341f7f7197 100644
--- a/src/map/map.cpp
+++ b/src/map/map.cpp
@@ -21,8 +21,9 @@ Map::Map(Settings& settings)
min_zoom(0),
max_zoom(14) {
- sprite = std::make_shared<Sprite>();
- sprite->load("http://localhost:3333/gl/debug/img/sprite");
+ // TODO: Extract that information from the stylesheet instead of hard coding
+ style.sprite = std::make_shared<Sprite>();
+ style.sprite->load("http://localhost:3333/gl/debug/img/sprite");
}
Map::~Map() {
diff --git a/src/renderer/fill_bucket.cpp b/src/renderer/fill_bucket.cpp
index 13de7edf88..4e20620aa5 100644
--- a/src/renderer/fill_bucket.cpp
+++ b/src/renderer/fill_bucket.cpp
@@ -116,8 +116,8 @@ void FillBucket::drawVertices(int32_t attrib) {
glDrawArrays(GL_LINE_STRIP, 0, length);
}
-void FillBucket::render(Painter& painter, const std::string& layer_name) {
- painter.renderFill(*this, layer_name);
+void FillBucket::render(Painter& painter, const std::string& layer_name, const Tile::ID& id) {
+ painter.renderFill(*this, layer_name, id);
}
uint32_t FillBucket::size() const {
diff --git a/src/renderer/line_bucket.cpp b/src/renderer/line_bucket.cpp
index 964e7879f5..51178ffd49 100644
--- a/src/renderer/line_bucket.cpp
+++ b/src/renderer/line_bucket.cpp
@@ -259,8 +259,8 @@ void LineBucket::addGeometry(const std::vector<Coordinate>& vertices) {
length = buffer->length() - start;
}
-void LineBucket::render(Painter& painter, const std::string& layer_name) {
- painter.renderLine(*this, layer_name);
+void LineBucket::render(Painter& painter, const std::string& layer_name, const Tile::ID& id) {
+ painter.renderLine(*this, layer_name, id);
}
uint32_t LineBucket::size() const {
diff --git a/src/renderer/painter.cpp b/src/renderer/painter.cpp
index 35224ab837..cb33964fc8 100644
--- a/src/renderer/painter.cpp
+++ b/src/renderer/painter.cpp
@@ -35,6 +35,7 @@ void Painter::setup() {
assert(plainShader);
assert(outlineShader);
assert(lineShader);
+ assert(patternShader);
glEnable(GL_STENCIL_TEST);
@@ -49,6 +50,7 @@ void Painter::setupShaders() {
plainShader = std::make_shared<PlainShader>();
outlineShader = std::make_shared<OutlineShader>();
lineShader = std::make_shared<LineShader>();
+ patternShader = std::make_shared<PatternShader>();
}
void Painter::changeMatrix(const Tile::ID& id) {
@@ -146,13 +148,13 @@ void Painter::renderLayers(const std::shared_ptr<Tile>& tile, const std::vector<
auto bucket_it = tile->buckets.find(layer_desc.bucket_name);
if (bucket_it != tile->buckets.end()) {
assert(bucket_it->second);
- bucket_it->second->render(*this, layer_desc.name);
+ bucket_it->second->render(*this, layer_desc.name, tile->id);
}
}
}
}
-void Painter::renderFill(FillBucket& bucket, const std::string& layer_name) {
+void Painter::renderFill(FillBucket& bucket, const std::string& layer_name, const Tile::ID& id) {
const FillProperties& properties = style.computed.fills[layer_name];
// Abort early.
@@ -238,50 +240,54 @@ void Painter::renderFill(FillBucket& bucket, const std::string& layer_name) {
bucket.drawVertices(outlineShader->a_pos);
}
- // var imagePos = layerStyle.image && imageSprite.getPosition(layerStyle.image, true);
- bool imagePos = false;
- if (imagePos) {
- // // Draw texture fill
+ // Only draw regions that we marked
+ glStencilFunc(GL_NOTEQUAL, 0x0, 0x3F);
+
+ if (properties.image.size() && style.sprite) {
+ // Draw texture fill
+ ImagePosition imagePos = style.sprite->getPosition(properties.image, true);
+
+ double factor = 8.0 / pow(2, transform.getIntegerZoom() - id.z);
+ double mix = fmod(transform.getZoom(), 1.0);
+ vec2<double> imageSize { imagePos.size.x * factor, imagePos.size.y * factor };
+
+ vec2<double> offset {
+ fmod(id.x * 4096, imageSize.x),
+ fmod(id.y * 4096, imageSize.y)
+ };
+
+ switchShader(patternShader);
+ glUniformMatrix4fv(patternShader->u_matrix, 1, GL_FALSE, matrix.data());
+ glUniform2f(patternShader->u_pattern_size, imageSize.x, imageSize.y);
+ glUniform2f(patternShader->u_offset, offset.x, offset.y);
+ glUniform2f(patternShader->u_pattern_tl, imagePos.tl.x, imagePos.tl.y);
+ glUniform2f(patternShader->u_pattern_br, imagePos.br.x, imagePos.br.y);
+ glUniform4fv(patternShader->u_color, 1, fill_color.data());
+ glUniform1f(patternShader->u_mix, mix);
+ style.sprite->bind(true);
+
+ // Draw a rectangle that covers the entire viewport.
+ tileStencilBuffer.bind();
+ glVertexAttribPointer(patternShader->a_pos, 2, GL_SHORT, false, 0, BUFFER_OFFSET(0));
+ glDrawArrays(GL_TRIANGLES, 0, tileStencilBuffer.length());
- // var factor = 8 / Math.pow(2, painter.transform.zoom - params.z);
- // var mix = painter.transform.z % 1.0;
- // var imageSize = [imagePos.size[0] * factor, imagePos.size[1] * factor];
-
- // var offset = [
- // (params.x * 4096) % imageSize[0],
- // (params.y * 4096) % imageSize[1]
- // ];
-
- // glSwitchShader(painter.patternShader, painter.posMatrix, painter.exMatrix);
- // glUniform1i(painter.patternShader.u_image, 0);
- // glUniform2fv(painter.patternShader.u_pattern_size, imageSize);
- // glUniform2fv(painter.patternShader.u_offset, offset);
- // glUniform2fv(painter.patternShader.u_rotate, [1, 1]);
- // glUniform2fv(painter.patternShader.u_pattern_tl, imagePos.tl);
- // glUniform2fv(painter.patternShader.u_pattern_br, imagePos.br);
- // glUniform4fv(painter.patternShader.u_color, color);
- // glUniform1f(painter.patternShader.u_mix, mix);
- // imageSprite.bind(gl, true);
} else {
// Draw filling rectangle.
switchShader(fillShader);
glUniformMatrix4fv(fillShader->u_matrix, 1, GL_FALSE, matrix.data());
glUniform4fv(fillShader->u_color, 1, fill_color.data());
- }
- // Only draw regions that we marked
- glStencilFunc(GL_NOTEQUAL, 0x0, 0x3F);
-
- // Draw a rectangle that covers the entire viewport.
- tileStencilBuffer.bind();
- glVertexAttribPointer(fillShader->a_pos, 2, GL_SHORT, false, 0, BUFFER_OFFSET(0));
- glDrawArrays(GL_TRIANGLES, 0, tileStencilBuffer.length());
+ // Draw a rectangle that covers the entire viewport.
+ tileStencilBuffer.bind();
+ glVertexAttribPointer(fillShader->a_pos, 2, GL_SHORT, false, 0, BUFFER_OFFSET(0));
+ glDrawArrays(GL_TRIANGLES, 0, tileStencilBuffer.length());
+ }
glStencilMask(0x00);
glStencilFunc(GL_EQUAL, 0x80, 0x80);
}
-void Painter::renderLine(LineBucket& bucket, const std::string& layer_name) {
+void Painter::renderLine(LineBucket& bucket, const std::string& layer_name, const Tile::ID& id) {
const LineProperties& properties = style.computed.lines[layer_name];
// Abort early.
diff --git a/src/renderer/shader-pattern.cpp b/src/renderer/shader-pattern.cpp
new file mode 100644
index 0000000000..4a921c665b
--- /dev/null
+++ b/src/renderer/shader-pattern.cpp
@@ -0,0 +1,27 @@
+#include <llmr/renderer/shader-pattern.hpp>
+#include <llmr/shader/shaders.hpp>
+#include <llmr/platform/gl.hpp>
+
+using namespace llmr;
+
+PatternShader::PatternShader()
+ : Shader(
+ shaders[PATTERN_SHADER].vertex,
+ shaders[PATTERN_SHADER].fragment
+ ) {
+ if (!valid) {
+ fprintf(stderr, "invalid pattern shader\n");
+ return;
+ }
+
+ a_pos = glGetAttribLocation(program, "a_pos");
+ attributes.emplace_front(a_pos);
+
+ u_matrix = glGetUniformLocation(program, "u_matrix");
+ u_color = glGetUniformLocation(program, "u_color");
+ u_offset = glGetUniformLocation(program, "u_offset");
+ u_pattern_size = glGetUniformLocation(program, "u_pattern_size");
+ u_pattern_tl = glGetUniformLocation(program, "u_pattern_tl");
+ u_pattern_br = glGetUniformLocation(program, "u_pattern_br");
+ u_mix = glGetUniformLocation(program, "u_mix");
+}
diff --git a/src/shader/pattern.fragment.glsl b/src/shader/pattern.fragment.glsl
new file mode 100644
index 0000000000..850c7afaff
--- /dev/null
+++ b/src/shader/pattern.fragment.glsl
@@ -0,0 +1,26 @@
+uniform vec4 u_color;
+
+uniform vec2 u_offset;
+uniform vec2 u_pattern_size;
+uniform vec2 u_pattern_tl;
+uniform vec2 u_pattern_br;
+uniform float u_mix;
+
+
+uniform sampler2D u_image;
+
+varying vec2 v_pos;
+
+void main() {
+
+ vec2 imagecoord = mod((v_pos + u_offset) / u_pattern_size, 1.0);
+ vec2 pos = mix(u_pattern_tl, u_pattern_br, imagecoord);
+ vec4 color1 = texture2D(u_image, pos);
+
+ vec2 imagecoord2 = mod(imagecoord * 2.0, 1.0);
+ vec2 pos2 = mix(u_pattern_tl, u_pattern_br, imagecoord2);
+ vec4 color2 = texture2D(u_image, pos2);
+
+ vec4 color = mix(color1, color2, u_mix);
+ gl_FragColor = color + u_color * (1.0 - color.a);
+}
diff --git a/src/shader/pattern.vertex.glsl b/src/shader/pattern.vertex.glsl
new file mode 100644
index 0000000000..eeee39930f
--- /dev/null
+++ b/src/shader/pattern.vertex.glsl
@@ -0,0 +1,10 @@
+uniform mat4 u_matrix;
+
+attribute vec2 a_pos;
+
+varying vec2 v_pos;
+
+void main() {
+ v_pos = a_pos;
+ gl_Position = u_matrix * vec4(a_pos, 0, 1);
+}
diff --git a/src/shader/shaders.cpp b/src/shader/shaders.cpp
index 1b57bb68da..cd7222b3e1 100644
--- a/src/shader/shaders.cpp
+++ b/src/shader/shaders.cpp
@@ -10,12 +10,16 @@ const shader_source llmr::shaders[SHADER_COUNT] = {
},
[LINE_SHADER] = {
.vertex = "// these are the shaders for rendering antialiased lines\n\n// floor(127 / 2) == 63.0\n// the maximum allowed miter limit is 2.0 at the moment. the extrude normal is\n// stored in a byte (-128..127). we scale regular normals up to length 63, but\n// there are also \"special\" normals that have a bigger length (of up to 126 in\n// this case).\n#define scale 63.0\n\nattribute vec2 a_pos;\nattribute vec2 a_extrude;\nattribute float a_linesofar;\n\n// matrix is for the vertex position, exmatrix is for rotating and projecting\n// the extrusion vector.\nuniform mat4 u_matrix;\nuniform mat4 u_exmatrix;\n\n\nuniform float u_debug;\n\n// shared\nuniform float u_ratio;\nuniform vec2 u_linewidth;\nuniform vec4 u_color;\nuniform float u_point;\n\nvarying vec2 v_normal;\nvarying float v_linesofar;\n\nvoid main() {\n // We store the texture normals in the most insignificant bit\n // transform y so that 0 => -1 and 1 => 1\n // In the texture normal, x is 0 if the normal points straight up/down and 1 if it's a round cap\n // y is 1 if the normal points up, and -1 if it points down\n vec2 normal = mod(a_pos, 2.0);\n normal.y = sign(normal.y - 0.5);\n v_normal = normal;\n\n // Scale the extrusion vector down to a normal and then up by the line width\n // of this vertex.\n vec2 extrude = a_extrude / scale;\n vec2 dist = u_linewidth.s * extrude * (1.0 - u_point);\n\n // If the x coordinate is the maximum integer, we move the z coordinates out\n // of the view plane so that the triangle gets clipped. This makes it easier\n // for us to create degenerate triangle strips.\n float z = step(32767.0, a_pos.x);\n\n // When drawing points, skip every other vertex\n z += u_point * step(1.0, v_normal.y);\n\n // Remove the texture normal bit of the position before scaling it with the\n // model/view matrix. Add the extrusion vector *after* the model/view matrix\n // because we're extruding the line in pixel space, regardless of the current\n // tile's zoom level.\n gl_Position = u_matrix * vec4(floor(a_pos / 2.0), 0.0, 1.0) + u_exmatrix * vec4(dist, z, 0.0);\n v_linesofar = a_linesofar * u_ratio;\n\n\n gl_PointSize = 2.0 * u_linewidth.s - 1.0;\n}\n",
- .fragment = "#version 120\n// shared\nuniform float u_debug;\nuniform vec2 u_linewidth;\nuniform vec4 u_color;\nuniform float u_point;\nuniform float u_gamma;\n\nuniform vec2 u_dasharray;\n\nvarying vec2 v_normal;\nvarying float v_linesofar;\n\nvoid main() {\n // Calculate the distance of the pixel from the line in pixels.\n float dist = length(v_normal) * (1.0 - u_point) + u_point * length(gl_PointCoord * 2.0 - 1.0);\n\n dist *= u_linewidth.s;\n\n // Calculate the antialiasing fade factor. This is either when fading in\n // the line in case of an offset line (v_linewidth.t) or when fading out\n // (v_linewidth.s)\n float alpha = clamp(min(dist - (u_linewidth.t - 1.0), u_linewidth.s - dist) * u_gamma, 0.0, 1.0);\n\n // Calculate the antialiasing fade factor based on distance to the dash.\n // Only affects alpha when line is dashed\n float pos = mod(v_linesofar, u_dasharray.x + u_dasharray.y);\n alpha *= max(step(0.0, -u_dasharray.y), clamp(min(pos, u_dasharray.x - pos), 0.0, 1.0));\n\n gl_FragColor = u_color * alpha;\n\n if (u_debug > 0.0) {\n gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n }\n}\n",
+ .fragment = "#version 120\n\n// shared\nuniform float u_debug;\nuniform vec2 u_linewidth;\nuniform vec4 u_color;\nuniform float u_point;\nuniform float u_gamma;\n\nuniform vec2 u_dasharray;\n\nvarying vec2 v_normal;\nvarying float v_linesofar;\n\nvoid main() {\n // Calculate the distance of the pixel from the line in pixels.\n float dist = length(v_normal) * (1.0 - u_point) + u_point * length(gl_PointCoord * 2.0 - 1.0);\n\n dist *= u_linewidth.s;\n\n // Calculate the antialiasing fade factor. This is either when fading in\n // the line in case of an offset line (v_linewidth.t) or when fading out\n // (v_linewidth.s)\n float alpha = clamp(min(dist - (u_linewidth.t - 1.0), u_linewidth.s - dist) * u_gamma, 0.0, 1.0);\n\n // Calculate the antialiasing fade factor based on distance to the dash.\n // Only affects alpha when line is dashed\n float pos = mod(v_linesofar, u_dasharray.x + u_dasharray.y);\n alpha *= max(step(0.0, -u_dasharray.y), clamp(min(pos, u_dasharray.x - pos), 0.0, 1.0));\n\n gl_FragColor = u_color * alpha;\n\n if (u_debug > 0.0) {\n gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n }\n}\n",
},
[OUTLINE_SHADER] = {
.vertex = "attribute vec2 a_pos;\nuniform mat4 u_matrix;\nuniform vec2 u_world;\n\nvarying vec2 v_pos;\n\nvoid main() {\n // If the x coordinate is the maximum integer, we move the z coordinates out\n // of the view plane so that the triangle gets clipped. This makes it easier\n // for us to create degenerate triangle strips.\n float z = step(32767.0, a_pos.x) * 2.0;\n gl_Position = u_matrix * vec4(a_pos, z, 1);\n\n v_pos = (gl_Position.xy + 1.0) / 2.0 * u_world;\n}\n",
.fragment = "uniform vec4 u_color;\n\nvarying vec2 v_pos;\n\nvoid main() {\n float dist = length(v_pos - gl_FragCoord.xy);\n float alpha = smoothstep(1.0, 0.0, dist);\n gl_FragColor = u_color * alpha;\n}\n",
},
+ [PATTERN_SHADER] = {
+ .vertex = "uniform mat4 u_matrix;\n\nattribute vec2 a_pos;\n\nvarying vec2 v_pos;\n\nvoid main() {\n v_pos = a_pos;\n gl_Position = u_matrix * vec4(a_pos, 0, 1);\n}\n",
+ .fragment = "uniform vec4 u_color;\n\nuniform vec2 u_offset;\nuniform vec2 u_pattern_size;\nuniform vec2 u_pattern_tl;\nuniform vec2 u_pattern_br;\nuniform float u_mix;\n\n\nuniform sampler2D u_image;\n\nvarying vec2 v_pos;\n\nvoid main() {\n\n vec2 imagecoord = mod((v_pos + u_offset) / u_pattern_size, 1.0);\n vec2 pos = mix(u_pattern_tl, u_pattern_br, imagecoord);\n vec4 color1 = texture2D(u_image, pos);\n\n vec2 imagecoord2 = mod(imagecoord * 2.0, 1.0);\n vec2 pos2 = mix(u_pattern_tl, u_pattern_br, imagecoord2);\n vec4 color2 = texture2D(u_image, pos2);\n\n vec4 color = mix(color1, color2, u_mix);\n gl_FragColor = color + u_color * (1.0 - color.a);\n}\n",
+ },
[PLAIN_SHADER] = {
.vertex = "attribute vec2 a_pos;\n\nuniform mat4 u_matrix;\n\nvoid main() {\n float z = step(32767.0, a_pos.x) * 2.0;\n gl_Position = u_matrix * vec4(a_pos, z, 1);\n}\n",
.fragment = "uniform vec4 u_color;\n\nvoid main() {\n gl_FragColor = u_color;\n}\n",
diff --git a/src/style/resources.cpp b/src/style/resources.cpp
index cfdc0d7ce7..0c45e59c5d 100644
--- a/src/style/resources.cpp
+++ b/src/style/resources.cpp
@@ -47,27 +47,27 @@ const unsigned char resources::style[] = {
12, 114, 111, 97, 100, 95, 114, 101, 103, 117, 108, 97, 114, 18, 24, 10,
10, 114, 111, 97, 100, 95, 108, 97, 114, 103, 101, 18, 10, 114, 111, 97,
100, 95, 108, 97, 114, 103, 101, 18, 18, 10, 7, 97, 108, 99, 111, 104,
- 111, 108, 18, 7, 97, 108, 99, 111, 104, 111, 108, 26, 197, 2, 10, 7,
- 100, 101, 102, 97, 117, 108, 116, 18, 21, 10, 4, 112, 97, 114, 107, 34,
- 8, 8, 2, 18, 4, 0, 0, 128, 63, 45, 255, 159, 223, 200, 18, 31,
- 10, 4, 119, 111, 111, 100, 34, 8, 8, 2, 18, 4, 0, 0, 128, 63,
- 45, 255, 102, 170, 51, 58, 8, 8, 2, 18, 4, 205, 204, 204, 61, 18,
- 22, 10, 5, 119, 97, 116, 101, 114, 34, 8, 8, 2, 18, 4, 0, 0,
- 128, 63, 45, 255, 230, 182, 115, 18, 51, 10, 8, 98, 117, 105, 108, 100,
- 105, 110, 103, 34, 8, 8, 2, 18, 4, 0, 0, 128, 63, 45, 255, 0,
- 0, 0, 58, 24, 8, 4, 18, 20, 0, 0, 80, 65, 0, 0, 0, 0,
- 205, 204, 204, 61, 0, 0, 0, 0, 205, 204, 204, 61, 26, 41, 10, 12,
- 114, 111, 97, 100, 95, 108, 105, 109, 105, 116, 101, 100, 29, 255, 187, 187,
- 187, 34, 20, 8, 3, 18, 16, 0, 0, 0, 0, 0, 0, 128, 63, 0,
- 0, 240, 65, 0, 0, 128, 63, 26, 65, 10, 12, 114, 111, 97, 100, 95,
- 114, 101, 103, 117, 108, 97, 114, 29, 255, 153, 153, 153, 34, 44, 8, 3,
- 18, 40, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 80, 65, 0, 0,
- 0, 63, 0, 0, 128, 65, 0, 0, 0, 64, 0, 0, 160, 65, 0, 0,
- 0, 66, 0, 0, 240, 65, 0, 0, 0, 66, 26, 71, 10, 10, 114, 111,
- 97, 100, 95, 108, 97, 114, 103, 101, 29, 255, 102, 102, 102, 34, 52, 8,
- 3, 18, 48, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 48, 65, 0,
- 0, 0, 63, 0, 0, 80, 65, 0, 0, 128, 63, 0, 0, 128, 65, 0,
- 0, 128, 64, 0, 0, 160, 65, 0, 0, 128, 66, 0, 0, 240, 65, 0,
- 0, 128, 66
+ 111, 108, 18, 7, 97, 108, 99, 111, 104, 111, 108, 26, 203, 2, 10, 7,
+ 100, 101, 102, 97, 117, 108, 116, 18, 27, 10, 4, 112, 97, 114, 107, 34,
+ 8, 8, 2, 18, 4, 0, 0, 128, 63, 45, 255, 159, 223, 200, 66, 4,
+ 112, 97, 114, 107, 18, 31, 10, 4, 119, 111, 111, 100, 34, 8, 8, 2,
+ 18, 4, 0, 0, 128, 63, 45, 255, 102, 170, 51, 58, 8, 8, 2, 18,
+ 4, 205, 204, 204, 61, 18, 22, 10, 5, 119, 97, 116, 101, 114, 34, 8,
+ 8, 2, 18, 4, 0, 0, 128, 63, 45, 255, 230, 182, 115, 18, 51, 10,
+ 8, 98, 117, 105, 108, 100, 105, 110, 103, 34, 8, 8, 2, 18, 4, 0,
+ 0, 128, 63, 45, 255, 0, 0, 0, 58, 24, 8, 4, 18, 20, 0, 0,
+ 80, 65, 0, 0, 0, 0, 205, 204, 204, 61, 0, 0, 0, 0, 205, 204,
+ 204, 61, 26, 41, 10, 12, 114, 111, 97, 100, 95, 108, 105, 109, 105, 116,
+ 101, 100, 29, 255, 187, 187, 187, 34, 20, 8, 3, 18, 16, 0, 0, 0,
+ 0, 0, 0, 128, 63, 0, 0, 240, 65, 0, 0, 128, 63, 26, 65, 10,
+ 12, 114, 111, 97, 100, 95, 114, 101, 103, 117, 108, 97, 114, 29, 255, 153,
+ 153, 153, 34, 44, 8, 3, 18, 40, 0, 0, 0, 0, 0, 0, 0, 63,
+ 0, 0, 80, 65, 0, 0, 0, 63, 0, 0, 128, 65, 0, 0, 0, 64,
+ 0, 0, 160, 65, 0, 0, 0, 66, 0, 0, 240, 65, 0, 0, 0, 66,
+ 26, 71, 10, 10, 114, 111, 97, 100, 95, 108, 97, 114, 103, 101, 29, 255,
+ 102, 102, 102, 34, 52, 8, 3, 18, 48, 0, 0, 0, 0, 0, 0, 0,
+ 63, 0, 0, 48, 65, 0, 0, 0, 63, 0, 0, 80, 65, 0, 0, 128,
+ 63, 0, 0, 128, 65, 0, 0, 128, 64, 0, 0, 160, 65, 0, 0, 128,
+ 66, 0, 0, 240, 65, 0, 0, 128, 66
};
const unsigned long resources::style_size = sizeof(resources::style);
diff --git a/src/style/style.cpp b/src/style/style.cpp
index fd8d7e8bd5..85c85b979c 100644
--- a/src/style/style.cpp
+++ b/src/style/style.cpp
@@ -123,6 +123,8 @@ std::pair<std::string, FillClass> Style::parseFillClass(pbf data) {
fill.stroke_color = parseColor(data);
} else if (data.tag == 7) { // opacity
fill.opacity = parseProperty<float>(data.message());
+ } else if (data.tag == 8) { // image
+ fill.image = data.string();
} else {
data.skip();
}
@@ -221,6 +223,7 @@ void Style::cascade(float z) {
fill.fill_color = layer.fill_color;
fill.stroke_color = layer.stroke_color;
fill.opacity = layer.opacity(z);
+ fill.image = layer.image;
}
// Cascade line classes