diff options
Diffstat (limited to 'src/mbgl/shader')
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 |