我遇到了令我困惑的事情,但我找不到答案。当我这样编写着色器时:

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;
};

每个 vector 彼此紧紧地坐着,没有填充,大小为8 * sizeof(float),32字节。我将其传递给制服,并且着色器可以很好地读取它,因此我知道它们都是对齐的。

但是,当涉及到GLSL中的统一块时,例如,使用std140标准时,在添加另一个vec3或vec4之前,必须用额外的四个字节来填充vec3:



但是,您也可以在vec3和下一个vec3之间存储一个四字节的int或四字节的bool来缩小大小。那么这是否意味着顶点布局的attrib指针值不遵循std140布局?另外,例如,如果我在C++代码中使用SIMD 16字节对齐 vector ,这是否意味着我将无法再将attrib指针值设置为vec3,vec3,vec2,而是拥有所有vec4?

另外,我在文档中看到以下警告:



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

最佳答案

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

关于警告:是的,在vec3之后使用空格来存储和int/float/bool是一种聪明的技术。但是,如警告所示,驱动程序实现有时会出错。因此,如果要确保代码在任何地方都能可靠运行,则必须进行大量测试或完全不使用vec3。再次注意,这仅在接口(interface)块的情况下才有意义。正常的vec3制服不会受到此影响。

您可以做的就是打包以存储3个浮点数和C++端的int值,但可以通过接口(interface)块中的vec4对其进行访问。然后,您可以使用floatBitsToInt(myBlock.myVec4.w)检索整数。

关于c++ - OpenGL和GLSL内存对齐以实现统一和变化,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/47616015/

10-11 16:27