#pragma once #include #include namespace Donut { struct VertexBufferElement { uint32_t type; uint32_t count; uint8_t normalized; uint32_t offset; static auto get_size_of_type(uint32_t type) -> uint32_t; }; class VertexBufferLayout { public: VertexBufferLayout() = default; ~VertexBufferLayout() = default; template auto push(uint32_t count) -> void { static_assert(false); } template<> void push(uint32_t count) { m_elements.push_back({ 0x1406, count, 0, m_stride }); // GL_FLOAT m_stride += count * VertexBufferElement::get_size_of_type(0x1406); } template<> void push(uint32_t count) { m_elements.push_back({ 0x1405, count, 0, m_stride }); // GL_UNSIGNED_INT m_stride += count * VertexBufferElement::get_size_of_type(0x1405); } template<> void push(uint32_t count) { m_elements.push_back({ 0x1401, count, 1, m_stride }); // GL_UNSIGNED_BYTE m_stride += count * VertexBufferElement::get_size_of_type(0x1401); } inline auto get_elements() const -> const std::vector& { return m_elements; } inline auto get_stride() const -> uint32_t { return m_stride; } private: std::vector m_elements; uint32_t m_stride = 0; }; class VertexBuffer { public: virtual ~VertexBuffer() = default; virtual auto bind() const -> void = 0; virtual auto unbind() const -> void = 0; virtual auto set_data(const void* data, uint32_t size) -> void = 0; virtual auto get_layout() const -> const VertexBufferLayout& = 0; virtual auto set_layout(const VertexBufferLayout& layout) -> void = 0; static auto create(const void* data, uint32_t size) -> VertexBuffer*; }; };