使用 uvec3[] 的统一缓冲区

Use uniform buffer of uvec3[]

我有以下统一缓冲区:

uniform EDGE_ID_TO_START_POS{
    uint[12*3] pos;
} edgeIdToStartPos;

写入此缓冲区工作正常:

#define EDGE_ID_TO_START_POS_SIZE (12*3)
    const uint32_t edgeIdToStartPos_constBuffer[EDGE_ID_TO_START_POS_SIZE] = {
        /* 0*/ 0, 0, 0, /* 1*/ 0, 1, 0, /* 2*/ 1, 0, 0, /* 3*/ 0, 0, 0,
        /* 4*/ 0, 0, 1, /* 5*/ 0, 1, 1, /* 6*/ 1, 0, 1, /* 7*/ 0, 0, 1,
        /* 8*/ 0, 0, 0, /* 9*/ 0, 1, 0, /*10*/ 1, 1, 0, /*11*/ 1, 0, 0
    };
    glBindBuffer(GL_UNIFORM_BUFFER, ubo);
    glBufferData(GL_UNIFORM_BUFFER, EDGE_ID_TO_START_POS_SIZE * sizeof(uint32_t), edgeIdToStartPos_constBuffer, GL_STATIC_DRAW);
    glBindBuffer(GL_UNIFORM_BUFFER, 0);

现在我想将统一缓冲区更改为以下结构:

uniform EDGE_ID_TO_START_POS{
    uvec3[12] pos;
} edgeIdToStartPos;

这种结构更有意义,也更容易使用。并且它应该具有与以前版本相同的内存布局(?)。 但是,从该结构读取时,只有向量 0..3 包含数据。所有索引为 4 或更高的 uvec 都包含零。

为什么会发生这种情况,如何正确初始化这样一个统一缓冲区? (C/C++, glew, glfw)

一个uvec3有一个16字节的对齐,所以你必须添加填充。请参阅 OpenGL 4.5 规范,第 7.6.22 节:

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

这是它的样子:

static const int EDGE_ID_TO_START_POS_SIZE = 12 * 4;
const uint32_t edgeIdToStartPos_constBuffer[EDGE_ID_TO_START_POS_SIZE] = {
    /* 0*/ 0, 0, 0, 0, /* 1*/ 0, 1, 0, 0, /* 2*/ 1, 0, 0, 0, /* 3*/ 0, 0, 0, 0,
    /* 4*/ 0, 0, 1, 0, /* 5*/ 0, 1, 1, 0, /* 6*/ 1, 0, 1, 0, /* 7*/ 0, 0, 1, 0,
    /* 8*/ 0, 0, 0, 0, /* 9*/ 0, 1, 0, 0, /*10*/ 1, 1, 0, 0, /*11*/ 1, 0, 0, 0,
};