c++ - 了解 GLSL 统一缓冲区 block 对齐

标签 c++ opengl glsl shader

我无法理解 GLSL 统一缓冲区对象的 std140 布局。我的印象是,在下面的 uniform block 中,int 将从偏移量 0 开始,而矩阵将从偏移量 16 开始。下面的 uniform 给我一个错误的矩阵,很明显,因为屏幕上没有绘制任何内容。

layout (std140) uniform Camera
{
    int renderMode;
    mat4 projection;
} camera;

renderMode是它告诉我统一更新代码不起作用。

我有以下代码(自制的)来帮助我。这是在我的 C++ 应用程序中进行 Open GL 调用的代码。此代码位于名为 UniformBufferObject 的类中.

#define UpdateExData(o, s, d) glBindBuffer(GL_UNIFORM_BUFFER, _uboId); \
    glBufferSubData(GL_UNIFORM_BUFFER, o, s, d); \
    glBindBuffer(GL_UNIFORM_BUFFER, 0);

int Alignment(int offset, int alignment)
{
    int leftOver = offset % alignment;
    if (leftOver > 0)
    {
        return offset + (alignment - leftOver);
    }
    else
    {
        return offset;
    }
}

template<typename T, typename... Args>
void UpdateEx(int offset, const std::vector<T>& data, Args&... args)
{
    auto mySize = sizeof(T) * data.size();
    int myAlignment = Alignment(offset, 16); // fixed for vectors of vec4 for now
    UpdateExData(myAlignment, mySize, data.data());
    UpdateEx(myAlignment + mySize, args...);
}

template<typename... Args>
void UpdateEx(int offset, int& data, Args&... args)
{
    auto mySize = sizeof(int);
    int myAlignment = Alignment(offset, mySize); // assume 4 byte alignment for ints
    UpdateExData(myAlignment, mySize, &data);
    UpdateEx(myAlignment + mySize, args...);
}

template<typename... Args>
void UpdateEx(int offset, const glm::mat4& data, Args&... args)
{
    auto mySize = sizeof(glm::mat4);
    int myAlignment = Alignment(offset, 16); // assume 16-byte alignment for mat4
    UpdateExData(myAlignment, mySize, &data);
    UpdateEx(myAlignment + mySize, args...);
}

启动更新的代码行如下。 m是一个整数。 cam是 glm::mat4。这篇文章的目的是更新我的着色器中的相机。

cameraUbo->UpdateEx(0, m, cam);

如果我翻转 uniform 使得矩阵在前,并将上面的调用更新为 cameraUbo->UpdateEx(0, cam, m) ,矩阵更新但 renderMode 不再有效。

我真的不知道出了什么问题,真正让我困惑的是 GL_UNIFORM_BLOCK_DATA_SIZE 返回的值远远超出了我预期的 80。在它所在的 5 个着色器中,我得到了不同的值,高于 1000。

我确实有另一个 uniform 看起来工作完美,并且在出现的两个着色器中具有相同的大小。

struct TowerLight
{
    vec4 position;
    vec4 color;
};

layout(std140) uniform Towers
{
    int lightCount;
    TowerLight lights[MaxLights];
};

使用以下代码。 count是一个整数并且lightsstd::vector<struct_of_2_vec4> .

ubo->UpdateEx(0, towerCount, lights);

[编辑]

这可能是我的视频卡驱动程序中的错误。我有一个 Radeon 6870。如果我使用默认的统一 block 布局或将我的着色器版本从 440 降低到 430,我在所有着色器中得到的 block 大小为 80。

最佳答案

此页面很好地解释了对齐的工作原理 http://learnopengl.com/#!Advanced-OpenGL/Advanced-GLSL

layout (std140) uniform ExampleBlock
{
    //               // base alignment  // aligned offset
    float value;     // 4               // 0 
    vec3 vector;     // 16              // 16  (must be multiple of 16 so 4->16)
    mat4 matrix;     // 16              // 32  (column 0)
                     // 16              // 48  (column 1)
                     // 16              // 64  (column 2)
                     // 16              // 80  (column 3)
    float values[3]; // 16              // 96  (values[0])
                     // 16              // 112 (values[1])
                     // 16              // 128 (values[2])
    bool boolean;    // 4               // 144
    int integer;     // 4               // 148
}; 

关于c++ - 了解 GLSL 统一缓冲区 block 对齐,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31488266/

相关文章:

macos - Mac OS 10.8 支持 GLSL 3.30?

c++ - 如何测试某些代码不能用 C++ 编译?

c++ - 嵌套模板类

java - 如何将 GUI 组件放入 OpenGL 屏幕中

c# - GLSL 自旋锁永远阻塞

angular - 在 Angular nx 项目中导入 glsl 文件

javascript - 你如何在 glsl/webgl 中将一个 32 位的整数打包成 4 个、8 位的整数?

c++ - Eigen 库中的稀疏稀疏积 A^T*A 优化

c++ - 从数组中的文件中读取多个 float

c++ - 平滑过渡到标准 3D View 方向