StapleGL
Header-only C++20 OpenGL wrapper
Loading...
Searching...
No Matches
uniform_buffer.hpp
Go to the documentation of this file.
1
17#pragma once
18
19#include "gl_functions.hpp"
21
22#include <span>
23#include <string_view>
24#include <unordered_map>
25#include <utility>
26
27namespace staplegl {
28
34
35public:
47 uniform_buffer(std::span<const float> contents, vertex_buffer_layout layout, int32_t binding_point) noexcept;
48
60
62 auto operator=(const uniform_buffer&) -> uniform_buffer& = delete;
63
72 uniform_buffer(uniform_buffer&& other) noexcept;
73
80 [[nodiscard]] auto operator=(uniform_buffer&& other) noexcept -> uniform_buffer&;
81
86 void bind() const;
87
92 static void unbind();
93
102 void set_attribute_data(std::span<const float> uniform_data, const std::string& name);
103
114 void set_attribute_data(std::span<const float> uniform_data, const std::string& name, std::size_t offset);
115
116 void set_attribute_data(std::span<const float> uniform_data,
117 size_t attribute_index);
118
119 void set_attribute_data(std::span<const float> uniform_data,
120 size_t attribute_index,
121 std::size_t offset);
122
124
125 // UTILITIES
126
132 constexpr auto binding_point() const noexcept -> int32_t { return m_binding_point; }
133
139 constexpr auto id() const noexcept -> uint32_t { return m_id; }
140
146 [[nodiscard]] constexpr auto layout() const noexcept -> vertex_buffer_layout const& { return m_layout; }
147
148private:
149 using attr_ref = std::reference_wrapper<const vertex_attribute>;
150
151 std::uint32_t m_id {};
152 int32_t m_binding_point {};
153 std::unordered_map<std::string_view, attr_ref> m_attr_cache;
155
156}; // class uniform_buffer
157
158inline uniform_buffer::uniform_buffer(std::span<const float> contents, vertex_buffer_layout layout, int32_t binding_point) noexcept
159 : m_binding_point { binding_point }
160 , m_layout { std::move(layout) }
161{
162 glGenBuffers(1, &m_id);
163 glBindBuffer(GL_UNIFORM_BUFFER, m_id);
164 glBufferData(GL_UNIFORM_BUFFER,
165 static_cast<ptrdiff_t>(contents.size_bytes()),
166 contents.data(),
167 GL_DYNAMIC_DRAW);
168 glBindBufferBase(GL_UNIFORM_BUFFER, m_binding_point, m_id);
169
170 glBindBuffer(GL_UNIFORM_BUFFER, 0);
171
172 // fill up the uniform attribute cache
173 for (auto const& attr : m_layout.get_attributes()) {
174 m_attr_cache.emplace(attr.name, std::cref(attr));
175 }
176}
177
178inline uniform_buffer::uniform_buffer(vertex_buffer_layout const& layout, int32_t binding_point) noexcept
179 : m_binding_point { binding_point }
180 , m_layout { layout }
181{
182 glGenBuffers(1, &m_id);
183 glBindBuffer(GL_UNIFORM_BUFFER, m_id);
184 glBufferData(GL_UNIFORM_BUFFER, static_cast<std::ptrdiff_t>(layout.stride()), nullptr, GL_DYNAMIC_DRAW);
185 glBindBufferBase(GL_UNIFORM_BUFFER, m_binding_point, m_id);
186
187 glBindBuffer(GL_UNIFORM_BUFFER, 0);
188
189 // fill up the uniform attribute cache
190 for (auto const& attr : m_layout.get_attributes()) {
191 m_attr_cache.emplace(attr.name, std::cref(attr));
192 }
193}
194
195inline void uniform_buffer::bind() const
196{
197 glBindBuffer(GL_UNIFORM_BUFFER, m_id);
198}
199
201{
202 glBindBuffer(GL_UNIFORM_BUFFER, 0);
203}
204
206{
207 if (m_id != 0) {
208 glDeleteBuffers(1, &m_id);
209 }
210}
211
213 : m_id { other.m_id }
214 , m_binding_point { other.m_binding_point }
215 , m_attr_cache { std::move(other.m_attr_cache) }
216 , m_layout { std::move(other.m_layout) }
217{
218 other.m_id = 0;
219}
220
221[[nodiscard]] inline auto uniform_buffer::operator=(uniform_buffer&& other) noexcept -> uniform_buffer&
222{
223 if (this != &other) {
224 glDeleteBuffers(1, &m_id);
225 m_id = other.m_id;
226 m_binding_point = other.m_binding_point;
227 m_layout = std::move(other.m_layout);
228 m_attr_cache = std::move(other.m_attr_cache);
229
230 other.m_id = 0;
231 }
232
233 return *this;
234}
235
236inline void uniform_buffer::set_attribute_data(std::span<const float> uniform_data, const std::string& name)
237{
238 set_attribute_data(uniform_data, name, 0);
239}
240
241inline void uniform_buffer::set_attribute_data(std::span<const float> uniform_data, const std::string& name, std::size_t offset)
242{
243 auto const attr = m_attr_cache.at(name);
244
245 glBufferSubData(GL_UNIFORM_BUFFER,
246 static_cast<ptrdiff_t>(attr.get().offset + offset * sizeof(float)),
247 static_cast<ptrdiff_t>(uniform_data.size_bytes()),
248 uniform_data.data());
249}
250
251inline void uniform_buffer::set_attribute_data(std::span<const float> uniform_data, size_t attribute_index)
252{
253 set_attribute_data(uniform_data, attribute_index, 0);
254}
255
256inline void uniform_buffer::set_attribute_data(std::span<const float> uniform_data, size_t attribute_index, std::size_t offset)
257{
258 auto const& attr = m_layout[attribute_index];
259
260 glBufferSubData(GL_UNIFORM_BUFFER,
261 static_cast<ptrdiff_t>(attr.offset + offset * sizeof(float)),
262 static_cast<ptrdiff_t>(uniform_data.size_bytes()),
263 uniform_data.data());
264}
265
266} // namespace staplegl
Uniform Buffer Object (UBO) wrapper.
constexpr auto layout() const noexcept -> vertex_buffer_layout const &
Gets the UBO's layout.
static void unbind()
Unbind any uniform from the OpenGL context.
auto operator=(const uniform_buffer &) -> uniform_buffer &=delete
void set_attribute_data(std::span< const float > uniform_data, const std::string &name)
Set the attribute data object.
void bind() const
Bind the uniform to the OpenGL context.
uniform_buffer(std::span< const float > contents, vertex_buffer_layout layout, int32_t binding_point) noexcept
Construct a new uniform buffer object.
uniform_buffer(const uniform_buffer &)=delete
constexpr auto binding_point() const noexcept -> int32_t
Get the binding point.
constexpr auto id() const noexcept -> uint32_t
Get the OpenGL identifier.
std::reference_wrapper< const vertex_attribute > attr_ref
vertex_buffer_layout m_layout
std::unordered_map< std::string_view, attr_ref > m_attr_cache
Loads OpenGL functions.
Vertex Buffer Layout abstraction.