Alright, so these textures are really confusing me. I've been looking at this tutorial (which I think is great), particularly the image captioned with "You can define up to 32 Texture Units, but just up to 8 textures per shader.". As I understand it, here's how it works:
You activate a texture unit. You then bind a texture object (analogous to the 'Texture Data' cubes in the image) to a certain target within that unit. So, glGenTextures to make the objects & get their names, and then glBindTexture to bind that texture to TEXTURE_2D or something (I'm not interested in other targets at the moment). Then you can specify the texture data with glTexImage2D.
Now. I'm using 3 shader programs, each with different textures required. Here's what I want to do:
In an initialization stage, I go through each of my texture units, and go
and for the shaders, I glUniform to match a uniform in each shader to the 'i' value specified in GL_TEXTUREi of glActiveTexture. I need a total of only four textures, and they're pretty tiny.
Now, during rendering, I should be able to switch programs fine, and everything works, right? Each program already has a uniform specifying which unit to use, and each unit already has an object bound to its TEXTURE_2D target, and each object has data specified by glTexImage2D, right? So no binding or activating units required in my render function? At least that's how I understood it, but I'm getting the wrong textures drawn in the wrong places.
Furthermore, in one of my programs I want to switch between three textures for a single surface. So I figured I load each of the textures into an object, and bind each of the objects to a unit, then at render time I can just glUniform to tell the program which texture unit to use.
So I'm wondering whether I've misunderstood the fundamental structure of texturing in OpenGL, or whether bindings of objects to units expire when programs are switched, or something like that. Or whether I have to bind a texture multiple times -- but when, and why?
Don't forget to set glTexParameteri for each texture object.
void loadTextures() {
GLint texture_object_handles[3];
glGenTextures(3, texture_object_handles);
for (int i = 0 ; i < 3 ; ++i) {
glActiveTexture(GL_TEXTURE0 + i);
glBindTexture(GL_TEXTURE_2D, texture_object_handles[i]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, ...);
}
return;
}
void draw() {
// Draw three different materials without rebinding any textures.
for (i = 0 ; i < 3 : ++i) {
... specify other uniforms and attributes
glUniform1i(texture_location, i);
...
glDrawElements(...);
}
return;
}