【问题标题】:GLSL layout std140 padding dilemmaGLSL布局std140填充困境
【发布时间】:2024-01-04 13:04:01
【问题描述】:

我有以下统一缓冲区:

layout(std140) uniform Light
{
    vec4  AmbientLight;
    vec4  LightIntensity;
    vec3  LightPosition;
    float LightAttenuation;
};  

在缓冲数据和需要添加的填充时,我遇到了一些问题。我已经阅读了http://ptgmedia.pearsoncmg.com/images/9780321552624/downloads/0321552628_AppL.pdf,它说我必须在 vec3 的末尾添加额外的 4 个字节用于填充 - 所以我将为“Light”上传总共 13 个字节。然而,当我这样做时,'LightAttenuation' 会得到我在'LightPosition' 上填充的值,而不是提前一个字节,所以当我不填充时,我会在着色器中得到正确的值。这是为什么呢?

【问题讨论】:

  • "我已阅读 [PDF] 中的内容" 谁在乎它说什么? The OpenGL specification 是主要来源;其他一切都是次要的。而且std140布局的描述并不像人们说的那么难读。

标签: c++ opengl glsl uniform


【解决方案1】:

有关详细信息,请参阅 OpenGL 规范的第 7.6.2.2 节,但基本上,std140 布局表示每个变量将立即布置在前一个变量之后,并为变量类型所需的对齐添加了足够的填充。 vec3vec4 都需要 16 字节对齐,分别为 12 和 16 字节。 float 需要 4 字节对齐并且有 4 字节大小。因此,对于std140 布局,LightPosition 将获得 16 字节对齐,因此将始终以 12 mod 16 的地址结束。由于这是 4 字节对齐,因此不会在 LightAttenuation 之前插入额外的填充。

【讨论】:

    【解决方案2】:

    通常是的,openGL 会将 vec3 视为 vec4。但是在这种情况下,AFAIK 将浮动 LightAttenuation 附加到 vec3 LightPosition - 形成一个整体 vec4(它的某种优化,由 glsl 编译器完成)。 整个结构的大小将是 3x vec4。

    尝试使用 vec3 或 vec4 进行 LightAttenuation。

    【讨论】: