Getting a list of active vertex input attributes and indices
As covered in the previous recipe, the input variables within a vertex shader are linked to generic vertex attribute indices at the time the program is linked. If we need to specify the relationship, we can either call glBindAttribLocation
before linking, or we can use layout qualifiers within the shader itself.
However, it may be preferable to let the linker create the mappings automatically and query for them after program linking is complete. In this recipe, we'll see a simple example that prints all the active attributes and their indices.
Getting ready
Start with an OpenGL program that compiles and links a shader pair. You could use the shaders from the previous recipe.
As in previous recipes, we'll assume that the handle to the shader program is stored in a variable named programHandle
.
How to do it...
After linking the shader program, use the following steps to print information about the active attributes in your shader program:
Retrieve the number of active attributes and the maximum length of their names using
glGetProgramiv
.GLint maxLength, nAttribs; glGetProgramiv(programHandle, GL_ACTIVE_ATTRIBUTES, &nAttribs); glGetProgramiv(programHandle, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxLength);
Allocate a buffer to hold each attribute name.
GLchar * name = (GLchar *) malloc( maxLength );
Get and print information about each active attribute using
glGetActiveAttrib
andglGetAttribLocation
.GLint written, size, location; GLenum type; printf(" Index | Name\n"); printf("------------------------------------------------\n"); for( int i = 0; i < nAttribs; i++ ) { glGetActiveAttrib( programHandle, i, maxLength, &written, &size, &type, name ); location = glGetAttribLocation(programHandle, name); printf(" %-5d | %s\n",location, name); } free(name);
How it works...
We start by querying for the number of active attributes by calling glGetProgramiv
with the argument GL_ACTIVE_ATTRIBUTES
. The result is stored in nAttribs
. Next, we query for the length of the longest attribute name (GL_ACTIVE_ATTRIBUTE_MAX_LENGTH
) and store the result in maxLength
. This includes the null terminating character, so we use that value to allocate space to store each variable name.
Next, we loop over each index (0 to nAttrib
- 1), and retrieve information about each attribute by calling glGetActiveAttrib
and glGetAttribLocation
. The function glGetActiveAttrib
returns a bunch of information about the attribute at the index provided as the second argument. Note that this index is not necessarily the same as the generic vertex attribute index (location) for the variable. The function provides the attribute name, size, and type, which are stored in the variables name
, size
, and type
. Once we have the variable name, we can query for its location (the generic attribute index), by calling glGetAttribLocation
, and passing in the program handle and the variable name. We then print the variable's location and name to standard out.
There's more...
It should be noted that, in order for a vertex shader input variable to be considered active, it must be used within the vertex shader. In other words, a variable is considered active if it is determined by the GLSL linker that it may be accessed during program execution. If a variable is declared within a shader, but not used, the above code will not display the variable because it is not considered active and will be effectively ignored by OpenGL.
See also
Compiling a shader
Linking a shader program
Sending data to a shader using per-vertex attributes and vertex buffer objects