OpenGL规范在于(或者这是一个错误?)...参考std140的布局,使用共享的统一缓冲区,它指出:
“Tabl e 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个字节是浮点数(GLfloat的机器标量类型的大小),接下来的16个字节是vec4,后面的12个字节是vec3(末尾有4个字节,考虑到规则vec3真的是一个vec4)。
当我改变CPU端以指定一个浮点数与vec4的大小相同时,即16个字节,并做我的偏移和缓冲区大小做出这个假设,着色器按预期工作。
所以,无论是规范是错还是我在这种情况下误解了“标量”的含义,或者ATI有驱动程序错误。任何人都可以对这个谜团有所了解吗?
答案 0 :(得分:11)
您链接的PDF是不 OpenGL specification。我不知道你从哪里得到它,但那肯定不是完整的规则列表。始终检查您的来源;规范并不像许多人声称的那样难以理解。
是的,基本类型变量的 size 与基本机器类型的大小相同(即:4个字节)。但是单独的大小并不能确定变量的位置。
每种类型都有一个基本对齐,无论在统一块中找到哪种类型,它的整体字节偏移必须适合该对齐。 vec4
的基本对齐方式是其基本类型的对齐方式(即:float)。所以vec4
的基本对齐是16。
因为Light_Intensity
在4个字节之后结束,所以编译器必须插入12个字节的填充,因为Light_Ambient
不能在4字节边界上。它必须在16字节边界上,因此编译器使用12个字节的空白空间。
ATI确实在std140布局周围有一些驱动程序错误,但这不是其中之一。
作为一般规则,我喜欢明确地将填充放入我的结构中,并且我避免使用vec3
(因为它具有16字节对齐)。这样做通常可以减少编译器错误以及对事情发展的意外误解以及他们实际需要多少空间。