c++ - 结构的 glBufferSubData 偏移量

标签 c++ opengl glsl buffer

我实际上正在使用 OpenGL 3.3 渲染引擎,确切地说,我正在尝试在我的场景中创建动态数量的灯光。

为此,我正在使用统一缓冲区对象 (UBO),当我尝试传递数据时遇到问题,而 UBO 将在具有不同类型数据的结构中读取或写入。

我为点光源和定向光源做了这件事,一切都很好,因为我只使用了 vec3数据。问题是当我定义焦点灯时,它的结构是:

#version 330 core

#define MAX_NUM_TOTAL_LIGHTS 100
...
struct FocalLight{
    vec3 f_light_position;
    vec3 f_light_direction;
    vec3 f_light_diffuse_intensity;
    vec3 f_light_specular_intensity;
    float f_apperture_angle;
    float f_attenuation;
};
layout(std140) uniform focalLights{
    FocalLight f_lights[MAX_NUM_TOTAL_LIGHTS];
};

好吧,位置、方向、漫反射强度和镜面反射强度都很好,我的片段从缓冲区正确接收了这些数据。但我无法为 f_apperture_angle 写入和读取数据和 f_attenuation .

这是我用来写入缓冲区数据的 CPU 上执行的代码,其中 focal_lights是一个包含我的 FocalLight 实例的 vector class ( std::vector<FocalLight> focal_lights ) 我检查的内容是正确的:

if(block_focal_lights_id != -1) {
    glUniformBlockBinding(programId, block_focal_lights_id, 2);
    //Loading from light vectors
    glGenBuffers(1, &buffer_focal_lights_id);
    glBindBuffer(GL_UNIFORM_BUFFER, buffer_focal_lights_id);
    glBufferData(GL_UNIFORM_BUFFER, sizeof(float) * 24 * focal_lights.size(), 0, GL_DYNAMIC_DRAW);
    int offset = 0;
    for (unsigned int i=0; i<focal_lights.size(); i++) {
        glBufferSubData(GL_UNIFORM_BUFFER, offset, sizeof(float) * 3, focal_lights[i].position);
        offset += 16;
        glBufferSubData(GL_UNIFORM_BUFFER, offset, sizeof(float) * 3, focal_lights[i].direction);
        offset += 16;
        glBufferSubData(GL_UNIFORM_BUFFER, offset, sizeof(float) * 3, focal_lights[i].diffuse_intensity);
        offset += 16;
        glBufferSubData(GL_UNIFORM_BUFFER, offset, sizeof(float) * 3, focal_lights[i].specular_intensity);
        offset += 16;
        glBufferSubData(GL_UNIFORM_BUFFER, offset, sizeof(float), &focal_lights[i].apperture_angle);
        offset += 16;
        glBufferSubData(GL_UNIFORM_BUFFER, offset, sizeof(float), &focal_lights[i].attenuation);
        offset += 16;
    }
}

我试图更改我的 f_apperture_angle 的数据类型至 vec3我可以使用之前定义的偏移量来读取它,但与使用简单的 float 无关。我确定缓冲区的绑定(bind)是正确的,我知道问题出在 glBufferData 上或 glBufferSubdata代码。

有人看到问题了吗?

终于可以工作了,感谢 Rabbid76: 2 focal lights, 2 directional lights and one point light

最佳答案

在将数据绑定(bind)到 std140 标准统一 block 布局时,您必须考虑特殊的对齐规则。

参见 OpenGL 4.6 API Compatibility Profile Specification; 7.6.2.2 Standard Uniform Block Layout; page 144

When the std140 layout is specified, the offset of each uniform in a uniform block can be derived from the definition of the uniform block by applying the set of rules described below.

  1. If the member is a scalar consuming N basic machine units, the base alignment is N

....

  1. If the member is a three-component vector with components consuming N basic machine units, the base alignment is 4N.

....

  1. If the member is a structure, the base alignment of the structure is N, where N is the largest base alignment value of any of its members, and rounded up to the base alignment of a vec4. The individual members of this substructure are then assigned offsets by applying this set of rules recursively, where the base offset of the first member of the sub-structure is equal to the aligned offset of the structure. The structure may have padding at the end; the base offset of the member following the sub-structure is rounded up to the next multiple of the base alignment of the structure.

  2. If the member is an array of S structures, the S elements of the array are laid out in order, according to rule (9).


当您将此规则应用于您的数据结构时,会产生以下偏移量:

struct FocalLight                    // size 80 (rule 9 and 10)
{
    vec3 f_light_position;           // offset 0  (rule 3 and 10)
    vec3 f_light_direction;          // offset 16 (rule 3)
    vec3 f_light_diffuse_intensity;  // offset 32 (rule 3)
    vec3 f_light_specular_intensity; // offset 48 (rule 3)
    float f_apperture_angle;         // offset 60 (rule 1)
    float f_attenuation;             // offset 64 (rule 1)
};
layout(std140) uniform focalLights{
    FocalLight f_lights[MAX_NUM_TOTAL_LIGHTS];
};

绑定(bind)数据:

int offset = 0;
for (unsigned int i=0; i<focal_lights.size(); i++) {

    glBufferSubData(GL_UNIFORM_BUFFER, offset, sizeof(float) * 3, focal_lights[i].position);

    offset += 16; // rule 3
    glBufferSubData(GL_UNIFORM_BUFFER, offset, sizeof(float) * 3, focal_lights[i].direction);

    offset += 16; // rule 3
    glBufferSubData(GL_UNIFORM_BUFFER, offset, sizeof(float) * 3, focal_lights[i].diffuse_intensity);

    offset += 16; // rule 3
    glBufferSubData(GL_UNIFORM_BUFFER, offset, sizeof(float) * 3, focal_lights[i].specular_intensity);

    offset += 12; // rule 1
    glBufferSubData(GL_UNIFORM_BUFFER, offset, sizeof(float), &focal_lights[i].apperture_angle);

    offset += 4; // rule 1
    glBufferSubData(GL_UNIFORM_BUFFER, offset, sizeof(float), &focal_lights[i].attenuation);

    offset += 16; // rules 9 and 10
}

关于c++ - 结构的 glBufferSubData 偏移量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49798189/

相关文章:

c++ - Xcode 4.5 问题与简单的 OpenGL C++ 代码

c++ - 如何从 X Y Z 旋转中找到四元数的 vector

opengl - 在 GLSL 中使用 glBindAttributeLocation 的目的是什么?

c++ - OpenGL 3.2 纹理问题

glsl - Vulkan GLSL 的统一纹素缓冲区

c++ - isdigit,如何区分字符和数字

c++ - 在 C++ 中对派生类使用基类指针有什么负面影响吗?

c++ - 松弛的内存顺序会导致这里无限循环吗?

c++ - 根据 C++ 中的外部输入选择类

c++ - 使用计算着色器进行纹理贴图