我遇到了困扰我的事情,我无法找到答案。当我写这样的着色器时:
layout (location = 0) in vec3 inPosition;
layout (location = 1) in vec3 inNormal;
layout (location = 2) in vec2 inTexCoords;
我知道vec3不是16字节对齐的,因为很多vec4都是,或SIMD兼容的数据类型。我知道这个(我想),因为我的C ++代码中的数据是:
struct Vertex
{
vec3 position;
vec3 normal;
vec2 texCoords;
};
每个向量彼此紧密相连,没有填充,大小为8 * sizeof(float),32个字节。我将它传递给制服,着色器读得很好,所以我知道它们都是对齐的。
但是当谈到GLSL中的统一块时,例如std140标准,在添加另一个vec3或vec4之前,必须用额外的四个字节填充vec3:
- 如果该成员是一个三分量向量,其组件消耗N个基本机器单位,则基本对齐为4N
醇>
但是,你也可以在vec3和下一个vec3之间存储一个四字节的int或四字节bool来压缩大小。那么这是否意味着顶点布局的attrib指针值不遵循std140布局?另外,如果我在我的C ++代码中使用SIMD 16字节对齐的向量,这是否意味着我将不再能够将attrib指针值设置为vec3,vec3,vec2,而是将所有vec4设置为?
此外,我在文档中看到以下警告:
警告:实现有时会导致std140布局错误 vec3组件。建议您手动填写 结构/数组输出并完全避免使用vec3。
这里说它完全避免使用vec3,但我认为这是一种智能节省空间的技术,可以在vec3之后打包一个四字节的int或bool。
答案 0 :(得分:5)
std140布局仅适用于interface blocks,而不适用于缓冲区的内容或接口块之外的属性。由于接口块不能用作顶点着色器的输入或片段着色器的输出,因此std140不会以任何方式影响glVertexAttribPointer
的设置方式或顶点数据的存储方式。
关于警告:是的,在vec3存储和int / float / bool之后使用空格是一种聪明的技巧。但正如警告所述,驱动程序实现有时会出错。因此,如果您想确保您的代码在任何地方都可靠运行,您必须进行大量测试或根本不使用vec3。再次注意,这仅适用于接口块。这件事不会触及正常的vec3制服。
你可以做的是打包以在C ++端存储3个浮点数和一个int,但是通过接口块中的vec4访问它。您可以使用floatBitsToInt(myBlock.myVec4.w)
来检索整数。