1

Sorry for the title, but I do not really know how I can name my problem. I am reading about uniform blocks in a opengl book and I am a bit confused about default std140 offsets shown there.

layout(std140) uniform TransformBlock
{
    //component             base alignment | offset | aligned offset
    float scale;            // 4  | 0  | 0
    vec3 translation;       // 16 | 4  | 16
    float rotation[3];      // 16 | 28 | 32 (rotation[0])
                            //           48 (rotation[1])
                            //           64 (rotation[2])
    mat4 projection_matrix; // 16 | 80 | 80 (column 0)
                            //           96 (column 1)
                            //           112 (column 2)
                            //           128 (column 3)
} transform;

I know that vec3's alignment = vec4's alignment = 32 bits.

Scale is the first component so offset is 0, also it is 4 bits, so it is clear to me that translation needs to be at - let's call it currentPosition - currentPosition + 4.

I do not understand why translation's offset's alignment is 16, though.

Also, it is unclear to me why rotation's offset is 28.

Translation is vec3, it means that there are 3 floats, so 3 * 4 = 12. My first thought was that we maybe want to round it to a, I do not know how it is called, bit value, but 28 is not a value of that kind.

Same with projection_matrix's offset.

Could someone explain it to me as if I were an idiot, please?

1 Answers1

5

OpenGL does not define a concept called "offset's alignment". Maybe your book is talking about some derived quantity, but since you did not name the book nor did you quote anything more than this example, I cannot say.

The quantities of worth when it comes to std140 layout are the size (how much space it takes up), base alignment, offset, and array stride (obviously only meaningful for arrays). The base alignment imposes a restriction on the offset; the offset must be divisible by the base alignment.

vec3 has a size of 12, since it contains 3 4-byte values. It has a base alignment of 16, because that's what the standard says it has:

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

The offset of a member is computed by computing the offset of the previous member, adding the previous member's size, and then applying the base alignment to that value.

So, given that scale has an offset of 0, size of 4, and a base alignment of 4, the offset of translation is 16 (4, rounded up to the nearest base alignment).

The base alignment and array stride of rotation is 16, because that's what the standard says:

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.

Emphasis added.

So, the offset of translation is 16, and its size is 12. Add them together, and you get 28. To get the offset of rotation, you apply rotation's base alignment, giving you 32.

Also, stop using vec3s.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
  • Now it is fully clear to me, thank you. The book is named OpenGL Superbible: Comprehensive Tutorial and Reference 7th Edition. My copy is translated into my language, with different cover and was hard to find it. –  Apr 30 '19 at 19:07