C++ OpenGL统一缓冲区对象(数组)每隔Vec2跳过一次

C++ OpenGL统一缓冲区对象(数组)每隔Vec2跳过一次,c++,debugging,opengl,C++,Debugging,Opengl,问题 这些白线之间不应该有空隙。这些线是由正方形组成的(最终我不会只生成另一个巨大的正方形;这是为了调试)。由于某种原因,当我通过我的统一缓冲区对象(下面的例子)发送数据时,我得到了间隙。它几乎就像是跳过了其他y值。实际上,每个位置上都有两个正方形,而不是(y)和(y+1)各有一个 代码片段 生成数据指针数组 顶点着色器(GLSL) 测试 当我改变blockData[I]=glm::vec2(x,y)toblockData[i]=glm::vec2(y,x)(切换y和x),间隙移动到x轴

问题 这些白线之间不应该有空隙。这些线是由正方形组成的(最终我不会只生成另一个巨大的正方形;这是为了调试)。由于某种原因,当我通过我的统一缓冲区对象(下面的例子)发送数据时,我得到了间隙。它几乎就像是跳过了其他y值。实际上,每个位置上都有两个正方形,而不是(y)和(y+1)各有一个

代码片段 生成数据指针数组

顶点着色器(GLSL)

测试
  • 当我改变
    blockData[I]=glm::vec2(x,y)
    to
    blockData[i]=glm::vec2(y,x)(切换y和x),间隙移动到x轴
  • 我已经尝试过在for循环中切换x和y,但这并不影响它。这个问题与y变量有关
  • 影响它的是,如果我在
    inti=x*24+y中切换x和y
  • 将vec2设置为(x,x)将导致正确放置对角线
  • 将vec2设置为(y,y)会导致一条奇怪的对角线(如下所示)
  • 在切换到UBO之前,我只是在着色器中使用了一致性,效果很好。这就是为什么我认为这与我通过UBO发送数据有关。

那么,现在发生的很可能是对齐问题。使用std140,必须对齐4个浮点数。然而,在没有看到所有代码的情况下,我不可能完全确定您是如何缓冲数据的。但是,我可以建议使用glGetActiveUniformsiv查询块偏移,然后在此基础上对齐对象。所以一个典型的例子是:

    char* bufferNames[] = [generate the values with a for loop, this should be pretty easy with string and sprintf e.g "blockData.blockDataPosition[0]" to "block.Data.blockDataPosition[5184]"];

    GLuint uniformBlockIndex = glGetUniformBlockIndex(yourprogram, "block name");

    GLuint uniformIndices[number of names in bufferNames];

    glGetUniformIndices(yourprogram, the number of names in bufferNames, bufferNames, indices);

    GLint uniformOffsets[the number of names in bufferNames];

    glGetActiveUniformsiv(yourprogram, 1, &uniformIndices, GL_UNIFORM_OFFSET, uniformOffsets);
偏移量会告诉你你需要知道的一切。它们是每个名称的偏移量(以字节为单位)。您可以使用for循环来填充每个偏移量,或者只是将其打印出来以查看所有内容是如何对齐的。这不应该在循环中完成,而应该在初始化等过程中完成一次。
如果您有任何问题或需要更具体的示例,请告诉我。

您是否可以包含GLSL着色器的相关部分?听起来有点像UBO中的对齐问题。谢谢你的建议,我忘了包括它。我知道使用std140时,vec3占用的空间量与vec4相同,但我使用的是vec2,所以我不确定会发生什么。这与变量对齐不同(即vec2需要2个浮点填充,vec3和vec4需要4)?@badcc否,它对由std140指定的对齐本身没有任何作用,打包的或共享的。然而,这确实允许您查看块中的所有内容是如何对齐的,您可以基于此填充缓冲区,或者简单地读取它以查看您请求的布局是否是您得到的。这是一种使用更快的布局规范(如打包)的方法,并且仍然可以保证不同供应商之间的正确行为。对于您的情况,这更多是为了调试,并查看您请求的统一布局是否正确显示。我已确定我的缓冲区(具有4个元素;因此为vec4*4;但我仅使用x和y。vec4用于填充)的大小为64。我发送的数据(sizeof(glm::vec2)*4)是32。我刚刚将着色器中的vec2更改为vec4。我还需要改变什么才能让它正常工作?编辑:我不是通过C++发送VEC2,而是将它更改为发送一个VEC4。现在它工作了!谢谢你的帮助:)
glBindBuffer(GL_UNIFORM_BUFFER, ubo);
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(glm::vec2) * blocksActive, blockData);
glBindBufferRange(GL_UNIFORM_BUFFER, uniBlockData, ubo, 0, sizeof(glm::vec2) * blocksActive);
glBindBuffer(GL_UNIFORM_BUFFER, 0);

glBindVertexArray(vao);
glDrawElementsInstanced(GL_TRIANGLES, 6, GL_UNSIGNED_INT, (void*)0, blocksActive);
glBindVertexArray(0);
layout (std140) uniform blockData {
    vec2 blockDataPosition[5184];
};
    char* bufferNames[] = [generate the values with a for loop, this should be pretty easy with string and sprintf e.g "blockData.blockDataPosition[0]" to "block.Data.blockDataPosition[5184]"];

    GLuint uniformBlockIndex = glGetUniformBlockIndex(yourprogram, "block name");

    GLuint uniformIndices[number of names in bufferNames];

    glGetUniformIndices(yourprogram, the number of names in bufferNames, bufferNames, indices);

    GLint uniformOffsets[the number of names in bufferNames];

    glGetActiveUniformsiv(yourprogram, 1, &uniformIndices, GL_UNIFORM_OFFSET, uniformOffsets);