17
votes

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

  • glActiveTexture
  • glBindTexture (operates on active texture unit)
  • glTexImage2D (operates on currently bound object)

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?

1
It sounds to me like you have the right idea, I don't see the flaw. Perhaps you could put up the minimal example in which you get the wrong textures drawn, so that we can see if you haven't made a mistake?Tim
I looked at this question when I was having a similar issue. My issue was due to a static variable that shouldn't have been static. I'm developing for iOS and I was able to figure it out using the OpenGL debugger in Xcode. Not sure if you're on iOS, but if you're just getting started with tutorials, I thought it would be helpful to point out this debugger: developer.apple.com/library/mac/#recipes/xcode_help-debugger/…GingerBreadMane
@Shitesh - did you ever solve your problem?nbubis
Hi! Wow, I completely forgot about this. I'll go back and look into it again, and post an update/answer sometime soonish. If I recall correctly, though, I ended up rewriting that whole section of code to avoid the problem entirely.Shitesh

1 Answers

11
votes

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;
}