0
votes

Using GLFW, GLEW (Although it shouldn't matter)

When passing a struct to the fragment shader, unexpected behavior is observed: If I pass the ambient color directly:

out vec3 color
...
color = MaterialCols.ambient

Everything works as expected. When passing diffuse, it is offset by 1 (i.e. the green channel is red, the blue channel is green)

When passing specular, the first value is the green channel of the previous vec3 (diffuse).

I believe this is an issue of alignment. It seems either that GLSL only wants to access vec3 components on a specific alignment, or that the C++ code is adding some padding (for reasons unkown).

This is the data allocation. It is passed as a uniform buffer object. If required, I can add the code used.

C++:

typedef  struct  material_colors{
    glm::vec3 ambient;
    glm::vec3 diffuse;
    glm::vec3 specular;
}material_cols;

GLSL:

uniform MaterialColors {
    vec3 ambient;
    vec3 diffuse;
    vec3 specular;
} MaterialCols;
1
UBOs have very clear alignment rules (when using one of the standard layouts, or the implementation might impose it's own rules if you don't). Have a look at my previous answer for a similiar question. - derhass
You are absolutely correct. If I had found those rules earlier, I wouldn't have asked this pointless question. Thank you! - GCon

1 Answers

0
votes

As per derhass' comment, and the related section 2.11.4 titled "Uniform Variables"in the OpenGL 3.2 Core specifications:

3. If the member is a three-component vector with components consuming N basic machine units, the base alignment is 4N.

So, by padding the c++ struct using a float after the first vec3, brings the diffuse into alignment.

C++

typedef  struct  material_colors{
    glm::vec3 ambient;
    float padding;
    glm::vec3 diffuse;
    glm::vec3 specular;
}material_cols;