着色器存储缓冲区发送数据错误

时间:2014-04-10 19:30:23

标签: c++ opengl

我有一个着色器存储缓冲区,它将一个带有一个vec3的结构发送到着色器。我这样发送:

GLint bufMask = GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT;
lightData * ld = (lightData *) glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(lightData), bufMask);
ld[0].ambient = glm::vec3(1.f, 0.5f, 1.f);
glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
glBindBufferBase( GL_SHADER_STORAGE_BUFFER, 0, m_lightData );

目前,它只是用于测试,所以不要错过为什么它的大小只有一个。

无论如何,在着色器中,当我绘制vec4(灯光[0] .ambient.x);当我画画时,我变黑了。我变白了,当我画画时。我变灰了。所以看起来元素是一个人。那是为什么?

编辑:

结构:

struct lightData {
    glm::vec3 ambient;
};

缓冲区生成:

glGenBuffers(1, &m_lightData);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_lightData);
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(lightData), NULL, GL_STATIC_DRAW);

缓冲区使用:见上文

着色器:

#version 430 core
layout(location = 0) out vec4 result;
struct lightData {
    vec3 ambient;
};
layout(std430, binding = 0) buffer BufferObject {
    lightData lights[];
};
void main() {
    result = vec4(lights[0].ambient, 1.f);
}

EDIT2:我用漂浮物尝试过它,这很有效。我回到了矢量,现在它的工作原理!我以前不知道出了什么问题。抱歉!可以关闭。

1 个答案:

答案 0 :(得分:2)

std430会将vec3的结构填充到vec4按照规则(3)(9)的大小::

OpenGL 4.4 Core Profile Specification - 7.6.2.2标准统一区块布局 - 第124页

  
    

(3)如果该成员是一个三分量向量,其组件消耗N.     基本机器单元,基准线是4N。

         

(9)如果成员是结构,则结构的基本对齐为N,其中N是其任何成员的最大基本对齐值,并向上舍入为vec4 的基本对齐方式。然后通过递归地应用这组规则来为该子结构的各个成员分配偏移,其中子结构的第一个成员的基本偏移等于结构的对齐偏移。该结构可以在末端具有填充物;子结构后面的成员的基本偏移量向上舍入到结构的基本对齐的下一个倍数。

  

* 注意:有关舍入vec4的基本对齐的要点不适用于std430;如果你读了规则(9),我划掉的部分实际上只适用于std140

您的vec3具有vec4的基本对齐方式,因此对于此结构的数组,要将vec3 ambient的每个实例与4N对齐,它必须填充结构的末尾。您可以使用以实现定义的方式打包结构的不同布局,但它比大多数时候的值更麻烦。

最重要的是,GL并不太关心任何3组件。大多数事情需要是1,2或4,这是GL无法用你的3种组件数据类型隐藏其中的一种情况。

对于解决方案,您可以将数据存储为glm::vec4,也可以将float添加到数据结构的末尾。无论哪种方式,存储要求都是相同的。