【问题标题】:Understanding GLSL Uniform Buffer Block Alignment了解 GLSL 统一缓冲区块对齐
【发布时间】:2015-07-18 05:57:57
【问题描述】:

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

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);

如果我翻转制服以使矩阵在前,并将上面的调用更新为 cameraUbo-&gt;UpdateEx(0, cam, m),矩阵会更新但 renderMode 不再起作用。

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

我确实有另一个制服,看起来工作得很好,并且在出现的两个着色器中具有相同的大小。

struct TowerLight
{
    vec4 position;
    vec4 color;
};

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

使用以下代码。 count 是整数,lightsstd::vector&lt;struct_of_2_vec4&gt;

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

[编辑]

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

【问题讨论】:

    标签: c++ opengl glsl shader


    【解决方案1】:

    这个页面很好地解释了对齐的工作原理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
    }; 
    

    【讨论】:

    • 原来是我的显卡驱动不支持Open GL 4.5。一旦我在着色器中将它降低到 4.4,它就起作用了。
    【解决方案2】:

    显卡驱动的东西。不支持 Open GL 4.5。

    【讨论】:

      猜你喜欢
      • 2014-05-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-23
      • 1970-01-01
      • 1970-01-01
      • 2021-05-03
      • 1970-01-01
      相关资源
      最近更新 更多