8

使用多个统一缓冲区时遇到问题。

这是我的 GLSL 代码:

layout(std140) uniform MaterialInfo {
    vec3 Ka;
    vec3 Ks;    
    vec3 Kd;
};


layout(std140) uniform LightInfo {
    vec3 La;
    vec3 Ls;
    vec3 Ld;
};

这就是我创建和填充缓冲区的方式:

    blockIndex = glGetUniformBlockIndex(program, "MaterialInfo");
    if (blockIndex == -1) {
        fprintf(stderr, "Could not bind uniform block\n");
    }
    glGenBuffers(1, &materialUbo);
    glBindBuffer(GL_UNIFORM_BUFFER, materialUbo);
    glBufferData(GL_UNIFORM_BUFFER, sizeof(MaterialBlock), &mesh->material, GL_DYNAMIC_DRAW);
    glBindBufferBase(GL_UNIFORM_BUFFER, blockIndex, materialUbo);


    blockIndex = glGetUniformBlockIndex(program, "LightInfo");
    if (blockIndex == -1) {
        fprintf(stderr, "Could not bind uniform block\n");
    }
    glGenBuffers(1, &lightUbo);
    glBindBuffer(GL_UNIFORM_BUFFER, lightUbo);
    glBufferData(GL_UNIFORM_BUFFER, sizeof(LightBlock), &light->lightBlock, GL_DYNAMIC_DRAW);
    glBindBufferBase(GL_UNIFORM_BUFFER, blockIndex, lightUbo);

当结构定义如下:

struct LightBlock { 
    glm::vec4 La;
    glm::vec4 Ld;
    glm::vec4 Ls;
};

struct MaterialBlock {
    glm::vec4 Ka;
    glm::vec4 Ks;
    glm::vec4 Kd;
};

如果我只使用一个统一缓冲区,则此代码可以正常工作。那就是 MaterialInfo。如果我包含 lightInfo 的第二个缓冲区,当我稍后在渲染中到达 glDrawElements() 时会崩溃。

像这样使用多个统一缓冲区有问题吗?我可以把它变成 1 个 UBO 吗?

4

2 回答 2

13

glGetUniformBlockIndex不能那样工作。它检索一个标识该特定统一块的数字。它不是要传递给的统一缓冲区绑定索引glBindBufferRange/Base

UBO 绑定很像纹理绑定。您告诉程序要查看哪个插槽。使用纹理,您可以获得纹理的统一位置,然后将该统一的值设置为纹理单元索引。使用 UBO,您可以获得块的块索引,将该块索引的绑定值设置为它将查找的统一缓冲区绑定点。

因此,您应该从中获取索引glGetUniformBlockIndex并使用glUniformBlockBinding为它分配一个缓冲区绑定点。然后将缓冲区绑定到分配给统一块的绑定点。

于 2012-10-05T15:25:24.430 回答
4

只是为了扩展尼科尔的答案。大多数示例将分配和使用混为一谈,并且他们对使用槽进行硬编码,以便只支持一个缓冲区,这真的很混乱,我自己只是浪费了一天的时间。

着色器初始化设置:

    m_ubo_transform_block_index = glGetUniformBlockIndex(m_gl_program_object, "transform_uniforms");
    if (m_ubo_transform_block_index != -1)
    {
        glUniformBlockBinding(m_gl_program_object, m_ubo_transform_block_index, UBO_TRANSFORM_INDEX);
    }

UBO_TRANSFORM_INDEX 是一个插槽,就像纹理单元一样。

绘制时的用法:

        if(m_ubo_transform_block_index != -1)
        {
            glBindBufferBase(GL_UNIFORM_BUFFER, UBO_TRANSFORM_INDEX, uniform_buffer->m_uniform_transform_buffer_object);
        }
于 2016-04-14T12:54:18.523 回答