UBOs are typically associated with a named uniform block, which looks like this in GLSL version 150 (and 140+ i think, I’m not completely sure what version introduced what)
uniform nameBlock
{
vec3 trans;
vec4 proj;
vec4 quat;
vec3 cquat;
};
when linked to GLSL, the shader program will draw values from the buffer associated with these variables. This is nice because the variables are already on the GPU via the buffer.
So using a VBO and a named uniform buffer has a few steps:
-declare the named buffer in the shader program (“nameBlock”)
-get info about the block in your OpenGL API
-make an appropriate buffer for the named buffer
-link the shader program to the buffer object.
Here’s an example:
// char array of the variable names in my shader program
const GLchar* names[] = {“trans”, “proj”, “quat”, “cquat”};
GLint uniActive; // how many active variables are in my shader program
// get block information
uniBlockID = glGetUniformBlockIndex(shader_Prog, "nBlock"); // get the named block ID
glGetActiveUniformBlockiv(shader_Prog, uniBlockID, GL_UNIFORM_BLOCK_BINDING,
&uniBlockBind); // get the named block binding
glGetActiveUniformBlockiv(shader_Prog, uniBlockID, GL_UNIFORM_BLOCK_DATA_SIZE,
&uniBlockSize); // get the named block size (in bytes)
glGetActiveUniformBlockiv(shader_Prog, uniBlockID, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS,
&uniActive); // get how many active uniforms are in the block, all uniforms in a block are considered active by default
// get the index of the uniforms
GLuint *uniIndex = new GLuint[uniActive];
glGetUniformIndices(shader_Prog, uniActive, names, uniIndex);
uniBufferOffset = new GLint[uniActive];
// NOTE: THIS IS COMPLETELY DIFFERENT THAN THE INDEX OF THE UNIFORMS WITHIN THE NAMED BUFFER (which are mostly likely 0,1,2,3 ect in order)
glGetActiveUniformsiv(shader_Prog, uniActive, uniIndex, GL_UNIFORM_OFFSET, uniBufferOffset);
// this gets the index of the uniform variables in your program and then sets an offset for how far in the data for each variable is. data is typically packed in block sof 16 bytes, so even if it’s one float, you’ll probably be indexed 16 bytes to the next uniform even if the previous only used 1 or 4 or whatever. offset[0] will be for your first variable, in the example ‘trans’ and offset[1] for the next, or proj
// now that we k now the data, make a buffer for us
glGenBuffers(1, &id_UniBuffer);
glBindBuffer(GL_UNIFORM_BUFFER, id_UniBuffer);
GLfloat *nullData = new GLfloat[uniBlockSize / 4];
memset(nullData,0,uniBlockSize);
glBufferData(GL_UNIFORM_BUFFER, uniBlockSize, nullData, GL_DYNAMIC_DRAW);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
and lastly we have to link up the shader program with our buffer:
glUniformBlockBinding(shader_Prog, uniBlockID, uniBlockBind);
glBindBufferBase(GL_UNIFORM_BUFFER, uniBlockID, id_UniBuffer);
if i want to change data in the buffer for the appropriate offset, where uniBufferOffset[0] is my offset for ‘trans’
GLfloat RGL_Translate[3];
glBufferSubData(GL_UNIFORM_BUFFER_EXT,uniBufferOffset[0],12,RGL_Translate);