summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKonstantin Käfer <mail@kkaefer.com>2014-02-11 15:51:54 +0100
committerKonstantin Käfer <mail@kkaefer.com>2014-02-11 15:51:54 +0100
commitbec0ad10c4b460941d08cca597bf352c96820d34 (patch)
tree39fd506db5deeeedc8aebc51b124e6a68ddd7de4
parenteb9a6b7068b9910301bfc7a3b83e114c7545c893 (diff)
downloadqtlocation-mapboxgl-bec0ad10c4b460941d08cca597bf352c96820d34.tar.gz
drawing lines with triangles
-rw-r--r--Makefile5
-rwxr-xr-xbin/convert-style.js2
-rw-r--r--bin/style.js6
-rw-r--r--include/llmr/geometry/buffer.hpp6
-rw-r--r--include/llmr/geometry/elements_buffer.hpp30
-rw-r--r--include/llmr/geometry/fill_buffer.hpp12
-rw-r--r--include/llmr/geometry/line_buffer.hpp17
-rw-r--r--include/llmr/geometry/vao.hpp43
-rw-r--r--include/llmr/map/tile.hpp10
-rw-r--r--include/llmr/renderer/fill_bucket.hpp6
-rw-r--r--include/llmr/renderer/line_bucket.hpp36
-rw-r--r--include/llmr/renderer/painter.hpp2
-rw-r--r--include/llmr/renderer/shader-line.hpp4
-rw-r--r--include/llmr/renderer/shader-linejoin.hpp24
-rw-r--r--include/llmr/shader/shaders.hpp1
-rw-r--r--include/llmr/style/bucket_description.hpp4
-rw-r--r--macosx/main.mm6
-rw-r--r--proto/style.proto2
-rw-r--r--resources/style.pbfbin1050 -> 1050 bytes
-rw-r--r--src/geometry/elements_buffer.cpp15
-rw-r--r--src/geometry/fill_buffer.cpp7
-rw-r--r--src/geometry/line_buffer.cpp7
-rw-r--r--src/map/tile.cpp10
-rw-r--r--src/renderer/fill_bucket.cpp12
-rw-r--r--src/renderer/line_bucket.cpp251
-rw-r--r--src/renderer/painter.cpp62
-rw-r--r--src/renderer/shader-line.cpp10
-rw-r--r--src/renderer/shader-linejoin.cpp31
-rw-r--r--src/shader/line.fragment.glsl17
-rw-r--r--src/shader/line.vertex.glsl29
-rw-r--r--src/shader/linejoin.fragment.glsl14
-rw-r--r--src/shader/linejoin.vertex.glsl12
-rw-r--r--src/shader/shaders.cpp8
-rw-r--r--src/style/resources.cpp6
34 files changed, 448 insertions, 259 deletions
diff --git a/Makefile b/Makefile
index f01f85addb..e108caebc6 100644
--- a/Makefile
+++ b/Makefile
@@ -19,6 +19,11 @@ app: config.gypi src macosx/llmr-app.gyp
xcode: config.gypi llmr.gyp
deps/run_gyp llmr.gyp -Goutput_dir=./out/ --depth=. --generator-output=./ -f xcode
+# build OS X app with Xcode
+xproj: config.gypi src macosx/llmr-app.gyp
+ deps/run_gyp macosx/llmr-app.gyp -Goutput_dir=./out/ --depth=. --generator-output=./ -f xcode
+ open ./macosx/llmr-app.xcodeproj
+
# build OS X app with xcodebuild
xapp: config.gypi src macosx/llmr-app.gyp
deps/run_gyp macosx/llmr-app.gyp -Goutput_dir=./out/ --depth=. --generator-output=./ -f xcode
diff --git a/bin/convert-style.js b/bin/convert-style.js
index da9a95a428..2f21d6a8bf 100755
--- a/bin/convert-style.js
+++ b/bin/convert-style.js
@@ -25,7 +25,7 @@ var cap_type = {
// enum
var join_type = {
- butt: 1,
+ miter: 1,
bevel: 2,
round: 3
};
diff --git a/bin/style.js b/bin/style.js
index 4099b420d4..1596e30a67 100644
--- a/bin/style.js
+++ b/bin/style.js
@@ -10,17 +10,17 @@ module.exports = {
"road_large": {
"datasource": "streets",
"layer": "road", "field": "class", "value": ["motorway", "main"],
- "type": "line", "cap": "round", "join": "bevel"
+ "type": "line", "cap": "round", "join": "round"
},
"road_regular": {
"datasource": "streets",
"layer": "road", "field": "class", "value": "street",
- "type": "line", "cap": "round", "join": "bevel"
+ "type": "line", "cap": "round", "join": "round"
},
"road_limited": {
"datasource": "streets",
"layer": "road", "field": "class", "value": "street_limited",
- "type": "line", "cap": "round", "join": "bevel"
+ "type": "line", "cap": "round", "join": "round"
},
"park": {
"datasource": "streets",
diff --git a/include/llmr/geometry/buffer.hpp b/include/llmr/geometry/buffer.hpp
index 1177bb196e..1b9e5c6307 100644
--- a/include/llmr/geometry/buffer.hpp
+++ b/include/llmr/geometry/buffer.hpp
@@ -8,7 +8,7 @@
namespace llmr {
template <
- size_t itemSize,
+ size_t item_size,
int bufferType = GL_ARRAY_BUFFER,
size_t defaultLength = 8192
>
@@ -44,6 +44,7 @@ public:
}
}
+
protected:
// increase the buffer size by at least /required/ bytes.
void *addElement() {
@@ -57,6 +58,9 @@ protected:
return static_cast<char *>(array) + (pos - itemSize);
}
+public:
+ const size_t itemSize = item_size;
+
private:
// CPU buffer
void *array = nullptr;
diff --git a/include/llmr/geometry/elements_buffer.hpp b/include/llmr/geometry/elements_buffer.hpp
new file mode 100644
index 0000000000..82d97f8b6d
--- /dev/null
+++ b/include/llmr/geometry/elements_buffer.hpp
@@ -0,0 +1,30 @@
+#ifndef LLMR_GEOMETRY_TRIANGLE_ELEMENTS_BUFFER
+#define LLMR_GEOMETRY_TRIANGLE_ELEMENTS_BUFFER
+
+#include "buffer.hpp"
+
+namespace llmr {
+
+class TriangleElementsBuffer : public Buffer<
+ 6, // bytes per triangle (3 * unsigned short == 6 bytes)
+ GL_ELEMENT_ARRAY_BUFFER
+> {
+public:
+ typedef uint16_t element_type;
+
+ void add(element_type a, element_type b, element_type c);
+};
+
+class PointElementsBuffer : public Buffer<
+ 2, // bytes per point (1 unsigned short)
+ GL_ELEMENT_ARRAY_BUFFER
+> {
+public:
+ typedef uint16_t element_type;
+
+ void add(element_type a);
+};
+
+}
+
+#endif
diff --git a/include/llmr/geometry/fill_buffer.hpp b/include/llmr/geometry/fill_buffer.hpp
index f413715042..90265b8b97 100644
--- a/include/llmr/geometry/fill_buffer.hpp
+++ b/include/llmr/geometry/fill_buffer.hpp
@@ -7,7 +7,6 @@
namespace llmr {
-
class FillVertexBuffer : public Buffer<
4 // bytes per coordinates (2 * unsigned short == 4 bytes)
> {
@@ -18,17 +17,6 @@ public:
void add(vertex_type x, vertex_type y);
};
-
-class FillElementsBuffer : public Buffer<
- 6, // bytes per triangle (3 * unsigned short == 6 bytes)
- GL_ELEMENT_ARRAY_BUFFER
-> {
-public:
- typedef uint16_t element_type;
-
- void add(element_type a, element_type b, element_type c);
-};
-
}
#endif
diff --git a/include/llmr/geometry/line_buffer.hpp b/include/llmr/geometry/line_buffer.hpp
index ccbdce1191..a18ea810ae 100644
--- a/include/llmr/geometry/line_buffer.hpp
+++ b/include/llmr/geometry/line_buffer.hpp
@@ -5,8 +5,7 @@
namespace llmr {
-
-class LineBuffer : public Buffer<
+class LineVertexBuffer : public Buffer<
8 // 2 coordinates per vertex + 1 linesofar + 1 extrude coord pair == 4 (== 8 bytes)
> {
public:
@@ -31,20 +30,10 @@ public:
* @param {number} tx texture normal
* @param {number} ty texture normal
*/
- void add(vertex_type x, vertex_type y, float ex, float ey, int8_t tx, int8_t ty, int32_t linesofar = 0);
-
- /*
- * Add a degenerate triangle to the buffer
- *
- * > So we need a way to get from the end of one triangle strip
- * to the beginning of the next strip without actually filling triangles
- * on the way. We can do this with "degenerate" triangles: We simply
- * repeat the last coordinate of the first triangle strip and the first
- * coordinate of the next triangle strip.
- */
- void addDegenerate();
+ size_t add(vertex_type x, vertex_type y, float ex, float ey, int8_t tx, int8_t ty, int32_t linesofar = 0);
};
+
}
#endif
diff --git a/include/llmr/geometry/vao.hpp b/include/llmr/geometry/vao.hpp
index 49401e01d2..a2a5a8a0d0 100644
--- a/include/llmr/geometry/vao.hpp
+++ b/include/llmr/geometry/vao.hpp
@@ -10,19 +10,47 @@ namespace llmr {
template <typename Shader>
class VertexArrayObject {
public:
- template <typename Buffer>
- void bind(Shader& shader, Buffer& buffer, char *offset) {
+ template <typename VertexBuffer>
+ void bind(Shader& shader, VertexBuffer& vertex_buffer, char *offset) {
if (!vao) {
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
- buffer.bind();
+ vertex_buffer.bind();
shader.bind(offset);
- buffer_ptr = &buffer;
+ vertex_buffer_ptr = &vertex_buffer;
+ elements_buffer_ptr = nullptr;
offset_ptr = offset;
- } else if (buffer_ptr != &buffer) {
- throw std::runtime_error("trying to bind VAO to another buffer");
+ } else if (vertex_buffer_ptr != &vertex_buffer) {
+ throw std::runtime_error("trying to bind VAO to another vertex buffer");
+ } else if (elements_buffer_ptr != nullptr) {
+ throw std::runtime_error("trying to bind VAO to another elements buffer");
+ } else if (offset_ptr != offset) {
+ throw std::runtime_error("trying to bind VAO to another offset");
+ } else {
+ // We have been given the correct information.
+ glBindVertexArray(vao);
+ }
+ }
+
+ template <typename VertexBuffer, typename ElementsBuffer>
+ void bind(Shader& shader, VertexBuffer& vertex_buffer, ElementsBuffer& elements_buffer, char *offset) {
+ if (!vao) {
+ glGenVertexArrays(1, &vao);
+ glBindVertexArray(vao);
+
+ vertex_buffer.bind();
+ elements_buffer.bind();
+ shader.bind(offset);
+
+ vertex_buffer_ptr = &vertex_buffer;
+ elements_buffer_ptr = &elements_buffer;
+ offset_ptr = offset;
+ } else if (vertex_buffer_ptr != &vertex_buffer) {
+ throw std::runtime_error("trying to bind VAO to another vertex buffer");
+ } else if (elements_buffer_ptr != &elements_buffer) {
+ throw std::runtime_error("trying to bind VAO to another elements buffer");
} else if (offset_ptr != offset) {
throw std::runtime_error("trying to bind VAO to another offset");
} else {
@@ -42,7 +70,8 @@ private:
// For debug reasons, we're storing the bind information so that we can
// detect errors and report
- void *buffer_ptr = nullptr;
+ void *vertex_buffer_ptr = nullptr;
+ void *elements_buffer_ptr = nullptr;
char *offset_ptr = 0;
};
diff --git a/include/llmr/map/tile.hpp b/include/llmr/map/tile.hpp
index d0d660a4e6..4b2aed8885 100644
--- a/include/llmr/map/tile.hpp
+++ b/include/llmr/map/tile.hpp
@@ -22,8 +22,9 @@ class BucketDescription;
class VectorTile;
class VectorTileLayer;
class FillVertexBuffer;
-class FillElementsBuffer;
-class LineBuffer;
+class LineVertexBuffer;
+class TriangleElementsBuffer;
+class PointElementsBuffer;
class PlainShader;
class Tile : public std::enable_shared_from_this<Tile>,
@@ -74,8 +75,9 @@ public:
VertexArrayObject<PlainShader> debugFontArray;
std::shared_ptr<FillVertexBuffer> fillVertexBuffer;
- std::shared_ptr<FillElementsBuffer> fillElementsBuffer;
- std::shared_ptr<LineBuffer> lineBuffer;
+ std::shared_ptr<LineVertexBuffer> lineVertexBuffer;
+ std::shared_ptr<TriangleElementsBuffer> triangleElementsBuffer;
+ std::shared_ptr<PointElementsBuffer> pointElementsBuffer;
// Holds the buckets of this tile.
// They contain the location offsets in the buffers stored above
diff --git a/include/llmr/renderer/fill_bucket.hpp b/include/llmr/renderer/fill_bucket.hpp
index 2992d77109..e8b278b329 100644
--- a/include/llmr/renderer/fill_bucket.hpp
+++ b/include/llmr/renderer/fill_bucket.hpp
@@ -17,7 +17,7 @@ namespace llmr {
class Style;
class FillVertexBuffer;
-class FillElementsBuffer;
+class TriangleElementsBuffer;
class BucketDescription;
class OutlineShader;
class PlainShader;
@@ -27,7 +27,7 @@ struct pbf;
class FillBucket : public Bucket {
public:
FillBucket(const std::shared_ptr<FillVertexBuffer>& vertexBuffer,
- const std::shared_ptr<FillElementsBuffer>& elementsBuffer,
+ const std::shared_ptr<TriangleElementsBuffer>& elementsBuffer,
const BucketDescription& bucket_desc);
virtual void render(Painter& painter, const std::string& layer_name, const Tile::ID& id);
@@ -44,7 +44,7 @@ public:
private:
std::shared_ptr<FillVertexBuffer> vertexBuffer;
- std::shared_ptr<FillElementsBuffer> elementsBuffer;
+ std::shared_ptr<TriangleElementsBuffer> elementsBuffer;
struct group {
VertexArrayObject<PlainShader> array;
diff --git a/include/llmr/renderer/line_bucket.hpp b/include/llmr/renderer/line_bucket.hpp
index 7d61af15e4..b94440cd69 100644
--- a/include/llmr/renderer/line_bucket.hpp
+++ b/include/llmr/renderer/line_bucket.hpp
@@ -10,34 +10,50 @@
namespace llmr {
class Style;
-class LineBuffer;
+class LineVertexBuffer;
+class TriangleElementsBuffer;
class LineShader;
+class LinejoinShader;
struct Coordinate;
struct pbf;
class LineBucket : public Bucket {
public:
- LineBucket(const std::shared_ptr<LineBuffer>& buffer, const BucketDescription& bucket_desc);
+ LineBucket(const std::shared_ptr<LineVertexBuffer>& vertexBuffer,
+ const std::shared_ptr<TriangleElementsBuffer>& triangleElementsBuffer,
+ const std::shared_ptr<PointElementsBuffer>& pointElementsBuffer,
+ const BucketDescription& bucket_desc);
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);
- size_t size() const;
+ bool empty() const;
+ bool hasPoints() const;
- void bind(LineShader& shader);
- void drawLines();
- void drawPoints();
+ void drawLines(LineShader& shader);
+ void drawDebugLines(LineShader& shader);
+ void drawPoints(LinejoinShader& shader);
public:
const BucketGeometryDescription geometry;
private:
- std::shared_ptr<LineBuffer> buffer;
- uint32_t start;
- uint32_t length;
- VertexArrayObject<LineShader> array;
+ std::shared_ptr<LineVertexBuffer> vertexBuffer;
+ const uint32_t vertex_start;
+ uint32_t vertex_length;
+
+ std::shared_ptr<TriangleElementsBuffer> triangleElementsBuffer;
+ const uint32_t triangle_elements_start;
+ uint32_t triangle_length;
+
+ std::shared_ptr<PointElementsBuffer> pointElementsBuffer;
+ const uint32_t point_elements_start;
+ uint32_t point_length;
+
+ VertexArrayObject<LineShader> lineArray;
+ VertexArrayObject<LinejoinShader> pointArray;
};
}
diff --git a/include/llmr/renderer/painter.hpp b/include/llmr/renderer/painter.hpp
index 925defd035..fed7128fc2 100644
--- a/include/llmr/renderer/painter.hpp
+++ b/include/llmr/renderer/painter.hpp
@@ -11,6 +11,7 @@
#include <llmr/renderer/shader-outline.hpp>
#include <llmr/renderer/shader-pattern.hpp>
#include <llmr/renderer/shader-line.hpp>
+#include <llmr/renderer/shader-linejoin.hpp>
namespace llmr {
@@ -54,6 +55,7 @@ private:
std::unique_ptr<PlainShader> plainShader;
std::unique_ptr<OutlineShader> outlineShader;
std::unique_ptr<LineShader> lineShader;
+ std::unique_ptr<LinejoinShader> linejoinShader;
std::unique_ptr<PatternShader> patternShader;
// Set up the stencil quad we're using to generate the stencil mask.
diff --git a/include/llmr/renderer/shader-line.hpp b/include/llmr/renderer/shader-line.hpp
index 00e50c1b1f..9c0dfbaba9 100644
--- a/include/llmr/renderer/shader-line.hpp
+++ b/include/llmr/renderer/shader-line.hpp
@@ -19,11 +19,9 @@ public:
int32_t u_exmatrix;
int32_t u_linewidth;
int32_t u_color;
- int32_t u_debug;
int32_t u_ratio;
int32_t u_dasharray;
- int32_t u_point;
- int32_t u_gamma;
+ int32_t u_debug;
};
}
diff --git a/include/llmr/renderer/shader-linejoin.hpp b/include/llmr/renderer/shader-linejoin.hpp
new file mode 100644
index 0000000000..05993e8f72
--- /dev/null
+++ b/include/llmr/renderer/shader-linejoin.hpp
@@ -0,0 +1,24 @@
+#ifndef LLMR_RENDERER_SHADER_LINEJOIN
+#define LLMR_RENDERER_SHADER_LINEJOIN
+
+#include "shader.hpp"
+
+namespace llmr {
+
+class LinejoinShader : public Shader {
+public:
+ LinejoinShader();
+
+ void bind(char *offset);
+
+ int32_t a_pos;
+
+ int32_t u_matrix;
+ int32_t u_world;
+ int32_t u_linewidth;
+ int32_t u_color;
+};
+
+}
+
+#endif
diff --git a/include/llmr/shader/shaders.hpp b/include/llmr/shader/shaders.hpp
index d3007b2ccf..c0f02337a0 100644
--- a/include/llmr/shader/shaders.hpp
+++ b/include/llmr/shader/shaders.hpp
@@ -12,6 +12,7 @@ struct shader_source {
enum {
LINE_SHADER,
+ LINEJOIN_SHADER,
OUTLINE_SHADER,
PATTERN_SHADER,
PLAIN_SHADER,
diff --git a/include/llmr/style/bucket_description.hpp b/include/llmr/style/bucket_description.hpp
index 9978cf364e..919d3db684 100644
--- a/include/llmr/style/bucket_description.hpp
+++ b/include/llmr/style/bucket_description.hpp
@@ -24,7 +24,7 @@ enum class CapType {
enum class JoinType {
None = 0,
- Butt = 1,
+ Miter = 1,
Bevel = 2,
Round = 3
};
@@ -46,7 +46,7 @@ inline CapType capType(const std::string& cap) {
inline JoinType joinType(const std::string& join) {
- if (join == "butt") return JoinType::Butt;
+ if (join == "miter") return JoinType::Miter;
else if (join == "bevel") return JoinType::Bevel;
else if (join == "round") return JoinType::Round;
else return JoinType::None;
diff --git a/macosx/main.mm b/macosx/main.mm
index b8f333ba23..db244da043 100644
--- a/macosx/main.mm
+++ b/macosx/main.mm
@@ -161,7 +161,11 @@ public:
int run() {
while (!glfwWindowShouldClose(window)) {
if (dirty) {
- dirty = render();
+ try {
+ dirty = render();
+ } catch(std::exception& ex) {
+ fprintf(stderr, "exception: %s\n", ex.what());
+ }
glfwSwapBuffers(window);
fps();
}
diff --git a/proto/style.proto b/proto/style.proto
index 8459477bf7..90e5b65061 100644
--- a/proto/style.proto
+++ b/proto/style.proto
@@ -13,7 +13,7 @@ enum cap_type {
}
enum join_type {
- butt_join = 1;
+ miter_join = 1;
bevel_join = 2;
round_join = 3;
}
diff --git a/resources/style.pbf b/resources/style.pbf
index d87f896d1a..1b991386c7 100644
--- a/resources/style.pbf
+++ b/resources/style.pbf
Binary files differ
diff --git a/src/geometry/elements_buffer.cpp b/src/geometry/elements_buffer.cpp
new file mode 100644
index 0000000000..ea4c43644c
--- /dev/null
+++ b/src/geometry/elements_buffer.cpp
@@ -0,0 +1,15 @@
+#include <llmr/geometry/elements_buffer.hpp>
+
+using namespace llmr;
+
+void TriangleElementsBuffer::add(element_type a, element_type b, element_type c) {
+ element_type *elements = static_cast<element_type *>(addElement());
+ elements[0] = a;
+ elements[1] = b;
+ elements[2] = c;
+}
+
+void PointElementsBuffer::add(element_type a) {
+ uint16_t *data = static_cast<element_type *>(addElement());
+ data[0] = a;
+}
diff --git a/src/geometry/fill_buffer.cpp b/src/geometry/fill_buffer.cpp
index 3de008a7a7..871c93ee06 100644
--- a/src/geometry/fill_buffer.cpp
+++ b/src/geometry/fill_buffer.cpp
@@ -16,10 +16,3 @@ void FillVertexBuffer::add(vertex_type x, vertex_type y) {
vertices[0] = x;
vertices[1] = y;
}
-
-void FillElementsBuffer::add(element_type a, element_type b, element_type c) {
- element_type *elements = static_cast<element_type *>(addElement());
- elements[0] = a;
- elements[1] = b;
- elements[2] = c;
-}
diff --git a/src/geometry/line_buffer.cpp b/src/geometry/line_buffer.cpp
index b9c770c04a..598a34c824 100644
--- a/src/geometry/line_buffer.cpp
+++ b/src/geometry/line_buffer.cpp
@@ -5,7 +5,8 @@
using namespace llmr;
-void LineBuffer::add(vertex_type x, vertex_type y, float ex, float ey, int8_t tx, int8_t ty, int32_t linesofar) {
+size_t LineVertexBuffer::add(vertex_type x, vertex_type y, float ex, float ey, int8_t tx, int8_t ty, int32_t linesofar) {
+ size_t idx = index();
void *data = addElement();
int16_t *coords = static_cast<int16_t *>(data);
@@ -16,8 +17,6 @@ void LineBuffer::add(vertex_type x, vertex_type y, float ex, float ey, int8_t tx
int8_t *extrude = static_cast<int8_t *>(data);
extrude[6] = round(extrudeScale * ex);
extrude[7] = round(extrudeScale * ey);
-};
-void LineBuffer::addDegenerate() {
- add(16383, 16383, 0, 0, 1, 1, 0);
+ return idx;
}
diff --git a/src/map/tile.cpp b/src/map/tile.cpp
index 016811af00..27ca2891eb 100644
--- a/src/map/tile.cpp
+++ b/src/map/tile.cpp
@@ -4,6 +4,7 @@
#include <llmr/map/vector_tile.hpp>
#include <llmr/geometry/fill_buffer.hpp>
#include <llmr/geometry/line_buffer.hpp>
+#include <llmr/geometry/elements_buffer.hpp>
#include <llmr/renderer/fill_bucket.hpp>
#include <llmr/renderer/line_bucket.hpp>
#include <llmr/platform/platform.hpp>
@@ -43,8 +44,9 @@ Tile::Tile(ID id, const Style& style)
: id(id),
state(initial),
fillVertexBuffer(std::make_shared<FillVertexBuffer>()),
- fillElementsBuffer(std::make_shared<FillElementsBuffer>()),
- lineBuffer(std::make_shared<LineBuffer>()),
+ lineVertexBuffer(std::make_shared<LineVertexBuffer>()),
+ triangleElementsBuffer(std::make_shared<TriangleElementsBuffer>()),
+ pointElementsBuffer(std::make_shared<PointElementsBuffer>()),
style(style) {
// Initialize tile debug coordinates
@@ -167,7 +169,7 @@ std::shared_ptr<Bucket> Tile::createBucket(const VectorTile& tile, const BucketD
}
std::shared_ptr<Bucket> Tile::createFillBucket(const VectorTileLayer& layer, const BucketDescription& bucket_desc) {
- std::shared_ptr<FillBucket> bucket = std::make_shared<FillBucket>(fillVertexBuffer, fillElementsBuffer, bucket_desc);
+ std::shared_ptr<FillBucket> bucket = std::make_shared<FillBucket>(fillVertexBuffer, triangleElementsBuffer, bucket_desc);
FilteredVectorTileLayer filtered_layer(layer, bucket_desc);
for (pbf feature : filtered_layer) {
@@ -183,7 +185,7 @@ std::shared_ptr<Bucket> Tile::createFillBucket(const VectorTileLayer& layer, con
}
std::shared_ptr<Bucket> Tile::createLineBucket(const VectorTileLayer& layer, const BucketDescription& bucket_desc) {
- std::shared_ptr<LineBucket> bucket = std::make_shared<LineBucket>(lineBuffer, bucket_desc);
+ std::shared_ptr<LineBucket> bucket = std::make_shared<LineBucket>(lineVertexBuffer, triangleElementsBuffer, pointElementsBuffer, bucket_desc);
FilteredVectorTileLayer filtered_layer(layer, bucket_desc);
for (pbf feature : filtered_layer) {
diff --git a/src/renderer/fill_bucket.cpp b/src/renderer/fill_bucket.cpp
index 8446c04f2b..2c52701742 100644
--- a/src/renderer/fill_bucket.cpp
+++ b/src/renderer/fill_bucket.cpp
@@ -1,5 +1,6 @@
#include <llmr/renderer/fill_bucket.hpp>
#include <llmr/geometry/fill_buffer.hpp>
+#include <llmr/geometry/elements_buffer.hpp>
#include <llmr/geometry/geometry.hpp>
#include <llmr/renderer/painter.hpp>
@@ -15,7 +16,7 @@ struct geometry_too_long_exception : std::exception {};
using namespace llmr;
FillBucket::FillBucket(const std::shared_ptr<FillVertexBuffer>& vertexBuffer,
- const std::shared_ptr<FillElementsBuffer>& elementsBuffer,
+ const std::shared_ptr<TriangleElementsBuffer>& elementsBuffer,
const BucketDescription& bucket_desc)
: geom_desc(bucket_desc.geometry),
vertexBuffer(vertexBuffer),
@@ -102,14 +103,11 @@ uint32_t FillBucket::size() const {
return length;
}
-
-
void FillBucket::drawElements(PlainShader& shader) {
- char *vertex_index = BUFFER_OFFSET(vertex_start * 2 * sizeof(int16_t));
- char *elements_index = BUFFER_OFFSET(elements_start * 3 * sizeof(int16_t));
+ char *vertex_index = BUFFER_OFFSET(vertex_start * vertexBuffer->itemSize);
+ char *elements_index = BUFFER_OFFSET(elements_start * elementsBuffer->itemSize);
for (group& group : groups) {
- group.array.bind(shader, *vertexBuffer, vertex_index);
- elementsBuffer->bind();
+ group.array.bind(shader, *vertexBuffer, *elementsBuffer, vertex_index);
glDrawElements(GL_TRIANGLES, group.elements_length * 3 - 3, GL_UNSIGNED_SHORT, elements_index);
vertex_index += group.vertex_length * 2 * sizeof(uint16_t);
elements_index += group.elements_length * 3 * sizeof(uint16_t);
diff --git a/src/renderer/line_bucket.cpp b/src/renderer/line_bucket.cpp
index 213d8a2856..e60b4fa6f4 100644
--- a/src/renderer/line_bucket.cpp
+++ b/src/renderer/line_bucket.cpp
@@ -1,9 +1,11 @@
#include <llmr/renderer/line_bucket.hpp>
#include <llmr/geometry/line_buffer.hpp>
+#include <llmr/geometry/elements_buffer.hpp>
#include <llmr/geometry/geometry.hpp>
#include <llmr/renderer/painter.hpp>
#include <llmr/renderer/shader-line.hpp>
+#include <llmr/renderer/shader-linejoin.hpp>
#include <llmr/style/style.hpp>
#include <llmr/map/vector_tile.hpp>
@@ -18,11 +20,20 @@ struct geometry_too_long_exception : std::exception {};
using namespace llmr;
-LineBucket::LineBucket(const std::shared_ptr<LineBuffer>& buffer, const BucketDescription& bucket_desc)
+LineBucket::LineBucket(const std::shared_ptr<LineVertexBuffer>& vertexBuffer,
+ const std::shared_ptr<TriangleElementsBuffer>& triangleElementsBuffer,
+ const std::shared_ptr<PointElementsBuffer>& pointElementsBuffer,
+ const BucketDescription& bucket_desc)
: geometry(bucket_desc.geometry),
- buffer(buffer),
- start(buffer->index()),
- length(0) {
+ vertexBuffer(vertexBuffer),
+ vertex_start(vertexBuffer->index()),
+ vertex_length(0),
+ triangleElementsBuffer(triangleElementsBuffer),
+ triangle_elements_start(triangleElementsBuffer->index()),
+ triangle_length(0),
+ pointElementsBuffer(pointElementsBuffer),
+ point_elements_start(pointElementsBuffer->index()),
+ point_length(0) {
}
void LineBucket::addGeometry(pbf& geom) {
@@ -52,15 +63,8 @@ void LineBucket::addGeometry(const std::vector<Coordinate>& vertices) {
const float miterLimit = geometry.miter_limit;
const float roundLimit = geometry.round_limit;
- if (vertices.size() < 1) {
- // alert('a line must have at least one vertex');
- return;
- }
-
- // Point
- if (vertices.size() == 1) {
- Coordinate coord = vertices.front();
- buffer->add(coord.x, coord.y, 1, 0, 0, 0);
+ if (vertices.size() < 2) {
+ // fprintf(stderr, "a line must have at least two vertices\n");
return;
}
@@ -69,19 +73,23 @@ void LineBucket::addGeometry(const std::vector<Coordinate>& vertices) {
bool closed = firstVertex.x == lastVertex.x && firstVertex.y == lastVertex.y;
if (vertices.size() == 2 && closed) {
- // alert('a line may not have coincident points');
+ // fprintf(stderr, "a line may not have coincident points\n");
return;
}
CapType beginCap = cap;
CapType endCap = closed ? CapType::Butt : cap;
+ JoinType currentJoin = JoinType::None;
+
Coordinate currentVertex = Coordinate::null(),
prevVertex = Coordinate::null(),
nextVertex = Coordinate::null();
vec2<double> prevNormal = vec2<double>::null(),
nextNormal = vec2<double>::null();
+ int32_t e1 = -1, e2 = -1, e3 = -1;
+
int8_t flip = 1;
double distance = 0;
@@ -90,14 +98,12 @@ void LineBucket::addGeometry(const std::vector<Coordinate>& vertices) {
nextNormal = util::normal<double>(currentVertex, lastVertex);
}
- // Start all lines with a degenerate vertex
- buffer->addDegenerate();
-
for (size_t i = 0; i < vertices.size(); ++i) {
if (nextNormal) prevNormal = { -nextNormal.x, -nextNormal.y };
if (currentVertex) prevVertex = currentVertex;
currentVertex = vertices[i];
+ currentJoin = join;
if (prevVertex) distance += util::dist<double>(currentVertex, prevVertex);
@@ -108,18 +114,11 @@ void LineBucket::addGeometry(const std::vector<Coordinate>& vertices) {
nextVertex = Coordinate::null();
}
- bool segment = false;
-
- if (closed && i >= 2 && (i + 1 < vertices.size())) {
- segment = true;
- }
-
// If the line is closed, we treat the last vertex like the first vertex.
if (!nextVertex && closed) {
nextVertex = vertices[1];
}
-
if (nextVertex) {
// if two consecutive vertices exist, skip one
if (currentVertex.x == nextVertex.x && currentVertex.y == nextVertex.y) continue;
@@ -155,67 +154,53 @@ void LineBucket::addGeometry(const std::vector<Coordinate>& vertices) {
double roundness = fmax(abs(joinNormal.x), abs(joinNormal.y));
- bool roundJoin = false;
- // Determine whether we should actually draw a round/bevelled/butt line join. It looks
- // better if we do, but we can get away with drawing a mitered join for
- // joins that have a very small angle. For this, we have the "roundLimit"
- // parameter. We do this to reduce the number of vertices we have to
- // write into the line vertex buffer. Note that joinAngularity may be 0,
- // so the roundness grows to infinity. This is intended.
- if ((join == JoinType::Round || join == JoinType::Bevel || join == JoinType::Butt) && roundness > roundLimit) {
- roundJoin = true;
+ // Switch to miter joins if the angle is very low.
+ if (currentJoin != JoinType::Miter) {
+ if (fabs(joinAngularity) < 0.5 && roundness < miterLimit) {
+ currentJoin = JoinType::Miter;
+ }
}
- // Close up the previous line for a round join
- if (roundJoin && prevVertex && nextVertex) {
+ // Add offset square begin cap.
+ if (!prevVertex && beginCap == CapType::Square) {
// Add first vertex
- buffer->add(currentVertex.x, currentVertex.y, // vertex pos
- flip * prevNormal.y, -flip * prevNormal.x, // extrude normal
- 0, 0, distance); // texture normal
-
- // Add second vertex.
- buffer->add(currentVertex.x, currentVertex.y, // vertex pos
- -flip * prevNormal.y, flip * prevNormal.x, // extrude normal
- 0, 1, distance); // texture normal
+ e3 = vertexBuffer->add(currentVertex.x, currentVertex.y, // vertex pos
+ flip * (prevNormal.x + prevNormal.y), flip * (-prevNormal.x + prevNormal.y), // extrude normal
+ 0, 0, distance) - vertex_start; // texture normal
- // Degenerate triangle
- if (join == JoinType::Round || join == JoinType::Butt) {
- buffer->addDegenerate();
- }
+ if (e1 >= 0 && e2 >= 0 && e3 >= 0) triangleElementsBuffer->add(e1, e2, e3);
+ e1 = e2; e2 = e3;
- if (join == JoinType::Round) prevVertex = Coordinate::null();
+ // Add second vertex
+ e3 = vertexBuffer->add(currentVertex.x, currentVertex.y, // vertex pos
+ flip * (prevNormal.x - prevNormal.y), flip * (prevNormal.x + prevNormal.y), // extrude normal
+ 0, 1, distance) - vertex_start; // texture normal
- prevNormal = { -nextNormal.x, -nextNormal.y };
- flip = 1;
+ if (e1 >= 0 && e2 >= 0 && e3 >= 0) triangleElementsBuffer->add(e1, e2, e3);
+ e1 = e2; e2 = e3;
}
- // Add a cap.
- if (!prevVertex && (beginCap == CapType::Round || beginCap == CapType::Square || (roundJoin && join == JoinType::Round))) {
- int8_t tex = beginCap == CapType::Round || roundJoin ? 1 : 0;
-
+ // Add offset square end cap.
+ else if (!nextVertex && endCap == CapType::Square) {
// Add first vertex
- buffer->add(currentVertex.x, currentVertex.y, // vertex pos
- flip * (prevNormal.x + prevNormal.y), flip * (-prevNormal.x + prevNormal.y), // extrude normal
- tex, 0, distance); // texture normal
+ e3 = vertexBuffer->add(currentVertex.x, currentVertex.y, // vertex pos
+ nextNormal.x - flip * nextNormal.y, flip * nextNormal.x + nextNormal.y, // extrude normal
+ 0, 0, distance) - vertex_start; // texture normal
+
+ if (e1 >= 0 && e2 >= 0 && e3 >= 0) triangleElementsBuffer->add(e1, e2, e3);
+ e1 = e2; e2 = e3;
// Add second vertex
- buffer->add(currentVertex.x, currentVertex.y, // vertex pos
- flip * (prevNormal.x - prevNormal.y), flip * (prevNormal.x + prevNormal.y), // extrude normal
- tex, 1, distance); // texture normal
- }
+ e3 = vertexBuffer->add(currentVertex.x, currentVertex.y, // vertex pos
+ nextNormal.x + flip * nextNormal.y, -flip * nextNormal.x + nextNormal.y, // extrude normal
+ 0, 1, distance) - vertex_start; // texture normal
- if (roundJoin) {
- // ROUND JOIN
- // Add first vertex
- buffer->add(currentVertex.x, currentVertex.y, // vertex pos
- -flip * nextNormal.y, flip * nextNormal.x, // extrude normal
- 0, 0, distance); // texture normal
+ if (e1 >= 0 && e2 >= 0 && e3 >= 0) triangleElementsBuffer->add(e1, e2, e3);
+ e1 = e2; e2 = e3;
+ }
- // Add second vertex
- buffer->add(currentVertex.x, currentVertex.y, // vertex pos
- flip * nextNormal.y, -flip * nextNormal.x, // extrude normal
- 0, 1, distance); // texture normal
- } else if ((nextVertex || endCap != CapType::Square) && (prevVertex || beginCap != CapType::Square)) {
+ else
+ if (currentJoin == JoinType::Miter) {
// MITER JOIN
if (fabs(joinAngularity) < 0.01) {
// The two normals are almost parallel.
@@ -226,58 +211,126 @@ void LineBucket::addGeometry(const std::vector<Coordinate>& vertices) {
// bevel join.
joinNormal.x = (prevNormal.x - nextNormal.x) / joinAngularity;
joinNormal.y = (prevNormal.y - nextNormal.y) / joinAngularity;
+ }
+
+ if (roundness > miterLimit) {
flip = -flip;
}
// Add first vertex
- buffer->add(currentVertex.x, currentVertex.y, // vertex pos
- flip * joinNormal.x, flip * joinNormal.y, // extrude normal
- 0, 0, distance); // texture normal
+ e3 = vertexBuffer->add(currentVertex.x, currentVertex.y, // vertex pos
+ flip * joinNormal.x, flip * joinNormal.y, // extrude normal
+ 0, 0, distance) - vertex_start; // texture normal
+
+ if (e1 >= 0 && e2 >= 0 && e3 >= 0) triangleElementsBuffer->add(e1, e2, e3);
+ e1 = e2; e2 = e3;
// Add second vertex
- buffer->add(currentVertex.x, currentVertex.y, // vertex pos
- -flip * joinNormal.x, -flip * joinNormal.y, // extrude normal
- 0, 1, distance); // texture normal
+ e3 = vertexBuffer->add(currentVertex.x, currentVertex.y, // vertex pos
+ -flip * joinNormal.x, -flip * joinNormal.y, // extrude normal
+ 0, 1, distance) - vertex_start; // texture normal
+
+ if (e1 >= 0 && e2 >= 0 && e3 >= 0) triangleElementsBuffer->add(e1, e2, e3);
+ e1 = e2; e2 = e3;
+
+ if ((!prevVertex && beginCap == CapType::Round) ||
+ (!nextVertex && endCap == CapType::Round)) {
+ pointElementsBuffer->add(e1);
+ }
}
- // Add the end cap, but only if this vertex is distinct from the begin
- // vertex.
- if (!nextVertex && (endCap == CapType::Round || endCap == CapType::Square)) {
- int8_t capTex = endCap == CapType::Round ? 1 : 0;
+ else {
+ // Close up the previous line
+ // Add first vertex
+ e3 = vertexBuffer->add(currentVertex.x, currentVertex.y, // vertex pos
+ flip * prevNormal.y, -flip * prevNormal.x, // extrude normal
+ 0, 0, distance) - vertex_start; // texture normal
+
+ if (e1 >= 0 && e2 >= 0 && e3 >= 0) triangleElementsBuffer->add(e1, e2, e3);
+ e1 = e2; e2 = e3;
+
+ // Add second vertex.
+ e3 = vertexBuffer->add(currentVertex.x, currentVertex.y, // vertex pos
+ -flip * prevNormal.y, flip * prevNormal.x, // extrude normal
+ 0, 1, distance) - vertex_start; // texture normal
+
+ if (e1 >= 0 && e2 >= 0 && e3 >= 0) triangleElementsBuffer->add(e1, e2, e3);
+ e1 = e2; e2 = e3;
+
+ prevNormal = { -nextNormal.x, -nextNormal.y };
+ flip = 1;
+
+
+ // begin/end caps
+ if ((!prevVertex && beginCap == CapType::Round) ||
+ (!nextVertex && endCap == CapType::Round)) {
+ pointElementsBuffer->add(e1);
+ }
+
+
+ if (currentJoin == JoinType::Round) {
+ if (prevVertex && nextVertex && (!closed || i > 0)) {
+ pointElementsBuffer->add(e1);
+ }
+ // Reset the previous vertices so that we don't accidentally create
+ // any triangles.
+ e1 = -1; e2 = -1; e3 = -1;
+ }
+
+ // Start the new quad.
// Add first vertex
- buffer->add(currentVertex.x, currentVertex.y, // vertex pos
- nextNormal.x - flip * nextNormal.y, flip * nextNormal.x + nextNormal.y, // extrude normal
- capTex, 0, distance); // texture normal
+ e3 = vertexBuffer->add(currentVertex.x, currentVertex.y, // vertex pos
+ -flip * nextNormal.y, flip * nextNormal.x, // extrude normal
+ 0, 0, distance) - vertex_start; // texture normal
+
+ if (e1 >= 0 && e2 >= 0 && e3 >= 0) triangleElementsBuffer->add(e1, e2, e3);
+ e1 = e2; e2 = e3;
// Add second vertex
- buffer->add(currentVertex.x, currentVertex.y, // vertex pos
- nextNormal.x + flip * nextNormal.y, -flip * nextNormal.x + nextNormal.y, // extrude normal
- capTex, 1, distance); // texture normal
+ e3 = vertexBuffer->add(currentVertex.x, currentVertex.y, // vertex pos
+ flip * nextNormal.y, -flip * nextNormal.x, // extrude normal
+ 0, 1, distance) - vertex_start; // texture normal
+
+ if (e1 >= 0 && e2 >= 0 && e3 >= 0) triangleElementsBuffer->add(e1, e2, e3);
+ e1 = e2; e2 = e3;
}
}
- // Update the length.
- length = buffer->index() - start;
+ // Update the lengths.
+ vertex_length = vertexBuffer->index() - vertex_start;
+ triangle_length = triangleElementsBuffer->index() - triangle_elements_start;
+ point_length = pointElementsBuffer->index() - point_elements_start;
}
void LineBucket::render(Painter& painter, const std::string& layer_name, const Tile::ID& id) {
painter.renderLine(*this, layer_name, id);
}
-size_t LineBucket::size() const {
- return length;
+bool LineBucket::empty() const {
+ return vertex_length == 0;
+}
+
+bool LineBucket::hasPoints() const {
+ return point_length > 0;
}
-void LineBucket::bind(LineShader& shader) {
- char *vertex_index = BUFFER_OFFSET(start * 4 * sizeof(int16_t));
- array.bind(shader, *buffer, vertex_index);
+void LineBucket::drawLines(LineShader& shader) {
+ char *vertex_index = BUFFER_OFFSET(vertex_start * vertexBuffer->itemSize);
+ char *elements_index = BUFFER_OFFSET(triangle_elements_start * triangleElementsBuffer->itemSize);
+ lineArray.bind(shader, *vertexBuffer, *triangleElementsBuffer, vertex_index);
+ glDrawElements(GL_TRIANGLES, triangle_length * 3, GL_UNSIGNED_SHORT, elements_index);
}
-void LineBucket::drawLines() {
- glDrawArrays(GL_TRIANGLE_STRIP, 0, length);
+void LineBucket::drawDebugLines(LineShader& shader) {
+ char *vertex_index = BUFFER_OFFSET(vertex_start * vertexBuffer->itemSize);
+ lineArray.bind(shader, *vertexBuffer, *triangleElementsBuffer, vertex_index);
+ glDrawArrays(GL_LINE_STRIP, 0, vertex_length);
}
-void LineBucket::drawPoints() {
- glDrawArrays(GL_POINTS, 0, length);
+void LineBucket::drawPoints(LinejoinShader& shader) {
+ char *vertex_index = BUFFER_OFFSET(vertex_start * vertexBuffer->itemSize);
+ char *elements_index = BUFFER_OFFSET(point_elements_start * pointElementsBuffer->itemSize);
+ pointArray.bind(shader, *vertexBuffer, *pointElementsBuffer, vertex_index);
+ glDrawElements(GL_POINTS, point_length, GL_UNSIGNED_SHORT, elements_index);
}
diff --git a/src/renderer/painter.cpp b/src/renderer/painter.cpp
index a00ead94fd..71e1dcfc86 100644
--- a/src/renderer/painter.cpp
+++ b/src/renderer/painter.cpp
@@ -32,6 +32,7 @@ void Painter::setup() {
assert(plainShader);
assert(outlineShader);
assert(lineShader);
+ assert(linejoinShader);
assert(patternShader);
glEnable(GL_STENCIL_TEST);
@@ -46,6 +47,7 @@ void Painter::setupShaders() {
plainShader = std::make_unique<PlainShader>();
outlineShader = std::make_unique<OutlineShader>();
lineShader = std::make_unique<LineShader>();
+ linejoinShader = std::make_unique<LinejoinShader>();
patternShader = std::make_unique<PatternShader>();
}
@@ -213,7 +215,7 @@ void Painter::renderFill(FillBucket& bucket, const std::string& layer_name, cons
if (properties.antialias) {
glUseProgram(outlineShader->program);
glUniformMatrix4fv(outlineShader->u_matrix, 1, GL_FALSE, matrix.data());
- glLineWidth(2);
+ glLineWidth(2.0f); // This is always fixed and does not depend on the pixelRatio!
if (properties.stroke_color != properties.fill_color) {
// If we defined a different color for the fill outline, we are
@@ -233,7 +235,6 @@ void Painter::renderFill(FillBucket& bucket, const std::string& layer_name, cons
// Draw the entire line
glUniform2f(outlineShader->u_world, transform.fb_width, transform.fb_height);
- glLineWidth(2.0f);
bucket.drawVertices(*outlineShader);
}
@@ -286,13 +287,16 @@ void Painter::renderLine(LineBucket& bucket, const std::string& layer_name, cons
const LineProperties& properties = style.computed.lines[layer_name];
// Abort early.
- if (!bucket.size()) return;
+ if (bucket.empty()) return;
if (properties.hidden) return;
double width = properties.width;
- double offset = (properties.offset || 0) / 2;
- double inset = fmax(-1, offset - width / 2 - 0.5) + 1;
- double outset = offset + width / 2 + 0.5;
+ double offset = properties.offset / 2;
+
+ // These are the radii of the line. We are limiting it to 16, which will result
+ // in a point size of 64 on retina.
+ double inset = fmin((fmax(-1, offset - width / 2 - 0.5) + 1), 16.0f);
+ double outset = fmin(offset + width / 2 + 0.5, 16.0f);
Color color = properties.color;
color[0] *= properties.opacity;
@@ -300,10 +304,19 @@ void Painter::renderLine(LineBucket& bucket, const std::string& layer_name, cons
color[2] *= properties.opacity;
color[3] *= properties.opacity;
+ // We're only drawing end caps + round line joins if the line is > 2px. Otherwise, they aren't visible anyway.
+ if (bucket.hasPoints() && outset > 1.0f) {
+ glUseProgram(linejoinShader->program);
+ glUniformMatrix4fv(linejoinShader->u_matrix, 1, GL_FALSE, matrix.data());
+ glUniform4fv(linejoinShader->u_color, 1, color.data());
+ glUniform2f(linejoinShader->u_world, transform.fb_width / 2, transform.fb_height / 2);
+ glUniform2f(linejoinShader->u_linewidth, (outset - 0.25) * transform.pixelRatio, (inset - 0.25) * transform.pixelRatio);
+ glPointSize(ceil(transform.pixelRatio * outset * 2.0));
+ bucket.drawPoints(*linejoinShader);
+ }
+
// var imagePos = properties.image && imageSprite.getPosition(properties.image);
- // var shader;
bool imagePos = false;
-
if (imagePos) {
// var factor = 8 / Math.pow(2, painter.transform.zoom - params.z);
@@ -321,38 +334,17 @@ void Painter::renderLine(LineBucket& bucket, const std::string& layer_name, cons
glUseProgram(lineShader->program);
glUniformMatrix4fv(lineShader->u_matrix, 1, GL_FALSE, matrix.data());
glUniformMatrix4fv(lineShader->u_exmatrix, 1, GL_FALSE, exMatrix.data());
- // glUniform2fv(painter.lineShader.u_dasharray, properties.dasharray || [1, -1]);
- glUniform2f(lineShader->u_dasharray, 1, -1);
-
// TODO: Move this to transform?
const double tilePixelRatio = transform.getScale() / (1 << transform.getIntegerZoom()) / 8;
+ glUniform2f(lineShader->u_dasharray, 1, -1);
glUniform2f(lineShader->u_linewidth, outset, inset);
glUniform1f(lineShader->u_ratio, tilePixelRatio);
- glUniform1f(lineShader->u_gamma, transform.pixelRatio);
-
- // const Color& color = properties.color;
- // if (!params.antialiasing) {
- // color[3] = Infinity;
- // glUniform4fv(lineShader->u_color, color);
- // } else {
glUniform4fv(lineShader->u_color, 1, color.data());
- // }
-
-
- glUniform1f(lineShader->u_point, 0);
- bucket.bind(*lineShader);
- bucket.drawLines();
-
- if (bucket.geometry.join == JoinType::Round) {
- glUniform1f(lineShader->u_point, 1);
- bucket.drawPoints();
- }
+ glUniform1f(lineShader->u_debug, 0);
+ bucket.drawLines(*lineShader);
}
-
- // statistics
- // stats.lines += count;
}
void Painter::renderDebug(const Tile::Ptr& tile) {
@@ -364,16 +356,16 @@ void Painter::renderDebug(const Tile::Ptr& tile) {
// draw tile outline
tileBorderArray.bind(*plainShader, tileBorderBuffer, BUFFER_OFFSET(0));
glUniform4f(plainShader->u_color, 1.0f, 0.0f, 0.0f, 1.0f);
- glLineWidth(4.0f);
+ glLineWidth(4.0f * transform.pixelRatio);
glDrawArrays(GL_LINE_STRIP, 0, tileBorderBuffer.index());
// draw debug info
tile->debugFontArray.bind(*plainShader, tile->debugFontBuffer, BUFFER_OFFSET(0));
glUniform4f(plainShader->u_color, 1.0f, 1.0f, 1.0f, 1.0f);
- glLineWidth(4.0f);
+ glLineWidth(4.0f * transform.pixelRatio);
glDrawArrays(GL_LINES, 0, tile->debugFontBuffer.index());
glUniform4f(plainShader->u_color, 0.0f, 0.0f, 0.0f, 1.0f);
- glLineWidth(2.0f);
+ glLineWidth(2.0f * transform.pixelRatio);
glDrawArrays(GL_LINES, 0, tile->debugFontBuffer.index());
// Revert blending mode to blend to the back.
diff --git a/src/renderer/shader-line.cpp b/src/renderer/shader-line.cpp
index feed1626e5..667af4fe12 100644
--- a/src/renderer/shader-line.cpp
+++ b/src/renderer/shader-line.cpp
@@ -24,20 +24,18 @@ LineShader::LineShader()
u_exmatrix = glGetUniformLocation(program, "u_exmatrix");
u_linewidth = glGetUniformLocation(program, "u_linewidth");
u_color = glGetUniformLocation(program, "u_color");
- u_debug = glGetUniformLocation(program, "u_debug");
u_ratio = glGetUniformLocation(program, "u_ratio");
u_dasharray = glGetUniformLocation(program, "u_dasharray");
- u_point = glGetUniformLocation(program, "u_point");
- u_gamma = glGetUniformLocation(program, "u_gamma");
+ u_debug = glGetUniformLocation(program, "u_debug");
}
void LineShader::bind(char *offset) {
glEnableVertexAttribArray(a_pos);
glVertexAttribPointer(a_pos, 2, GL_SHORT, false, 8, offset);
- glEnableVertexAttribArray(a_extrude);
- glVertexAttribPointer(a_extrude, 2, GL_BYTE, false, 8, offset + 6);
-
glEnableVertexAttribArray(a_linesofar);
glVertexAttribPointer(a_linesofar, 1, GL_SHORT, false, 8, offset + 4);
+
+ glEnableVertexAttribArray(a_extrude);
+ glVertexAttribPointer(a_extrude, 2, GL_BYTE, false, 8, offset + 6);
} \ No newline at end of file
diff --git a/src/renderer/shader-linejoin.cpp b/src/renderer/shader-linejoin.cpp
new file mode 100644
index 0000000000..5d9fa13ecb
--- /dev/null
+++ b/src/renderer/shader-linejoin.cpp
@@ -0,0 +1,31 @@
+#include <llmr/renderer/shader-linejoin.hpp>
+#include <llmr/shader/shaders.hpp>
+#include <llmr/platform/gl.hpp>
+
+#include <cstdio>
+
+using namespace llmr;
+
+LinejoinShader::LinejoinShader()
+ : Shader(
+ shaders[LINEJOIN_SHADER].vertex,
+ shaders[LINEJOIN_SHADER].fragment
+ ) {
+ if (!valid) {
+ fprintf(stderr, "invalid line shader\n");
+ return;
+ }
+
+ a_pos = glGetAttribLocation(program, "a_pos");
+
+ u_matrix = glGetUniformLocation(program, "u_matrix");
+ u_world = glGetUniformLocation(program, "u_world");
+ u_linewidth = glGetUniformLocation(program, "u_linewidth");
+ u_color = glGetUniformLocation(program, "u_color");
+}
+
+void LinejoinShader::bind(char *offset) {
+ glEnableVertexAttribArray(a_pos);
+ // Note: We're referring to the vertices in a line array, which are 8 bytes long!
+ glVertexAttribPointer(a_pos, 2, GL_SHORT, false, 8, offset);
+}
diff --git a/src/shader/line.fragment.glsl b/src/shader/line.fragment.glsl
index 8064e5c733..6cef488633 100644
--- a/src/shader/line.fragment.glsl
+++ b/src/shader/line.fragment.glsl
@@ -1,9 +1,6 @@
-// shared
uniform float u_debug;
uniform vec2 u_linewidth;
uniform vec4 u_color;
-uniform float u_point;
-uniform float u_gamma;
uniform vec2 u_dasharray;
@@ -12,23 +9,21 @@ varying float v_linesofar;
void main() {
// Calculate the distance of the pixel from the line in pixels.
- float dist = length(v_normal) * (1.0 - u_point) + u_point * length(gl_PointCoord * 2.0 - 1.0);
-
- dist *= u_linewidth.s;
+ 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 - 1.0), u_linewidth.s - dist) * u_gamma, 0.0, 1.0);
+ float alpha = clamp(min(dist - (u_linewidth.t - 1.0), u_linewidth.s - dist), 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;
-
if (u_debug > 0.0) {
- gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+ gl_FragColor = u_color;
+ } else {
+ gl_FragColor = u_color * alpha;
}
-}
+} \ No newline at end of file
diff --git a/src/shader/line.vertex.glsl b/src/shader/line.vertex.glsl
index 8520930b47..f70933046d 100644
--- a/src/shader/line.vertex.glsl
+++ b/src/shader/line.vertex.glsl
@@ -1,29 +1,26 @@
-// these are the shaders for rendering antialiased lines
-
// 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 63.0
+#define scale 0.015873016
attribute vec2 a_pos;
attribute vec2 a_extrude;
attribute float a_linesofar;
-// matrix is for the vertex position, exmatrix is for rotating and projecting
+// posmatrix is for the vertex position, exmatrix is for rotating and projecting
// the extrusion vector.
uniform mat4 u_matrix;
uniform mat4 u_exmatrix;
-
uniform float u_debug;
// shared
uniform float u_ratio;
uniform vec2 u_linewidth;
uniform vec4 u_color;
-uniform float u_point;
varying vec2 v_normal;
varying float v_linesofar;
@@ -39,24 +36,18 @@ void main() {
// Scale the extrusion vector down to a normal and then up by the line width
// of this vertex.
- vec2 extrude = a_extrude / scale;
- vec2 dist = u_linewidth.s * extrude * (1.0 - u_point);
-
- // If the x coordinate is the maximum integer, we move the z coordinates out
- // of the view plane so that the triangle gets clipped. This makes it easier
- // for us to create degenerate triangle strips.
- float z = step(32767.0, a_pos.x) * 2.0;
-
- // When drawing points, skip every other vertex
- z += u_point * step(1.0, v_normal.y);
+ 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 / 2.0), 0.0, 1.0) + u_exmatrix * vec4(dist, z, 0.0);
+ gl_Position = u_matrix * vec4(floor(a_pos * 0.5), 0.0, 1.0) + u_exmatrix * dist;
v_linesofar = a_linesofar * u_ratio;
+ gl_PointSize = 8.0;
- gl_PointSize = 2.0 * u_linewidth.s - 1.0;
-}
+ if (u_debug > 1.5) {
+ gl_Position = u_matrix * vec4(floor(a_pos * 0.5), 0.0, 1.0);
+ }
+} \ No newline at end of file
diff --git a/src/shader/linejoin.fragment.glsl b/src/shader/linejoin.fragment.glsl
new file mode 100644
index 0000000000..705a57766e
--- /dev/null
+++ b/src/shader/linejoin.fragment.glsl
@@ -0,0 +1,14 @@
+uniform vec4 u_color;
+uniform vec2 u_linewidth;
+
+varying vec2 v_pos;
+
+void main() {
+ float dist = length(v_pos - gl_FragCoord.xy);
+
+ // 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 - 1.0), u_linewidth.s - dist), 0.0, 1.0);
+ gl_FragColor = u_color * alpha;
+}
diff --git a/src/shader/linejoin.vertex.glsl b/src/shader/linejoin.vertex.glsl
new file mode 100644
index 0000000000..8e67af2539
--- /dev/null
+++ b/src/shader/linejoin.vertex.glsl
@@ -0,0 +1,12 @@
+attribute vec2 a_pos;
+
+uniform mat4 u_matrix;
+uniform vec2 u_world;
+
+varying vec2 v_pos;
+
+void main() {
+ gl_Position = u_matrix * vec4(floor(a_pos / 2.0), 0.0, 1.0);
+ v_pos = (gl_Position.xy + 1.0) * u_world;
+ gl_PointSize = u_linewidth.s * 2.0;
+}
diff --git a/src/shader/shaders.cpp b/src/shader/shaders.cpp
index 59fc34839e..3b06fbcf15 100644
--- a/src/shader/shaders.cpp
+++ b/src/shader/shaders.cpp
@@ -5,8 +5,12 @@ using namespace llmr;
const shader_source llmr::shaders[SHADER_COUNT] = {
{
- "// 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) * 2.0;\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",
- "// 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",
+ "// 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#define scale 0.015873016\n\nattribute vec2 a_pos;\nattribute vec2 a_extrude;\nattribute float a_linesofar;\n\n// posmatrix is for the vertex position, exmatrix is for rotating and projecting\n// the extrusion vector.\nuniform mat4 u_matrix;\nuniform mat4 u_exmatrix;\n\nuniform float u_debug;\n\n// shared\nuniform float u_ratio;\nuniform vec2 u_linewidth;\nuniform vec4 u_color;\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 vec4 dist = vec4(u_linewidth.s * a_extrude * scale, 0.0, 0.0);\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 * 0.5), 0.0, 1.0) + u_exmatrix * dist;\n v_linesofar = a_linesofar * u_ratio;\n\n gl_PointSize = 8.0;\n\n if (u_debug > 1.5) {\n gl_Position = u_matrix * vec4(floor(a_pos * 0.5), 0.0, 1.0);\n }\n}",
+ "uniform float u_debug;\nuniform vec2 u_linewidth;\nuniform vec4 u_color;\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) * 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), 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 if (u_debug > 0.0) {\n gl_FragColor = u_color;\n } else {\n gl_FragColor = u_color * alpha;\n }\n}",
+ },
+ {
+ "attribute vec2 a_pos;\n\nuniform mat4 u_matrix;\nuniform vec2 u_world;\n\nvarying vec2 v_pos;\n\nvoid main() {\n gl_Position = u_matrix * vec4(floor(a_pos / 2.0), 0.0, 1.0);\n v_pos = (gl_Position.xy + 1.0) * u_world;\n}\n",
+ "uniform vec4 u_color;\nuniform vec2 u_linewidth;\n\nvarying vec2 v_pos;\n\nvoid main() {\n float dist = length(v_pos - gl_FragCoord.xy);\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), 0.0, 1.0);\n gl_FragColor = u_color * alpha;\n}\n",
},
{
"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",
diff --git a/src/style/resources.cpp b/src/style/resources.cpp
index def1933ff2..15b6aa040a 100644
--- a/src/style/resources.cpp
+++ b/src/style/resources.cpp
@@ -9,14 +9,14 @@ const unsigned char resources::style[] = {
111, 97, 100, 95, 108, 97, 114, 103, 101, 16, 2, 26, 7, 115, 116, 114,
101, 101, 116, 115, 34, 4, 114, 111, 97, 100, 42, 5, 99, 108, 97, 115,
115, 50, 10, 10, 8, 109, 111, 116, 111, 114, 119, 97, 121, 50, 6, 10,
- 4, 109, 97, 105, 110, 56, 1, 64, 2, 10, 52, 10, 12, 114, 111, 97,
+ 4, 109, 97, 105, 110, 56, 1, 64, 3, 10, 52, 10, 12, 114, 111, 97,
100, 95, 114, 101, 103, 117, 108, 97, 114, 16, 2, 26, 7, 115, 116, 114,
101, 101, 116, 115, 34, 4, 114, 111, 97, 100, 42, 5, 99, 108, 97, 115,
- 115, 50, 8, 10, 6, 115, 116, 114, 101, 101, 116, 56, 1, 64, 2, 10,
+ 115, 50, 8, 10, 6, 115, 116, 114, 101, 101, 116, 56, 1, 64, 3, 10,
60, 10, 12, 114, 111, 97, 100, 95, 108, 105, 109, 105, 116, 101, 100, 16,
2, 26, 7, 115, 116, 114, 101, 101, 116, 115, 34, 4, 114, 111, 97, 100,
42, 5, 99, 108, 97, 115, 115, 50, 16, 10, 14, 115, 116, 114, 101, 101,
- 116, 95, 108, 105, 109, 105, 116, 101, 100, 56, 1, 64, 2, 10, 41, 10,
+ 116, 95, 108, 105, 109, 105, 116, 101, 100, 56, 1, 64, 3, 10, 41, 10,
4, 112, 97, 114, 107, 16, 1, 26, 7, 115, 116, 114, 101, 101, 116, 115,
34, 7, 108, 97, 110, 100, 117, 115, 101, 42, 5, 99, 108, 97, 115, 115,
50, 6, 10, 4, 112, 97, 114, 107, 10, 41, 10, 4, 119, 111, 111, 100,