summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorKonstantin Käfer <mail@kkaefer.com>2014-01-17 16:52:41 +0100
committerKonstantin Käfer <mail@kkaefer.com>2014-01-17 16:52:41 +0100
commit8443687092ef95f7eb73c5020fb8d47153a68ee7 (patch)
treed21c200e3f75c60df36b7455dba25fad33c79216 /src
parent509b223fbf63ea326b60e82dec2f0c0cdb160a66 (diff)
downloadqtlocation-mapboxgl-8443687092ef95f7eb73c5020fb8d47153a68ee7.tar.gz
add antialiased line shader
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt2
-rw-r--r--src/renderer/painter.cpp70
-rw-r--r--src/renderer/shader-fill.cpp7
-rw-r--r--src/renderer/shader-line.cpp10
-rw-r--r--src/renderer/shader-outline.cpp23
-rw-r--r--src/shader/outline.fragment.glsl9
-rw-r--r--src/shader/outline.vertex.glsl15
-rw-r--r--src/shader/shaders.c4
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",
}
};