2017-12-03 290 views
2

我想到了一些令我困惑的东西,我无法找到答案。当我写的着色器是这样的:用于制服和变化的OpenGL和GLSL内存对齐

layout (location = 0) in vec3 inPosition; 
layout (location = 1) in vec3 inNormal; 
layout (location = 2) in vec2 inTexCoords; 

我知道VEC3的不对齐,许多vec4的是,或SIMD兼容的数据类型的16字节。我知道这(我想),因为我在我的C++代码数据是:

struct Vertex 
{ 
    vec3 position; 
    vec3 normal; 
    vec2 texCoords; 
}; 

每个矢量彼此位于紧贴地,无填料,尺寸为8 *的sizeof(浮动),32个字节。我把它传递给制服,着色器读取它很好,所以我知道它们都是对齐的。

但是,当涉及到在GLSL均匀块,与例如std140标准一个VEC3必须用一个额外的4个字节填充添加另一VEC3或vec4之前:

  1. 如果构件是与耗时N基本机器单元部件三个成分的矢量,基座对准为4N

但是也可以存储在VEC3和下一VEC3之间的四字节int或四字节布尔压实尺寸。那么这是否意味着顶点布局的attrib指针值不遵循std140布局?另外,如果我在我的C++代码中使用SIMD 16字节对齐的向量,这是否意味着我将不能再将attrib指针值设置为vec3,vec3,vec2,而是拥有所有vec4的?

而且我看到的文件上以下警告:

警告:实现有时得到std140布局错 VEC3组件。建议您手动填充 结构/阵列,并避免使用vec3。

这里说的是避免使用vec3,但我认为这是一个聪明的节省空间的技术,在vec3之后打包一个四字节的int或bool。

回答

4

std140布局仅适用于interface blocks,而不适用于接口块外的缓冲区或属性的内容。由于接口块不能用作顶点着色器的输入或来自片段着色器的输出,因此std140不会以任何方式影响如何设置glVertexAttribPointer或顶点数据如何存储。

关于警告:是的,使用vec3之后的空间来存储和int/float/bool是一个聪明的技巧。但正如警告所述,驱动程序的实现有时会出错。所以如果你想确保你的代码在任何地方都能可靠地运行,你要么测试很多,要么根本不使用vec3。再次请注意,这只在接口块的情况下才有意义。普通的vec3制服不会被这个感动。

你可以做的是打包存储3个浮点数和一个int在你的C++端,但通过接口块中的vec4访问它。您可以使用floatBitsToInt(myBlock.myVec4.w)来检索整数。

+0

这很有帮助。该floatBitsToInt完全吹捧我的想法,因为起初我试图找到一个u8vec4来存储0 - 255 RGBA,然后发现glsl根本不处理单字节数据类型,所以我的下一个想法是发送一个int并使用位操作员可以获得正确的颜色通道。 – Zebrafish

+0

稍等片刻,我仍然不得不做甚至floatBitsToInt我刚才意识到。如果我的0 - 255颜色是我的vec4.w,我仍然需要移位并提取正确的字节。 – Zebrafish