diff options
author | Konstantin Käfer <mail@kkaefer.com> | 2014-01-17 16:52:41 +0100 |
---|---|---|
committer | Konstantin Käfer <mail@kkaefer.com> | 2014-01-17 16:52:41 +0100 |
commit | 8443687092ef95f7eb73c5020fb8d47153a68ee7 (patch) | |
tree | d21c200e3f75c60df36b7455dba25fad33c79216 /src | |
parent | 509b223fbf63ea326b60e82dec2f0c0cdb160a66 (diff) | |
download | qtlocation-mapboxgl-8443687092ef95f7eb73c5020fb8d47153a68ee7.tar.gz |
add antialiased line shader
Diffstat (limited to 'src')
-rw-r--r-- | src/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/renderer/painter.cpp | 70 | ||||
-rw-r--r-- | src/renderer/shader-fill.cpp | 7 | ||||
-rw-r--r-- | src/renderer/shader-line.cpp | 10 | ||||
-rw-r--r-- | src/renderer/shader-outline.cpp | 23 | ||||
-rw-r--r-- | src/shader/outline.fragment.glsl | 9 | ||||
-rw-r--r-- | src/shader/outline.vertex.glsl | 15 | ||||
-rw-r--r-- | src/shader/shaders.c | 4 |
8 files changed, 101 insertions, 39 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8d596e65f4..b54ba75063 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -7,6 +7,7 @@ SET(llmr_SOURCES renderer/painter.cpp renderer/shader-fill.cpp renderer/shader-line.cpp + renderer/shader-outline.cpp renderer/shader.cpp shader/shaders.c util/animation.cpp @@ -25,6 +26,7 @@ SET(llmr_HEADERS ../include/llmr/renderer/painter.hpp ../include/llmr/renderer/shader-fill.hpp ../include/llmr/renderer/shader-line.hpp + ../include/llmr/renderer/shader-outline.hpp ../include/llmr/renderer/shader.hpp ../include/llmr/util/animation.hpp ../include/llmr/util/math.hpp diff --git a/src/renderer/painter.cpp b/src/renderer/painter.cpp index 8ef4708521..ae7d610789 100644 --- a/src/renderer/painter.cpp +++ b/src/renderer/painter.cpp @@ -32,7 +32,8 @@ painter::painter(class transform *transform, class settings *settings) settings(settings), currentShader(NULL), fillShader(NULL), - lineShader(NULL) { + lineShader(NULL), + outlineShader(NULL) { } @@ -41,6 +42,7 @@ void painter::setup() { assert(fillShader); assert(lineShader); + assert(outlineShader); // Set up the stencil quad we're using to generate the stencil mask. glGenBuffers(1, &tile_stencil_buffer); @@ -63,6 +65,7 @@ void painter::setup() { void painter::setupShaders() { fillShader = new FillShader(); lineShader = new LineShader(); + outlineShader = new OutlineShader(); } void painter::teardown() { @@ -143,23 +146,21 @@ void painter::render(tile::ptr tile) { drawClippingMask(); - switchShader(lineShader); - glUniformMatrix4fv(lineShader->u_matrix, 1, GL_FALSE, matrix); - + switchShader(outlineShader); + glUniformMatrix4fv(outlineShader->u_matrix, 1, GL_FALSE, matrix); glStencilFunc(GL_EQUAL, 0x80, 0x80); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); // glDisable(GL_STENCIL_TEST); tile->lineVertex.bind(); - glVertexAttribPointer(lineShader->a_pos, 2, GL_SHORT, GL_FALSE, 0, BUFFER_OFFSET(0)); - glUniform4f(lineShader->u_color, 0.0f, 0.0f, 0.0f, 1.0f); - glLineWidth(1.0f); + glVertexAttribPointer(outlineShader->a_pos, 2, GL_SHORT, GL_FALSE, 0, BUFFER_OFFSET(0)); + glUniform4f(outlineShader->u_color, 0.0f, 0.0f, 0.0f, 1.0f); + glUniform2f(outlineShader->u_world, transform->width, transform->height); + glLineWidth(2.0f); glDrawArrays(GL_LINE_STRIP, 0, tile->lineVertex.length()); - - if (settings->debug) { // draw tile outline switchShader(lineShader); @@ -189,36 +190,47 @@ void painter::viewport() { } // Switches to a different shader program. -void painter::switchShader(Shader *shader) { +/** + * @return boolean whether the shader was actually switched + */ +bool painter::switchShader(Shader *shader) { if (currentShader != shader) { glUseProgram(shader->program); // Disable all attributes from the existing shader that aren't used in // the new shader. Note: attribute indices are *not* program specific! if (currentShader) { - // const std::vector<GLuint> &enabled = currentShader->attributes; - // const std::vector<GLuint> &required = shader->attributes; - // TODO - - // for (var i = 0; i < enabled.length; i++) { - // if (required.indexOf(enabled[i]) < 0) { - // gl.disableVertexAttribArray(enabled[i]); - // } - // } - - // // Enable all attributes for the new shader. - // for (var j = 0; j < required.length; j++) { - // if (enabled.indexOf(required[j]) < 0) { - // gl.enableVertexAttribArray(required[j]); - // } - // } + const std::forward_list<uint32_t> &hitherto = currentShader->attributes; + const std::forward_list<uint32_t> &henceforth = shader->attributes; + + // Find all attribute indices that are used in the old shader, + // but unused in the new one. + for (uint32_t i : hitherto) { + if (std::find(henceforth.begin(), henceforth.end(), i) == henceforth.end()) { + glDisableVertexAttribArray(i); + } + } + + // Enable all attributes for the new shader that were not already in + // use in the old one. + for (uint32_t i : henceforth) { + if (std::find(hitherto.begin(), hitherto.end(), i) == hitherto.end()) { + glEnableVertexAttribArray(i); + } + } + + currentShader = shader; } else { - // Enable all attributes for the new shader. + // Enable all attributes for the new shader (== first shader). for (GLuint index : shader->attributes) { glEnableVertexAttribArray(index); } } - } - currentShader = shader; + currentShader = shader; + + return true; + } else { + return false; + } } diff --git a/src/renderer/shader-fill.cpp b/src/renderer/shader-fill.cpp index e1380bfad8..99cc84eb2a 100644 --- a/src/renderer/shader-fill.cpp +++ b/src/renderer/shader-fill.cpp @@ -9,10 +9,13 @@ FillShader::FillShader() llmr_shaders[FILL_SHADER].vertex, llmr_shaders[FILL_SHADER].fragment ) { - if (!valid) return; + if (!valid) { + fprintf(stderr, "invalid fill shader\n"); + return; + } a_pos = glGetAttribLocation(program, "a_pos"); - attributes.push_back(a_pos); + attributes.emplace_front(a_pos); u_matrix = glGetUniformLocation(program, "u_matrix"); u_color = glGetUniformLocation(program, "u_color"); diff --git a/src/renderer/shader-line.cpp b/src/renderer/shader-line.cpp index 658e244d56..c9f409cbb3 100644 --- a/src/renderer/shader-line.cpp +++ b/src/renderer/shader-line.cpp @@ -2,26 +2,20 @@ #include <llmr/shader/shaders.h> #include <llmr/platform/gl.hpp> -#include <cstdio> - using namespace llmr; LineShader::LineShader() : Shader( llmr_shaders[LINE_SHADER].vertex, llmr_shaders[LINE_SHADER].fragment - ), - a_pos(42) { + ) { if (!valid) { fprintf(stderr, "invalid line shader\n"); return; } - GLint pos = glGetAttribLocation(program, "a_pos"); - fprintf(stderr, "a_pos: %d\n", pos); - a_pos = glGetAttribLocation(program, "a_pos"); - attributes.push_back(a_pos); + attributes.emplace_front(a_pos); u_matrix = glGetUniformLocation(program, "u_matrix"); u_color = glGetUniformLocation(program, "u_color"); diff --git a/src/renderer/shader-outline.cpp b/src/renderer/shader-outline.cpp new file mode 100644 index 0000000000..0aa86d8beb --- /dev/null +++ b/src/renderer/shader-outline.cpp @@ -0,0 +1,23 @@ +#include <llmr/renderer/shader-outline.hpp> +#include <llmr/shader/shaders.h> +#include <llmr/platform/gl.hpp> + +using namespace llmr; + +OutlineShader::OutlineShader() + : Shader( + llmr_shaders[OUTLINE_SHADER].vertex, + llmr_shaders[OUTLINE_SHADER].fragment + ) { + if (!valid) { + fprintf(stderr, "invalid outline shader\n"); + return; + } + + a_pos = glGetAttribLocation(program, "a_pos"); + attributes.emplace_front(a_pos); + + u_matrix = glGetUniformLocation(program, "u_matrix"); + u_color = glGetUniformLocation(program, "u_color"); + u_world = glGetUniformLocation(program, "u_world"); +} diff --git a/src/shader/outline.fragment.glsl b/src/shader/outline.fragment.glsl new file mode 100644 index 0000000000..eccda714e5 --- /dev/null +++ b/src/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/shader/outline.vertex.glsl b/src/shader/outline.vertex.glsl new file mode 100644 index 0000000000..c3d608fd70 --- /dev/null +++ b/src/shader/outline.vertex.glsl @@ -0,0 +1,15 @@ +attribute vec2 a_pos; +uniform mat4 u_matrix; +uniform vec2 u_world; + +varying vec2 v_pos; + +void main() { + // 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) * 2.0; + gl_Position = u_matrix * vec4(a_pos, z, 1); + + v_pos = (gl_Position.xy + 1.0) / 2.0 * u_world; +} diff --git a/src/shader/shaders.c b/src/shader/shaders.c index e505fac3f0..650c73a246 100644 --- a/src/shader/shaders.c +++ b/src/shader/shaders.c @@ -9,5 +9,9 @@ const llmr_shader_t llmr_shaders[SHADER_COUNT] = { [LINE_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", .fragment = "uniform vec4 u_color;\n\nvoid main() {\n gl_FragColor = u_color;\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", } }; |