diff options
author | Konstantin Käfer <mail@kkaefer.com> | 2014-01-28 18:40:17 +0100 |
---|---|---|
committer | Konstantin Käfer <mail@kkaefer.com> | 2014-01-28 18:40:17 +0100 |
commit | e359d697fbf92f91be78001f922657b8e015948c (patch) | |
tree | 6ba5ff241d122c594999ab27bf23a08eff958ecb /src | |
parent | 43ab6732d98c0020f28546cbf0377f4b6980f22a (diff) | |
download | qtlocation-mapboxgl-e359d697fbf92f91be78001f922657b8e015948c.tar.gz |
buggy line support
Diffstat (limited to 'src')
-rw-r--r-- | src/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/map/map.cpp | 1 | ||||
-rw-r--r-- | src/map/transform.cpp | 16 | ||||
-rw-r--r-- | src/renderer/line_bucket.cpp | 2 | ||||
-rw-r--r-- | src/renderer/painter.cpp | 79 | ||||
-rw-r--r-- | src/renderer/shader-line.cpp | 33 | ||||
-rw-r--r-- | src/renderer/shader.cpp | 4 | ||||
-rw-r--r-- | src/shader/line.fragment.glsl | 35 | ||||
-rw-r--r-- | src/shader/line.vertex.glsl | 62 | ||||
-rw-r--r-- | src/shader/plain.vertex.glsl | 2 | ||||
-rw-r--r-- | src/shader/shaders.cpp | 6 |
11 files changed, 223 insertions, 19 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4ae8d7a22a..178d4ce5bc 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -10,6 +10,7 @@ SET(llmr_SOURCES renderer/shader-fill.cpp renderer/shader-plain.cpp renderer/shader-outline.cpp + renderer/shader-line.cpp renderer/shader.cpp renderer/fill_bucket.cpp renderer/line_bucket.cpp @@ -39,6 +40,7 @@ SET(llmr_HEADERS ../include/llmr/renderer/shader-fill.hpp ../include/llmr/renderer/shader-plain.hpp ../include/llmr/renderer/shader-outline.hpp + ../include/llmr/renderer/shader-line.hpp ../include/llmr/renderer/shader.hpp ../include/llmr/shader/shaders.hpp ../include/llmr/util/animation.hpp diff --git a/src/map/map.cpp b/src/map/map.cpp index 2b008c2ccf..8e9c80e509 100644 --- a/src/map/map.cpp +++ b/src/map/map.cpp @@ -48,6 +48,7 @@ void Map::resize(uint32_t width, uint32_t height, uint32_t fb_width, uint32_t fb transform.height = height; transform.fb_width = fb_width; transform.fb_height = fb_height; + transform.pixelRatio = (double)fb_width / (double)width; update(); } diff --git a/src/map/transform.cpp b/src/map/transform.cpp index 7f8d9939d1..023e7c302d 100644 --- a/src/map/transform.cpp +++ b/src/map/transform.cpp @@ -1,7 +1,6 @@ #include <llmr/map/transform.hpp> #include <llmr/util/mat4.hpp> #include <llmr/util/math.hpp> -#include <cmath> #include <cstdio> using namespace llmr; @@ -14,16 +13,7 @@ const double M2PI = 2 * M_PI; const double A = 6378137; -Transform::Transform() - : - width(0), - height(0), - x(0), - y(0), - angle(0.0), - scale(1.0), - min_scale(pow(2, 0)), - max_scale(pow(2, 20)) { +Transform::Transform() { setScale(scale); setAngle(angle); } @@ -168,6 +158,10 @@ float Transform::getZoom() const { return log(scale) / M_LN2; } +int32_t Transform::getIntegerZoom() const { + return floor(log(scale) / M_LN2); +} + double Transform::getScale() const { return scale; } diff --git a/src/renderer/line_bucket.cpp b/src/renderer/line_bucket.cpp index 96c654f757..f62a299c79 100644 --- a/src/renderer/line_bucket.cpp +++ b/src/renderer/line_bucket.cpp @@ -23,6 +23,8 @@ LineBucket::LineBucket(const std::shared_ptr<LineBuffer>& buffer) } void LineBucket::addGeometry(pbf& geom, const BucketDescription& bucket_desc) { + join = bucket_desc.join; + std::vector<Coordinate> line; Geometry::command cmd; diff --git a/src/renderer/painter.cpp b/src/renderer/painter.cpp index 282cf3e39b..2e7d249225 100644 --- a/src/renderer/painter.cpp +++ b/src/renderer/painter.cpp @@ -54,6 +54,7 @@ void Painter::setup() { assert(fillShader); assert(plainShader); assert(outlineShader); + assert(lineShader); // Set up the stencil quad we're using to generate the stencil mask. glGenBuffers(1, &tile_stencil_buffer); @@ -78,6 +79,7 @@ void Painter::setupShaders() { fillShader = std::make_shared<FillShader>(); plainShader = std::make_shared<PlainShader>(); outlineShader = std::make_shared<OutlineShader>(); + lineShader = std::make_shared<LineShader>(); } void Painter::teardown() { @@ -89,10 +91,13 @@ void Painter::changeMatrix(const Tile::Ptr& tile) { float projMatrix[16]; mat4::ortho(projMatrix, 0, transform.width, transform.height, 0, 1, 10); - float mvMatrix[16]; - transform.matrixFor(mvMatrix, tile->id); + // The position matrix. + transform.matrixFor(matrix, tile->id); + mat4::multiply(matrix, projMatrix, matrix); - mat4::multiply(matrix, projMatrix, mvMatrix); + // The extrusion matrix. + mat4::copy(exMatrix, projMatrix); + mat4::rotate_z(exMatrix, exMatrix, transform.getAngle()); } void Painter::drawClippingMask() { @@ -318,7 +323,73 @@ void Painter::renderFill(FillBucket& bucket, const std::string& layer_name) { void Painter::renderLine(LineBucket& bucket, const std::string& layer_name) { const LineProperties& properties = style.computed.lines[layer_name]; - // TODO + double width = properties.width; + double offset = (properties.offset || 0) / 2; + double inset = fmax(-1, offset - width / 2 - 0.5) + 1; + double outset = offset + width / 2 + 0.5; + + // var imagePos = properties.image && imageSprite.getPosition(properties.image); + // var shader; + bool imagePos = false; + + if (imagePos) { + // var factor = 8 / Math.pow(2, painter.transform.zoom - params.z); + + // imageSprite.bind(gl, true); + + // //factor = Math.pow(2, 4 - painter.transform.zoom + params.z); + // gl.switchShader(painter.linepatternShader, painter.translatedMatrix || painter.posMatrix, painter.exMatrix); + // shader = painter.linepatternShader; + // glUniform2fv(painter.linepatternShader.u_pattern_size, [imagePos.size[0] * factor, imagePos.size[1] ]); + // glUniform2fv(painter.linepatternShader.u_pattern_tl, imagePos.tl); + // glUniform2fv(painter.linepatternShader.u_pattern_br, imagePos.br); + // glUniform1f(painter.linepatternShader.u_fade, painter.transform.z % 1.0); + + } else { + switchShader(lineShader); + glUniformMatrix4fv(lineShader->u_matrix, 1, GL_FALSE, matrix); + glUniformMatrix4fv(lineShader->u_exmatrix, 1, GL_FALSE, exMatrix); + // glUniform2fv(painter.lineShader.u_dasharray, properties.dasharray || [1, -1]); + glUniform2f(lineShader->u_dasharray, 1, -1); + } + + + const double tilePixelRatio = transform.getScale() / (1 << transform.getIntegerZoom()) / 8; + + glUniform2f(lineShader->u_linewidth, outset, inset); + glUniform1f(lineShader->u_ratio, tilePixelRatio); + glUniform1f(lineShader->u_gamma, transform.pixelRatio); + + // const Color& color = properties.color; + // if (!params.antialiasing) { + // color[3] = Infinity; + // glUniform4fv(lineShader->u_color, color); + // } else { + glUniform4fv(lineShader->u_color, 1, properties.color.data()); + // } + + + bucket.buffer->bind(); + + + char *vertex_index = BUFFER_OFFSET(bucket.start * 2 * sizeof(uint16_t)); + glVertexAttribPointer(lineShader->a_pos, 4, GL_SHORT, false, 8, vertex_index); + glVertexAttribPointer(lineShader->a_extrude, 2, GL_BYTE, false, 8, vertex_index + 6); + glVertexAttribPointer(lineShader->a_linesofar, 2, GL_SHORT, false, 8, vertex_index + 4); + + uint32_t begin = bucket.start; + uint32_t count = bucket.length; + + glUniform1f(lineShader->u_point, 0); + glDrawArrays(GL_TRIANGLE_STRIP, begin, count); + + if (bucket.join == JoinType::Round) { + glUniform1f(lineShader->u_point, 1); + glDrawArrays(GL_POINTS, begin, count); + } + + // statistics + // stats.lines += count; } void Painter::renderDebug(const Tile::Ptr& tile) { diff --git a/src/renderer/shader-line.cpp b/src/renderer/shader-line.cpp new file mode 100644 index 0000000000..ae73dbb4fd --- /dev/null +++ b/src/renderer/shader-line.cpp @@ -0,0 +1,33 @@ +#include <llmr/renderer/shader-line.hpp> +#include <llmr/shader/shaders.hpp> +#include <llmr/platform/gl.hpp> + +using namespace llmr; + +LineShader::LineShader() + : Shader( + shaders[LINE_SHADER].vertex, + shaders[LINE_SHADER].fragment + ) { + if (!valid) { + fprintf(stderr, "invalid line shader\n"); + return; + } + + a_pos = glGetAttribLocation(program, "a_pos"); + attributes.emplace_front(a_pos); + a_extrude = glGetAttribLocation(program, "a_extrude"); + attributes.emplace_front(a_extrude); + a_linesofar = glGetAttribLocation(program, "a_linesofar"); + attributes.emplace_front(a_linesofar); + + u_matrix = glGetUniformLocation(program, "u_matrix"); + u_exmatrix = glGetUniformLocation(program, "u_exmatrix"); + u_linewidth = glGetUniformLocation(program, "u_linewidth"); + u_color = glGetUniformLocation(program, "u_color"); + u_debug = glGetUniformLocation(program, "u_debug"); + u_ratio = glGetUniformLocation(program, "u_ratio"); + u_dasharray = glGetUniformLocation(program, "u_dasharray"); + u_point = glGetUniformLocation(program, "u_point"); + u_gamma = glGetUniformLocation(program, "u_gamma"); +} diff --git a/src/renderer/shader.cpp b/src/renderer/shader.cpp index d9614c0ad9..b2c735d22b 100644 --- a/src/renderer/shader.cpp +++ b/src/renderer/shader.cpp @@ -119,7 +119,7 @@ bool Shader::compileShader(GLuint *shader, GLenum type, const GLchar *source) { glCompileShader(*shader); -#if defined(DEBUG) +// #if defined(DEBUG) GLint logLength; glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); if (logLength > 0) { @@ -128,7 +128,7 @@ bool Shader::compileShader(GLuint *shader, GLenum type, const GLchar *source) { fprintf(stderr, "Shader compile log:\n%s", log); free(log); } -#endif +// #endif glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); if (status == 0) { diff --git a/src/shader/line.fragment.glsl b/src/shader/line.fragment.glsl new file mode 100644 index 0000000000..5dcc5ec660 --- /dev/null +++ b/src/shader/line.fragment.glsl @@ -0,0 +1,35 @@ +#version 120 +// shared +uniform float u_debug; +uniform vec2 u_linewidth; +uniform vec4 u_color; +uniform float u_point; +uniform float u_gamma; + +uniform vec2 u_dasharray; + +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 - 1.0), u_linewidth.s - dist) * u_gamma, 0.0, 1.0); + + // Calculate the antialiasing fade factor based on distance to the dash. + // Only affects alpha when line is dashed + float pos = mod(v_linesofar, u_dasharray.x + u_dasharray.y); + alpha *= max(step(0.0, -u_dasharray.y), clamp(min(pos, u_dasharray.x - pos), 0.0, 1.0)); + + gl_FragColor = u_color * alpha; + + if (u_debug > 0.0) { + gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); + } +} diff --git a/src/shader/line.vertex.glsl b/src/shader/line.vertex.glsl new file mode 100644 index 0000000000..b7cb2fed46 --- /dev/null +++ b/src/shader/line.vertex.glsl @@ -0,0 +1,62 @@ +// these are the shaders for rendering antialiased lines + +// floor(127 / 2) == 63.0 +// the maximum allowed miter limit is 2.0 at the moment. the extrude normal is +// stored in a byte (-128..127). we scale regular normals up to length 63, but +// there are also "special" normals that have a bigger length (of up to 126 in +// this case). +#define scale 63.0 + +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; + + +uniform float u_debug; + +// shared +uniform float u_ratio; +uniform vec2 u_linewidth; +uniform vec4 u_color; +uniform float u_point; + +varying vec2 v_normal; +varying float v_linesofar; + +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/shader/plain.vertex.glsl b/src/shader/plain.vertex.glsl index 547576757e..ef8225231c 100644 --- a/src/shader/plain.vertex.glsl +++ b/src/shader/plain.vertex.glsl @@ -5,4 +5,4 @@ uniform mat4 u_matrix; void main() { float z = step(32767.0, a_pos.x) * 2.0; gl_Position = u_matrix * vec4(a_pos, z, 1); - } +} diff --git a/src/shader/shaders.cpp b/src/shader/shaders.cpp index c5e33a0b93..1b57bb68da 100644 --- a/src/shader/shaders.cpp +++ b/src/shader/shaders.cpp @@ -8,12 +8,16 @@ const shader_source llmr::shaders[SHADER_COUNT] = { .vertex = "attribute vec2 a_pos;\n\nuniform mat4 u_matrix;\n\nvoid main() {\n gl_Position = u_matrix * vec4(a_pos, 0, 1);\n}\n", .fragment = "uniform vec4 u_color;\n\nvoid main() {\n gl_FragColor = u_color;\n}\n", }, + [LINE_SHADER] = { + .vertex = "// these are the shaders for rendering antialiased lines\n\n// floor(127 / 2) == 63.0\n// the maximum allowed miter limit is 2.0 at the moment. the extrude normal is\n// stored in a byte (-128..127). we scale regular normals up to length 63, but\n// there are also \"special\" normals that have a bigger length (of up to 126 in\n// this case).\n#define scale 63.0\n\nattribute vec2 a_pos;\nattribute vec2 a_extrude;\nattribute float a_linesofar;\n\n// matrix is for the vertex position, exmatrix is for rotating and projecting\n// the extrusion vector.\nuniform mat4 u_matrix;\nuniform mat4 u_exmatrix;\n\n\nuniform float u_debug;\n\n// shared\nuniform float u_ratio;\nuniform vec2 u_linewidth;\nuniform vec4 u_color;\nuniform float u_point;\n\nvarying vec2 v_normal;\nvarying float v_linesofar;\n\nvoid main() {\n // We store the texture normals in the most insignificant bit\n // transform y so that 0 => -1 and 1 => 1\n // In the texture normal, x is 0 if the normal points straight up/down and 1 if it's a round cap\n // y is 1 if the normal points up, and -1 if it points down\n vec2 normal = mod(a_pos, 2.0);\n normal.y = sign(normal.y - 0.5);\n v_normal = normal;\n\n // Scale the extrusion vector down to a normal and then up by the line width\n // of this vertex.\n vec2 extrude = a_extrude / scale;\n vec2 dist = u_linewidth.s * extrude * (1.0 - u_point);\n\n // If the x coordinate is the maximum integer, we move the z coordinates out\n // of the view plane so that the triangle gets clipped. This makes it easier\n // for us to create degenerate triangle strips.\n float z = step(32767.0, a_pos.x);\n\n // When drawing points, skip every other vertex\n z += u_point * step(1.0, v_normal.y);\n\n // Remove the texture normal bit of the position before scaling it with the\n // model/view matrix. Add the extrusion vector *after* the model/view matrix\n // because we're extruding the line in pixel space, regardless of the current\n // tile's zoom level.\n gl_Position = u_matrix * vec4(floor(a_pos / 2.0), 0.0, 1.0) + u_exmatrix * vec4(dist, z, 0.0);\n v_linesofar = a_linesofar * u_ratio;\n\n\n gl_PointSize = 2.0 * u_linewidth.s - 1.0;\n}\n", + .fragment = "#version 120\n// shared\nuniform float u_debug;\nuniform vec2 u_linewidth;\nuniform vec4 u_color;\nuniform float u_point;\nuniform float u_gamma;\n\nuniform vec2 u_dasharray;\n\nvarying vec2 v_normal;\nvarying float v_linesofar;\n\nvoid main() {\n // Calculate the distance of the pixel from the line in pixels.\n float dist = length(v_normal) * (1.0 - u_point) + u_point * length(gl_PointCoord * 2.0 - 1.0);\n\n dist *= u_linewidth.s;\n\n // Calculate the antialiasing fade factor. This is either when fading in\n // the line in case of an offset line (v_linewidth.t) or when fading out\n // (v_linewidth.s)\n float alpha = clamp(min(dist - (u_linewidth.t - 1.0), u_linewidth.s - dist) * u_gamma, 0.0, 1.0);\n\n // Calculate the antialiasing fade factor based on distance to the dash.\n // Only affects alpha when line is dashed\n float pos = mod(v_linesofar, u_dasharray.x + u_dasharray.y);\n alpha *= max(step(0.0, -u_dasharray.y), clamp(min(pos, u_dasharray.x - pos), 0.0, 1.0));\n\n gl_FragColor = u_color * alpha;\n\n if (u_debug > 0.0) {\n gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n }\n}\n", + }, [OUTLINE_SHADER] = { .vertex = "attribute vec2 a_pos;\nuniform mat4 u_matrix;\nuniform vec2 u_world;\n\nvarying vec2 v_pos;\n\nvoid main() {\n // If the x coordinate is the maximum integer, we move the z coordinates out\n // of the view plane so that the triangle gets clipped. This makes it easier\n // for us to create degenerate triangle strips.\n float z = step(32767.0, a_pos.x) * 2.0;\n gl_Position = u_matrix * vec4(a_pos, z, 1);\n\n v_pos = (gl_Position.xy + 1.0) / 2.0 * u_world;\n}\n", .fragment = "uniform vec4 u_color;\n\nvarying vec2 v_pos;\n\nvoid main() {\n float dist = length(v_pos - gl_FragCoord.xy);\n float alpha = smoothstep(1.0, 0.0, dist);\n gl_FragColor = u_color * alpha;\n}\n", }, [PLAIN_SHADER] = { - .vertex = "attribute vec2 a_pos;\n\nuniform mat4 u_matrix;\n\nvoid main() {\n float z = step(32767.0, a_pos.x) * 2.0;\n gl_Position = u_matrix * vec4(a_pos, z, 1);\n }\n", + .vertex = "attribute vec2 a_pos;\n\nuniform mat4 u_matrix;\n\nvoid main() {\n float z = step(32767.0, a_pos.x) * 2.0;\n gl_Position = u_matrix * vec4(a_pos, z, 1);\n}\n", .fragment = "uniform vec4 u_color;\n\nvoid main() {\n gl_FragColor = u_color;\n}\n", } }; |