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字节对齐(。这样做通常可以减少编译器错误,以及对事情进展和实际占用空间的意外误解。