先看一段vertex shader

#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
layout (location = 2) in vec2 aTexCoord;

out vec3 ourColor;
out vec2 TexCoord;

void main()
{
gl_Position = vec4(aPos, 1.0);
ourColor = aColor;
TexCoord = vec2(aTexCoord.x, aTexCoord.y);
}

当我们在调用shader之前,会声明vertex的attribPointer,实际上就是告诉显卡,这个vertex的内存布局

location=xxx,这个东东叫vertex attribute index

GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 8 * sizeof(float), 0);
GL.EnableVertexAttribArray(0);
GL.VertexAttribPointer(1, 3, VertexAttribPointerType.Float, false, 8 * sizeof(float), 3 * sizeof(float));
GL.EnableVertexAttribArray(1);
GL.VertexAttribPointer(2, 2, VertexAttribPointerType.Float, false, 8 * sizeof(float), 6 * sizeof(float));
GL.EnableVertexAttribArray(2);

三次调用GL.VertexAttribPointer的第一个参数,0,1,2,就是location

那么,能不能不按照递增顺序写呢?比如,第一个改成5,怎么样?

答案是,可以。

如果shader里这样写:(省略后半部分shader)

#version 330 core
layout (location = 5) in vec3 aPos;
layout (location = 1) in vec3 aColor;
layout (location = 2) in vec2 aTexCoord;

那么描述aPos的代码,就应该这样改:

GL.VertexAttribPointer(5, 3, VertexAttribPointerType.Float, false, 8 * sizeof(float), 0);
GL.EnableVertexAttribArray(5);

把vertex attribute index,都修改为5.

那么,最大的vertex attribute index是多少呢?可以通过一个函数来查询:

int maxVertexAttrib = GL.GetInteger(GetPName.MaxVertexAttribs);

我的显卡是gt 1030,这个值是16。

看官方文档,描述如下:

GL_MAX_VERTEX_ATTRIBS

data returns one value, the maximum number of 4-component generic vertex attributes accessible to a vertex shader. The value must be at least 16. See glVertexAttrib.

官方文档规定的最小值就是16。显卡也就只实现了16个。实际上也够用了,平时也就是位置法线纹理切线负切线。

也就是说,一般情况下,顶点可以有最多16个属性。