diff --git a/include/llmr/geometry/elements_buffer.hpp b/include/llmr/geometry/elements_buffer.hpp index 684b3acd3..a058312bd 100644 --- a/include/llmr/geometry/elements_buffer.hpp +++ b/include/llmr/geometry/elements_buffer.hpp @@ -2,15 +2,12 @@ #define LLMR_GEOMETRY_TRIANGLE_ELEMENTS_BUFFER #include +#include namespace llmr { -template -class VertexArrayObject; - -template struct ElementGroup { - VertexArrayObject array; + VertexArrayObject array; uint32_t vertex_length; uint32_t elements_length; diff --git a/include/llmr/geometry/vao.hpp b/include/llmr/geometry/vao.hpp index a2a5a8a0d..aa22e45e3 100644 --- a/include/llmr/geometry/vao.hpp +++ b/include/llmr/geometry/vao.hpp @@ -7,18 +7,26 @@ namespace llmr { -template class VertexArrayObject { public: - template + template void bind(Shader& shader, VertexBuffer& vertex_buffer, char *offset) { if (!vao) { glGenVertexArrays(1, &vao); glBindVertexArray(vao); + } else { + // We have been given the correct information. + glBindVertexArray(vao); + } + if (shader_ptr != &shader) { + if (shader_ptr != nullptr) { + fprintf(stderr, "shader rebind!"); + } vertex_buffer.bind(); shader.bind(offset); + shader_ptr = &shader; vertex_buffer_ptr = &vertex_buffer; elements_buffer_ptr = nullptr; offset_ptr = offset; @@ -28,22 +36,25 @@ public: throw std::runtime_error("trying to bind VAO to another elements buffer"); } else if (offset_ptr != offset) { throw std::runtime_error("trying to bind VAO to another offset"); - } else { - // We have been given the correct information. - glBindVertexArray(vao); } } - template + template void bind(Shader& shader, VertexBuffer& vertex_buffer, ElementsBuffer& elements_buffer, char *offset) { if (!vao) { glGenVertexArrays(1, &vao); glBindVertexArray(vao); + } else { + // We have been given the correct information. + glBindVertexArray(vao); + } + if (shader_ptr != &shader) { vertex_buffer.bind(); elements_buffer.bind(); shader.bind(offset); + shader_ptr = &shader; vertex_buffer_ptr = &vertex_buffer; elements_buffer_ptr = &elements_buffer; offset_ptr = offset; @@ -53,9 +64,6 @@ public: throw std::runtime_error("trying to bind VAO to another elements buffer"); } else if (offset_ptr != offset) { throw std::runtime_error("trying to bind VAO to another offset"); - } else { - // We have been given the correct information. - glBindVertexArray(vao); } } @@ -70,6 +78,7 @@ private: // For debug reasons, we're storing the bind information so that we can // detect errors and report + void *shader_ptr = nullptr; void *vertex_buffer_ptr = nullptr; void *elements_buffer_ptr = nullptr; char *offset_ptr = 0; diff --git a/include/llmr/map/tile.hpp b/include/llmr/map/tile.hpp index 99286a953..6c1c6f521 100644 --- a/include/llmr/map/tile.hpp +++ b/include/llmr/map/tile.hpp @@ -73,7 +73,7 @@ public: // Holds the actual geometries in this tile. DebugFontBuffer debugFontBuffer; - VertexArrayObject debugFontArray; + VertexArrayObject debugFontArray; std::shared_ptr fillVertexBuffer; std::shared_ptr lineVertexBuffer; diff --git a/include/llmr/renderer/fill_bucket.hpp b/include/llmr/renderer/fill_bucket.hpp index 4360e9715..bac4b2e9a 100644 --- a/include/llmr/renderer/fill_bucket.hpp +++ b/include/llmr/renderer/fill_bucket.hpp @@ -24,6 +24,7 @@ class LineElementsBuffer; class BucketDescription; class OutlineShader; class PlainShader; +class PatternShader; struct Coordinate; struct pbf; @@ -34,8 +35,8 @@ class FillBucket : public Bucket { static void free(void *userData, void *ptr); - typedef ElementGroup triangle_group_type; - typedef ElementGroup line_group_type; + typedef ElementGroup triangle_group_type; + typedef ElementGroup line_group_type; public: FillBucket(const std::shared_ptr& vertexBuffer, const std::shared_ptr& triangleElementsBuffer, @@ -52,6 +53,7 @@ public: void tessellate(); void drawElements(PlainShader& shader); + void drawElements(PatternShader& shader); void drawVertices(OutlineShader& shader); public: @@ -69,7 +71,7 @@ private: const uint32_t vertex_start; const uint32_t triangle_elements_start; const uint32_t line_elements_start; - VertexArrayObject array; + VertexArrayObject array; std::vector triangleGroups; std::vector lineGroups; diff --git a/include/llmr/renderer/line_bucket.hpp b/include/llmr/renderer/line_bucket.hpp index 6ec9d960d..993b1d18e 100644 --- a/include/llmr/renderer/line_bucket.hpp +++ b/include/llmr/renderer/line_bucket.hpp @@ -19,8 +19,8 @@ struct Coordinate; struct pbf; class LineBucket : public Bucket { - typedef ElementGroup triangle_group_type; - typedef ElementGroup point_group_type; + typedef ElementGroup triangle_group_type; + typedef ElementGroup point_group_type; public: LineBucket(const std::shared_ptr& vertexBuffer, const std::shared_ptr& triangleElementsBuffer, diff --git a/include/llmr/renderer/painter.hpp b/include/llmr/renderer/painter.hpp index 47d6a500c..b6934131d 100644 --- a/include/llmr/renderer/painter.hpp +++ b/include/llmr/renderer/painter.hpp @@ -77,8 +77,8 @@ private: 4096, 4096 }; - VertexArrayObject coveringPlainArray; - VertexArrayObject coveringPatternArray; + VertexArrayObject coveringPlainArray; + VertexArrayObject coveringPatternArray; // Set up the tile boundary lines we're using to draw the tile outlines. VertexBuffer tileBorderBuffer = { @@ -89,7 +89,7 @@ private: 0, 0 }; - VertexArrayObject tileBorderArray; + VertexArrayObject tileBorderArray; // Set up the matte buffer we're using to draw the filling background. VertexBuffer matteBuffer = { @@ -104,7 +104,7 @@ private: 16384, 16384 }; - VertexArrayObject matteArray; + VertexArrayObject matteArray; }; } diff --git a/src/renderer/fill_bucket.cpp b/src/renderer/fill_bucket.cpp index f5e05b9d9..d323ff9df 100644 --- a/src/renderer/fill_bucket.cpp +++ b/src/renderer/fill_bucket.cpp @@ -272,6 +272,17 @@ void FillBucket::drawElements(PlainShader& shader) { } } +void FillBucket::drawElements(PatternShader& shader) { + char *vertex_index = BUFFER_OFFSET(vertex_start * vertexBuffer->itemSize); + char *elements_index = BUFFER_OFFSET(triangle_elements_start * triangleElementsBuffer->itemSize); + for (triangle_group_type& group : triangleGroups) { + group.array.bind(shader, *vertexBuffer, *triangleElementsBuffer, vertex_index); + glDrawElements(GL_TRIANGLES, group.elements_length * 3, GL_UNSIGNED_SHORT, elements_index); + vertex_index += group.vertex_length * vertexBuffer->itemSize; + elements_index += group.elements_length * triangleElementsBuffer->itemSize; + } +} + void FillBucket::drawVertices(OutlineShader& shader) { char *vertex_index = BUFFER_OFFSET(vertex_start * vertexBuffer->itemSize); char *elements_index = BUFFER_OFFSET(line_elements_start * lineElementsBuffer->itemSize); diff --git a/src/renderer/painter.cpp b/src/renderer/painter.cpp index df56caaf6..cc1157e25 100644 --- a/src/renderer/painter.cpp +++ b/src/renderer/painter.cpp @@ -213,7 +213,7 @@ void Painter::renderFill(FillBucket& bucket, const std::string& layer_name, cons glStencilOp(GL_KEEP, GL_KEEP, GL_INCR_WRAP); } - if (false && properties.image.size() && *style.sprite) { + if (properties.image.size() && *style.sprite) { // Draw texture fill ImagePosition imagePos = style.sprite->getPosition(properties.image, true); @@ -242,16 +242,15 @@ void Painter::renderFill(FillBucket& bucket, const std::string& layer_name, cons patternShader->setMix(mix); style.sprite->bind(true); - // Draw a rectangle that covers the entire viewport. - coveringPatternArray.bind(*patternShader, tileStencilBuffer, BUFFER_OFFSET(0)); - glDrawArrays(GL_TRIANGLES, 0, tileStencilBuffer.index()); + // Draw the actual triangles into the color & stencil buffer. + bucket.drawElements(*patternShader); } else { // Draw filling rectangle. useProgram(plainShader->program); plainShader->setMatrix(matrix); plainShader->setColor(fill_color); - // Draw the actual triangle fan into the stencil buffer. + // Draw the actual triangles into the color & stencil buffer. bucket.drawElements(*plainShader); }