我遇到了困扰我的事情,我无法找到答案 . 当我写这样的着色器时:
layout (location = 0) in vec3 inPosition;
layout (location = 1) in vec3 inNormal;
layout (location = 2) in vec2 inTexCoords;
我知道vec3不是像许多vec4那样对齐16字节,或者是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的?
另外,我在文档中看到以下警告:
警告:实现有时会使vec3组件的std140布局错误 . 建议您手动填充结构/阵列,避免使用vec3 .
这里是为了避免使用vec3,但我认为这是一种智能节省空间的技术,可以在vec3之后打包一个四字节int或bool .
1 回答
std140布局仅适用于interface blocks,而不适用于缓冲区的内容或接口块之外的属性 . 由于接口块不能用作顶点着色器的输入或片段着色器的输出,因此std140不会以任何方式影响
glVertexAttribPointer
的设置方式或顶点数据的存储方式 .关于警告:是的,在vec3存储和int / float / bool之后使用空间是一种聪明的技术 . 但正如警告所述,驱动程序实现有时会出错 . 因此,如果您想确保您的代码在任何地方都可靠运行,您必须进行大量测试或根本不使用vec3 . 再次注意,这仅适用于接口块 . 正常的vec3制服没有被这个触及 .
您可以做的是打包以在C侧存储3个浮点数和一个int,但是通过接口块中的vec4访问它 . 您可以使用
floatBitsToInt(myBlock.myVec4.w)
检索整数 .