summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorKonstantin Käfer <mail@kkaefer.com>2014-01-22 18:07:30 +0100
committerKonstantin Käfer <mail@kkaefer.com>2014-01-22 18:07:30 +0100
commit1ad5970a0001b9dd7ca0bd521b361f0f15c65d0d (patch)
treedeea47dcc40167cb56da1a1d5d825859d0baff0f /src
parent0f74a4bc90e1d4d69b50a443aa9f1ed42d071d4d (diff)
downloadqtlocation-mapboxgl-1ad5970a0001b9dd7ca0bd521b361f0f15c65d0d.tar.gz
render shapes, but only the first one is drawn?
Diffstat (limited to 'src')
-rw-r--r--src/geometry/debug_font_buffer.cpp1
-rw-r--r--src/geometry/linevertexbuffer.cpp1
-rw-r--r--src/map/tile.cpp2
-rw-r--r--src/renderer/painter.cpp165
4 files changed, 150 insertions, 19 deletions
diff --git a/src/geometry/debug_font_buffer.cpp b/src/geometry/debug_font_buffer.cpp
index e2086ef42a..a383ca5734 100644
--- a/src/geometry/debug_font_buffer.cpp
+++ b/src/geometry/debug_font_buffer.cpp
@@ -15,6 +15,7 @@ debug_font_buffer::debug_font_buffer()
debug_font_buffer::~debug_font_buffer() {
if (buffer != 0) {
glDeleteBuffers(1, &buffer);
+ buffer = 0;
}
}
diff --git a/src/geometry/linevertexbuffer.cpp b/src/geometry/linevertexbuffer.cpp
index 2086a0e865..3c8521bc39 100644
--- a/src/geometry/linevertexbuffer.cpp
+++ b/src/geometry/linevertexbuffer.cpp
@@ -12,6 +12,7 @@ linevertexbuffer::linevertexbuffer()
linevertexbuffer::~linevertexbuffer() {
if (buffer != 0) {
glDeleteBuffers(1, &buffer);
+ buffer = 0;
}
}
diff --git a/src/map/tile.cpp b/src/map/tile.cpp
index 1d4a660ac5..4d744cb971 100644
--- a/src/map/tile.cpp
+++ b/src/map/tile.cpp
@@ -51,6 +51,8 @@ Tile::Tile(ID id)
}
Tile::~Tile() {
+ std::lock_guard<std::mutex> lock(mtx);
+
// fprintf(stderr, "[%p] deleting tile %d/%d/%d\n", this, id.z, id.x, id.y);
if (this->data) {
free(this->data);
diff --git a/src/renderer/painter.cpp b/src/renderer/painter.cpp
index 02269a76b7..af5ecb55dd 100644
--- a/src/renderer/painter.cpp
+++ b/src/renderer/painter.cpp
@@ -8,6 +8,8 @@
#include <llmr/platform/gl.hpp>
#include <llmr/map/settings.hpp>
+#include <cmath>
+
#include <numeric>
using namespace llmr;
@@ -59,9 +61,10 @@ void Painter::setup() {
glEnable(GL_STENCIL_TEST);
-
+ // We are blending the new pixels *behind* the existing pixels. That way we can
+ // draw front-to-back and use then stencil buffer to cull opaque pixels early.
glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_ONE);
}
void Painter::setupShaders() {
@@ -131,7 +134,7 @@ void Painter::drawClippingMask() {
}
void Painter::clear() {
- glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
+ glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClearStencil(0x0);
glStencilMask(0xFF);
glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
@@ -162,37 +165,146 @@ void Painter::render(const Tile::Ptr& tile) {
glDrawArrays(GL_LINE_STRIP, 0, tile->lineVertex.length());
// draw fills:
+
+ // TODO: expose this to the stylesheet
+ bool evenodd = false;
+ bool antialiasing = true;
+
+
tile->fillBuffer.bind();
float i = 0.0f;
+ fprintf(stderr, "----\n");
for (const Tile::fill_index& index : tile->fillIndices) {
+ float color[] = { i, i, 1.0f, 1.0f };
+ i = sqrt(i);
if (!index.length) continue;
+ // if (index.name != "water") continue;
+ fprintf(stderr, "%s: %d\n", index.name.c_str(), index.length);
+
+
+ glStencilMask(0x0);
+ glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+ glStencilFunc(GL_EQUAL, 0x80, 0x80);
+ glColorMask(true, true, true, true);
+
+ // Draw the stencil mask.
+ {
+ // We're only drawing to the first seven bits (== support a maximum of
+ // 127 overlapping polygons in one place before we get rendering errors).
+ glStencilMask(0x3F);
+ glClear(GL_STENCIL_BUFFER_BIT);
+
+ // Draw front facing triangles. Wherever the 0x80 bit is 1, we are
+ // increasing the lower 7 bits by one if the triangle is a front-facing
+ // triangle. This means that all visible polygons should be in CCW
+ // orientation, while all holes (see below) are in CW orientation.
+ glStencilFunc(GL_NOTEQUAL, 0x80, 0x80);
+
+ if (evenodd) {
+ // When we draw an even/odd winding fill, we just invert all the bits.
+ glStencilOp(GL_INVERT, GL_KEEP, GL_KEEP);
+ } else {
+ // When we do a nonzero fill, we count the number of times a pixel is
+ // covered by a counterclockwise polygon, and subtract the number of
+ // times it is "uncovered" by a clockwise polygon.
+ glStencilOpSeparate(GL_FRONT, GL_INCR_WRAP, GL_KEEP, GL_KEEP);
+ glStencilOpSeparate(GL_BACK, GL_DECR_WRAP, GL_KEEP, GL_KEEP);
+ }
+
+ // When drawing a shape, we first draw all shapes to the stencil buffer
+ // and incrementing all areas where polygons are
+ glColorMask(false, false, false, false);
+
+ // Draw the actual triangle fan into the stencil buffer.
+ switchShader(fillShader);
+ glUniformMatrix4fv(fillShader->u_matrix, 1, GL_FALSE, matrix);
+
+ // Draw all groups
+ char *vertex_index = BUFFER_OFFSET(index.vertex_start * 2 * sizeof(uint16_t));
+ char *elements_index = BUFFER_OFFSET(index.elements_start * 3 * sizeof(uint16_t));
+ for (const Tile::fill_index::group& group : index.groups) {
+ fprintf(stderr, "- vertex: %d, elements: %d, length: %d\n", vertex_index, elements_index, group.elements_length * 3);
+
+ glVertexAttribPointer(fillShader->a_pos, 2, GL_SHORT, GL_FALSE, 0, vertex_index);
+ glDrawElements(GL_TRIANGLES, group.elements_length * 3, GL_UNSIGNED_SHORT, elements_index);
+ vertex_index += group.vertex_length * 2 * sizeof(uint16_t);
+ elements_index += group.elements_length * 3 * sizeof(uint16_t);
+ }
+
+ // Now that we have the stencil mask in the stencil buffer, we can start
+ // writing to the color buffer.
+ glColorMask(true, true, true, true);
+ }
- glUniform4f(outlineShader->u_color, i, 0.0f, 1.0f, 0.5f);
- glUniform2f(outlineShader->u_world, transform.fb_width, transform.fb_height);
- glLineWidth(2.0f);
-
- char *vertex_index = BUFFER_OFFSET(index.vertex_start * 2 * sizeof(uint16_t));
- char *elements_index = BUFFER_OFFSET(index.elements_start * 3 * sizeof(uint16_t));
- for (const Tile::fill_index::group& group : index.groups) {
- glVertexAttribPointer(outlineShader->a_pos, 2, GL_SHORT, GL_FALSE, 0, vertex_index);
- glDrawElements(GL_TRIANGLES, group.elements_length * 3, GL_UNSIGNED_SHORT, elements_index);
- vertex_index += group.vertex_length * 2 * sizeof(uint16_t);
- elements_index += group.elements_length * 3 * sizeof(uint16_t);
+ // From now on, we don't want to update the stencil buffer anymore.
+ glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+ glStencilMask(0x0);
+
+ // // Because we're drawing top-to-bottom, and we update the stencil mask
+ // // below, we have to draw the outline first (!)
+ // if (antialiasing) {
+
+ // // if (layerStyle.stroke) {
+ // // // If we defined a different color for the fill outline, we are
+ // // // going to ignore the bits in 0x3F and just care about the global
+ // // // clipping mask.
+ // // glStencilFunc(GL_EQUAL, 0x80, 0x80);
+ // // } else {
+ // // Otherwise, we only want to draw the antialiased parts that are
+ // // *outside* the current shape. This is important in case the fill
+ // // or stroke color is translucent. If we wouldn't clip to outside
+ // // the current shape, some pixels from the outline stroke overlapped
+ // // the (non-antialiased) fill.
+ // glStencilFunc(GL_EQUAL, 0x80, 0xBF);
+ // // }
+
+ // switchShader(outlineShader);
+ // glUniformMatrix4fv(outlineShader->u_matrix, 1, GL_FALSE, matrix);
+ // glUniform2f(outlineShader->u_world, transform.fb_width, transform.fb_height);
+ // glUniform4f(outlineShader->u_color, color[0], color[1], color[2], color[3]);
+ // glLineWidth(2);
+
+ // // Draw the entire line
+ // char *vertex_index = BUFFER_OFFSET(index.vertex_start * 2 * sizeof(uint16_t));
+ // glVertexAttribPointer(outlineShader->a_pos, 2, GL_SHORT, GL_FALSE, 0, vertex_index);
+ // glLineWidth(2.0f);
+ // glDrawArrays(GL_LINE_STRIP, 0, index.length);
+ // }
+
+ // Now finally, draw a tile-covering quad that paints the parts of the
+ // image that we marked in the stencil buffer.
+ {
+ // Only draw regions that we marked
+ glStencilFunc(GL_NOTEQUAL, 0x0, 0x3F);
+
+ switchShader(fillShader);
+ glUniformMatrix4fv(fillShader->u_matrix, 1, GL_FALSE, matrix);
+
+ // Draw a rectangle that covers the entire viewport.
+ glBindBuffer(GL_ARRAY_BUFFER, tile_stencil_buffer);
+ glVertexAttribPointer(fillShader->a_pos, 2, GL_SHORT, false, 0, BUFFER_OFFSET(0));
+ glUniform4f(fillShader->u_color, color[0], color[1], color[2], color[3]);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, sizeof(tile_stencil_vertices));
+
+ glStencilMask(0x00);
+ glStencilFunc(GL_EQUAL, 0x80, 0x80);
}
- vertex_index = BUFFER_OFFSET(index.vertex_start * 2 * sizeof(uint16_t));
- glUniform4f(outlineShader->u_color, i, 1.0f, 1.0f, 1.0f);
- glVertexAttribPointer(outlineShader->a_pos, 2, GL_SHORT, GL_FALSE, 0, vertex_index);
- glDrawArrays(GL_LINE_STRIP, 0, index.length);
- i += 0.1f;
+
+ // break;
}
if (settings.debug) {
renderDebug(tile);
}
+
+ renderBackground();
}
void Painter::renderDebug(const Tile::Ptr& tile) {
+ // Blend to the front, not the back.
+ glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+
// draw tile outline
switchShader(lineShader);
glUniformMatrix4fv(lineShader->u_matrix, 1, GL_FALSE, matrix);
@@ -213,8 +325,23 @@ void Painter::renderDebug(const Tile::Ptr& tile) {
glUniform4f(lineShader->u_color, 0.0f, 0.0f, 0.0f, 1.0f);
glLineWidth(2.0f);
glDrawArrays(GL_LINES, 0, tile->debugFontVertex.length());
+
+ // Revert blending mode to blend to the back.
+ glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_ONE);
+}
+
+void Painter::renderBackground() {
+ switchShader(fillShader);
+ glUniformMatrix4fv(fillShader->u_matrix, 1, GL_FALSE, matrix);
+
+ // Draw the clipping mask
+ glBindBuffer(GL_ARRAY_BUFFER, tile_stencil_buffer);
+ glVertexAttribPointer(fillShader->a_pos, 2, GL_SHORT, false, 0, BUFFER_OFFSET(0));
+ glUniform4f(fillShader->u_color, 1.0f, 1.0f, 1.0f, 1.0f);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, sizeof(tile_stencil_vertices));
}
+
// Switches to a different shader program.
/**
* @return boolean whether the shader was actually switched