我发现GLSL统一块的大小错误。
这是着色器中的块:
uniform MaterialInfo {
vec3 Ka;
vec3 Ks;
vec3 Kd;
};
然后使用以下代码准备我的统一缓冲区对象:
blockIndex = glGetUniformBlockIndex(program, "MaterialInfo");
if (blockIndex == -1) {
fprintf(stderr, "Could not bind uniform block\n");
}
printf("Found blockindex materialinfo: %d\n", blockIndex);
glGetActiveUniformBlockiv(program, blockIndex, GL_UNIFORM_BLOCK_DATA_SIZE, &blockSize);
blockBuffer = (GLubyte *) malloc(blockSize);
cout << "GLSL blocksize: " << blockSize << endl;
cout << "sizeof glm::vec3 type: " << sizeof(mesh->Ka) << endl;
cout << "sizeof 3 x glm::vec3 type: " << 3 * sizeof(mesh->Ka) << endl;
报告如下:
GLSL blocksize: 48
sizeof glm::vec3 type: 12
sizeof 3 x glm::vec3 type: 36
总之,我期待GLSL块大小为36,而不是48.GLSL中的vec3应该像我的glm :: vec3类型一样浮动。
另请注意,我使用的是HD4000 beta驱动程序:OpenGL 4.0.0 Build 9.17.10.2792。我没有机会在另一台计算机上进行测试。 这是我误解了什么吗?
回复后的跟进:
所以在这种情况下提交我的glm :: vec3浮动的正确方法如下?
glGetUniformIndices(program, 3, namesMaterial, indices);
glGetActiveUniformsiv(program, 3, indices, GL_UNIFORM_OFFSET, offset);
memcpy(blockBuffer + offset[0], glm::value_ptr(mesh->Ka), 4 * sizeof(GLfloat));
memcpy(blockBuffer + offset[1], glm::value_ptr(mesh->Ks), 4 * sizeof(GLfloat));
memcpy(blockBuffer + offset[2], glm::value_ptr(mesh->Kd), 4 * sizeof(GLfloat));
答案 0 :(得分:3)
许多GPU将每个制服填充为vec4的大小:
从OpenGL wiki(强调我的)看到这个implementation note:
实施说明:由于实现原因,允许OpenGL实现拒绝着色器。因此,通过计算,您可以减少活动的统一组件,但由于统一限制,仍然无法链接。这通常是硬件上的矢量硬件。 Pre GeForce 8xxx硬件和所有ATi硬件都可以做到这一点。在这种情况下,您应该假设每个单独的制服占用4个组件,就像在D3D中一样。这意味着“均匀浮动”是4个组件,mat2x4是16个组件(每行是4个组件),但是mat4x2是8个组件。
答案 1 :(得分:3)
总之,我期待GLSL块大小为36,而不是48.GLSL中的vec3应该像我的glm :: vec3类型一样浮动。
为什么呢? OpenGL规范中没有任何内容可以保证块大小。
或者至少,不是 统一块的定义。
如果不提供proper memory layout qualifier,则默认使用shared
。这允许实现在元素之间放置任何感觉舒适的填充。所以你不能只假设3 vec3
s将连续12个float
s大小。每个vec3
将是3个连续的float
,但不能保证不会有填充。
如果您需要统一块的固定,已知和一致布局,则需要使用std140
布局。否则,您将获得实现为您提供的功能。 OpenGL规范详细说明了std140
元素布局的规则。
当然,使用std140
布局时,此块的大小也为48,因为它会将所有vec3
元素填充到vec4
s。< / p>
所以在这种情况下提交我的glm :: vec3浮动的正确方法如下?
这是正确的,假设:
memoryBlock
是映射的缓冲区对象指针或您使用glBufferSubData
GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
对齐)。mesh->Ka
及其同类实际上有4个花车。否则你将从未分配的内存中复制。同样,我敦促你停止查询这些内容并使用std140
布局。当你这样做时,你不必查询偏移量或任何东西;您可以设计与所有硬件上的GLSL定义完美布局兼容的结构。