StapleGL
Header-only C++20 OpenGL wrapper
Loading...
Searching...
No Matches
vertex_buffer.hpp
Go to the documentation of this file.
1
23#pragma once
24#include "gl_functions.hpp"
26#include <concepts>
27#include <functional>
28#include <span>
29#include <utility>
30
31namespace staplegl {
32
38template <typename T>
39concept plain_old_data = std::is_standard_layout_v<T> && std::is_trivial_v<T>;
40
52 STATIC_DRAW = GL_STATIC_DRAW,
53 DYNAMIC_DRAW = GL_DYNAMIC_DRAW,
54 STREAM_DRAW = GL_STREAM_DRAW
55};
56
65 READ_ONLY = GL_READ_ONLY,
66 WRITE_ONLY = GL_WRITE_ONLY,
67 READ_WRITE = GL_READ_WRITE
68};
69
80public:
90 vertex_buffer(std::span<const float> vertices) noexcept;
91 vertex_buffer(std::span<const float> vertices, driver_draw_hint hint) noexcept;
92 vertex_buffer(std::span<const float> vertices, vertex_buffer_layout&& layout) noexcept;
93 vertex_buffer(std::span<const float> vertices, vertex_buffer_layout&& layout,
94 driver_draw_hint hint) noexcept;
96
97 // delete copy and assignment, only move is allowed
98 vertex_buffer(const vertex_buffer&) = delete;
99 auto operator=(const vertex_buffer&) -> vertex_buffer& = delete;
100
101 vertex_buffer(vertex_buffer&& other) noexcept;
102 auto operator=(vertex_buffer&& other) noexcept -> vertex_buffer&;
103
108 void bind() const;
109
114 static void unbind();
115
123 [[nodiscard]] constexpr auto layout() const -> const vertex_buffer_layout&;
124
130 void set_data(std::span<const float> vertices) const noexcept;
131
140 void set_data(std::span<const float> vertices, driver_draw_hint hint) const noexcept;
141
142 // UTILITIES
143
149 [[nodiscard]] constexpr auto id() const noexcept -> std::uint32_t { return m_id; }
150
157 [[nodiscard]] constexpr auto size() const noexcept -> std::size_t { return m_size; }
158
164 [[nodiscard]] constexpr auto draw_hint() const noexcept -> driver_draw_hint { return m_hint; }
165
171 [[nodiscard]] constexpr auto size_bytes() const noexcept -> std::size_t { return m_size * m_layout.stride(); }
172
173 // APPLY FUNCTION
174
195 template <plain_old_data T>
196 void apply(const std::function<void(std::span<T> vertices)>& func, driver_access_specifier access_specifier = staplegl::READ_WRITE) noexcept;
197
198protected:
199 std::uint32_t m_id {};
202 std::size_t m_size {};
203};
204
205/*
206
207 IMPLEMENTATIONS
208
209*/
210
211inline vertex_buffer::vertex_buffer(std::span<const float> vertices, vertex_buffer_layout&& layout,
212 driver_draw_hint hint) noexcept
213 : m_hint(hint)
214 , m_layout(std::move(layout))
215 , m_size((m_layout.stride()) ? vertices.size_bytes() / m_layout.stride() : static_cast<size_t>(0))
216{
217 glGenBuffers(1, &m_id);
218 glBindBuffer(GL_ARRAY_BUFFER, m_id);
219 glBufferData(GL_ARRAY_BUFFER, static_cast<ptrdiff_t>(vertices.size_bytes()), vertices.data(), hint);
220}
221
222inline vertex_buffer::vertex_buffer(std::span<const float> vertices, driver_draw_hint hint) noexcept
223 : vertex_buffer(vertices, vertex_buffer_layout {}, hint)
224{
225}
226
227inline vertex_buffer::vertex_buffer(std::span<const float> vertices, vertex_buffer_layout&& layout) noexcept
228 : vertex_buffer(vertices, std::move(layout), driver_draw_hint::STATIC_DRAW)
229{
230}
231
232inline vertex_buffer::vertex_buffer(std::span<const float> vertices) noexcept
234{
235}
236
238{
239 if (m_id != 0) {
240 glDeleteBuffers(1, &m_id);
241 }
242}
243
245 : m_id { other.m_id }
246 , m_hint { other.m_hint }
247 , m_layout { std::move(other.m_layout) }
248 , m_size { other.m_size }
249{
250 other.m_id = 0;
251}
252
253inline auto vertex_buffer::operator=(vertex_buffer&& other) noexcept -> vertex_buffer&
254{
255 if (this != &other) {
256 glDeleteBuffers(1, &m_id);
257 m_id = other.m_id;
258 m_layout = other.m_layout;
259 m_hint = other.m_hint;
260 m_size = other.m_size;
261
262 other.m_id = 0;
263 }
264
265 return *this;
266}
267
268inline void vertex_buffer::bind() const
269{
270 glBindBuffer(GL_ARRAY_BUFFER, m_id);
271}
272
274{
275 glBindBuffer(GL_ARRAY_BUFFER, 0);
276}
277
279{
281}
282
283[[nodiscard]] constexpr auto vertex_buffer::layout() const -> const vertex_buffer_layout&
284{
285 return m_layout;
286}
287
288inline void vertex_buffer::set_data(std::span<const float> vertices) const noexcept
289{
290
291 this->set_data(vertices, m_hint);
292}
293
294inline void vertex_buffer::set_data(std::span<const float> vertices, driver_draw_hint hint) const noexcept
295{
296 glBindBuffer(GL_ARRAY_BUFFER, m_id);
297 glBufferData(GL_ARRAY_BUFFER, static_cast<ptrdiff_t>(vertices.size_bytes()), vertices.data(), hint);
298}
299
300template <plain_old_data T>
301void vertex_buffer::apply(const std::function<void(std::span<T> vertices)>& func, driver_access_specifier access_specifier) noexcept
302{
303 glBindBuffer(GL_ARRAY_BUFFER, m_id);
304
305 func(std::span { reinterpret_cast<T*>(glMapBuffer(GL_ARRAY_BUFFER, access_specifier)), // NOLINT (reinterpret-cast)
306 m_size });
307
308 glUnmapBuffer(GL_ARRAY_BUFFER);
309}
310
311} // namespace staplegl
constexpr auto stride() const noexcept -> std::size_t
Get the stride of the vertex buffer layout.
Vertex Buffer Object (VBO) wrapper.
constexpr auto layout() const -> const vertex_buffer_layout &
vertex_buffer_layout m_layout
constexpr auto draw_hint() const noexcept -> driver_draw_hint
Return the driver draw hint of the vertex buffer object.
vertex_buffer(const vertex_buffer &)=delete
void set_layout(const vertex_buffer_layout &layout)
Set the layout object.
staplegl::driver_draw_hint m_hint
auto operator=(const vertex_buffer &) -> vertex_buffer &=delete
void apply(const std::function< void(std::span< T > vertices)> &func, driver_access_specifier access_specifier=staplegl::READ_WRITE) noexcept
Applies a function to the vertices of the vertex buffer object.
void bind() const
Bind the vertex buffer object.
static void unbind()
Unbind the vertex buffer object.
vertex_buffer(std::span< const float > vertices) noexcept
Construct a new vertex buffer object.
constexpr auto size_bytes() const noexcept -> std::size_t
Get the size of the vertex buffer object in bytes.
constexpr auto size() const noexcept -> std::size_t
Get the number of vertices in the vertex buffer object.
void set_data(std::span< const float > vertices) const noexcept
Give new data to the vertex buffer object, overwriting the old one.
Concept that specifies that a type is a Plain Old Data (POD) type.
Loads OpenGL functions.
driver_draw_hint
Enum that specifies the usage hint of a buffer.
driver_access_specifier
Enum that specifies the access specifier of a buffer.
Vertex Buffer Layout abstraction.