OpenGL Uniform Buffer std140布局,驱动程序错误或我误解了规范



OpenGL规范存在(或者这是一个错误?(。。。参考std140的布局,使用共享的统一缓冲区,它指出:

"表L-1中显示的一组规则由GLSL编译器用于在std140限定的统一块中布局成员。的偏移块中的成员是基于块中以前的成员(在中的变量之前声明的成员问题(以及起始偏移量。第一个的起始偏移成员始终为零。

标量变量类型(bool、int、uint、float(-中标量的大小基本机器类型">

(http://www.opengl-redbook.com/appendices/AppL.pdf)

因此,有了这些信息,我在着色器中设置了一个统一的块,看起来像这样:

// Spotlight.
layout (std140) uniform Spotlight
{
    float Light_Intensity;
    vec4  Light_Ambient;
    vec3  Light_Position;   
};

结果发现它不适用于我在CPU端设置的后续std140布局。也就是说,前4个字节是float(GLfloat的机器标量类型的大小(,接下来的16个字节是vec4,接下来的12个字节是vec3(考虑到vec3实际上是vec4的规则,末尾还有4个字节(。

当我更改CPU端以将浮点指定为与vec4相同的大小(即16字节(,并进行偏移和缓冲区大小的假设时,着色器会按预期工作。

因此,要么是规范错误,要么是我误解了"标量"在本文中的含义,要么是ATI有驱动程序错误。有人能揭开这个谜吗?

您链接到的PDF是而不是OpenGL规范。我不知道你从哪里得到的,但这肯定不是完整的规则列表。始终检查您的来源;该规范并不像许多人声称的那样不可读。

是的,基本类型变量的大小与基本机器类型的大小相同(即:4字节(。但大小本身并不能决定变量的位置

每个类型都有一个基本对齐方式,无论该类型在统一块中的何处,其总字节偏移量都必须符合该对齐方式。vec4的基本排列是其基本类型(即:浮点(的排列的4*。因此CCD_ 2的碱基排列是16。

由于Light_Intensity在4个字节之后结束,编译器必须插入12个字节的填充,因为Light_Ambient不能位于4个字节的边界上。它必须在16字节的边界上,因此编译器使用12字节的空白空间。

ATI在std140布局方面确实存在一些驱动程序错误,但这不是其中之一。

一般来说,我喜欢将填充显式地放入我的结构中,并且我避免使用vec3(因为它有16字节对齐(。这样做通常可以减少编译器错误,以及对事情进展和实际占用空间的意外误解。

最新更新