summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLauren Budorick <lauren@mapbox.com>2014-07-25 18:17:37 -0700
committerJohn Firebaugh <john.firebaugh@gmail.com>2014-09-03 18:12:40 -0700
commit71c31cee2499d44fcd590136d15c5da7fbfb65ec (patch)
treebdbaf4289a156af7be552a3758e257ef25e2caf4
parentc1280f0b380bfb21ce9e811b87bcf7d8ab380f25 (diff)
downloadqtlocation-mapboxgl-71c31cee2499d44fcd590136d15c5da7fbfb65ec.tar.gz
linepattern in progress
-rw-r--r--include/mbgl/renderer/line_bucket.hpp4
-rw-r--r--include/mbgl/renderer/painter.hpp2
-rw-r--r--include/mbgl/shader/linepattern_shader.hpp59
-rw-r--r--src/renderer/line_bucket.cpp14
-rw-r--r--src/renderer/painter.cpp2
-rw-r--r--src/renderer/painter_line.cpp57
-rw-r--r--src/shader/linepattern.fragment.glsl34
-rw-r--r--src/shader/linepattern.vertex.glsl53
-rw-r--r--src/shader/linepattern_shader.cpp121
9 files changed, 333 insertions, 13 deletions
diff --git a/include/mbgl/renderer/line_bucket.hpp b/include/mbgl/renderer/line_bucket.hpp
index c7e375a0a1..8babb734ed 100644
--- a/include/mbgl/renderer/line_bucket.hpp
+++ b/include/mbgl/renderer/line_bucket.hpp
@@ -17,10 +17,11 @@ class LineVertexBuffer;
class TriangleElementsBuffer;
class LineShader;
class LinejoinShader;
+class LinepatternShader;
struct pbf;
class LineBucket : public Bucket {
- typedef ElementGroup<1> triangle_group_type;
+ typedef ElementGroup<2> triangle_group_type;
typedef ElementGroup<1> point_group_type;
public:
@@ -38,6 +39,7 @@ public:
bool hasPoints() const;
void drawLines(LineShader& shader);
+ void drawLinePatterns(LinepatternShader& shader);
void drawPoints(LinejoinShader& shader);
public:
diff --git a/include/mbgl/renderer/painter.hpp b/include/mbgl/renderer/painter.hpp
index a8fe62b550..534323dd5d 100644
--- a/include/mbgl/renderer/painter.hpp
+++ b/include/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/linepattern_shader.hpp>
#include <mbgl/shader/icon_shader.hpp>
#include <mbgl/shader/raster_shader.hpp>
#include <mbgl/shader/text_shader.hpp>
@@ -169,6 +170,7 @@ public:
std::unique_ptr<OutlineShader> outlineShader;
std::unique_ptr<LineShader> lineShader;
std::unique_ptr<LinejoinShader> linejoinShader;
+ std::unique_ptr<LinepatternShader> linepatternShader;
std::unique_ptr<PatternShader> patternShader;
std::unique_ptr<IconShader> iconShader;
std::unique_ptr<RasterShader> rasterShader;
diff --git a/include/mbgl/shader/linepattern_shader.hpp b/include/mbgl/shader/linepattern_shader.hpp
new file mode 100644
index 0000000000..7d98b295a8
--- /dev/null
+++ b/include/mbgl/shader/linepattern_shader.hpp
@@ -0,0 +1,59 @@
+#ifndef MBGL_SHADER_SHADER_LINEPATTERN
+#define MBGL_SHADER_SHADER_LINEPATTERN
+
+#include <mbgl/shader/shader.hpp>
+
+namespace mbgl {
+
+class LinepatternShader : public Shader {
+public:
+ LinepatternShader();
+
+ void bind(char *offset);
+
+ void setExtrudeMatrix(const std::array<float, 16>& exmatrix);
+ void setLineWidth(const std::array<float, 2>& linewidth);
+ void setRatio(float ratio);
+ void setDebug(float debug);
+ void setPatternSize(const std::array<float, 2>& new_pattern_size);
+ void setPatternTopLeft(const std::array<float, 2>& new_pattern_tl);
+ void setPatternBottomRight(const std::array<float, 2>& new_pattern_br);
+ void setOffset(const std::array<float, 2>& offset);
+ void setGamma(float new_gamma);
+ void setFade(float new_fade);
+
+private:
+ int32_t a_pos = -1;
+ int32_t a_extrude = -1;
+ int32_t a_linesofar = -1;
+
+ std::array<float, 16> exmatrix = {{}};
+ int32_t u_exmatrix = -1;
+
+ std::array<float, 2> linewidth = {{}};
+ int32_t u_linewidth = -1;
+
+ float ratio = 0;
+ int32_t u_ratio = -1;
+
+ std::array<float, 2> pattern_size = {{}};
+ int32_t u_pattern_size = -1;
+
+ std::array<float, 2> pattern_tl = {{}};
+ int32_t u_pattern_tl = -1;
+
+ std::array<float, 2> pattern_br = {{}};
+ int32_t u_pattern_br = -1;
+
+ std::array<float, 2> offset = {{}};
+ int32_t u_offset = -1;
+
+ float gamma = 0.0f;
+ int32_t u_gamma = -1;
+
+ float fade = 0;
+ int32_t u_fade = -1;
+};
+}
+
+#endif
diff --git a/src/renderer/line_bucket.cpp b/src/renderer/line_bucket.cpp
index e089d7f61b..2e89a7c35d 100644
--- a/src/renderer/line_bucket.cpp
+++ b/src/renderer/line_bucket.cpp
@@ -374,6 +374,20 @@ void LineBucket::drawLines(LineShader& shader) {
}
}
+void LineBucket::drawLinePatterns(LinepatternShader& 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[1].bind(shader, vertexBuffer, triangleElementsBuffer, vertex_index);
+ 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::drawPoints(LinejoinShader& shader) {
char *vertex_index = BUFFER_OFFSET(vertex_start * vertexBuffer.itemSize);
char *elements_index = BUFFER_OFFSET(point_elements_start * pointElementsBuffer.itemSize);
diff --git a/src/renderer/painter.cpp b/src/renderer/painter.cpp
index 2a3d45c9ed..938bd5bd84 100644
--- a/src/renderer/painter.cpp
+++ b/src/renderer/painter.cpp
@@ -41,6 +41,7 @@ void Painter::setup() {
assert(outlineShader);
assert(lineShader);
assert(linejoinShader);
+ assert(linepatternShader);
assert(patternShader);
assert(rasterShader);
assert(textShader);
@@ -70,6 +71,7 @@ void Painter::setupShaders() {
if (!outlineShader) outlineShader = std::make_unique<OutlineShader>();
if (!lineShader) lineShader = std::make_unique<LineShader>();
if (!linejoinShader) linejoinShader = std::make_unique<LinejoinShader>();
+ if (!linepatternShader) linepatternShader = std::make_unique<LinepatternShader>();
if (!patternShader) patternShader = std::make_unique<PatternShader>();
if (!iconShader) iconShader = std::make_unique<IconShader>();
if (!rasterShader) rasterShader = std::make_unique<RasterShader>();
diff --git a/src/renderer/painter_line.cpp b/src/renderer/painter_line.cpp
index ad0778fc0b..df2fb88193 100644
--- a/src/renderer/painter_line.cpp
+++ b/src/renderer/painter_line.cpp
@@ -1,6 +1,9 @@
#include <mbgl/renderer/painter.hpp>
#include <mbgl/renderer/line_bucket.hpp>
+#include <mbgl/style/style.hpp>
#include <mbgl/style/style_layer.hpp>
+#include <mbgl/map/sprite.hpp>
+#include <mbgl/geometry/sprite_atlas.hpp>
#include <mbgl/map/map.hpp>
using namespace mbgl;
@@ -60,20 +63,50 @@ void Painter::renderLine(LineBucket& bucket, std::shared_ptr<StyleLayer> layer_d
bucket.drawPoints(*linejoinShader);
}
- // var imagePos = properties.image && imageSprite.getPosition(properties.image);
- bool imagePos = false;
- if (imagePos) {
- // var factor = 8 / Math.pow(2, painter.transform.zoom - params.z);
+ const std::shared_ptr<Sprite> &sprite = map.getSprite();
+ if (properties.image.size() && sprite) {
+ SpriteAtlas &spriteAtlas = *map.getSpriteAtlas();
+ Rect<uint16_t> imagePos = spriteAtlas.getImage(properties.image, *sprite);
+
+ float factor = 8.0 / std::pow(2, map.getState().getIntegerZoom() - id.z);
+
+ float fade = std::fmod(map.getState().getZoom(), 1.0);
- // imageSprite.bind(gl, true);
+ std::array<float, 2> imageSize = {{
+ imagePos.w * factor,
+ imagePos.h * factor
+ }
+ };
- // //factor = Math.pow(2, 4 - painter.transform.zoom + params.z);
- // gl.switchShader(painter.linepatternShader, painter.translatedMatrix || painter.posMatrix, painter.extrudeMatrix);
- // shader = painter.linepatternShader;
- // glUniform2fv(painter.linepatternShader.u_pattern_size, [imagePos.size[0] * factor, imagePos.size[1] ]);
- // glUniform2fv(painter.linepatternShader.u_pattern_tl, imagePos.tl);
- // glUniform2fv(painter.linepatternShader.u_pattern_br, imagePos.br);
- // glUniform1f(painter.linepatternShader.u_fade, painter.transform.z % 1.0);
+ std::array<float, 2> offset = {{
+ (float)std::fmod(id.x * 4096, imageSize[0]),
+ (float)std::fmod(id.y * 4096, imageSize[1])
+ }
+ };
+ useProgram(linepatternShader->program);
+ linepatternShader->setMatrix(vtxMatrix);
+ linepatternShader->setExtrudeMatrix(extrudeMatrix);
+ lineShader->setDashArray({{ dash_length, dash_gap }});
+ linepatternShader->setLineWidth({{ outset, inset }});
+ linepatternShader->setRatio(map.getState().getPixelRatio());
+
+ linepatternShader->setPatternSize(imageSize);
+ linepatternShader->setPatternTopLeft({{
+ float(imagePos.x) / spriteAtlas.getWidth(),
+ float(imagePos.y) / spriteAtlas.getHeight(),
+ }});
+ linepatternShader->setPatternBottomRight({{
+ float(imagePos.x + imagePos.w) / spriteAtlas.getWidth(),
+ float(imagePos.y + imagePos.h) / spriteAtlas.getHeight(),
+ }});
+ linepatternShader->setOffset(offset);
+ linepatternShader->setGamma(map.getState().getPixelRatio());
+ linepatternShader->setFade(fade);
+
+ spriteAtlas.bind(true);
+ glDepthRange(strata + strata_epsilon, 1.0f); // may or may not matter
+
+ bucket.drawLinePatterns(*linepatternShader);
} else {
useProgram(lineShader->program);
diff --git a/src/shader/linepattern.fragment.glsl b/src/shader/linepattern.fragment.glsl
new file mode 100644
index 0000000000..9d48adc5d4
--- /dev/null
+++ b/src/shader/linepattern.fragment.glsl
@@ -0,0 +1,34 @@
+uniform vec2 u_linewidth;
+uniform float u_gamma;
+uniform float u_fade;
+
+uniform vec2 u_pattern_size;
+uniform vec2 u_pattern_tl;
+uniform vec2 u_pattern_br;
+
+uniform sampler2D u_image;
+
+varying vec2 v_normal;
+varying float v_linesofar;
+
+void main() {
+ // Calculate the distance of the pixel from the line in pixels.
+ float dist = length(v_normal) * length(gl_PointCoord * 2.0 - 1.0);
+
+ // 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 x = mod(v_linesofar / u_pattern_size.x, 1.0);
+ float y = 0.5 + (v_normal.y * u_linewidth.s / u_pattern_size.y);
+ vec2 pos = mix(u_pattern_tl, u_pattern_br, vec2(x, y));
+ float x2 = mod(x * 2.0, 1.0);
+ vec2 pos2 = mix(u_pattern_tl, u_pattern_br, vec2(x2, y));
+
+ vec4 color = texture2D(u_image, pos) * (1.0 - u_fade) + u_fade * texture2D(u_image, pos2);
+
+ color.rgb *= color.a;
+
+ gl_FragColor = color * alpha;
+}
diff --git a/src/shader/linepattern.vertex.glsl b/src/shader/linepattern.vertex.glsl
new file mode 100644
index 0000000000..faf284c90a
--- /dev/null
+++ b/src/shader/linepattern.vertex.glsl
@@ -0,0 +1,53 @@
+// 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
+
+attribute vec2 a_pos;
+attribute vec2 a_extrude;
+attribute float a_linesofar;
+
+// posmatrix 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 vec4 u_color;
+
+varying vec2 v_normal;
+varying float v_linesofar;
+
+void main() {
+ // 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.
+ vec2 extrude = a_extrude / scale;
+ vec4 dist = vec4(u_linewidth.s * extrude, 0.0, 0.0);
+
+ // 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);
+
+ z += step(1.0, v_normal.y);
+
+ // 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 * dist;
+ v_linesofar = a_linesofar; // * u_ratio;
+}
diff --git a/src/shader/linepattern_shader.cpp b/src/shader/linepattern_shader.cpp
new file mode 100644
index 0000000000..ec235f648e
--- /dev/null
+++ b/src/shader/linepattern_shader.cpp
@@ -0,0 +1,121 @@
+#include <mbgl/shader/linepattern_shader.hpp>
+#include <mbgl/shader/shaders.hpp>
+#include <mbgl/platform/gl.hpp>
+#include <iostream>
+
+#include <cstdio>
+
+using namespace mbgl;
+
+LinepatternShader::LinepatternShader()
+ : Shader(
+ "linepattern",
+ shaders[LINEPATTERN_SHADER].vertex,
+ shaders[LINEPATTERN_SHADER].fragment
+ ) {
+ if (!valid) {
+ fprintf(stderr, "invalid line pattern shader\n");
+ return;
+ }
+
+ a_pos = glGetAttribLocation(program, "a_pos");
+ a_extrude = glGetAttribLocation(program, "a_extrude");
+ a_linesofar = glGetAttribLocation(program, "a_linesofar");
+
+ u_matrix = glGetUniformLocation(program, "u_matrix");
+ u_exmatrix = glGetUniformLocation(program, "u_exmatrix");
+ u_linewidth = glGetUniformLocation(program, "u_linewidth");
+ u_ratio = glGetUniformLocation(program, "u_ratio");
+ 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_offset = glGetUniformLocation(program, "u_offset");
+ u_gamma = glGetUniformLocation(program, "u_gamma");
+ u_fade = glGetUniformLocation(program, "u_fade");
+
+ //fprintf(stderr, "LinepatternShader:\n");
+ //fprintf(stderr, " - u_matrix: %d\n", u_matrix);
+ //fprintf(stderr, " - u_exmatrix: %d\n", u_exmatrix);
+ //fprintf(stderr, " - u_linewidth: %d\n", u_linewidth);
+ //fprintf(stderr, " - u_ratio: %d\n", u_ratio);
+ //fprintf(stderr, " - u_pattern_size: %d\n", u_pattern_size);
+ //fprintf(stderr, " - u_pattern_tl: %d\n", u_pattern_tl);
+ //fprintf(stderr, " - u_pattern_br: %d\n", u_pattern_br);
+ //fprintf(stderr, " - u_offset: %d\n", u_offset);
+ //fprintf(stderr, " - u_gamma: %d\n", u_gamma);
+}
+
+void LinepatternShader::bind(char *offset) {
+ glEnableVertexAttribArray(a_pos);
+ glVertexAttribPointer(a_pos, 2, GL_SHORT, false, 8, offset + 0);
+
+ glEnableVertexAttribArray(a_extrude);
+ glVertexAttribPointer(a_extrude, 2, GL_BYTE, false, 8, offset + 4);
+
+ glEnableVertexAttribArray(a_linesofar);
+ glVertexAttribPointer(a_linesofar, 1, GL_SHORT, false, 8, offset + 6);
+}
+
+void LinepatternShader::setExtrudeMatrix(const std::array<float, 16>& new_exmatrix) {
+ if (exmatrix != new_exmatrix) {
+ glUniformMatrix4fv(u_exmatrix, 1, GL_FALSE, new_exmatrix.data());
+ exmatrix = new_exmatrix;
+ }
+}
+
+void LinepatternShader::setPatternSize(const std::array<float, 2>& new_pattern_size) {
+ if (pattern_size != new_pattern_size) {
+ glUniform2fv(u_pattern_size, 1, new_pattern_size.data());
+ pattern_size = new_pattern_size;
+ }
+}
+
+void LinepatternShader::setLineWidth(const std::array<float, 2>& new_linewidth) {
+ if (linewidth != new_linewidth) {
+ glUniform2fv(u_linewidth, 1, new_linewidth.data());
+ linewidth = new_linewidth;
+ }
+}
+
+void LinepatternShader::setRatio(float new_ratio) {
+ if (ratio != new_ratio) {
+ glUniform1f(u_ratio, new_ratio);
+ ratio = new_ratio;
+ }
+}
+
+void LinepatternShader::setPatternTopLeft(const std::array<float, 2>& new_pattern_tl) {
+ if (pattern_tl != new_pattern_tl) {
+ glUniform2fv(u_pattern_tl, 1, new_pattern_tl.data());
+ pattern_tl = new_pattern_tl;
+ }
+}
+
+void LinepatternShader::setPatternBottomRight(const std::array<float, 2>& new_pattern_br) {
+ if (pattern_br != new_pattern_br) {
+ glUniform2fv(u_pattern_br, 1, new_pattern_br.data());
+ pattern_br = new_pattern_br;
+ }
+}
+
+void LinepatternShader::setOffset(const std::array<float, 2>& new_offset) {
+ if (offset != new_offset) {
+ glUniform2fv(u_offset, 1, new_offset.data());
+ offset = new_offset;
+ }
+}
+
+void LinepatternShader::setGamma(float new_gamma) {
+ if (gamma != new_gamma) {
+ glUniform1f(u_gamma, new_gamma);
+ gamma = new_gamma;
+ }
+}
+
+void LinepatternShader::setFade(float new_fade) {
+ if (fade != new_fade) {
+ glUniform1f(u_fade, new_fade);
+ fade = new_fade;
+ }
+};