summaryrefslogtreecommitdiff
path: root/src/mbgl/shader
diff options
context:
space:
mode:
Diffstat (limited to 'src/mbgl/shader')
-rw-r--r--src/mbgl/shader/dot.fragment.glsl9
-rw-r--r--src/mbgl/shader/dot.vertex.glsl9
-rw-r--r--src/mbgl/shader/dot_shader.cpp26
-rw-r--r--src/mbgl/shader/dot_shader.hpp26
-rw-r--r--src/mbgl/shader/gaussian.fragment.glsl11
-rw-r--r--src/mbgl/shader/gaussian.vertex.glsl15
-rw-r--r--src/mbgl/shader/gaussian_shader.cpp28
-rw-r--r--src/mbgl/shader/gaussian_shader.hpp25
-rw-r--r--src/mbgl/shader/icon.fragment.glsl8
-rw-r--r--src/mbgl/shader/icon.vertex.glsl73
-rw-r--r--src/mbgl/shader/icon_shader.cpp60
-rw-r--r--src/mbgl/shader/icon_shader.hpp41
-rw-r--r--src/mbgl/shader/line.fragment.glsl25
-rw-r--r--src/mbgl/shader/line.vertex.glsl45
-rw-r--r--src/mbgl/shader/line_shader.cpp34
-rw-r--r--src/mbgl/shader/line_shader.hpp32
-rw-r--r--src/mbgl/shader/linejoin.fragment.glsl14
-rw-r--r--src/mbgl/shader/linejoin.vertex.glsl13
-rw-r--r--src/mbgl/shader/linejoin_shader.cpp27
-rw-r--r--src/mbgl/shader/linejoin_shader.hpp27
-rw-r--r--src/mbgl/shader/linepattern.fragment.glsl37
-rw-r--r--src/mbgl/shader/linepattern.vertex.glsl57
-rw-r--r--src/mbgl/shader/linepattern_shader.cpp35
-rw-r--r--src/mbgl/shader/linepattern_shader.hpp33
-rw-r--r--src/mbgl/shader/outline.fragment.glsl9
-rw-r--r--src/mbgl/shader/outline.vertex.glsl10
-rw-r--r--src/mbgl/shader/outline_shader.cpp26
-rw-r--r--src/mbgl/shader/outline_shader.hpp25
-rw-r--r--src/mbgl/shader/pattern.fragment.glsl21
-rw-r--r--src/mbgl/shader/pattern.vertex.glsl11
-rw-r--r--src/mbgl/shader/pattern_shader.cpp26
-rw-r--r--src/mbgl/shader/pattern_shader.hpp29
-rw-r--r--src/mbgl/shader/plain.fragment.glsl5
-rw-r--r--src/mbgl/shader/plain.vertex.glsl7
-rw-r--r--src/mbgl/shader/plain_shader.cpp26
-rw-r--r--src/mbgl/shader/plain_shader.hpp24
-rw-r--r--src/mbgl/shader/raster.fragment.glsl36
-rw-r--r--src/mbgl/shader/raster.vertex.glsl13
-rw-r--r--src/mbgl/shader/raster_shader.cpp28
-rw-r--r--src/mbgl/shader/raster_shader.hpp31
-rw-r--r--src/mbgl/shader/sdf.fragment.glsl13
-rw-r--r--src/mbgl/shader/sdf.vertex.glsl69
-rw-r--r--src/mbgl/shader/sdf_shader.cpp91
-rw-r--r--src/mbgl/shader/sdf_shader.hpp53
-rw-r--r--src/mbgl/shader/shader.cpp133
-rw-r--r--src/mbgl/shader/shader.hpp28
-rw-r--r--src/mbgl/shader/uniform.cpp47
-rw-r--r--src/mbgl/shader/uniform.hpp53
48 files changed, 1524 insertions, 0 deletions
diff --git a/src/mbgl/shader/dot.fragment.glsl b/src/mbgl/shader/dot.fragment.glsl
new file mode 100644
index 0000000000..6d998b5611
--- /dev/null
+++ b/src/mbgl/shader/dot.fragment.glsl
@@ -0,0 +1,9 @@
+uniform vec4 u_color;
+uniform float u_blur;
+
+void main() {
+ float dist = length(gl_PointCoord - 0.5);
+ float t = smoothstep(0.5, 0.5 - u_blur, dist);
+
+ gl_FragColor = u_color * t;
+}
diff --git a/src/mbgl/shader/dot.vertex.glsl b/src/mbgl/shader/dot.vertex.glsl
new file mode 100644
index 0000000000..5310ae745e
--- /dev/null
+++ b/src/mbgl/shader/dot.vertex.glsl
@@ -0,0 +1,9 @@
+uniform mat4 u_matrix;
+uniform float u_size;
+
+attribute vec2 a_pos;
+
+void main(void) {
+ gl_Position = u_matrix * vec4(a_pos, 0, 1);
+ gl_PointSize = u_size;
+}
diff --git a/src/mbgl/shader/dot_shader.cpp b/src/mbgl/shader/dot_shader.cpp
new file mode 100644
index 0000000000..a897f410a7
--- /dev/null
+++ b/src/mbgl/shader/dot_shader.cpp
@@ -0,0 +1,26 @@
+#include <mbgl/shader/dot_shader.hpp>
+#include <mbgl/shader/shaders.hpp>
+#include <mbgl/platform/gl.hpp>
+
+#include <cstdio>
+
+using namespace mbgl;
+
+DotShader::DotShader()
+: Shader(
+ "dot",
+ shaders[DOT_SHADER].vertex,
+ shaders[DOT_SHADER].fragment
+ ) {
+ if (!valid) {
+ fprintf(stderr, "invalid dot shader\n");
+ return;
+ }
+
+ a_pos = glGetAttribLocation(program, "a_pos");
+}
+
+void DotShader::bind(char *offset) {
+ glEnableVertexAttribArray(a_pos);
+ glVertexAttribPointer(a_pos, 2, GL_SHORT, false, 8, offset);
+}
diff --git a/src/mbgl/shader/dot_shader.hpp b/src/mbgl/shader/dot_shader.hpp
new file mode 100644
index 0000000000..2c4176f364
--- /dev/null
+++ b/src/mbgl/shader/dot_shader.hpp
@@ -0,0 +1,26 @@
+#ifndef MBGL_SHADER_SHADER_DOT
+#define MBGL_SHADER_SHADER_DOT
+
+#include <mbgl/shader/shader.hpp>
+#include <mbgl/shader/uniform.hpp>
+
+namespace mbgl {
+
+class DotShader : public Shader {
+public:
+ DotShader();
+
+ void bind(char *offset);
+
+ UniformMatrix<4> u_matrix = {"u_matrix", *this};
+ Uniform<std::array<float, 4>> u_color = {"u_color", *this};
+ Uniform<float> u_size = {"u_size", *this};
+ Uniform<float> u_blur = {"u_blur", *this};
+
+private:
+ int32_t a_pos = -1;
+};
+
+}
+
+#endif
diff --git a/src/mbgl/shader/gaussian.fragment.glsl b/src/mbgl/shader/gaussian.fragment.glsl
new file mode 100644
index 0000000000..ee8406e9e1
--- /dev/null
+++ b/src/mbgl/shader/gaussian.fragment.glsl
@@ -0,0 +1,11 @@
+uniform sampler2D u_image;
+
+varying vec2 v_coords[3];
+
+void main() {
+ vec4 sum = vec4(0.0);
+ sum += texture2D(u_image, v_coords[0]) * 0.40261994689424746;
+ sum += texture2D(u_image, v_coords[1]) * 0.2986900265528763;
+ sum += texture2D(u_image, v_coords[2]) * 0.2986900265528763;
+ gl_FragColor = sum;
+}
diff --git a/src/mbgl/shader/gaussian.vertex.glsl b/src/mbgl/shader/gaussian.vertex.glsl
new file mode 100644
index 0000000000..26a8394204
--- /dev/null
+++ b/src/mbgl/shader/gaussian.vertex.glsl
@@ -0,0 +1,15 @@
+attribute vec2 a_pos;
+
+uniform mat4 u_matrix;
+uniform vec2 u_offset;
+
+varying vec2 v_coords[3];
+
+void main() {
+ gl_Position = u_matrix * vec4(a_pos, 0, 1);
+
+ vec2 tex = gl_Position.xy / 2.0 + 0.5;
+ v_coords[0] = tex;
+ v_coords[1] = tex + u_offset * 1.1824255238063563;
+ v_coords[2] = tex - u_offset * 1.1824255238063563;
+}
diff --git a/src/mbgl/shader/gaussian_shader.cpp b/src/mbgl/shader/gaussian_shader.cpp
new file mode 100644
index 0000000000..9060f0ee71
--- /dev/null
+++ b/src/mbgl/shader/gaussian_shader.cpp
@@ -0,0 +1,28 @@
+#include <mbgl/shader/gaussian_shader.hpp>
+#include <mbgl/shader/shaders.hpp>
+#include <mbgl/platform/gl.hpp>
+
+#include <cstdio>
+
+using namespace mbgl;
+
+GaussianShader::GaussianShader()
+ : Shader(
+ "gaussian",
+ shaders[GAUSSIAN_SHADER].vertex,
+ shaders[GAUSSIAN_SHADER].fragment
+ ) {
+ if (!valid) {
+#if defined(DEBUG)
+ fprintf(stderr, "invalid raster shader\n");
+#endif
+ return;
+ }
+
+ a_pos = glGetAttribLocation(program, "a_pos");
+}
+
+void GaussianShader::bind(char *offset) {
+ glEnableVertexAttribArray(a_pos);
+ glVertexAttribPointer(a_pos, 2, GL_SHORT, false, 0, offset);
+}
diff --git a/src/mbgl/shader/gaussian_shader.hpp b/src/mbgl/shader/gaussian_shader.hpp
new file mode 100644
index 0000000000..0f494f5c7e
--- /dev/null
+++ b/src/mbgl/shader/gaussian_shader.hpp
@@ -0,0 +1,25 @@
+#ifndef MBGL_RENDERER_SHADER_GAUSSIAN
+#define MBGL_RENDERER_SHADER_GAUSSIAN
+
+#include <mbgl/shader/shader.hpp>
+#include <mbgl/shader/uniform.hpp>
+
+namespace mbgl {
+
+class GaussianShader : public Shader {
+public:
+ GaussianShader();
+
+ void bind(char *offset);
+
+ UniformMatrix<4> u_matrix = {"u_matrix", *this};
+ Uniform<std::array<float, 2>> u_offset = {"u_offset", *this};
+ Uniform<int32_t> u_image = {"u_image", *this};
+
+private:
+ int32_t a_pos = -1;
+};
+
+}
+
+#endif
diff --git a/src/mbgl/shader/icon.fragment.glsl b/src/mbgl/shader/icon.fragment.glsl
new file mode 100644
index 0000000000..45b56793eb
--- /dev/null
+++ b/src/mbgl/shader/icon.fragment.glsl
@@ -0,0 +1,8 @@
+uniform sampler2D u_texture;
+
+varying vec2 v_tex;
+varying float v_alpha;
+
+void main() {
+ gl_FragColor = texture2D(u_texture, v_tex) * v_alpha;
+}
diff --git a/src/mbgl/shader/icon.vertex.glsl b/src/mbgl/shader/icon.vertex.glsl
new file mode 100644
index 0000000000..8c69c40410
--- /dev/null
+++ b/src/mbgl/shader/icon.vertex.glsl
@@ -0,0 +1,73 @@
+attribute vec2 a_pos;
+attribute vec2 a_offset;
+attribute vec2 a_tex;
+attribute float a_angle;
+attribute float a_minzoom;
+attribute float a_maxzoom;
+attribute float a_rangeend;
+attribute float a_rangestart;
+attribute float a_labelminzoom;
+
+
+// matrix 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_angle;
+uniform float u_zoom;
+uniform float u_flip;
+uniform float u_fadedist;
+uniform float u_minfadezoom;
+uniform float u_maxfadezoom;
+uniform float u_fadezoom;
+uniform float u_opacity;
+
+uniform vec2 u_texsize;
+
+varying vec2 v_tex;
+varying float v_alpha;
+
+void main() {
+
+ float a_fadedist = 10.0;
+ float rev = 0.0;
+
+ // u_angle is angle of the map, -128..128 representing 0..2PI
+ // a_angle is angle of the label, 0..256 representing 0..2PI, where 0 is horizontal text
+ float rotated = mod(a_angle + u_angle, 256.0);
+ // if the label rotates with the map, and if the rotated label is upside down, hide it
+ if (u_flip > 0.0 && rotated >= 64.0 && rotated < 192.0) rev = 1.0;
+
+ // If the label should be invisible, we move the vertex outside
+ // of the view plane so that the triangle gets clipped. This makes it easier
+ // for us to create degenerate triangle strips.
+ // u_zoom is the current zoom level adjusted for the change in font size
+ float z = 2.0 - step(a_minzoom, u_zoom) - (1.0 - step(a_maxzoom, u_zoom)) + rev;
+
+ // fade out labels
+ float alpha = clamp((u_fadezoom - a_labelminzoom) / u_fadedist, 0.0, 1.0);
+
+ if (u_fadedist >= 0.0) {
+ v_alpha = alpha;
+ } else {
+ v_alpha = 1.0 - alpha;
+ }
+ if (u_maxfadezoom < a_labelminzoom) {
+ v_alpha = 0.0;
+ }
+ if (u_minfadezoom >= a_labelminzoom) {
+ v_alpha = 1.0;
+ }
+
+ // if label has been faded out, clip it
+ z += step(v_alpha, 0.0);
+
+ // all the angles are 0..256 representing 0..2PI
+ // hide if (angle >= a_rangeend && angle < rangestart)
+ z += step(a_rangeend, u_angle) * (1.0 - step(a_rangestart, u_angle));
+
+ gl_Position = u_matrix * vec4(a_pos, 0, 1) + u_exmatrix * vec4(a_offset / 64.0, z, 0);
+ v_tex = a_tex / u_texsize;
+
+ v_alpha *= u_opacity;
+}
diff --git a/src/mbgl/shader/icon_shader.cpp b/src/mbgl/shader/icon_shader.cpp
new file mode 100644
index 0000000000..5c54177eb6
--- /dev/null
+++ b/src/mbgl/shader/icon_shader.cpp
@@ -0,0 +1,60 @@
+#include <mbgl/shader/icon_shader.hpp>
+#include <mbgl/shader/shaders.hpp>
+#include <mbgl/platform/gl.hpp>
+
+#include <cstdio>
+
+using namespace mbgl;
+
+IconShader::IconShader()
+ : Shader(
+ "icon",
+ shaders[ICON_SHADER].vertex,
+ shaders[ICON_SHADER].fragment
+ ) {
+ if (!valid) {
+ fprintf(stderr, "invalid icon shader\n");
+ return;
+ }
+
+ a_pos = glGetAttribLocation(program, "a_pos");
+ a_offset = glGetAttribLocation(program, "a_offset");
+ a_tex = glGetAttribLocation(program, "a_tex");
+ a_angle = glGetAttribLocation(program, "a_angle");
+ a_minzoom = glGetAttribLocation(program, "a_minzoom");
+ a_maxzoom = glGetAttribLocation(program, "a_maxzoom");
+ a_rangeend = glGetAttribLocation(program, "a_rangeend");
+ a_rangestart = glGetAttribLocation(program, "a_rangestart");
+ a_labelminzoom = glGetAttribLocation(program, "a_labelminzoom");
+}
+
+void IconShader::bind(char *offset) {
+ const int stride = 20;
+
+ glEnableVertexAttribArray(a_pos);
+ glVertexAttribPointer(a_pos, 2, GL_SHORT, false, stride, offset + 0);
+
+ glEnableVertexAttribArray(a_offset);
+ glVertexAttribPointer(a_offset, 2, GL_SHORT, false, stride, offset + 4);
+
+ glEnableVertexAttribArray(a_labelminzoom);
+ glVertexAttribPointer(a_labelminzoom, 1, GL_UNSIGNED_BYTE, false, stride, offset + 8);
+
+ glEnableVertexAttribArray(a_minzoom);
+ glVertexAttribPointer(a_minzoom, 1, GL_UNSIGNED_BYTE, false, stride, offset + 9);
+
+ glEnableVertexAttribArray(a_maxzoom);
+ glVertexAttribPointer(a_maxzoom, 1, GL_UNSIGNED_BYTE, false, stride, offset + 10);
+
+ glEnableVertexAttribArray(a_angle);
+ glVertexAttribPointer(a_angle, 1, GL_UNSIGNED_BYTE, false, stride, offset + 11);
+
+ glEnableVertexAttribArray(a_rangeend);
+ glVertexAttribPointer(a_rangeend, 1, GL_UNSIGNED_BYTE, false, stride, offset + 12);
+
+ glEnableVertexAttribArray(a_rangestart);
+ glVertexAttribPointer(a_rangestart, 1, GL_UNSIGNED_BYTE, false, stride, offset + 13);
+
+ glEnableVertexAttribArray(a_tex);
+ glVertexAttribPointer(a_tex, 2, GL_SHORT, false, stride, offset + 16);
+}
diff --git a/src/mbgl/shader/icon_shader.hpp b/src/mbgl/shader/icon_shader.hpp
new file mode 100644
index 0000000000..645d7e21b6
--- /dev/null
+++ b/src/mbgl/shader/icon_shader.hpp
@@ -0,0 +1,41 @@
+#ifndef MBGL_SHADER_SHADER_ICON
+#define MBGL_SHADER_SHADER_ICON
+
+#include <mbgl/shader/shader.hpp>
+#include <mbgl/shader/uniform.hpp>
+
+namespace mbgl {
+
+class IconShader : public Shader {
+public:
+ IconShader();
+
+ void bind(char *offset);
+
+ UniformMatrix<4> u_matrix = {"u_matrix", *this};
+ UniformMatrix<4> u_exmatrix = {"u_exmatrix", *this};
+ Uniform<float> u_angle = {"u_angle", *this};
+ Uniform<float> u_zoom = {"u_zoom", *this};
+ Uniform<float> u_flip = {"u_flip", *this};
+ Uniform<float> u_fadedist = {"u_fadedist", *this};
+ Uniform<float> u_minfadezoom = {"u_minfadezoom", *this};
+ Uniform<float> u_maxfadezoom = {"u_maxfadezoom", *this};
+ Uniform<float> u_fadezoom = {"u_fadezoom", *this};
+ Uniform<float> u_opacity = {"u_opacity", *this};
+ Uniform<std::array<float, 2>> u_texsize = {"u_texsize", *this};
+
+private:
+ int32_t a_pos = -1;
+ int32_t a_offset = -1;
+ int32_t a_tex = -1;
+ int32_t a_angle = -1;
+ int32_t a_minzoom = -1;
+ int32_t a_maxzoom = -1;
+ int32_t a_rangeend = -1;
+ int32_t a_rangestart = -1;
+ int32_t a_labelminzoom = -1;
+};
+
+}
+
+#endif
diff --git a/src/mbgl/shader/line.fragment.glsl b/src/mbgl/shader/line.fragment.glsl
new file mode 100644
index 0000000000..f4ac1458b3
--- /dev/null
+++ b/src/mbgl/shader/line.fragment.glsl
@@ -0,0 +1,25 @@
+uniform vec2 u_linewidth;
+uniform vec4 u_color;
+uniform float u_blur;
+
+uniform vec2 u_dasharray;
+
+varying vec2 v_normal;
+varying float v_linesofar;
+
+void main() {
+ // Calculate the distance of the pixel from the line in pixels.
+ float dist = length(v_normal) * u_linewidth.s;
+
+ // Calculate the antialiasing fade factor. This is either when fading in
+ // the line in case of an offset line (v_linewidth.t) or when fading out
+ // (v_linewidth.s)
+ float alpha = clamp(min(dist - (u_linewidth.t - u_blur), u_linewidth.s - dist) / u_blur, 0.0, 1.0);
+
+ // Calculate the antialiasing fade factor based on distance to the dash.
+ // Only affects alpha when line is dashed
+ float pos = mod(v_linesofar, u_dasharray.x + u_dasharray.y);
+ alpha *= max(step(0.0, -u_dasharray.y), clamp(min(pos, u_dasharray.x - pos), 0.0, 1.0));
+
+ gl_FragColor = u_color * alpha;
+}
diff --git a/src/mbgl/shader/line.vertex.glsl b/src/mbgl/shader/line.vertex.glsl
new file mode 100644
index 0000000000..1d8e687c95
--- /dev/null
+++ b/src/mbgl/shader/line.vertex.glsl
@@ -0,0 +1,45 @@
+// floor(127 / 2) == 63.0
+// the maximum allowed miter limit is 2.0 at the moment. the extrude normal is
+// stored in a byte (-128..127). we scale regular normals up to length 63, but
+// there are also "special" normals that have a bigger length (of up to 126 in
+// this case).
+// #define scale 63.0
+#define scale 0.015873016
+
+attribute vec2 a_pos;
+attribute vec2 a_extrude;
+attribute float a_linesofar;
+
+// matrix is for the vertex position, exmatrix is for rotating and projecting
+// the extrusion vector.
+uniform mat4 u_matrix;
+uniform mat4 u_exmatrix;
+
+// shared
+uniform float u_ratio;
+uniform vec2 u_linewidth;
+uniform 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.
+ vec4 dist = vec4(u_linewidth.s * a_extrude * scale, 0.0, 0.0);
+
+ // Remove the texture normal bit of the position before scaling it with the
+ // model/view matrix. Add the extrusion vector *after* the model/view matrix
+ // because we're extruding the line in pixel space, regardless of the current
+ // tile's zoom level.
+ gl_Position = u_matrix * vec4(floor(a_pos * 0.5), 0.0, 1.0) + u_exmatrix * dist;
+ v_linesofar = a_linesofar * u_ratio;
+}
diff --git a/src/mbgl/shader/line_shader.cpp b/src/mbgl/shader/line_shader.cpp
new file mode 100644
index 0000000000..8353f4c6ca
--- /dev/null
+++ b/src/mbgl/shader/line_shader.cpp
@@ -0,0 +1,34 @@
+#include <mbgl/shader/line_shader.hpp>
+#include <mbgl/shader/shaders.hpp>
+#include <mbgl/platform/gl.hpp>
+
+#include <cstdio>
+
+using namespace mbgl;
+
+LineShader::LineShader()
+ : Shader(
+ "line",
+ shaders[LINE_SHADER].vertex,
+ shaders[LINE_SHADER].fragment
+ ) {
+ if (!valid) {
+ fprintf(stderr, "invalid line shader\n");
+ return;
+ }
+
+ a_pos = glGetAttribLocation(program, "a_pos");
+ a_extrude = glGetAttribLocation(program, "a_extrude");
+ a_linesofar = glGetAttribLocation(program, "a_linesofar");
+}
+
+void LineShader::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);
+}
diff --git a/src/mbgl/shader/line_shader.hpp b/src/mbgl/shader/line_shader.hpp
new file mode 100644
index 0000000000..b789330882
--- /dev/null
+++ b/src/mbgl/shader/line_shader.hpp
@@ -0,0 +1,32 @@
+#ifndef MBGL_SHADER_SHADER_LINE
+#define MBGL_SHADER_SHADER_LINE
+
+#include <mbgl/shader/shader.hpp>
+#include <mbgl/shader/uniform.hpp>
+
+namespace mbgl {
+
+class LineShader : public Shader {
+public:
+ LineShader();
+
+ void bind(char *offset);
+
+ UniformMatrix<4> u_matrix = {"u_matrix", *this};
+ UniformMatrix<4> u_exmatrix = {"u_exmatrix", *this};
+ Uniform<std::array<float, 4>> u_color = {"u_color", *this};
+ Uniform<std::array<float, 2>> u_linewidth = {"u_linewidth", *this};
+ Uniform<std::array<float, 2>> u_dasharray = {"u_dasharray", *this};
+ Uniform<float> u_ratio = {"u_ratio", *this};
+ Uniform<float> u_blur = {"u_blur", *this};
+
+private:
+ int32_t a_pos = -1;
+ int32_t a_extrude = -1;
+ int32_t a_linesofar = -1;
+};
+
+
+}
+
+#endif
diff --git a/src/mbgl/shader/linejoin.fragment.glsl b/src/mbgl/shader/linejoin.fragment.glsl
new file mode 100644
index 0000000000..705a57766e
--- /dev/null
+++ b/src/mbgl/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/mbgl/shader/linejoin.vertex.glsl b/src/mbgl/shader/linejoin.vertex.glsl
new file mode 100644
index 0000000000..2e03561e5b
--- /dev/null
+++ b/src/mbgl/shader/linejoin.vertex.glsl
@@ -0,0 +1,13 @@
+attribute vec2 a_pos;
+
+uniform mat4 u_matrix;
+uniform vec2 u_world;
+uniform float u_size;
+
+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_size;
+}
diff --git a/src/mbgl/shader/linejoin_shader.cpp b/src/mbgl/shader/linejoin_shader.cpp
new file mode 100644
index 0000000000..050e180e00
--- /dev/null
+++ b/src/mbgl/shader/linejoin_shader.cpp
@@ -0,0 +1,27 @@
+#include <mbgl/shader/linejoin_shader.hpp>
+#include <mbgl/shader/shaders.hpp>
+#include <mbgl/platform/gl.hpp>
+
+#include <cstdio>
+
+using namespace mbgl;
+
+LinejoinShader::LinejoinShader()
+ : Shader(
+ "linejoin",
+ shaders[LINEJOIN_SHADER].vertex,
+ shaders[LINEJOIN_SHADER].fragment
+ ) {
+ if (!valid) {
+ fprintf(stderr, "invalid line shader\n");
+ return;
+ }
+
+ a_pos = glGetAttribLocation(program, "a_pos");
+}
+
+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/mbgl/shader/linejoin_shader.hpp b/src/mbgl/shader/linejoin_shader.hpp
new file mode 100644
index 0000000000..61406fd45c
--- /dev/null
+++ b/src/mbgl/shader/linejoin_shader.hpp
@@ -0,0 +1,27 @@
+#ifndef MBGL_SHADER_SHADER_LINEJOIN
+#define MBGL_SHADER_SHADER_LINEJOIN
+
+#include <mbgl/shader/shader.hpp>
+#include <mbgl/shader/uniform.hpp>
+
+namespace mbgl {
+
+class LinejoinShader : public Shader {
+public:
+ LinejoinShader();
+
+ void bind(char *offset);
+
+ UniformMatrix<4> u_matrix = {"u_matrix", *this};
+ Uniform<std::array<float, 4>> u_color = {"u_color", *this};
+ Uniform<std::array<float, 2>> u_world = {"u_world", *this};
+ Uniform<std::array<float, 2>> u_linewidth = {"u_linewidth", *this};
+ Uniform<float> u_size = {"u_size", *this};
+
+private:
+ int32_t a_pos = -1;
+};
+
+}
+
+#endif
diff --git a/src/mbgl/shader/linepattern.fragment.glsl b/src/mbgl/shader/linepattern.fragment.glsl
new file mode 100644
index 0000000000..52ca823a3b
--- /dev/null
+++ b/src/mbgl/shader/linepattern.fragment.glsl
@@ -0,0 +1,37 @@
+uniform vec2 u_linewidth;
+uniform float u_point;
+uniform float u_blur;
+
+uniform vec2 u_pattern_size;
+uniform vec2 u_pattern_tl;
+uniform vec2 u_pattern_br;
+uniform float u_fade;
+
+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) * (1.0 - u_point) + u_point * length(gl_PointCoord * 2.0 - 1.0);
+
+ dist *= u_linewidth.s;
+
+ // Calculate the antialiasing fade factor. This is either when fading in
+ // the line in case of an offset line (v_linewidth.t) or when fading out
+ // (v_linewidth.s)
+ float alpha = clamp(min(dist - (u_linewidth.t - u_blur), u_linewidth.s - dist) / u_blur, 0.0, 1.0);
+
+ float 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; // premultiply
+
+ gl_FragColor = color * alpha;
+}
diff --git a/src/mbgl/shader/linepattern.vertex.glsl b/src/mbgl/shader/linepattern.vertex.glsl
new file mode 100644
index 0000000000..4600ebf65b
--- /dev/null
+++ b/src/mbgl/shader/linepattern.vertex.glsl
@@ -0,0 +1,57 @@
+// 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;
+
+// matrix is for the vertex position, exmatrix is for rotating and projecting
+// the extrusion vector.
+uniform mat4 u_matrix;
+uniform mat4 u_exmatrix;
+
+// shared
+uniform float u_ratio;
+uniform vec2 u_linewidth;
+uniform vec4 u_color;
+uniform float u_point;
+
+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;
+ 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);
+
+ // When drawing points, skip every other vertex
+ z += u_point * 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 * vec4(dist, z, 0.0);
+ v_linesofar = a_linesofar;// * u_ratio;
+
+
+ gl_PointSize = 2.0 * u_linewidth.s - 1.0;
+}
diff --git a/src/mbgl/shader/linepattern_shader.cpp b/src/mbgl/shader/linepattern_shader.cpp
new file mode 100644
index 0000000000..954dbd2b3f
--- /dev/null
+++ b/src/mbgl/shader/linepattern_shader.cpp
@@ -0,0 +1,35 @@
+#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");
+}
+
+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);
+}
diff --git a/src/mbgl/shader/linepattern_shader.hpp b/src/mbgl/shader/linepattern_shader.hpp
new file mode 100644
index 0000000000..bf85940b8a
--- /dev/null
+++ b/src/mbgl/shader/linepattern_shader.hpp
@@ -0,0 +1,33 @@
+#ifndef MBGL_SHADER_SHADER_LINEPATTERN
+#define MBGL_SHADER_SHADER_LINEPATTERN
+
+#include <mbgl/shader/shader.hpp>
+#include <mbgl/shader/uniform.hpp>
+
+namespace mbgl {
+
+class LinepatternShader : public Shader {
+public:
+ LinepatternShader();
+
+ void bind(char *offset);
+
+ UniformMatrix<4> u_matrix = {"u_matrix", *this};
+ UniformMatrix<4> u_exmatrix = {"u_exmatrix", *this};
+ Uniform<std::array<float, 2>> u_linewidth = {"u_linewidth", *this};
+ Uniform<std::array<float, 2>> u_pattern_size = {"u_pattern_size", *this};
+ Uniform<std::array<float, 2>> u_pattern_tl = {"u_pattern_tl", *this};
+ Uniform<std::array<float, 2>> u_pattern_br = {"u_pattern_br", *this};
+ Uniform<float> u_ratio = {"u_ratio", *this};
+ Uniform<float> u_point = {"u_point", *this};
+ Uniform<float> u_blur = {"u_blur", *this};
+ Uniform<float> u_fade = {"u_fade", *this};
+
+private:
+ int32_t a_pos = -1;
+ int32_t a_extrude = -1;
+ int32_t a_linesofar = -1;
+};
+}
+
+#endif
diff --git a/src/mbgl/shader/outline.fragment.glsl b/src/mbgl/shader/outline.fragment.glsl
new file mode 100644
index 0000000000..eccda714e5
--- /dev/null
+++ b/src/mbgl/shader/outline.fragment.glsl
@@ -0,0 +1,9 @@
+uniform vec4 u_color;
+
+varying vec2 v_pos;
+
+void main() {
+ float dist = length(v_pos - gl_FragCoord.xy);
+ float alpha = smoothstep(1.0, 0.0, dist);
+ gl_FragColor = u_color * alpha;
+}
diff --git a/src/mbgl/shader/outline.vertex.glsl b/src/mbgl/shader/outline.vertex.glsl
new file mode 100644
index 0000000000..29c16e3ded
--- /dev/null
+++ b/src/mbgl/shader/outline.vertex.glsl
@@ -0,0 +1,10 @@
+attribute vec2 a_pos;
+uniform mat4 u_matrix;
+uniform vec2 u_world;
+
+varying vec2 v_pos;
+
+void main() {
+ gl_Position = u_matrix * vec4(a_pos, 0, 1);
+ v_pos = (gl_Position.xy + 1.0) / 2.0 * u_world;
+}
diff --git a/src/mbgl/shader/outline_shader.cpp b/src/mbgl/shader/outline_shader.cpp
new file mode 100644
index 0000000000..ddabfa5d0d
--- /dev/null
+++ b/src/mbgl/shader/outline_shader.cpp
@@ -0,0 +1,26 @@
+#include <mbgl/shader/outline_shader.hpp>
+#include <mbgl/shader/shaders.hpp>
+#include <mbgl/platform/gl.hpp>
+
+#include <cstdio>
+
+using namespace mbgl;
+
+OutlineShader::OutlineShader()
+ : Shader(
+ "outline",
+ shaders[OUTLINE_SHADER].vertex,
+ shaders[OUTLINE_SHADER].fragment
+ ) {
+ if (!valid) {
+ fprintf(stderr, "invalid outline shader\n");
+ return;
+ }
+
+ a_pos = glGetAttribLocation(program, "a_pos");
+}
+
+void OutlineShader::bind(char *offset) {
+ glEnableVertexAttribArray(a_pos);
+ glVertexAttribPointer(a_pos, 2, GL_SHORT, false, 0, offset);
+}
diff --git a/src/mbgl/shader/outline_shader.hpp b/src/mbgl/shader/outline_shader.hpp
new file mode 100644
index 0000000000..f3e8175fd7
--- /dev/null
+++ b/src/mbgl/shader/outline_shader.hpp
@@ -0,0 +1,25 @@
+#ifndef MBGL_SHADER_SHADER_OUTLINE
+#define MBGL_SHADER_SHADER_OUTLINE
+
+#include <mbgl/shader/shader.hpp>
+#include <mbgl/shader/uniform.hpp>
+
+namespace mbgl {
+
+class OutlineShader : public Shader {
+public:
+ OutlineShader();
+
+ void bind(char *offset);
+
+ UniformMatrix<4> u_matrix = {"u_matrix", *this};
+ Uniform<std::array<float, 4>> u_color = {"u_color", *this};
+ Uniform<std::array<float, 2>> u_world = {"u_world", *this};
+
+private:
+ int32_t a_pos = -1;
+};
+
+}
+
+#endif
diff --git a/src/mbgl/shader/pattern.fragment.glsl b/src/mbgl/shader/pattern.fragment.glsl
new file mode 100644
index 0000000000..ba6aed3023
--- /dev/null
+++ b/src/mbgl/shader/pattern.fragment.glsl
@@ -0,0 +1,21 @@
+uniform float u_opacity;
+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, 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);
+
+ gl_FragColor = mix(color1, color2, u_mix) * u_opacity;
+}
diff --git a/src/mbgl/shader/pattern.vertex.glsl b/src/mbgl/shader/pattern.vertex.glsl
new file mode 100644
index 0000000000..f2de884ead
--- /dev/null
+++ b/src/mbgl/shader/pattern.vertex.glsl
@@ -0,0 +1,11 @@
+uniform mat4 u_matrix;
+uniform mat3 u_patternmatrix;
+
+attribute vec2 a_pos;
+
+varying vec2 v_pos;
+
+void main() {
+ gl_Position = u_matrix * vec4(a_pos, 0, 1);
+ v_pos = (u_patternmatrix * vec3(a_pos, 1)).xy;
+}
diff --git a/src/mbgl/shader/pattern_shader.cpp b/src/mbgl/shader/pattern_shader.cpp
new file mode 100644
index 0000000000..31374bc3e8
--- /dev/null
+++ b/src/mbgl/shader/pattern_shader.cpp
@@ -0,0 +1,26 @@
+#include <mbgl/shader/pattern_shader.hpp>
+#include <mbgl/shader/shaders.hpp>
+#include <mbgl/platform/gl.hpp>
+
+#include <cstdio>
+
+using namespace mbgl;
+
+PatternShader::PatternShader()
+ : Shader(
+ "pattern",
+ shaders[PATTERN_SHADER].vertex,
+ shaders[PATTERN_SHADER].fragment
+ ) {
+ if (!valid) {
+ fprintf(stderr, "invalid pattern shader\n");
+ return;
+ }
+
+ a_pos = glGetAttribLocation(program, "a_pos");
+}
+
+void PatternShader::bind(char *offset) {
+ glEnableVertexAttribArray(a_pos);
+ glVertexAttribPointer(a_pos, 2, GL_SHORT, false, 0, offset);
+}
diff --git a/src/mbgl/shader/pattern_shader.hpp b/src/mbgl/shader/pattern_shader.hpp
new file mode 100644
index 0000000000..9fabd8e18a
--- /dev/null
+++ b/src/mbgl/shader/pattern_shader.hpp
@@ -0,0 +1,29 @@
+#ifndef MBGL_SHADER_SHADER_PATTERN
+#define MBGL_SHADER_SHADER_PATTERN
+
+#include <mbgl/shader/shader.hpp>
+#include <mbgl/shader/uniform.hpp>
+
+namespace mbgl {
+
+class PatternShader : public Shader {
+public:
+ PatternShader();
+
+ void bind(char *offset);
+
+ UniformMatrix<4> u_matrix = {"u_matrix", *this};
+ Uniform<std::array<float, 2>> u_pattern_tl = {"u_pattern_tl", *this};
+ Uniform<std::array<float, 2>> u_pattern_br = {"u_pattern_br", *this};
+ Uniform<float> u_opacity = {"u_opacity", *this};
+ Uniform<float> u_mix = {"u_mix", *this};
+ Uniform<int32_t> u_image = {"u_image", *this};
+ UniformMatrix<3> u_patternmatrix = {"u_patternmatrix", *this};
+
+private:
+ int32_t a_pos = -1;
+};
+
+}
+
+#endif
diff --git a/src/mbgl/shader/plain.fragment.glsl b/src/mbgl/shader/plain.fragment.glsl
new file mode 100644
index 0000000000..8df552c171
--- /dev/null
+++ b/src/mbgl/shader/plain.fragment.glsl
@@ -0,0 +1,5 @@
+uniform vec4 u_color;
+
+void main() {
+ gl_FragColor = u_color;
+}
diff --git a/src/mbgl/shader/plain.vertex.glsl b/src/mbgl/shader/plain.vertex.glsl
new file mode 100644
index 0000000000..866c3cd2f3
--- /dev/null
+++ b/src/mbgl/shader/plain.vertex.glsl
@@ -0,0 +1,7 @@
+attribute vec2 a_pos;
+
+uniform mat4 u_matrix;
+
+void main() {
+ gl_Position = u_matrix * vec4(a_pos, 0, 1);
+}
diff --git a/src/mbgl/shader/plain_shader.cpp b/src/mbgl/shader/plain_shader.cpp
new file mode 100644
index 0000000000..8a37837b30
--- /dev/null
+++ b/src/mbgl/shader/plain_shader.cpp
@@ -0,0 +1,26 @@
+#include <mbgl/shader/plain_shader.hpp>
+#include <mbgl/shader/shaders.hpp>
+#include <mbgl/platform/gl.hpp>
+
+#include <cstdio>
+
+using namespace mbgl;
+
+PlainShader::PlainShader()
+ : Shader(
+ "plain",
+ shaders[PLAIN_SHADER].vertex,
+ shaders[PLAIN_SHADER].fragment
+ ) {
+ if (!valid) {
+ fprintf(stderr, "invalid plain shader\n");
+ return;
+ }
+
+ a_pos = glGetAttribLocation(program, "a_pos");
+}
+
+void PlainShader::bind(char *offset) {
+ glEnableVertexAttribArray(a_pos);
+ glVertexAttribPointer(a_pos, 2, GL_SHORT, false, 0, offset);
+}
diff --git a/src/mbgl/shader/plain_shader.hpp b/src/mbgl/shader/plain_shader.hpp
new file mode 100644
index 0000000000..051501c3c9
--- /dev/null
+++ b/src/mbgl/shader/plain_shader.hpp
@@ -0,0 +1,24 @@
+#ifndef MBGL_SHADER_SHADER_PLAIN
+#define MBGL_SHADER_SHADER_PLAIN
+
+#include <mbgl/shader/shader.hpp>
+#include <mbgl/shader/uniform.hpp>
+
+namespace mbgl {
+
+class PlainShader : public Shader {
+public:
+ PlainShader();
+
+ void bind(char *offset);
+
+ UniformMatrix<4> u_matrix = {"u_matrix", *this};
+ Uniform<std::array<float, 4>> u_color = {"u_color", *this};
+
+private:
+ int32_t a_pos = -1;
+};
+
+}
+
+#endif
diff --git a/src/mbgl/shader/raster.fragment.glsl b/src/mbgl/shader/raster.fragment.glsl
new file mode 100644
index 0000000000..333de76dc1
--- /dev/null
+++ b/src/mbgl/shader/raster.fragment.glsl
@@ -0,0 +1,36 @@
+uniform sampler2D u_image;
+uniform float u_opacity;
+
+varying vec2 v_pos;
+
+uniform float u_brightness_low;
+uniform float u_brightness_high;
+
+uniform float u_saturation_factor;
+uniform float u_contrast_factor;
+uniform vec3 u_spin_weights;
+
+void main() {
+
+ vec4 color = texture2D(u_image, v_pos) * u_opacity;
+ vec3 rgb = color.rgb;
+
+ // spin
+ rgb = vec3(
+ dot(rgb, u_spin_weights.xyz),
+ dot(rgb, u_spin_weights.zxy),
+ dot(rgb, u_spin_weights.yzx));
+
+ // saturation
+ float average = (color.r + color.g + color.b) / 3.0;
+ rgb += (average - rgb) * u_saturation_factor;
+
+ // contrast
+ rgb = (rgb - 0.5) * u_contrast_factor + 0.5;
+
+ // brightness
+ vec3 u_high_vec = vec3(u_brightness_low, u_brightness_low, u_brightness_low);
+ vec3 u_low_vec = vec3(u_brightness_high, u_brightness_high, u_brightness_high);
+
+ gl_FragColor = vec4(mix(u_high_vec, u_low_vec, rgb), color.a);
+}
diff --git a/src/mbgl/shader/raster.vertex.glsl b/src/mbgl/shader/raster.vertex.glsl
new file mode 100644
index 0000000000..97e563f585
--- /dev/null
+++ b/src/mbgl/shader/raster.vertex.glsl
@@ -0,0 +1,13 @@
+uniform mat4 u_matrix;
+uniform float u_buffer;
+
+attribute vec2 a_pos;
+
+varying vec2 v_pos;
+
+
+void main() {
+ gl_Position = u_matrix * vec4(a_pos, 0, 1);
+ float dimension = (4096.0 + 2.0 * u_buffer);
+ v_pos = (a_pos / dimension) + (u_buffer / dimension);
+}
diff --git a/src/mbgl/shader/raster_shader.cpp b/src/mbgl/shader/raster_shader.cpp
new file mode 100644
index 0000000000..7351f7d0c4
--- /dev/null
+++ b/src/mbgl/shader/raster_shader.cpp
@@ -0,0 +1,28 @@
+#include <mbgl/shader/raster_shader.hpp>
+#include <mbgl/shader/shaders.hpp>
+#include <mbgl/platform/gl.hpp>
+
+#include <cstdio>
+
+using namespace mbgl;
+
+RasterShader::RasterShader()
+ : Shader(
+ "raster",
+ shaders[RASTER_SHADER].vertex,
+ shaders[RASTER_SHADER].fragment
+ ) {
+ if (!valid) {
+#if defined(DEBUG)
+ fprintf(stderr, "invalid raster shader\n");
+#endif
+ return;
+ }
+
+ a_pos = glGetAttribLocation(program, "a_pos");
+}
+
+void RasterShader::bind(char *offset) {
+ glEnableVertexAttribArray(a_pos);
+ glVertexAttribPointer(a_pos, 2, GL_SHORT, false, 0, offset);
+}
diff --git a/src/mbgl/shader/raster_shader.hpp b/src/mbgl/shader/raster_shader.hpp
new file mode 100644
index 0000000000..8cf97055a2
--- /dev/null
+++ b/src/mbgl/shader/raster_shader.hpp
@@ -0,0 +1,31 @@
+#ifndef MBGL_RENDERER_SHADER_RASTER
+#define MBGL_RENDERER_SHADER_RASTER
+
+#include <mbgl/shader/shader.hpp>
+#include <mbgl/shader/uniform.hpp>
+
+namespace mbgl {
+
+class RasterShader : public Shader {
+public:
+ RasterShader();
+
+ void bind(char *offset);
+
+ UniformMatrix<4> u_matrix = {"u_matrix", *this};
+ Uniform<int32_t> u_image = {"u_image", *this};
+ Uniform<float> u_opacity = {"u_opacity", *this};
+ Uniform<float> u_buffer = {"u_buffer", *this};
+ Uniform<float> u_brightness_low = {"u_brightness_low", *this};
+ Uniform<float> u_brightness_high = {"u_brightness_high", *this};
+ Uniform<float> u_saturation_factor = {"u_saturation_factor", *this};
+ Uniform<float> u_contrast_factor = {"u_contrast_factor", *this};
+ Uniform<std::array<float, 3>> u_spin_weights = {"u_spin_weights", *this};
+
+private:
+ int32_t a_pos = -1;
+};
+
+}
+
+#endif
diff --git a/src/mbgl/shader/sdf.fragment.glsl b/src/mbgl/shader/sdf.fragment.glsl
new file mode 100644
index 0000000000..d72d61dab1
--- /dev/null
+++ b/src/mbgl/shader/sdf.fragment.glsl
@@ -0,0 +1,13 @@
+uniform sampler2D u_texture;
+uniform vec4 u_color;
+uniform float u_buffer;
+uniform float u_gamma;
+
+varying vec2 v_tex;
+varying float v_alpha;
+
+void main() {
+ float dist = texture2D(u_texture, v_tex).a;
+ float alpha = smoothstep(u_buffer - u_gamma, u_buffer + u_gamma, dist) * v_alpha;
+ gl_FragColor = u_color * alpha;
+}
diff --git a/src/mbgl/shader/sdf.vertex.glsl b/src/mbgl/shader/sdf.vertex.glsl
new file mode 100644
index 0000000000..c5166ae46f
--- /dev/null
+++ b/src/mbgl/shader/sdf.vertex.glsl
@@ -0,0 +1,69 @@
+attribute vec2 a_pos;
+attribute vec2 a_offset;
+attribute vec2 a_tex;
+attribute float a_angle;
+attribute float a_minzoom;
+attribute float a_maxzoom;
+attribute float a_rangeend;
+attribute float a_rangestart;
+attribute float a_labelminzoom;
+
+
+// matrix 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_angle;
+uniform float u_zoom;
+uniform float u_flip;
+uniform float u_fadedist;
+uniform float u_minfadezoom;
+uniform float u_maxfadezoom;
+uniform float u_fadezoom;
+
+uniform vec2 u_texsize;
+
+varying vec2 v_tex;
+varying float v_alpha;
+
+void main() {
+
+ float rev = 0.0;
+
+ // u_angle is angle of the map, -128..128 representing 0..2PI
+ // a_angle is angle of the label, 0..256 representing 0..2PI, where 0 is horizontal text
+ float rotated = mod(a_angle + u_angle, 256.0);
+ // if the label rotates with the map, and if the rotated label is upside down, hide it
+ if (u_flip > 0.0 && rotated >= 64.0 && rotated < 192.0) rev = 1.0;
+
+ // If the label should be invisible, we move the vertex outside
+ // of the view plane so that the triangle gets clipped. This makes it easier
+ // for us to create degenerate triangle strips.
+ // u_zoom is the current zoom level adjusted for the change in font size
+ float z = 2.0 - step(a_minzoom, u_zoom) - (1.0 - step(a_maxzoom, u_zoom)) + rev;
+
+ // fade out labels
+ float alpha = clamp((u_fadezoom - a_labelminzoom) / u_fadedist, 0.0, 1.0);
+
+ if (u_fadedist >= 0.0) {
+ v_alpha = alpha;
+ } else {
+ v_alpha = 1.0 - alpha;
+ }
+ if (u_maxfadezoom < a_labelminzoom) {
+ v_alpha = 0.0;
+ }
+ if (u_minfadezoom >= a_labelminzoom) {
+ v_alpha = 1.0;
+ }
+
+ // if label has been faded out, clip it
+ z += step(v_alpha, 0.0);
+
+ // all the angles are 0..256 representing 0..2PI
+ // hide if (angle >= a_rangeend && angle < rangestart)
+ z += step(a_rangeend, u_angle) * (1.0 - step(a_rangestart, u_angle));
+
+ gl_Position = u_matrix * vec4(a_pos, 0, 1) + u_exmatrix * vec4(a_offset / 64.0, z, 0);
+ v_tex = a_tex / u_texsize;
+}
diff --git a/src/mbgl/shader/sdf_shader.cpp b/src/mbgl/shader/sdf_shader.cpp
new file mode 100644
index 0000000000..b86733c0e4
--- /dev/null
+++ b/src/mbgl/shader/sdf_shader.cpp
@@ -0,0 +1,91 @@
+#include <mbgl/shader/sdf_shader.hpp>
+#include <mbgl/shader/shaders.hpp>
+#include <mbgl/platform/gl.hpp>
+
+#include <cstdio>
+
+using namespace mbgl;
+
+SDFShader::SDFShader()
+ : Shader(
+ "sdf",
+ shaders[SDF_SHADER].vertex,
+ shaders[SDF_SHADER].fragment
+ ) {
+ if (!valid) {
+ fprintf(stderr, "invalid sdf shader\n");
+ return;
+ }
+
+ a_pos = glGetAttribLocation(program, "a_pos");
+ a_offset = glGetAttribLocation(program, "a_offset");
+ a_tex = glGetAttribLocation(program, "a_tex");
+ a_angle = glGetAttribLocation(program, "a_angle");
+ a_minzoom = glGetAttribLocation(program, "a_minzoom");
+ a_maxzoom = glGetAttribLocation(program, "a_maxzoom");
+ a_rangeend = glGetAttribLocation(program, "a_rangeend");
+ a_rangestart = glGetAttribLocation(program, "a_rangestart");
+ a_labelminzoom = glGetAttribLocation(program, "a_labelminzoom");
+}
+
+void SDFGlyphShader::bind(char *offset) {
+ const int stride = 16;
+
+ glEnableVertexAttribArray(a_pos);
+ glVertexAttribPointer(a_pos, 2, GL_SHORT, false, stride, offset + 0);
+
+ glEnableVertexAttribArray(a_offset);
+ glVertexAttribPointer(a_offset, 2, GL_SHORT, false, stride, offset + 4);
+
+ glEnableVertexAttribArray(a_labelminzoom);
+ glVertexAttribPointer(a_labelminzoom, 1, GL_UNSIGNED_BYTE, false, stride, offset + 8);
+
+ glEnableVertexAttribArray(a_minzoom);
+ glVertexAttribPointer(a_minzoom, 1, GL_UNSIGNED_BYTE, false, stride, offset + 9);
+
+ glEnableVertexAttribArray(a_maxzoom);
+ glVertexAttribPointer(a_maxzoom, 1, GL_UNSIGNED_BYTE, false, stride, offset + 10);
+
+ glEnableVertexAttribArray(a_angle);
+ glVertexAttribPointer(a_angle, 1, GL_UNSIGNED_BYTE, false, stride, offset + 11);
+
+ glEnableVertexAttribArray(a_rangeend);
+ glVertexAttribPointer(a_rangeend, 1, GL_UNSIGNED_BYTE, false, stride, offset + 12);
+
+ glEnableVertexAttribArray(a_rangestart);
+ glVertexAttribPointer(a_rangestart, 1, GL_UNSIGNED_BYTE, false, stride, offset + 13);
+
+ glEnableVertexAttribArray(a_tex);
+ glVertexAttribPointer(a_tex, 2, GL_UNSIGNED_BYTE, false, stride, offset + 14);
+}
+
+void SDFIconShader::bind(char *offset) {
+ const int stride = 20;
+
+ glEnableVertexAttribArray(a_pos);
+ glVertexAttribPointer(a_pos, 2, GL_SHORT, false, stride, offset + 0);
+
+ glEnableVertexAttribArray(a_offset);
+ glVertexAttribPointer(a_offset, 2, GL_SHORT, false, stride, offset + 4);
+
+ glEnableVertexAttribArray(a_labelminzoom);
+ glVertexAttribPointer(a_labelminzoom, 1, GL_UNSIGNED_BYTE, false, stride, offset + 8);
+
+ glEnableVertexAttribArray(a_minzoom);
+ glVertexAttribPointer(a_minzoom, 1, GL_UNSIGNED_BYTE, false, stride, offset + 9);
+
+ glEnableVertexAttribArray(a_maxzoom);
+ glVertexAttribPointer(a_maxzoom, 1, GL_UNSIGNED_BYTE, false, stride, offset + 10);
+
+ glEnableVertexAttribArray(a_angle);
+ glVertexAttribPointer(a_angle, 1, GL_UNSIGNED_BYTE, false, stride, offset + 11);
+
+ glEnableVertexAttribArray(a_rangeend);
+ glVertexAttribPointer(a_rangeend, 1, GL_UNSIGNED_BYTE, false, stride, offset + 12);
+
+ glEnableVertexAttribArray(a_rangestart);
+ glVertexAttribPointer(a_rangestart, 1, GL_UNSIGNED_BYTE, false, stride, offset + 13);
+
+ glEnableVertexAttribArray(a_tex);
+ glVertexAttribPointer(a_tex, 2, GL_SHORT, false, stride, offset + 16);
+}
diff --git a/src/mbgl/shader/sdf_shader.hpp b/src/mbgl/shader/sdf_shader.hpp
new file mode 100644
index 0000000000..0737c25ee1
--- /dev/null
+++ b/src/mbgl/shader/sdf_shader.hpp
@@ -0,0 +1,53 @@
+#ifndef MBGL_SHADER_SDF_SHADER
+#define MBGL_SHADER_SDF_SHADER
+
+#include <mbgl/shader/shader.hpp>
+#include <mbgl/shader/uniform.hpp>
+
+namespace mbgl {
+
+class SDFShader : public Shader {
+public:
+ SDFShader();
+
+ virtual void bind(char *offset) = 0;
+
+ UniformMatrix<4> u_matrix = {"u_matrix", *this};
+ UniformMatrix<4> u_exmatrix = {"u_exmatrix", *this};
+ Uniform<std::array<float, 4>> u_color = {"u_color", *this};
+ Uniform<std::array<float, 2>> u_texsize = {"u_texsize", *this};
+ Uniform<float> u_buffer = {"u_buffer", *this};
+ Uniform<float> u_gamma = {"u_gamma", *this};
+ Uniform<float> u_angle = {"u_angle", *this};
+ Uniform<float> u_zoom = {"u_zoom", *this};
+ Uniform<float> u_flip = {"u_flip", *this};
+ Uniform<float> u_fadedist = {"u_fadedist", *this};
+ Uniform<float> u_minfadezoom = {"u_minfadezoom", *this};
+ Uniform<float> u_maxfadezoom = {"u_maxfadezoom", *this};
+ Uniform<float> u_fadezoom = {"u_fadezoom", *this};
+
+protected:
+ int32_t a_pos = -1;
+ int32_t a_offset = -1;
+ int32_t a_tex = -1;
+ int32_t a_angle = -1;
+ int32_t a_minzoom = -1;
+ int32_t a_maxzoom = -1;
+ int32_t a_rangeend = -1;
+ int32_t a_rangestart = -1;
+ int32_t a_labelminzoom = -1;
+};
+
+class SDFGlyphShader : public SDFShader {
+public:
+ void bind(char *offset);
+};
+
+class SDFIconShader : public SDFShader {
+public:
+ void bind(char *offset);
+};
+
+}
+
+#endif
diff --git a/src/mbgl/shader/shader.cpp b/src/mbgl/shader/shader.cpp
new file mode 100644
index 0000000000..84cb55eac4
--- /dev/null
+++ b/src/mbgl/shader/shader.cpp
@@ -0,0 +1,133 @@
+#include <mbgl/shader/shader.hpp>
+#include <mbgl/platform/gl.hpp>
+#include <mbgl/util/stopwatch.hpp>
+#include <mbgl/platform/log.hpp>
+
+#include <cstring>
+#include <cstdlib>
+
+using namespace mbgl;
+
+Shader::Shader(const char *name_, const GLchar *vertSource, const GLchar *fragSource)
+ : name(name_),
+ valid(false),
+ program(0) {
+ util::stopwatch stopwatch("shader compilation", Event::Shader);
+
+ GLuint vertShader;
+ if (!compileShader(&vertShader, GL_VERTEX_SHADER, vertSource)) {
+ Log::Error(Event::Shader, "Vertex shader failed to compile: %s", vertSource);
+ return;
+ }
+
+ GLuint fragShader;
+ if (!compileShader(&fragShader, GL_FRAGMENT_SHADER, fragSource)) {
+ Log::Error(Event::Shader, "Fragment shader failed to compile: %s", fragSource);
+ return;
+ }
+
+ program = glCreateProgram();
+
+ // Attach shaders
+ glAttachShader(program, vertShader);
+ glAttachShader(program, fragShader);
+
+
+ {
+ // Link program
+ GLint status;
+ glLinkProgram(program);
+
+ glGetProgramiv(program, GL_LINK_STATUS, &status);
+ if (status == 0) {
+ GLint logLength;
+ glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength);
+ if (logLength > 0) {
+ GLchar *log = (GLchar *)malloc(logLength);
+ glGetProgramInfoLog(program, logLength, &logLength, log);
+ Log::Error(Event::Shader, "Program failed to link: %s", log);
+ free(log);
+ }
+
+ glDeleteShader(vertShader);
+ vertShader = 0;
+ glDeleteShader(fragShader);
+ fragShader = 0;
+ glDeleteProgram(program);
+ program = 0;
+ return;
+ }
+ }
+
+ {
+ // Validate program
+ GLint status;
+ glValidateProgram(program);
+
+ glGetProgramiv(program, GL_VALIDATE_STATUS, &status);
+ if (status == 0) {
+ GLint logLength;
+ glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength);
+ if (logLength > 0) {
+ GLchar *log = (GLchar *)malloc(logLength);
+ glGetProgramInfoLog(program, logLength, &logLength, log);
+ Log::Error(Event::Shader, "Program failed to validate: %s", log);
+ free(log);
+ }
+
+ glDeleteShader(vertShader);
+ vertShader = 0;
+ glDeleteShader(fragShader);
+ fragShader = 0;
+ glDeleteProgram(program);
+ program = 0;
+ }
+
+ }
+
+ // Remove the compiled shaders; they are now part of the program.
+ glDetachShader(program, vertShader);
+ glDeleteShader(vertShader);
+ glDetachShader(program, fragShader);
+ glDeleteShader(fragShader);
+
+ valid = true;
+}
+
+
+bool Shader::compileShader(GLuint *shader, GLenum type, const GLchar *source) {
+ GLint status;
+
+ *shader = glCreateShader(type);
+ const GLchar *strings[] = { source };
+ const GLint lengths[] = { (GLint)strlen(source) };
+ glShaderSource(*shader, 1, strings, lengths);
+
+ glCompileShader(*shader);
+
+ glGetShaderiv(*shader, GL_COMPILE_STATUS, &status);
+ if (status == 0) {
+ GLint logLength;
+ glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength);
+ if (logLength > 0) {
+ GLchar *log = (GLchar *)malloc(logLength);
+ glGetShaderInfoLog(*shader, logLength, &logLength, log);
+ Log::Error(Event::Shader, "Shader failed to compile: %s", log);
+ free(log);
+ }
+
+ glDeleteShader(*shader);
+ *shader = 0;
+ return false;
+ }
+
+ return true;
+}
+
+Shader::~Shader() {
+ if (program) {
+ glDeleteProgram(program);
+ program = 0;
+ valid = false;
+ }
+}
diff --git a/src/mbgl/shader/shader.hpp b/src/mbgl/shader/shader.hpp
new file mode 100644
index 0000000000..27e831a510
--- /dev/null
+++ b/src/mbgl/shader/shader.hpp
@@ -0,0 +1,28 @@
+#ifndef MBGL_RENDERER_SHADER
+#define MBGL_RENDERER_SHADER
+
+#include <cstdint>
+#include <array>
+#include <mbgl/util/noncopyable.hpp>
+
+namespace mbgl {
+
+class Shader : private util::noncopyable {
+public:
+ Shader(const char *name, const char *vertex, const char *fragment);
+ ~Shader();
+ const char *name;
+ bool valid;
+ uint32_t program;
+
+ inline uint32_t getID() const {
+ return program;
+ }
+
+private:
+ bool compileShader(uint32_t *shader, uint32_t type, const char *source);
+};
+
+}
+
+#endif
diff --git a/src/mbgl/shader/uniform.cpp b/src/mbgl/shader/uniform.cpp
new file mode 100644
index 0000000000..24f179baf1
--- /dev/null
+++ b/src/mbgl/shader/uniform.cpp
@@ -0,0 +1,47 @@
+#include <mbgl/shader/uniform.hpp>
+
+namespace mbgl {
+
+template <>
+void Uniform<float>::bind(const float& t) {
+ glUniform1f(location, t);
+}
+
+template <>
+void Uniform<int32_t>::bind(const int32_t& t) {
+ glUniform1i(location, t);
+}
+
+template <>
+void Uniform<std::array<float, 2>>::bind(const std::array<float, 2>& t) {
+ glUniform2fv(location, 1, t.data());
+}
+
+template <>
+void Uniform<std::array<float, 3>>::bind(const std::array<float, 3>& t) {
+ glUniform3fv(location, 1, t.data());
+}
+
+template <>
+void Uniform<std::array<float, 4>>::bind(const std::array<float, 4>& t) {
+ glUniform4fv(location, 1, t.data());
+}
+
+template <>
+void UniformMatrix<2>::bind(const std::array<float, 4>& t) {
+ glUniformMatrix2fv(location, 1, GL_FALSE, t.data());
+}
+
+template <>
+void UniformMatrix<3>::bind(const std::array<float, 9>& t) {
+ glUniformMatrix3fv(location, 1, GL_FALSE, t.data());
+}
+
+template <>
+void UniformMatrix<4>::bind(const std::array<float, 16>& t) {
+ glUniformMatrix4fv(location, 1, GL_FALSE, t.data());
+}
+
+// Add more as needed.
+
+}
diff --git a/src/mbgl/shader/uniform.hpp b/src/mbgl/shader/uniform.hpp
new file mode 100644
index 0000000000..8579ae22c7
--- /dev/null
+++ b/src/mbgl/shader/uniform.hpp
@@ -0,0 +1,53 @@
+#ifndef MBGL_SHADER_UNIFORM
+#define MBGL_SHADER_UNIFORM
+
+#include <mbgl/shader/shader.hpp>
+#include <mbgl/platform/gl.hpp>
+
+namespace mbgl {
+
+template <typename T>
+class Uniform {
+public:
+ Uniform(const GLchar* name, const Shader& shader)
+ : location(glGetUniformLocation(shader.program, name)) {}
+
+ void operator=(const T& t) {
+ if (current != t) {
+ current = t;
+ bind(t);
+ }
+ }
+
+private:
+ void bind(const T&);
+
+ T current;
+ GLint location;
+};
+
+template <size_t C, size_t R = C>
+class UniformMatrix {
+public:
+ typedef std::array<float, C*R> T;
+
+ UniformMatrix(const GLchar* name, const Shader& shader)
+ : location(glGetUniformLocation(shader.program, name)) {}
+
+ void operator=(const T& t) {
+ if (current != t) {
+ current = t;
+ bind(t);
+ }
+ }
+
+private:
+ void bind(const T&);
+
+ T current;
+ GLint location;
+};
+
+}
+
+#endif