diff --git a/include/llmr/geometry/vertex_buffer.hpp b/include/llmr/geometry/vertex_buffer.hpp new file mode 100644 index 000000000..b4c31e419 --- /dev/null +++ b/include/llmr/geometry/vertex_buffer.hpp @@ -0,0 +1,33 @@ +#ifndef LLMR_GEOMETRY_VERTEX_BUFFER +#define LLMR_GEOMETRY_VERTEX_BUFFER + +#include + +#include + +namespace llmr { + +class VertexBuffer { +public: + VertexBuffer(std::initializer_list init); + ~VertexBuffer(); + + /* + * Returns the number of elements in this buffer. This is not the number of + * bytes, but rather the number of coordinates with associated information. + */ + uint32_t length() const; + + /* + * Transfers this buffer to the GPU and binds the buffer to the GL context. + */ + void bind(); + +private: + const std::vector array; + uint32_t buffer = 0; +}; + +} + +#endif diff --git a/include/llmr/renderer/painter.hpp b/include/llmr/renderer/painter.hpp index 44cd3da4d..b79aeb8f9 100644 --- a/include/llmr/renderer/painter.hpp +++ b/include/llmr/renderer/painter.hpp @@ -7,6 +7,7 @@ #include "shader-line.hpp" #include "../map/tile.hpp" +#include "../geometry/vertex_buffer.hpp" #include "../util/mat4.hpp" namespace llmr { @@ -26,12 +27,11 @@ public: // Make noncopyable Painter(const Painter&) = delete; Painter(const Painter&&) = delete; - Painter &operator=(const Painter&) = delete; - Painter &operator=(const Painter&&) = delete; + Painter& operator=(const Painter&) = delete; + Painter& operator=(const Painter && ) = delete; void setup(); - void teardown(); void clear(); void render(const std::shared_ptr& tile); @@ -68,9 +68,41 @@ private: std::shared_ptr outlineShader; std::shared_ptr lineShader; - uint32_t tile_stencil_buffer; - uint32_t tile_border_buffer; - uint32_t matte_buffer; + // Set up the stencil quad we're using to generate the stencil mask. + VertexBuffer tileStencilBuffer = { + // top left triangle + 0, 0, + 4096, 0, + 0, 4096, + + // bottom right triangle + 4096, 0, + 0, 4096, + 4096, 4096 + }; + + // Set up the tile boundary lines we're using to draw the tile outlines. + VertexBuffer tileBorderBuffer = { + 0, 0, + 4096, 0, + 4096, 4096, + 0, 4096, + 0, 0 + }; + + // Set up the matte buffer we're using to draw the filling background. + VertexBuffer matteBuffer = { + // top left triangle + 0, 0, + 16384, 0, + 0, 16384, + + // bottom right triangle + 16384, 0, + 0, 16384, + 16384, 16384 + }; + }; } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 178d4ce5b..0c81c1300 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -2,6 +2,7 @@ SET(llmr_SOURCES geometry/debug_font_buffer.cpp geometry/fill_buffer.cpp geometry/line_buffer.cpp + geometry/vertex_buffer.cpp map/map.cpp map/tile.cpp map/transform.cpp @@ -29,6 +30,7 @@ SET(llmr_HEADERS ../include/llmr/geometry/debug_font_buffer.hpp ../include/llmr/geometry/fill_buffer.hpp ../include/llmr/geometry/line_buffer.hpp + ../include/llmr/geometry/vertex_buffer.hpp ../include/llmr/llmr.hpp ../include/llmr/map/map.hpp ../include/llmr/map/tile.hpp diff --git a/src/geometry/vertex_buffer.cpp b/src/geometry/vertex_buffer.cpp new file mode 100644 index 000000000..b190e31d8 --- /dev/null +++ b/src/geometry/vertex_buffer.cpp @@ -0,0 +1,30 @@ +#include +#include + +using namespace llmr; + + +VertexBuffer::VertexBuffer(std::initializer_list init) : array(init) {} + +VertexBuffer::~VertexBuffer() { + if (buffer != 0) { + glDeleteBuffers(1, &buffer); + buffer = 0; + } +} + +uint32_t VertexBuffer::length() const { + // We store 2 coordinates per vertex + 1 linesofar + 1 extrude coord pair == 4 (== 8 bytes) + return array.size() / 2; +} + +void VertexBuffer::bind() { + if (buffer == 0) { + glGenBuffers(1, &buffer); + glBindBuffer(GL_ARRAY_BUFFER, buffer); + glBufferData(GL_ARRAY_BUFFER, array.size() * sizeof(int16_t), array.data(), GL_STATIC_DRAW); + } else { + glBindBuffer(GL_ARRAY_BUFFER, buffer); + } + +} diff --git a/src/renderer/painter.cpp b/src/renderer/painter.cpp index 6c35db8c3..297fa3d2b 100644 --- a/src/renderer/painter.cpp +++ b/src/renderer/painter.cpp @@ -20,38 +20,6 @@ using namespace llmr; #define BUFFER_OFFSET(i) ((char *)NULL + (i)) -GLshort tile_stencil_vertices[] = { - // top left triangle - 0, 0, - 4096, 0, - 0, 4096, - - // bottom right triangle - 4096, 0, - 0, 4096, - 4096, 4096 -}; - -GLshort tile_border_vertices[] = { - 0, 0, - 4096, 0, - 4096, 4096, - 0, 4096, - 0, 0 -}; - -GLshort matte_vertices[] = { - // top left triangle - 0, 0, - 16384, 0, - 0, 16384, - - // bottom right triangle - 16384, 0, - 0, 16384, - 16384, 16384 -}; - Painter::Painter(Transform& transform, Settings& settings, Style& style) : transform(transform), settings(settings), @@ -68,22 +36,6 @@ void Painter::setup() { assert(outlineShader); assert(lineShader); - // Set up the stencil quad we're using to generate the stencil mask. - glGenBuffers(1, &tile_stencil_buffer); - glBindBuffer(GL_ARRAY_BUFFER, tile_stencil_buffer); - glBufferData(GL_ARRAY_BUFFER, sizeof(tile_stencil_vertices), tile_stencil_vertices, GL_STATIC_DRAW); - - // Set up the tile boundary lines we're using to draw the tile outlines. - glGenBuffers(1, &tile_border_buffer); - glBindBuffer(GL_ARRAY_BUFFER, tile_border_buffer); - glBufferData(GL_ARRAY_BUFFER, sizeof(tile_border_vertices), tile_border_vertices, GL_STATIC_DRAW); - - // Set up the tile boundary lines we're using to draw the tile outlines. - glGenBuffers(1, &matte_buffer); - glBindBuffer(GL_ARRAY_BUFFER, matte_buffer); - glBufferData(GL_ARRAY_BUFFER, sizeof(matte_vertices), matte_vertices, GL_STATIC_DRAW); - - glEnable(GL_STENCIL_TEST); // We are blending the new pixels *behind* the existing pixels. That way we can @@ -99,12 +51,6 @@ void Painter::setupShaders() { lineShader = std::make_shared(); } -void Painter::teardown() { - glDeleteBuffers(1, &tile_stencil_buffer); - glDeleteBuffers(1, &tile_border_buffer); - glDeleteBuffers(1, &matte_buffer); -} - void Painter::changeMatrix(const Tile::Ptr& tile) { // Initialize projection matrix mat4 projMatrix; @@ -148,10 +94,10 @@ void Painter::drawClippingMask() { glStencilOp(GL_REPLACE, GL_KEEP, GL_KEEP); // Draw the clipping mask - glBindBuffer(GL_ARRAY_BUFFER, tile_stencil_buffer); + tileStencilBuffer.bind(); glVertexAttribPointer(plainShader->a_pos, 2, GL_SHORT, false, 0, BUFFER_OFFSET(0)); glUniform4f(plainShader->u_color, 1.0f, 0.0f, 1.0f, 1.0f); - glDrawArrays(GL_TRIANGLES, 0, sizeof(tile_stencil_vertices)); + glDrawArrays(GL_TRIANGLES, 0, tileStencilBuffer.length()); // glEnable(GL_STENCIL_TEST); glStencilFunc(GL_EQUAL, 0x80, 0x80); @@ -329,9 +275,9 @@ void Painter::renderFill(FillBucket& bucket, const std::string& layer_name) { glStencilFunc(GL_NOTEQUAL, 0x0, 0x3F); // Draw a rectangle that covers the entire viewport. - glBindBuffer(GL_ARRAY_BUFFER, tile_stencil_buffer); + tileStencilBuffer.bind(); glVertexAttribPointer(fillShader->a_pos, 2, GL_SHORT, false, 0, BUFFER_OFFSET(0)); - glDrawArrays(GL_TRIANGLES, 0, sizeof(tile_stencil_vertices)); + glDrawArrays(GL_TRIANGLES, 0, tileStencilBuffer.length()); glStencilMask(0x00); glStencilFunc(GL_EQUAL, 0x80, 0x80); @@ -422,11 +368,11 @@ void Painter::renderDebug(const Tile::Ptr& tile) { // draw tile outline switchShader(plainShader); glUniformMatrix4fv(plainShader->u_matrix, 1, GL_FALSE, matrix.data()); - glBindBuffer(GL_ARRAY_BUFFER, tile_border_buffer); + tileBorderBuffer.bind(); glVertexAttribPointer(plainShader->a_pos, 2, GL_SHORT, false, 0, BUFFER_OFFSET(0)); glUniform4f(plainShader->u_color, 1.0f, 1.0f, 1.0f, 1.0f); glLineWidth(4.0f); - glDrawArrays(GL_LINE_STRIP, 0, sizeof(tile_border_vertices)); + glDrawArrays(GL_LINE_STRIP, 0, tileBorderBuffer.length()); // draw debug info switchShader(plainShader); @@ -453,10 +399,10 @@ void Painter::renderMatte() { Color white = {{ 1, 1, 1, 1 }}; // Draw the clipping mask - glBindBuffer(GL_ARRAY_BUFFER, matte_buffer); + matteBuffer.bind(); glVertexAttribPointer(fillShader->a_pos, 2, GL_SHORT, false, 0, BUFFER_OFFSET(0)); glUniform4fv(fillShader->u_color, 1, white.data()); - glDrawArrays(GL_TRIANGLES, 0, sizeof(matte_vertices)); + glDrawArrays(GL_TRIANGLES, 0, matteBuffer.length()); glEnable(GL_STENCIL_TEST); } @@ -468,10 +414,10 @@ void Painter::renderBackground() { Color white = {{ 1, 1, 1, 1 }}; // Draw the clipping mask - glBindBuffer(GL_ARRAY_BUFFER, tile_stencil_buffer); + tileStencilBuffer.bind(); glVertexAttribPointer(fillShader->a_pos, 2, GL_SHORT, false, 0, BUFFER_OFFSET(0)); glUniform4fv(fillShader->u_color, 1, white.data()); - glDrawArrays(GL_TRIANGLES, 0, sizeof(tile_stencil_vertices)); + glDrawArrays(GL_TRIANGLES, 0, tileStencilBuffer.length()); }