A uniform is only active if the GLSL compiler and/or linker determine that it is used in the shader, or cannot conclusively determine that it is not used in the shader. As an example, in the following shader pair foo, rex, and gl_LightModel.ambient are the only active uniforms.
Even though v_color, f_color, and rex are all used in the code as written they do not have any affect on the final vertex position or fragment color. As such, a good GLSL compiler/linker will determine that they are unused.
Vertex attributes have similar rules. In order to be considered active they must in some way affect the final vertex position or fragment color.
This differentiation between active and inactive can be important, especially if you are dealing with procedurally generated shaders. Only active uniforms and attributes count towards implementation defined limits. That is, if your implementation has a limit of 16 vertex attributes you can still declare more than 16 as long as 16 or fewer actually affect the final vertex position or fragment color.
Rendering to multiple buffers, known as MRT to the Direct3D world, can be accomplished with the GL_ARB_draw_buffers extension. Using this extension is incredibly simple. For example, to draw to the back and AUX0 buffers simultaneously, you would use the following code:
Of course, this is rather dull unless we can actually write different colors to different buffers. In order to do this, shaders must be used. In GLSL, you can select which buffer is written to by writing to gl_FragData[n] in place of gl_FragColor. If you are using GL_ARB_fragment_program, you can select which buffer is written to by writing to result.color[n].
writeImage(pboMemory); // Writes data into pboMemory
// Unmaps buffer, indicating we are done writing data to it glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER_ARB); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, (char *)NULL);
Normally the driver must copy the data you pass into glTexSubImage2D. However, by storing the data in a buffer, which is memory managed by the driver, we can avoid this copy. Furthermore, by using a universally hardware accelerated texture format (see this tip) we prevent any data processing, ensuring the fastest possible download to the GPU.
While you can query the location of a generic vertex attribute in a GLSL shader by calling glGetAttribLocation(GLuint program, const GLchar *name), you can also set the location of a generic vertex attribute manually using glBindAttribLocation(GLuint program, GLuint index, const GLchar *name)
NOTES: Manually set attribute locations do not take effect until glLinkProgram(GLuint program) is called.
You cannot manually assign a location to a built in vertex attribute (e.g. gl_Vertex).
It is possible to assign the same location to multiple attributes. This process is known as aliasing, and is only allowed if just one of the aliased attributes is active in the executable program. HOWEVER the implementation is not required to check for aliasing and is free to employ optimizations that only work in the abscence of aliasing.
Any vertex attribute which is not manually assigned a location will be assigned one by the linker, and this location can be queried with glGetAttribLocation(GLuint program, const GLchar *name).