OpenGL GLSL 统一缓冲区对象

Posted

技术标签:

【中文标题】OpenGL GLSL 统一缓冲区对象【英文标题】:OpenGL GLSL uniform buffer objects 【发布时间】:2021-12-27 10:47:33 【问题描述】:

我有一个 UBO,这是片段着色器中的代码。

layout (std140,binding = 5) uniform uAmbientLights

    vec4 position[10];
    vec4 color[10];
    vec4 intensity[10];
    vec4 radius[3];
;

我的 C++ 代码是这样的。我的代码所做的是创建一个缓冲区、向量容器,最多可以容纳 10 个光数据。我将设置位置 x/y、颜色和强度 x/y/z 以及半径值。当我读到我需要做填充时,我使用了 vec4。

    glCreateBuffers(1, &UBO);

    std::vector<float> pos(40);
    std::vector<float> clr(40);
    std::vector<float> intensity(40);
    std::vector<float> radius(12);

    glNamedBufferData(UBO, sizeof(float) * (pos.size() + clr.size() + intensity.size() + radius.size()), NULL, GL_DYNAMIC_DRAW);

    size_t posCount, clrCount, intensityCount, radiusCount, numOfAmbientLights;

    for (eID curr : engine.GetSystem<sIdentifierSystem>().FindTaggedEntities(engine, "AMBIENTLIGHT"))
    
        Transform& LTR = engine.GetComponent<Transform>(curr);
        Lighting& LL = engine.GetComponent<Lighting>(curr);

        pos[posCount++] = LTR.GetPosition().x;
        pos[posCount] = LTR.GetPosition().y;

        clr[clrCount++] = LL.getColor().x;
        clr[clrCount++] = LL.getColor().y;
        clr[clrCount] = LL.getColor().z;

        intensity[intensityCount++] = LL.getIntensity().x;
        intensity[intensityCount++] = LL.getIntensity().y;
        intensity[intensityCount] = LL.getIntensity().z;

        radius[radiusCount] = LL.getRadius();

        posCount += 3;
        clrCount += 2;
        intensityCount += 2;
        ++radiusCount;
        ++numOfAmbientLights;
    

    glNamedBufferSubData(UBO, 0, sizeof(float) * pos.size(), &pos);
    glNamedBufferSubData(UBO, sizeof(float) * pos.size(), sizeof(float) * clr.size(), &clr);
    glNamedBufferSubData(UBO, sizeof(float) * pos.size() + sizeof(float) * clr.size(), sizeof(float) * intensity.size(), &intensity);
    glNamedBufferSubData(UBO, sizeof(float) * pos.size() + sizeof(float) * clr.size() + sizeof(float) * intensity.size(), sizeof(float) * radius.size(), &radius);

    glBindBufferBase(GL_UNIFORM_BUFFER, 5, UBO);

我的值根本没有传递到着色器中。在为多个灯光使用数组之前,我的代码在它只包含 1 个灯光数据时工作。

我做错了什么?我避免使用 vec3s 和浮点数,将我所有的值存储在 vec4 中,值为 0 进行填充。我检查了我的矢量容器值是否按顺序正确。

我的 GL_MAX_UNIFORM_BLOCK_SIZE 给了我 65k 字节,而我只占用 (40+40+40+12)*4 = 528 字节

【问题讨论】:

【参考方案1】:

我的坏.. 更新缓冲区时,应改为 4 行

    glNamedBufferSubData(UBO, 0, sizeof(float) * pos.size(), pos.data());
    glNamedBufferSubData(UBO, sizeof(float) * pos.size(), sizeof(float) * clr.size(), clr.data());
    glNamedBufferSubData(UBO, sizeof(float) * pos.size() + sizeof(float) * clr.size(), sizeof(float) * intensity.size(), intensity.data());
    glNamedBufferSubData(UBO, sizeof(float) * pos.size() + sizeof(float) * clr.size() + sizeof(float) * intensity.size(), sizeof(float) * radius.size(), radius.data());

我将地址传递给向量,而不是直接传递向量数据

【讨论】:

以上是关于OpenGL GLSL 统一缓冲区对象的主要内容,如果未能解决你的问题,请参考以下文章

用于片段着色器的 OpenGL GLSL 绑定采样器

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

GLSL:采样器上传仅在删除未使用的采样器时有效

我的OpenGL学习进阶之旅统一变量和属性

我的OpenGL学习进阶之旅统一变量和属性

✠OpenGL-2-图像管线