diff --git a/.idea/editor.xml b/.idea/editor.xml
index 907ea1b..5bf27ce 100644
--- a/.idea/editor.xml
+++ b/.idea/editor.xml
@@ -283,11 +283,8 @@
-
-
-
\ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a0943e0..a12bd91 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.25)
-project(gpu-particles VERSION 0.0.9)
+project(gpu-particles VERSION 0.0.10)
option(ENABLE_ADDRSAN "Enable the address sanitizer" OFF)
option(ENABLE_UBSAN "Enable the ub sanitizer" OFF)
diff --git a/include/vao.h b/include/vao.h
new file mode 100644
index 0000000..3f249aa
--- /dev/null
+++ b/include/vao.h
@@ -0,0 +1,60 @@
+#pragma once
+/*
+ * Copyright (C) 2024 Brett Terpstra
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifndef BLT_GFX_VAO_H
+#define BLT_GFX_VAO_H
+
+#include
+
+namespace blt::gfx
+{
+
+ class unique_vao_t
+ {
+ public:
+ unique_vao_t(): vaoID(0)
+ {
+ glGenVertexArrays(1, &*vaoID);
+ }
+
+ unique_vao_t(const unique_vao_t&) = delete;
+
+ unique_vao_t& operator=(const unique_vao_t&) = delete;
+
+ unique_vao_t(unique_vao_t&& other) noexcept: vaoID(std::exchange(other.vaoID, std::nullopt))
+ {}
+
+ unique_vao_t& operator=(unique_vao_t&& other) noexcept
+ {
+ vaoID = std::exchange(other.vaoID, vaoID);
+ return *this;
+ }
+
+ ~unique_vao_t()
+ {
+ if (vaoID)
+ glDeleteVertexArrays(1, &*vaoID);
+ }
+
+ private:
+ std::optional vaoID;
+ };
+
+}
+
+#endif //BLT_GFX_VAO_H
diff --git a/include/vbo.h b/include/vbo.h
new file mode 100644
index 0000000..b7dcfa1
--- /dev/null
+++ b/include/vbo.h
@@ -0,0 +1,147 @@
+#pragma once
+/*
+ * Copyright (C) 2024 Brett Terpstra
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifndef BLT_GFX_VBO_H
+#define BLT_GFX_VBO_H
+
+#include
+#include
+#include
+#include
+
+namespace blt::gfx
+{
+ class unique_vbo_t;
+
+ namespace detail
+ {
+ class vbo_context_t
+ {
+ public:
+ explicit vbo_context_t(unique_vbo_t& vbo): vbo(vbo)
+ {
+ bind();
+ }
+
+ /**
+ * By default, the VBO is bound when this class is constructed (this class should only be constructed through the VBO bind() method)
+ *
+ * It is very unlikely that you need this method!
+ */
+ vbo_context_t& bind();
+
+ vbo_context_t& unbind();
+
+ vbo_context_t& reserve(GLsizeiptr size, GLint mem_type);
+
+ vbo_context_t& reserve(const size_t size, const GLint mem_type)
+ {
+ return reserve(static_cast(size), mem_type);
+ }
+
+ vbo_context_t& upload(size_t size, void* ptr, GLint mem_type);
+
+ template
+ vbo_context_t& upload(const size_t size, T* ptr, const GLint mem_type)
+ {
+ return upload(size, static_cast(ptr), mem_type);
+ }
+
+ vbo_context_t& update(size_t offset, size_t size, const void* ptr);
+
+ template
+ vbo_context_t& update(size_t offset, const size_t size, T* ptr)
+ {
+ return upload(offset, size, static_cast(ptr));
+ }
+
+ private:
+ unique_vbo_t& vbo;
+ };
+ }
+
+ class unique_vbo_t
+ {
+ friend class detail::vbo_context_t;
+
+ public:
+ explicit unique_vbo_t(const GLuint type): buffer_type(type)
+ {
+ glGenBuffers(1, &*vboID);
+ }
+
+ unique_vbo_t(const unique_vbo_t&) = delete;
+
+ unique_vbo_t& operator=(const unique_vbo_t&) = delete;
+
+ unique_vbo_t(unique_vbo_t&& other) noexcept: vboID(std::exchange(other.vboID, std::nullopt)), buffer_type(other.buffer_type),
+ size(other.size), memory_type(other.memory_type)
+ {}
+
+ unique_vbo_t& operator=(unique_vbo_t&& other) noexcept
+ {
+ vboID = std::exchange(other.vboID, vboID);
+ buffer_type = std::exchange(other.buffer_type, buffer_type);
+ size = std::exchange(other.size, size);
+ memory_type = std::exchange(other.memory_type, memory_type);
+ return *this;
+ }
+
+ GLuint change_type(const GLuint type)
+ {
+ return std::exchange(this->buffer_type, type);
+ }
+
+ [[nodiscard]] auto bind();
+
+ ~unique_vbo_t()
+ {
+ if (vboID)
+ glDeleteBuffers(1, &*vboID);
+ }
+
+ private:
+ std::optional vboID;
+ GLuint buffer_type;
+ GLsizeiptr size = 0;
+ GLint memory_type = 0;
+ };
+
+ class unique_ssbo_t : public unique_vbo_t
+ {
+ public:
+ unique_ssbo_t(): unique_vbo_t{GL_SHADER_STORAGE_BUFFER}
+ {}
+ };
+
+ class unique_ebo_t : public unique_vbo_t
+ {
+ public:
+ unique_ebo_t(): unique_vbo_t{GL_ELEMENT_ARRAY_BUFFER}
+ {}
+ };
+
+ class unique_ubo_t : public unique_vbo_t
+ {
+ public:
+ unique_ubo_t(): unique_vbo_t{GL_UNIFORM_BUFFER}
+ {}
+ };
+}
+
+#endif //BLT_GFX_VBO_H
diff --git a/src/main.cpp b/src/main.cpp
index 4d37469..ff36a8a 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -19,7 +19,8 @@
#include "blt/gfx/renderer/batch_2d_renderer.h"
#include "blt/gfx/renderer/camera.h"
#include
-#include
+#include
+#include
#include
#include
#include
@@ -34,122 +35,6 @@ blt::gfx::first_person_camera camera;
// use types for state that way you are not confused about what is happening?
-class unique_vbo_t;
-
-namespace detail
-{
- class vbo_context_t
- {
- public:
- explicit vbo_context_t(unique_vbo_t& vbo): vbo(vbo)
- {
- bind();
- }
-
- /**
- * By default, the VBO is bound when this class is constructed (this class should only be constructed through the VBO bind() method)
- * This function is provided in case you need to rebind the VBO
- */
- vbo_context_t& bind();
-
- vbo_context_t& unbind();
-
- private:
- unique_vbo_t& vbo;
- };
-}
-
-class unique_vbo_t
-{
- friend class detail::vbo_context_t;
-
-public:
- explicit unique_vbo_t(const GLuint type): type(type)
- {
- glGenBuffers(1, &*vboID);
- }
-
- unique_vbo_t(const unique_vbo_t&) = delete;
-
- unique_vbo_t& operator=(const unique_vbo_t&) = delete;
-
- unique_vbo_t(unique_vbo_t&& other) noexcept: vboID(std::exchange(other.vboID, std::nullopt)), type(other.type)
- {}
-
- unique_vbo_t& operator=(unique_vbo_t&& other) noexcept
- {
- vboID = std::exchange(other.vboID, vboID);
- type = std::exchange(other.type, type);
- return *this;
- }
-
- GLuint change_type(const GLuint type)
- {
- return std::exchange(this->type, type);
- }
-
- [[nodiscard]] auto bind()
- {
- return detail::vbo_context_t{*this};
- }
-
- ~unique_vbo_t()
- {
- if (vboID)
- glDeleteBuffers(1, &*vboID);
- }
-
-private:
- std::optional vboID;
- GLuint type;
-};
-
-namespace detail
-{
- vbo_context_t& vbo_context_t::bind()
- {
- glBindBuffer(vbo.type, *vbo.vboID);
- return *this;
- }
-
- vbo_context_t& vbo_context_t::unbind()
- {
- glBindBuffer(vbo.type, 0);
- return *this;
- }
-}
-
-class unique_vao_t
-{
-public:
- unique_vao_t(): vaoID(0)
- {
- glGenVertexArrays(1, &*vaoID);
- }
-
- unique_vao_t(const unique_vao_t&) = delete;
-
- unique_vao_t& operator=(const unique_vao_t&) = delete;
-
- unique_vao_t(unique_vao_t&& other) noexcept: vaoID(std::exchange(other.vaoID, std::nullopt))
- {}
-
- unique_vao_t& operator=(unique_vao_t&& other) noexcept
- {
- vaoID = std::exchange(other.vaoID, vaoID);
- return *this;
- }
-
- ~unique_vao_t()
- {
- if (vaoID)
- glDeleteVertexArrays(1, &*vaoID);
- }
-
-private:
- std::optional vaoID;
-};
-
struct particle_t
{
blt::vec2 position;
diff --git a/src/vao.cpp b/src/vao.cpp
new file mode 100644
index 0000000..931cdeb
--- /dev/null
+++ b/src/vao.cpp
@@ -0,0 +1,23 @@
+/*
+ *
+ * Copyright (C) 2025 Brett Terpstra
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+#include
+
+namespace blt::gfx
+{
+
+}
\ No newline at end of file
diff --git a/src/vbo.cpp b/src/vbo.cpp
new file mode 100644
index 0000000..92c9822
--- /dev/null
+++ b/src/vbo.cpp
@@ -0,0 +1,73 @@
+/*
+ *
+ * Copyright (C) 2025 Brett Terpstra
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+#include
+#include
+#include
+
+namespace blt::gfx
+{
+ namespace detail
+ {
+ vbo_context_t& vbo_context_t::bind()
+ {
+ BLT_CONTRACT(vbo.vboID, "Expected VBO to have an assoicated VBO ID!");
+ glBindBuffer(vbo.type, *vbo.vboID);
+ return *this;
+ }
+
+ vbo_context_t& vbo_context_t::unbind()
+ {
+ glBindBuffer(vbo.type, 0);
+ return *this;
+ }
+
+ vbo_context_t& vbo_context_t::reserve(const GLsizeiptr size, const GLint mem_type)
+ {
+ vbo.size = size;
+ vbo.memory_type = mem_type;
+ glBufferData(vbo.buffer_type, size, nullptr, mem_type);
+ return *this;
+ }
+
+ vbo_context_t& vbo_context_t::upload(const size_t size, void* ptr, const GLint mem_type)
+ {
+ if (mem_type != vbo.memory_type || vbo.size < size)
+ {
+ vbo.size = static_cast(size);
+ vbo.memory_type = mem_type;
+ glBufferData(vbo.buffer_type, vbo.size, ptr, mem_type);
+ } else
+ {
+ update(0, size, ptr);
+ }
+ return *this;
+ }
+
+ vbo_context_t& vbo_context_t::update(const size_t offset, const size_t size, const void* ptr)
+ {
+ glBufferSubData(vbo.buffer_type, static_cast(offset), static_cast(size), ptr);
+ return *this;
+ }
+ }
+
+ auto unique_vbo_t::bind()
+ {
+ BLT_CONTRACT(glfwGetCurrentContext() != nullptr, "Expected active OpenGL context!");
+ return detail::vbo_context_t{*this};
+ }
+}