OpenGL中的统一块

Posted

技术标签:

【中文标题】OpenGL中的统一块【英文标题】:Uniform block in OpenGL 【发布时间】:2015-08-14 18:20:18 【问题描述】:

我正在按照 David Wolff 的一本书 GLSL 将数据发送到 OpenGL 中的统一块。

layout(std140) uniform BlobSettings 
    vec4 InnerColor;
    vec4 OuterColor;
    float RadiusInner;
    float RadiusOuter;
;

客户端代码:

GLuint blockIndex = glGetUniformBlockIndex(programHandle, "BlobSettings");

// Allocate space for the buffer
GLint blockSize;
glGetActiveUniformBlockiv(programHandle, blockIndex,
                          GL_UNIFORM_BLOCK_DATA_SIZE, &blockSize);
GLubyte* blockBuffer = (GLubyte *) malloc(blockSize);

// Query for the offsets of each block variable
const GLchar *names[] =  "BlobSettings.InnerColor", "BlobSettings.OuterColor",
                          "BlobSettings.RadiusInner", "BlobSettings.RadiusOuter" ;

GLuint indices[4];
glGetUniformIndices(programHandle, 4, names, indices);

GLint offset[4];
glGetActiveUniformsiv(programHandle, 4, indices, GL_UNIFORM_OFFSET, offset);

// Store data within the buffer at the appropriate offsets
GLfloat outerColor[] = 0.0f, 0.0f, 0.0f, 0.0f;
GLfloat innerColor[] = 1.0f, 1.0f, 0.75f, 1.0f;
GLfloat innerRadius = 0.25f, outerRadius = 0.45f;

memcpy(blockBuffer + offset[0], innerColor, 4 * sizeof(GLfloat));
memcpy(blockBuffer + offset[1], outerColor, 4 * sizeof(GLfloat));
memcpy(blockBuffer + offset[2], &innerRadius, sizeof(GLfloat));
memcpy(blockBuffer + offset[3], &outerRadius, sizeof(GLfloat));

程序在执行 memcpy 时出现分段错误。当我在那里设置断点时,我发现 glGetActiveUniformsiv 返回偏移量和索引错误。例如:

offset[]
0: 530332809
1: 2686632
2: 1971058176
3:0

虽然我希望它们是 0、4、8、12 等或接近的值。如何解决此错误?

【问题讨论】:

【参考方案1】:

我想知道你为什么在首先使用std140 时使用这种偏移机制?

我认为你的书没有提到std140 有非常具体的对齐规则,这意味着你可以在不查询它们的情况下找出所有这些成员的偏移量。这是一个重要的概念,如果跳过它对您毫无帮助。

遵循std140 规则,您已经拥有了正确对齐的数据结构。

layout(std140) uniform BlobSettings 
    vec4 InnerColor;   // 4N begins at 0
    vec4 OuterColor;   // 4N begins at 4 (divisible by 4 -- YES)
    float RadiusInner; // 1N begins at 8 (divisible by 1 -- YES)
    float RadiusOuter; // 1N begins at 9 (divisible by 1 -- YES)
;

这个数据结构的偏移量将是

0  (InnerColor),
16 (OuterColor),  // 4x sizeof GLfloat                   (vec4)
32 (RadiusInner), // 8x sizeof GLfloat                   (vec4, vec4)
36 (RadiusOuter)  // 8x sizeof GLfloat + sizeof GLfloat  (vec4, vec4, float)

这里你需要记住一件事,如果你要按照std140 规则声明这个结构的数组,那么你需要在结构的末尾添加一个额外的 8 字节正确对齐。否则vec4 InnerColor 将在数组中第一个元素之后的错误边界开始(请参阅下面链接文档中的规则 10)

这在 OpenGL 4.5 规范的7.6.2.2 Standard Uniform Block Layout 中有更正式的讨论。

【讨论】:

谢谢。我的 OpenGL 实现只有 4.2,但 std140 不兼容 :( std140 来自 OpenGL 3.1。如果它不兼容,则说明您存在驱动程序错误。

以上是关于OpenGL中的统一块的主要内容,如果未能解决你的问题,请参考以下文章

opengl:将数组类型加载到统一缓冲区对象

OpenGL / GLSL - 统一块数据值不正确

具有可分离程序的 OpenGL 统一块绑定

统一值和 OpenGL 着色器

C ++ / OpenGL glm无法将矩阵插入着色器中的统一

如何修复 OpenGL 中的“错误 0:60 采样器不能是结构或块成员”?