diff --git a/include/blt/gfx/model.h b/include/blt/gfx/model.h index e4f2962..e2a4e18 100644 --- a/include/blt/gfx/model.h +++ b/include/blt/gfx/model.h @@ -24,6 +24,7 @@ #include #include #include +#include namespace blt::gfx { @@ -40,16 +41,18 @@ namespace blt::gfx { GLuint bufferID_ = 0; GLsizeiptr size_ = 0; + GLint buffer_type; + GLint memory_type; - void create(); + void create(GLint type); - void bind(GLint buffer_type = GL_ARRAY_BUFFER) const; + void bind() const; - void allocate(GLsizeiptr size, GLint buffer_type = GL_ARRAY_BUFFER, GLint memory_type = GL_STATIC_DRAW, void* data = nullptr); + void allocate(GLsizeiptr size, GLint memory_type = GL_STATIC_DRAW, void* data = nullptr); - static void sub_update(GLsizeiptr offset, GLsizeiptr size, void* data, GLint buffer_type = GL_ARRAY_BUFFER); + void sub_update(GLsizeiptr offset, GLsizeiptr size, void* data); - void update(GLsizeiptr size, void* data, GLint buffer_type = GL_ARRAY_BUFFER, GLint memory_type = GL_STATIC_DRAW); + void update(GLsizeiptr size, void* data); void destroy(); }; @@ -68,6 +71,7 @@ namespace blt::gfx size_t max = 0; void swap(); + public: static_dynamic_array(); @@ -79,18 +83,10 @@ namespace blt::gfx static_dynamic_array& operator=(static_dynamic_array&& move) noexcept = default; - vbo_t& operator[](size_t index) - { - if (index >= size_) - swap(); - max = std::max(index, max); - if (std::holds_alternative(data_)) - return std::get(data_)[index]; - else - return std::get(data_)[index]; - } + vbo_t& operator[](size_t index); - [[nodiscard]] size_t used() const noexcept { + [[nodiscard]] inline size_t used() const noexcept + { return max; } @@ -107,12 +103,47 @@ namespace blt::gfx class basic_vertex_array { private: - - GLuint vaoID; static_dynamic_array VBOs; + HASHSET used_attributes; + vbo_t element; public: basic_vertex_array(); + + basic_vertex_array(const basic_vertex_array&) = delete; + + basic_vertex_array(basic_vertex_array&&) = delete; + + basic_vertex_array& operator=(const basic_vertex_array&) = delete; + + basic_vertex_array& operator=(basic_vertex_array&&) = delete; + + /** + * This function takes ownership of the underlying VBO (GPU side). It will be freed when the basic vertex array is deleted + * @param vbo vbo to bind to this attribute + * @param attribute_number attribute number to bind to + * @param coordinate_size size of the data (number of + * @param type type of data + * @param stride how many bytes this data takes (for the entire per-vertex data structure) 0 will assume packed data + * @param offset offset into the data structure to where the data is stored + */ + void bindVBO(const vbo_t& vbo, int attribute_number, int coordinate_size, GLenum type, int stride, long offset); + + /** + * Returns a non-owning reference to a vbo allowing for updating the VBO + * The VBO is considered invalid if its ID is 0 + */ + inline vbo_t& operator[](size_t index) + { + return VBOs[index]; + } + + inline void bind() + { + glBindVertexArray(vaoID); + } + + ~basic_vertex_array(); }; } diff --git a/libraries/BLT b/libraries/BLT index b135e5b..5ae17f4 160000 --- a/libraries/BLT +++ b/libraries/BLT @@ -1 +1 @@ -Subproject commit b135e5b915e0efaae2f8d9dc30d4752726b74bb4 +Subproject commit 5ae17f4a86a021fb914f0c17b116dc511e5f3f93 diff --git a/src/blt/gfx/model.cpp b/src/blt/gfx/model.cpp index d53f53b..75d19c0 100644 --- a/src/blt/gfx/model.cpp +++ b/src/blt/gfx/model.cpp @@ -45,14 +45,26 @@ namespace blt::gfx std::memset(ptr.data(), 0, DATA_SIZE); } + vbo_t& static_dynamic_array::operator[](size_t index) + { + if (index >= size_) + swap(); + max = std::max(index, max); + if (std::holds_alternative(data_)) + return std::get(data_)[index]; + else + return std::get(data_)[index]; + } + /* * ----------------------------------- * vbo_t * ----------------------------------- */ - void vbo_t::create() + void vbo_t::create(GLint type) { glGenBuffers(1, &bufferID_); + buffer_type = type; } void vbo_t::destroy() @@ -60,27 +72,28 @@ namespace blt::gfx glDeleteBuffers(1, &bufferID_); } - void vbo_t::allocate(GLsizeiptr size, GLint buffer_type, GLint memory_type, void* data) + void vbo_t::allocate(GLsizeiptr size, GLint mem_type, void* data) { size_ = size; - glBufferData(buffer_type, size, data, memory_type); + glBufferData(buffer_type, size, data, mem_type); + memory_type = mem_type; } - void vbo_t::update(GLsizeiptr size, void* data, GLint buffer_type, GLint memory_type) + void vbo_t::update(GLsizeiptr size, void* data) { if (size <= size_) - sub_update(0, size, data, buffer_type); + sub_update(0, size, data); else - allocate(size, buffer_type, memory_type, data); + allocate(size, memory_type, data); size_ = size; } - void vbo_t::sub_update(GLsizeiptr offset, GLsizeiptr size, void* data, GLint buffer_type) + void vbo_t::sub_update(GLsizeiptr offset, GLsizeiptr size, void* data) { glBufferSubData(buffer_type, offset, size, data); } - void vbo_t::bind(GLint buffer_type) const + void vbo_t::bind() const { glBindBuffer(buffer_type, bufferID_); } @@ -95,4 +108,28 @@ namespace blt::gfx { glGenVertexArrays(1, &vaoID); } + + basic_vertex_array::~basic_vertex_array() + { + // free all VBOs + for (size_t i = 0; i < VBOs.used(); i++) + if (VBOs[i].bufferID_) + VBOs[i].destroy(); + // then free the vertex array + glDeleteVertexArrays(1, &vaoID); + } + + void basic_vertex_array::bindVBO(const vbo_t& vbo, int attribute_number, int coordinate_size, GLenum type, int stride, long offset) + { + used_attributes.insert(attribute_number); + bind(); + vbo.bind(); + + glVertexAttribPointer( + attribute_number, coordinate_size, type, GL_FALSE, stride < 0 ? 0 : stride, (void*) offset + ); + glEnableVertexAttribArray(attribute_number); + + VBOs[attribute_number] = vbo; + } } \ No newline at end of file