在将数据(顶点、纹理等)传送给GPU之前,我们需要获取到相对应缓冲的索引,之前我都是使用
GLint glGetAttribLocation(GLuint program,const GLchar *name);
其中,program指定查询的程序对象,name指定要查询位置的属性变量的名称,返回的就是属性变量的位置。
glGetAttribLocation查询由program指定的先前链接的程序对象,用于name指定的属性变量,并返回绑定到该属性变量的通用顶点属性的索引。 如果name是矩阵属性变量,则返回矩阵的第一列的索引。 如果指定的属性变量不是指定程序对象中的活动属性,或者名称以保留前缀“gl_”开头,则返回-1。
可以通过调用glBindAttribLocation随时指定属性变量名和通用属性索引之间的关联。 在调用glLinkProgram之前,属性绑定不会生效。 成功链接程序对象后,属性变量的索引值将保持固定,直到发生下一个链接命令。 如果链接成功,则只能在链接后查询属性值。 glGetAttribLocation返回上次为指定程序对象调用glLinkProgram时实际生效的绑定。 glGetAttribLocation不返回自上次链接操作以来指定的属性绑定。
一般也没啥问题,只要shader里面有的属性,在这里都可以获取的到。但是这次顶点着色器中的三个属性中的my_Color就是获取不到,返回-1,以下是两个着色器内容:
vs:
attribute vec4 my_Vertex;
attribute vec4 my_Color;
uniform mat4 my_TransformMatrix;
attribute vec2 my_Texcoor;
varying vec2 vTexcoor;
varying vec4 color;
void main()
{
vTexcoor = my_Texcoor;
color = my_Color;
gl_Position = my_TransformMatrix * my_Vertex;
}
fs:
varying vec4 color;
uniform sampler2D my_Sampler;
varying vec2 vTexcoor;
void main (void)
{
vec4 tex = texture2D(my_Sampler, vTexcoor);
gl_FragColor = tex;
}
接下来想查询一下有哪些激活的属性:
GLint count;
GLint size; // size of the variable
GLenum type; // type of the variable (float, vec3 or mat4, etc)
const GLsizei bufSize = 256; // maximum name length
GLchar name[bufSize]; // variable name in GLSL
GLsizei length; // name length
glGetProgramiv(programHandle, GL_ACTIVE_ATTRIBUTES, &count);
printf("Active Attributes: %d\n", count);
for (int idx = 0; idx < count; idx++)
{
glGetActiveAttrib(programHandle, (GLuint)idx, bufSize, &length, &size, &type, name);
printf("Attribute #%d Type: 0x%x Name: %s\n", idx, type, name);
GLuint location = glGetAttribLocation(programHandle, name);
printf("location = %d \n",location);
}
结果也还是一样,没有my_Color.
纠结了好久,最终发现是因为shader在编译的时候做了优化,对于一些没有真正参与到计算的属性直接移除掉了,所以怎么找也找不到my_Color。
解决方案,使用glBindAttribLocation。
void glBindAttribLocation(GLuint program, GLuint index, const GLchar *name);
其中,program指定要在其中建立关联的程序对象的句柄。index指定要绑定的通用顶点属性的索引。name指定一个以空终止符结尾的字符串,其中包含要绑定索引的顶点着色器属性变量的名称。
在调用glLinkProgram之前,属性绑定不会生效。成功链接程序对象后,通用属性的索引值保持固定(并且可以查询它们的值),直到发生下一个链接命令。
可以在任何顶点着色器对象绑定到指定程序对象之前调用glBindAttribLocation。也允许将通用属性索引绑定到从未在顶点着色器中使用的属性变量名称。
如果以前绑定了name,则该信息将丢失。因此,您不能将一个用户定义的属性变量绑定到多个索引,但您可以将多个用户定义的属性变量绑定到同一索引。
允许应用程序将多个用户定义的属性变量绑定到相同的通用顶点属性索引。这称为aliasing(别名),仅当可执行程序中只有一个别名属性处于活动状态时,或者如果没有通过着色器的路径消耗属于同一位置的一组属性的多个属性时,才允许使用别名。允许编译器和链接器假定没有进行别名,并且可以自由地使用仅在没有别名的情况下工作的优化。不需要OpenGL实现来进行错误检查以检测别名。由于无法绑定标准属性,因此无法使用常规属性对通用属性进行别名(通用属性0除外)。
调用glLinkProgram时,链接器将绑定未显式绑定的活动属性。可以通过调用glGetAttribLocation来查询分配的位置。
调用glBindAttribLocation时,OpenGL会复制名称字符串,因此应用程序可以在函数返回后立即释放其名称字符串的副本。