Silverlan
Silverlan

Reputation: 2911

OpenGL / GLSL - Uniform block data values incorrect

My shader has a uniform block as such:

layout (std140) uniform LightSourceBlock
{
    vec3 test;
    vec3 color;
} LightSources;

The data for this block is supposed to come from a buffer object which is created like so:

GLuint buffer;
glGenBuffers(1,&buffer);

GLfloat data[6] = {
    0,0,0,
    0,0,1
};
glBindBuffer(GL_UNIFORM_BUFFER,buffer);
glBufferData(GL_UNIFORM_BUFFER,sizeof(data),&data[0],GL_DYNAMIC_DRAW);

The buffer is linked to the uniform block before rendering:

unsigned int locLightSourceBlock = glGetUniformBlockIndex(program,"LightSourceBlock");
glUniformBlockBinding(program,locLightSourceBlock,8);
glBindBufferBase(GL_UNIFORM_BUFFER,8,buffer);

From my understanding this should be setting 'color' inside the block in the shader to (0,0,1), but the value I'm getting instead is (0,1,0).

If I remove the 'test' variable from the block and only bind the three floats (0,0,1) to the shader, it works as intended.

What's going on?

Upvotes: 1

Views: 1530

Answers (1)

derhass
derhass

Reputation: 45362

As you did specify layout (std140) for your UBO, you must obey the alginment rules defined there. That layout was first specified (in core) in the OpenGL 3.2 core spec, section 2.11.4 "Uniform Variables" in subsection "Standard Uniform Block Layout":

  1. If the member is a scalar consuming N basic machine units, the base alignment is N.
  2. If the member is a two- or four-component vector with components consuming N basic machine units, the base alignment is 2N or 4N, respectively.
  3. If the member is a three-component vector with components consuming N basic machine units, the base alignment is 4N.
  4. If the member is an array of scalars or vectors, the base alignment and array stride are set to match the base alignment of a single array element, according to rules (1), (2), and (3), and rounded up to the base alignment of a vec4. The array may have padding at the end; the base offset of the member following the array is rounded up to the next multiple of the base alignment.
  5. If the member is a column-major matrix with C columns and R rows, the matrix is stored identically to an array of C column vectors with R components each, according to rule (4).
  6. If the member is an array of S column-major matrices with C columns and R rows, the matrix is stored identically to a row of S C column vectors with R components each, according to rule (4).
  7. If the member is a row-major matrix with C columns and R rows, the matrix is stored identically to an array of R row vectors with C components each, according to rule (4).
  8. If the member is an array of S row-major matrices with C columns and R rows, the matrix is stored identically to a row of S R row vectors with C components each, according to rule (4).
  9. If the member is a structure, the base alignment of the structure is N, where N is the largest base alignment value of any of its members, and rounded up to the base alignment of a vec4. The individual members of this substructure are then assigned offsets by applying this set of rules recursively, where the base offset of the first member of the sub-structure is equal to the aligned offset of the structure. The structure may have padding at the end; the base offset of the member following the sub-structure is rounded up to the next multiple of the base alignment of the structure.
  10. If the member is an array of S structures, the S elements of the array are laid out in order, according to rule (9).

For your case, point 3 applies. So, you need to pad another float before the second vector begins.

Upvotes: 3

Related Questions