CSCI441 OpenGL Library 6.1.0.0
CS@Mines CSCI441 Computer Graphics Course Library
Loading...
Searching...
No Matches
UniformBufferObject.hpp
Go to the documentation of this file.
1
11#ifndef CSCI441_UNIFORM_BUFFER_OBJECT_HPP
12#define CSCI441_UNIFORM_BUFFER_OBJECT_HPP
13
14#include "constants.h"
15#include "LogUtils.hpp"
16#include "ShaderProgram.hpp"
17
18#ifdef CSCI441_USE_GLEW
19 #include <GL/glew.h>
20#else
21 #include <glad/gl.h>
22#endif
23
24#include <cstdio>
25#include <vector>
26
27//******************************************************************************
28
29namespace CSCI441 {
30
35 class [[maybe_unused]] UniformBufferObject final {
36 public:
41
50
59 UniformBufferObject& operator=(UniformBufferObject&&) noexcept;
60
66 [[maybe_unused]] UniformBufferObject(const char* UNIFORM_BLOCK_NAME, const std::initializer_list<const char*> uniformNamesList);
71
79 UniformBufferObject& operator=(const UniformBufferObject&) = delete;
80
88 [[maybe_unused]] void setupWithShaderProgram( ShaderProgram *shaderProgram, GLuint bindingPoint );
89
95 [[maybe_unused]] void bindToShaderProgram( ShaderProgram *shaderProgram );
96
103 [[maybe_unused]] void copyToOffset( unsigned int offset, const void * src, size_t len );
104
111 [[maybe_unused]] void copyToBuffer( const char* UNIFORM_NAME, const void * src, size_t len );
112
118 [[maybe_unused]] void setUniform( const char* UNIFORM_NAME, GLboolean value );
124 [[maybe_unused]] void setUniform( const char* UNIFORM_NAME, GLint value );
130 [[maybe_unused]] void setUniform( const char* UNIFORM_NAME, GLfloat value );
136 [[maybe_unused]] void setUniform( const char* UNIFORM_NAME, glm::vec3 vec );
142 [[maybe_unused]] void setUniform( const char* UNIFORM_NAME, glm::vec4 vec );
148 [[maybe_unused]] void setUniform( const char* UNIFORM_NAME, glm::mat4 mtx );
155 [[maybe_unused]] void setUniform( const char* UNIFORM_NAME, const GLint* pArray, GLint count );
162 [[maybe_unused]] void setUniform( const char* UNIFORM_NAME, const glm::ivec4* pArray, GLint count );
163
167 void bindBuffer() const;
168
172 [[maybe_unused]] void bufferSubData() const;
173
174 private:
175 char* _blockName;
176 std::vector<char*> _uniformNames;
177 GLint _blockSize;
178 GLubyte* _buffer;
179 GLuint _numUniforms;
180 GLuint* _uniformIndices;
181 GLint* _uniformOffsets;
182 GLuint _ubod;
183 GLuint _bindingPoint;
184
185 void _cleanupSelf();
186 void _moveFromSource(UniformBufferObject&);
187 };
188}
189
190//******************************************************************************
191
192[[maybe_unused]]
193inline CSCI441::UniformBufferObject::UniformBufferObject(const char* UNIFORM_BLOCK_NAME, const std::initializer_list<const char*> uniformNamesList) {
194 _blockName = new char[strlen(UNIFORM_BLOCK_NAME) + 1];
195 strncpy(_blockName, UNIFORM_BLOCK_NAME, strlen(UNIFORM_BLOCK_NAME));
196 _blockName[ strlen(UNIFORM_BLOCK_NAME) ] = '\0';
197
198 _numUniforms = uniformNamesList.size();
199
200 for(const auto &uniformName : uniformNamesList ) {
201 const auto un = new char[ strlen(uniformName) + 1];
202 strncpy(un, uniformName, strlen(uniformName));
203 un[strlen(uniformName)] = '\0';
204 _uniformNames.push_back(un);
205 }
206
207 _uniformIndices = new GLuint[_numUniforms];
208 _uniformOffsets = new GLint[_numUniforms];
209
210 _blockSize = 0;
211 _buffer = nullptr;
212 _bindingPoint = 0;
213 _ubod = 0;
214}
215
217 _moveFromSource(src);
218}
219
221 if (this != &src) { // guard against self movement
222 _cleanupSelf(); // cleanup existing UBO
223 _moveFromSource(src); // move source UBO
224 }
225 return *this; // return ourselves
226}
227
229 _cleanupSelf();
230}
231
232[[maybe_unused]]
233inline void CSCI441::UniformBufferObject::setupWithShaderProgram( ShaderProgram * shaderProgram, const GLuint bindingPoint ) {
234 _blockSize = shaderProgram->getUniformBlockSize( _blockName );
235 _buffer = new GLubyte[ _blockSize ];
236
237 glGetUniformIndices(shaderProgram->getShaderProgramHandle(), _numUniforms, &_uniformNames[0], _uniformIndices);
238 glGetActiveUniformsiv(shaderProgram->getShaderProgramHandle(), _numUniforms, _uniformIndices, GL_UNIFORM_OFFSET, _uniformOffsets);
239
240 glGenBuffers(1, &_ubod);
241 bindBuffer();
242 glBufferData(GL_UNIFORM_BUFFER, _blockSize, nullptr, GL_DYNAMIC_DRAW);
243
244 _bindingPoint = bindingPoint;
245 glBindBufferBase(GL_UNIFORM_BUFFER, _bindingPoint, _ubod);
246 shaderProgram->setUniformBlockBinding(_blockName, _bindingPoint);
247}
248
249[[maybe_unused]]
251 shaderProgram->setUniformBlockBinding(_blockName, _bindingPoint);
252}
253
254[[maybe_unused]]
255inline void CSCI441::UniformBufferObject::copyToOffset( const unsigned int offset, const void * src, const size_t len ) {
256 if(offset < _numUniforms) {
257 memcpy(_buffer + _uniformOffsets[offset], src, len);
258 } else {
259 CSCI441::LogUtils::logError("[ERROR]: Offset %d exceeds size of Uniform Block %s which is %d\n", offset, _blockName, _numUniforms);
260 }
261}
262
263[[maybe_unused]]
264inline void CSCI441::UniformBufferObject::copyToBuffer( const char* UNIFORM_NAME, const void * src, const size_t len ) {
265 bool found = false;
266 for(GLuint i = 0; i < _numUniforms; i++) {
267 if( strcmp(_uniformNames[i], UNIFORM_NAME) == 0 ) {
268 memcpy( _buffer + _uniformOffsets[i], src, len );
269 found = true;
270 break;
271 }
272 }
273 if(!found) {
274 CSCI441::LogUtils::logError("[ERROR]: Uniform Name \"%s\" not found within Uniform Block \"%s\"\n", UNIFORM_NAME, _blockName);
275 }
276}
277
278[[maybe_unused]]
279inline void CSCI441::UniformBufferObject::setUniform( const char* UNIFORM_NAME, const GLboolean value ) {
280 copyToBuffer(UNIFORM_NAME, &value, sizeof(GLboolean));
281}
282
283[[maybe_unused]]
284inline void CSCI441::UniformBufferObject::setUniform( const char* UNIFORM_NAME, const GLint value ) {
285 copyToBuffer(UNIFORM_NAME, &value, sizeof(GLint));
286}
287
288[[maybe_unused]]
289inline void CSCI441::UniformBufferObject::setUniform( const char* UNIFORM_NAME, const GLfloat value ) {
290 copyToBuffer(UNIFORM_NAME, &value, sizeof(GLfloat));
291}
292
293[[maybe_unused]]
294inline void CSCI441::UniformBufferObject::setUniform( const char* UNIFORM_NAME, const glm::vec3 vec ) {
295 copyToBuffer(UNIFORM_NAME, glm::value_ptr(vec), sizeof(glm::vec3));
296}
297
298[[maybe_unused]]
299inline void CSCI441::UniformBufferObject::setUniform( const char* UNIFORM_NAME, const glm::vec4 vec ) {
300 copyToBuffer(UNIFORM_NAME, glm::value_ptr(vec), sizeof(glm::vec4));
301}
302
303[[maybe_unused]]
304inline void CSCI441::UniformBufferObject::setUniform( const char* UNIFORM_NAME, const glm::mat4 mtx ) {
305 copyToBuffer(UNIFORM_NAME, glm::value_ptr(mtx), sizeof(glm::mat4));
306}
307
308[[maybe_unused]]
309inline void CSCI441::UniformBufferObject::setUniform( const char* UNIFORM_NAME, const GLint * const pArray, const GLint count ) {
310 copyToBuffer(UNIFORM_NAME, pArray, sizeof(GLint) * count);
311}
312
313[[maybe_unused]]
314inline void CSCI441::UniformBufferObject::setUniform( const char* UNIFORM_NAME, const glm::ivec4 * const pArray, const GLint count ) {
315 copyToBuffer(UNIFORM_NAME, pArray, sizeof(glm::ivec4) * count);
316}
317
319 glBindBuffer(GL_UNIFORM_BUFFER, _ubod);
320}
321
322[[maybe_unused]]
324 glBufferSubData(GL_UNIFORM_BUFFER, 0, _blockSize, _buffer);
325}
326
327inline void CSCI441::UniformBufferObject::_cleanupSelf() {
328 glDeleteBuffers(1, &_ubod);
329 _ubod = 0;
330
331 for(GLuint i = 0; i < _numUniforms; i++) {
332 delete[] _uniformNames[i];
333 }
334 _uniformNames.clear();
335
336 delete[] _uniformIndices;
337 _uniformIndices = nullptr;
338
339 delete[] _uniformOffsets;
340 _uniformOffsets = nullptr;
341
342 delete[] _buffer;
343 _buffer = nullptr;
344
345 delete[] _blockName;
346 _blockName = nullptr;
347
348 _numUniforms = 0;
349 _blockSize = 0;
350 _bindingPoint = 0;
351}
352
353
354inline void CSCI441::UniformBufferObject::_moveFromSource(UniformBufferObject &src) {
355 _blockName = src._blockName;
356 src._blockName = nullptr;
357
358 _numUniforms = src._numUniforms;
359 src._numUniforms = 0;
360
361 _uniformNames = std::move(src._uniformNames);
362 src._uniformNames.clear();
363
364 _uniformIndices = src._uniformIndices;
365 src._uniformIndices = nullptr;
366
367 _uniformOffsets = src._uniformOffsets;
368 src._uniformOffsets = nullptr;
369
370 _blockSize = src._blockSize;
371 src._blockSize = 0;
372
373 _buffer = src._buffer;
374 src._buffer = nullptr;
375
376 _bindingPoint = src._bindingPoint;
377 src._bindingPoint = 0;
378
379 _ubod = src._ubod;
380 src._ubod = 0;
381}
382
383#endif //CSCI441_UNIFORM_BUFFER_OBJECT_HPP
Class to work with OpenGL 4.0+ Shaders.
Handles registration and compilation of Shaders.
Definition: ShaderProgram.hpp:37
virtual void setUniformBlockBinding(const GLchar *uniformBlockName, GLuint binding) const final
Set the binding point for the given uniform block in this shader program.
Definition: ShaderProgram.hpp:1383
virtual GLuint getShaderProgramHandle() const final
Returns the handle for this shader program.
Definition: ShaderProgram.hpp:1529
virtual GLint getUniformBlockSize(const GLchar *uniformBlockName) const final
Returns the size of the given uniform block in this shader program.
Definition: ShaderProgram.hpp:1337
Storage of UBO related data.
Definition: UniformBufferObject.hpp:35
void bindBuffer() const
binds UBO object to UBO buffer
Definition: UniformBufferObject.hpp:318
~UniformBufferObject()
Deletes the UBO from the GPU and frees all memory on the CPU.
Definition: UniformBufferObject.hpp:228
void bindToShaderProgram(ShaderProgram *shaderProgram)
sets the shader programs binding point to match this uniform buffer object
Definition: UniformBufferObject.hpp:250
void setUniform(const char *UNIFORM_NAME, GLboolean value)
sets the uniform value within the uniform buffer block
Definition: UniformBufferObject.hpp:279
UniformBufferObject(UniformBufferObject &unused)=delete
void copyToBuffer(const char *UNIFORM_NAME, const void *src, size_t len)
copies the value pointed to by addr to the corresponding location within the UBO as denoted by the un...
Definition: UniformBufferObject.hpp:264
void copyToOffset(unsigned int offset, const void *src, size_t len)
copies the value pointed to by addr to the corresponding location within the UBO as denoted by the of...
Definition: UniformBufferObject.hpp:255
void setupWithShaderProgram(ShaderProgram *shaderProgram, GLuint bindingPoint)
creates the UBO and allocates memory on both the CPU & GPU. binds the UBO and the uniform block for t...
Definition: UniformBufferObject.hpp:233
void bufferSubData() const
transfers UBO data to UBO buffer
Definition: UniformBufferObject.hpp:323
UniformBufferObject & operator=(UniformBufferObject &unused)=delete
void logError(const char *MSG,...)
log a message to both the standard error stream and file
Definition: LogUtils.hpp:128
CSCI441 Helper Functions for OpenGL.
Definition: ArcballCam.hpp:17