From a7b9b96d4de44d8f8bf87f5fc5104190c3233945 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20Ka=CC=88fer?= Date: Fri, 21 Mar 2014 14:26:25 +0100 Subject: add textshader --- include/llmr/renderer/painter.hpp | 2 + include/llmr/shader/text_shader.hpp | 55 +++++++++++++- src/renderer/painter.cpp | 4 + src/shader/shaders.cpp | 4 +- src/shader/text.fragment.glsl | 10 ++- src/shader/text.vertex.glsl | 65 +++++++++++++++- src/shader/text_shader.cpp | 147 +++++++++++++++++++++++++++++++++++- 7 files changed, 279 insertions(+), 8 deletions(-) diff --git a/include/llmr/renderer/painter.hpp b/include/llmr/renderer/painter.hpp index 0f8118ca5f..71973aba08 100644 --- a/include/llmr/renderer/painter.hpp +++ b/include/llmr/renderer/painter.hpp @@ -14,6 +14,7 @@ #include #include #include +#include namespace llmr { @@ -84,6 +85,7 @@ private: std::unique_ptr patternShader; std::unique_ptr pointShader; std::unique_ptr rasterShader; + std::unique_ptr textShader; // Set up the stencil quad we're using to generate the stencil mask. VertexBuffer tileStencilBuffer = { diff --git a/include/llmr/shader/text_shader.hpp b/include/llmr/shader/text_shader.hpp index ec0d49460e..7edf10d235 100644 --- a/include/llmr/shader/text_shader.hpp +++ b/include/llmr/shader/text_shader.hpp @@ -12,15 +12,66 @@ public: void bind(char *offset); void setColor(float r, float g, float b, float a); - void setColor(const std::array& color); + void setColor(const std::array &color); + void setBuffer(float buffer); + void setGamma(float gamma); + void setExmatrix(const std::array &exmatrix); + void setAngle(float angle); + void setZoom(float zoom); + void setFlip(float flip); + void setFadedist(float fadedist); + void setMinfadezoom(float minfadezoom); + void setMaxfadezoom(float maxfadezoom); + void setFadezoom(float fadezoom); + void setTexsize(const std::array &texsize); 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; std::array color = {{}}; int32_t u_color = -1; -}; + float buffer = 0.0f; + int32_t u_buffer = -1; + + float gamma = 0.0f; + int32_t u_gamma = -1; + + std::array exmatrix = {{}}; + int32_t u_exmatrix = -1; + + float angle = 0.0f; + int32_t u_angle = -1; + + float zoom = 0.0f; + int32_t u_zoom = -1; + + float flip = 0.0f; + int32_t u_flip = -1; + + float fadedist = 0.0f; + int32_t u_fadedist = -1; + + float minfadezoom = 0.0f; + int32_t u_minfadezoom = -1; + + float maxfadezoom = 0.0f; + int32_t u_maxfadezoom = -1; + + float fadezoom = 0.0f; + int32_t u_fadezoom = -1; + + std::array texsize = {{}}; + int32_t u_texsize = -1; +}; } #endif diff --git a/src/renderer/painter.cpp b/src/renderer/painter.cpp index 4e625ab435..91f466f5b3 100644 --- a/src/renderer/painter.cpp +++ b/src/renderer/painter.cpp @@ -38,6 +38,7 @@ void Painter::setup() { assert(linejoinShader); assert(patternShader); assert(rasterShader); + assert(textShader); // Blending @@ -65,6 +66,7 @@ void Painter::setupShaders() { patternShader = std::make_unique(); pointShader = std::make_unique(); rasterShader = std::make_unique(); + textShader = std::make_unique(); } void Painter::resize(int width, int height) { @@ -476,6 +478,8 @@ void Painter::renderPoint(PointBucket& bucket, const std::string& layer_name, co void Painter::renderText(TextBucket& bucket, const std::string& layer_name, const Tile::ID& id) { // noop + useProgram(textShader->program); + textShader->setMatrix(matrix); } void Painter::renderDebug(const TileData::Ptr& tile_data) { diff --git a/src/shader/shaders.cpp b/src/shader/shaders.cpp index ff83a1af27..0b99521b98 100644 --- a/src/shader/shaders.cpp +++ b/src/shader/shaders.cpp @@ -33,7 +33,7 @@ const shader_source llmr::shaders[SHADER_COUNT] = { "uniform sampler2D u_image;\nuniform float u_opacity;\n\nvarying vec2 v_pos;\n\nvoid main() {\n gl_FragColor = texture2D(u_image, v_pos) * u_opacity;\n}\n", }, { - "attribute vec2 a_pos;\n\nuniform mat4 u_matrix;\n\nvoid main() {\n gl_Position = u_matrix * vec4(a_pos, 0, 1);\n}\n", - "uniform vec4 u_color;\n\nvoid main() {\n gl_FragColor = u_color;\n}\n", + "attribute vec2 a_pos;\nattribute vec2 a_offset;\nattribute vec2 a_tex;\nattribute float a_angle;\nattribute float a_minzoom;\nattribute float a_maxzoom;\nattribute float a_rangeend;\nattribute float a_rangestart;\nattribute float a_labelminzoom;\n\n\n// posmatrix is for the vertex position, exmatrix is for rotating and projecting\n// the extrusion vector.\nuniform mat4 u_matrix;\nuniform mat4 u_exmatrix;\nuniform float u_angle;\nuniform float u_zoom;\nuniform float u_flip;\nuniform float u_fadedist;\nuniform float u_minfadezoom;\nuniform float u_maxfadezoom;\nuniform float u_fadezoom;\n\nuniform vec2 u_texsize;\n\nvarying vec2 v_tex;\nvarying float v_alpha;\n\nvoid main() {\n\n float a_fadedist = 10.0;\n float rev = 0.0;\n\n // u_angle is angle of the map, -128..128 representing 0..2PI\n // a_angle is angle of the label, 0..256 representing 0..2PI, where 0 is horizontal text\n float rotated = mod(a_angle + u_angle, 256.0);\n // if the label rotates with the map, and if the rotated label is upside down, hide it\n if (u_flip > 0.0 && rotated >= 64.0 && rotated < 192.0) rev = 1.0;\n\n // If the label should be invisible, we move the vertex outside\n // of the view plane so that the triangle gets clipped. This makes it easier\n // for us to create degenerate triangle strips.\n // u_zoom is the current zoom level adjusted for the change in font size\n float z = 2.0 - step(a_minzoom, u_zoom) - (1.0 - step(a_maxzoom, u_zoom)) + rev;\n\n // fade out labels\n float alpha = clamp((u_fadezoom - a_labelminzoom) / u_fadedist, 0.0, 1.0);\n\n if (u_fadedist >= 0.0) {\n v_alpha = alpha;\n } else {\n v_alpha = 1.0 - alpha;\n }\n if (u_maxfadezoom < a_labelminzoom) {\n v_alpha = 0.0;\n }\n if (u_minfadezoom >= a_labelminzoom) {\n v_alpha = 1.0;\n }\n\n // if label has been faded out, clip it\n z += step(v_alpha, 0.0);\n\n // all the angles are 0..256 representing 0..2PI\n // hide if (angle >= a_rangeend && angle < rangestart)\n z += step(a_rangeend, u_angle) * (1.0 - step(a_rangestart, u_angle));\n\n gl_Position = u_matrix * vec4(a_pos, 0, 1) + u_exmatrix * vec4(a_offset / 64.0, z, 0);\n v_tex = a_tex * 4.0 / u_texsize;\n}\n", + "uniform sampler2D u_texture;\nuniform vec4 u_color;\nuniform float u_buffer;\nuniform float u_gamma;\n\nvarying vec2 v_tex;\nvarying float v_alpha;\n\nvoid main() {\n float dist = texture2D(u_texture, v_tex).a;\n float alpha = smoothstep(u_buffer - u_gamma, u_buffer + u_gamma, dist) * v_alpha;\n gl_FragColor = u_color * alpha;\n}\n", } }; diff --git a/src/shader/text.fragment.glsl b/src/shader/text.fragment.glsl index 8df552c171..d72d61dab1 100644 --- a/src/shader/text.fragment.glsl +++ b/src/shader/text.fragment.glsl @@ -1,5 +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() { - gl_FragColor = u_color; + 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/shader/text.vertex.glsl b/src/shader/text.vertex.glsl index 866c3cd2f3..8e1e1817fc 100644 --- a/src/shader/text.vertex.glsl +++ b/src/shader/text.vertex.glsl @@ -1,7 +1,70 @@ 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; + +// posmatrix is for the vertex position, exmatrix is for rotating and projecting +// the extrusion vector. uniform mat4 u_matrix; +uniform mat4 u_exmatrix; +uniform float u_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() { - gl_Position = u_matrix * vec4(a_pos, 0, 1); + + 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 * 4.0 / u_texsize; } diff --git a/src/shader/text_shader.cpp b/src/shader/text_shader.cpp index 84649bdb06..4c8301affb 100644 --- a/src/shader/text_shader.cpp +++ b/src/shader/text_shader.cpp @@ -17,19 +17,85 @@ TextShader::TextShader() } 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"); u_matrix = glGetUniformLocation(program, "u_matrix"); u_color = glGetUniformLocation(program, "u_color"); + u_buffer = glGetUniformLocation(program, "u_buffer"); + u_gamma = glGetUniformLocation(program, "u_gamma"); + u_exmatrix = glGetUniformLocation(program, "u_exmatrix"); + u_angle = glGetUniformLocation(program, "u_angle"); + u_zoom = glGetUniformLocation(program, "u_zoom"); + u_flip = glGetUniformLocation(program, "u_flip"); + u_fadedist = glGetUniformLocation(program, "u_fadedist"); + u_minfadezoom = glGetUniformLocation(program, "u_minfadezoom"); + u_maxfadezoom = glGetUniformLocation(program, "u_maxfadezoom"); + u_fadezoom = glGetUniformLocation(program, "u_fadezoom"); + u_texsize = glGetUniformLocation(program, "u_texsize"); // fprintf(stderr, "TextShader:\n"); // fprintf(stderr, " - a_pos: %d\n", a_pos); - // fprintf(stderr, " - u_matrix: %d\n", u_matrix); + // fprintf(stderr, " - a_offset: %d\n", a_offset); + // fprintf(stderr, " - a_tex: %d\n", a_tex); + // fprintf(stderr, " - a_angle: %d\n", a_angle); + // fprintf(stderr, " - a_minzoom: %d\n", a_minzoom); + // fprintf(stderr, " - a_maxzoom: %d\n", a_maxzoom); + // fprintf(stderr, " - a_rangeend: %d\n", a_rangeend); + // fprintf(stderr, " - a_rangestart: %d\n", a_rangestart); + // fprintf(stderr, " - a_labelminzoom: %d\n", a_labelminzoom); // fprintf(stderr, " - u_color: %d\n", u_color); + // fprintf(stderr, " - u_buffer: %d\n", u_buffer); + // fprintf(stderr, " - u_gamma: %d\n", u_gamma); + // fprintf(stderr, " - u_exmatrix: %d\n", u_exmatrix); + // fprintf(stderr, " - u_angle: %d\n", u_angle); + // fprintf(stderr, " - u_zoom: %d\n", u_zoom); + // fprintf(stderr, " - u_flip: %d\n", u_flip); + // fprintf(stderr, " - u_fadedist: %d\n", u_fadedist); + // fprintf(stderr, " - u_minfadezoom: %d\n", u_minfadezoom); + // fprintf(stderr, " - u_maxfadezoom: %d\n", u_maxfadezoom); + // fprintf(stderr, " - u_fadezoom: %d\n", u_fadezoom); + // fprintf(stderr, " - u_texsize: %d\n", u_texsize); } void TextShader::bind(char *offset) { glEnableVertexAttribArray(a_pos); - glVertexAttribPointer(a_pos, 2, GL_SHORT, false, 0, offset); + glVertexAttribPointer(a_pos, 2, GL_SHORT, false, 16, offset + 0); + + glEnableVertexAttribArray(a_offset); + glVertexAttribPointer(a_offset, 2, GL_SHORT, false, 16, offset + 4); + + glEnableVertexAttribArray(a_tex); + glVertexAttribPointer(a_tex, 2, GL_UNSIGNED_BYTE, false, 16, offset + 8); + + glEnableVertexAttribArray(a_labelminzoom); + glVertexAttribPointer(a_labelminzoom, 1, GL_UNSIGNED_BYTE, false, 16, + offset + 10); + + glEnableVertexAttribArray(a_minzoom); + glVertexAttribPointer(a_minzoom, 1, GL_UNSIGNED_BYTE, false, 16, + offset + 11); + + glEnableVertexAttribArray(a_maxzoom); + glVertexAttribPointer(a_maxzoom, 1, GL_UNSIGNED_BYTE, false, 16, + offset + 12); + + glEnableVertexAttribArray(a_angle); + glVertexAttribPointer(a_angle, 1, GL_UNSIGNED_BYTE, false, 16, offset + 13); + + glEnableVertexAttribArray(a_rangeend); + glVertexAttribPointer(a_rangeend, 1, GL_UNSIGNED_BYTE, false, 16, + offset + 14); + + glEnableVertexAttribArray(a_rangestart); + glVertexAttribPointer(a_rangestart, 1, GL_UNSIGNED_BYTE, false, 16, + offset + 15); } void TextShader::setColor(const std::array& new_color) { @@ -42,3 +108,80 @@ void TextShader::setColor(const std::array& new_color) { void TextShader::setColor(float r, float g, float b, float a) { setColor({{ r, g, b, a }}); } + +void TextShader::setBuffer(float new_buffer) { + if (buffer != new_buffer) { + glUniform1f(u_buffer, new_buffer); + buffer = new_buffer; + } +} + +void TextShader::setGamma(float new_gamma) { + if (gamma != new_gamma) { + glUniform1f(u_gamma, new_gamma); + gamma = new_gamma; + } +} + +void TextShader::setExmatrix(const std::array &new_exmatrix) { + if (exmatrix != new_exmatrix) { + glUniformMatrix4fv(u_exmatrix, 1, GL_FALSE, new_exmatrix.data()); + exmatrix = new_exmatrix; + } +} + +void TextShader::setAngle(float new_angle) { + if (angle != new_angle) { + glUniform1f(u_angle, new_angle); + angle = new_angle; + } +} + +void TextShader::setZoom(float new_zoom) { + if (zoom != new_zoom) { + glUniform1f(u_zoom, new_zoom); + zoom = new_zoom; + } +} + +void TextShader::setFlip(float new_flip) { + if (flip != new_flip) { + glUniform1f(u_flip, new_flip); + flip = new_flip; + } +} + +void TextShader::setFadedist(float new_fadedist) { + if (fadedist != new_fadedist) { + glUniform1f(u_fadedist, new_fadedist); + fadedist = new_fadedist; + } +} + +void TextShader::setMinfadezoom(float new_minfadezoom) { + if (minfadezoom != new_minfadezoom) { + glUniform1f(u_minfadezoom, new_minfadezoom); + minfadezoom = new_minfadezoom; + } +} + +void TextShader::setMaxfadezoom(float new_maxfadezoom) { + if (maxfadezoom != new_maxfadezoom) { + glUniform1f(u_maxfadezoom, new_maxfadezoom); + maxfadezoom = new_maxfadezoom; + } +} + +void TextShader::setFadezoom(float new_fadezoom) { + if (fadezoom != new_fadezoom) { + glUniform1f(u_fadezoom, new_fadezoom); + fadezoom = new_fadezoom; + } +} + +void TextShader::setTexsize(const std::array &new_texsize) { + if (texsize != new_texsize) { + glUniform2fv(u_texsize, 1, new_texsize.data()); + texsize = new_texsize; + } +} -- cgit v1.2.1