vbo and vao

main
Brett 2025-06-10 22:04:27 -04:00
parent b1bf0a58f6
commit 67785f465e
6 changed files with 88 additions and 23 deletions

View File

@ -283,11 +283,8 @@
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_CAST_EXPRESSION_PARENTHESES/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/TOPLEVEL_FUNCTION_DECLARATION_RETURN_TYPE_STYLE/@EntryValue" value="ON_SINGLE_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/TOPLEVEL_FUNCTION_DEFINITION_RETURN_TYPE_STYLE/@EntryValue" value="ON_SINGLE_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BRACED_INIT_LIST_STYLE/@EntryValue" value="CHOP_IF_LONG" type="string" />
<option name="/Default/CodeStyle/CppIncludeDirective/SortIncludeDirectives/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CppIncludeDirective/UseAngleBracketsInsteadOfQuotes/@EntryValue" value="WhenPossible" type="string" />
<option name="/Default/CodeStyle/CppIncludeDirective/UseRelativePaths/@EntryValue" value="Never" type="string" />
<option name="/Default/CodeStyle/Generate/=CppDefinitions/@KeyIndexDefined" value="true" type="bool" />
<option name="/Default/CodeStyle/Generate/=CppDefinitions/Options/=GenerateInlineDefinitions/@EntryIndexedValue" value="False" type="string" />
</component>
</project>

View File

@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.25)
project(gpu-particles VERSION 0.0.12)
project(gpu-particles VERSION 0.0.13)
option(ENABLE_ADDRSAN "Enable the address sanitizer" OFF)
option(ENABLE_UBSAN "Enable the ub sanitizer" OFF)

View File

@ -32,7 +32,7 @@ namespace blt::gfx
struct vao_vbo_storage_t
{
std::unique_ptr<unique_vbo_t> vbo;
u32 attribute_number = 0;
std::optional<std::vector<u32>> attribute_numbers;
[[nodiscard]] bool is_element() const
{
@ -47,21 +47,55 @@ namespace blt::gfx
{
friend class vao_context_t;
public:
vao_vbo_context_t(const vao_vbo_context_t& copy) = delete;
vao_vbo_context_t(vao_vbo_context_t&& move) = delete;
vao_vbo_context_t& operator=(const vao_vbo_context_t& copy) = delete;
vao_vbo_context_t& operator=(vao_vbo_context_t&& move) = delete;
/**
* This function takes ownership of the underlying VBO (GPU side). It will be freed when the basic vertex array is deleted
* @param attribute_number attribute number to bind to
* @param coordinate_size size of the data (number of elements, not the number of bytes)
* @param type GL_TYPE type of data
* @param stride how many bytes this data takes (for the entire per-vertex data structure) 0 will assume packed data
* This is in effect how many bytes until the next block of data
* @param offset offset into the data structure to where the data is stored
*/
vao_vbo_context_t& attribute_ptr(int attribute_number, int coordinate_size, GLenum type, int stride, long offset);
vao_vbo_context_t& silence()
{
attributed = true;
return *this;
}
/**
* Useless function, but if it makes you feel better, feel free to use it.
*/
vao_vbo_context_t& as_element()
{
return *this;
}
~vao_vbo_context_t();
private:
vao_vbo_context_t(unique_vao_t& vao, vao_vbo_storage_t& vbo): vbo(vbo), vao(vao)
{}
vao_vbo_storage_t& vbo;
unique_vao_t& vao;
bool attributed = false;
};
class vao_context_t
{
friend vao_vbo_context_t;
friend class unique_vao_t;
friend unique_vao_t;
public:
vao_context_t(const vao_context_t& copy) = delete;
vao_context_t(vao_context_t&& move) = delete;
vao_context_t& operator=(const vao_context_t& copy) = delete;
vao_context_t& operator=(vao_context_t&& move) = delete;
vao_context_t& bind();
vao_context_t& unbind();

View File

@ -38,6 +38,10 @@ namespace blt::gfx
{
friend unique_vbo_t;
public:
vbo_context_t(const vbo_context_t& copy) = delete;
vbo_context_t(vbo_context_t&& move) = delete;
vbo_context_t& operator=(const vbo_context_t& copy) = delete;
vbo_context_t& operator=(vbo_context_t&& move) = delete;
/**
* By default, the VBO is bound when this class is constructed (this class should only be constructed through the VBO bind() method)
*

View File

@ -24,7 +24,6 @@
#include <shaders/particle.frag>
#include <shaders/particle.vert>
#include <imgui.h>
#include <blt/std/ranges.h>
constexpr blt::size_t PARTICLE_COUNT = 8192;
@ -48,9 +47,7 @@ struct particle_t
}
};
std::unique_ptr<blt::gfx::vertex_array_t> particle_vao;
std::unique_ptr<blt::gfx::vertex_buffer_t> particle_vbo;
std::unique_ptr<blt::gfx::element_buffer_t> alive_particles_ebo;
std::optional<blt::gfx::unique_vao_t> particle_vao;
std::unique_ptr<blt::gfx::shader_t> particle_shader;
std::vector<blt::u32> alive_particles;
@ -69,17 +66,16 @@ void init(const blt::gfx::window_data&)
alive_particles.push_back(i);
}
particle_vbo = std::make_unique<vertex_buffer_t>();
particle_vbo->create(GL_ARRAY_BUFFER);
particle_vbo->allocate(sizeof(particle_t) * particles.size(), GL_DYNAMIC_DRAW, particles.data());
unique_vbo_t particle_vbo(GL_ARRAY_BUFFER);
particle_vbo.bind().upload(sizeof(particle_t) * particles.size(), particles.data(), GL_DYNAMIC_DRAW);
alive_particles_ebo = std::make_unique<element_buffer_t>();
alive_particles_ebo->create();
alive_particles_ebo->allocate(sizeof(blt::u32) * alive_particles.size(), GL_DYNAMIC_DRAW, alive_particles.data());
unique_ebo_t alive_particles_ebo;
alive_particles_ebo.bind().upload(sizeof(blt::u32) * alive_particles.size(), alive_particles.data(), GL_DYNAMIC_DRAW);
particle_vao = std::make_unique<vertex_array_t>();
particle_vao->bindVBO(*particle_vbo, 0, 2, GL_FLOAT, sizeof(particle_t), 0);
particle_vao->bindElement(*alive_particles_ebo);
particle_vao = unique_vao_t();
const auto vao_ctx = particle_vao->bind();
vao_ctx.attach_vbo(std::move(particle_vbo)).attribute_ptr(0, 2, GL_FLOAT, sizeof(particle_t), 0);
vao_ctx.attach_vbo(std::move(alive_particles_ebo));
global_matrices.create_internals();
resources.load_resources();
@ -99,6 +95,8 @@ void update(const blt::gfx::window_data& data)
void destroy(const blt::gfx::window_data&)
{
particle_vao.reset();
particle_shader.reset();
global_matrices.cleanup();
resources.cleanup();
renderer_2d.cleanup();

View File

@ -22,14 +22,45 @@
namespace blt::gfx
{
#define BLT_DEBUG_LEVEL BLT_DEBUG_CONTRACTS
#define ENSURE_CONTEXT_BOUND BLT_CONTRACT(glfwGetCurrentContext() != nullptr, "Expected active OpenGL context!")
#if blt_debug_has_flag(BLT_DEBUG_CONTRACTS)
GLuint bound_vao_id;
GLuint bound_vao_id;
#endif
detail::vao_vbo_context_t& detail::vao_vbo_context_t::attribute_ptr(const int attribute_number, const int coordinate_size, const GLenum type,
const int stride, const long offset)
{
if (auto& vec = vbo.attribute_numbers)
{
for (const auto& v : *vec)
{
if (static_cast<i32>(v) == attribute_number)
goto use;
}
vec->push_back(attribute_number);
}
use:
glEnableVertexAttribArray(attribute_number);
glVertexAttribPointer(attribute_number, coordinate_size, type, GL_FALSE, stride < 0 ? 0 : stride, reinterpret_cast<void*>(offset));
attributed = true;
return *this;
}
detail::vao_vbo_context_t::~vao_vbo_context_t()
{
#if blt_debug_has_flag(BLT_DEBUG_CONTRACTS)
if (!(vbo.is_element() || attributed))
{
BLT_WARN("VBO is not an element array buffer or been assigned to an attribute, are you sure this is what you want?");
BLT_WARN("You can silence this warning by calling .silence()");
}
#endif
}
detail::vao_context_t& detail::vao_context_t::bind()
{
ENSURE_CONTEXT_BOUND;
BLT_CONTRACT(vao.vaoID, "Expected VAO to have an associated VAO ID!");
glBindVertexArray(*vao.vaoID);
bound_vao_id = *vao.vaoID;
@ -45,6 +76,7 @@ namespace blt::gfx
detail::vao_vbo_context_t detail::vao_context_t::attach_vbo(unique_vbo_t&& vbo) const
{
ENSURE_CONTEXT_BOUND;
BLT_CONTRACT(vao.vaoID, "Expected VAO to have an associated VAO ID!");
BLT_CONTRACT(is_bound(), "Expected VAO to be bound before attaching VBO! (If you are using this API correctly, this has been done for you!)");
@ -60,7 +92,7 @@ namespace blt::gfx
detail::vao_context_t unique_vao_t::bind()
{
BLT_CONTRACT(glfwGetCurrentContext() != nullptr, "Expected active OpenGL context!");
ENSURE_CONTEXT_BOUND;
return detail::vao_context_t{*this};
}
}