Multitexturing Conflicting with Single Texturing

Hello,
I asked this question in the beginners section, but perhaps this is a better place!

I have been using single texturing for my terrain and models in my scene.

I then decided to add multitexturing for the terrain, which works fine.

But, somehow the single texturing no longer works. The models are no longer textured, nor is the skybox.

Somehow I’ve got to be able to activate and deactivate the multitexturing when I need it. But, I’m not sure how. I suppose I could implement multitexturing for everything, but would prefer to keep the code as is if possible. Any feedback would be appreciated.

Thanks!

Below is part of the code I’m using for the terrain.

renderTerrain() {
lActiveTextureARB(GL_TEXTURE0_ARB);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, g_oTM.getTex(textureIdx0));
glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
glActiveTextureARB(GL_TEXTURE1_ARB);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, g_oTM.getTex(textureIdx1));
glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD);

//Render Triangle Strips Here

glActiveTextureARB(GL_TEXTURE0_ARB);
glDisable(GL_TEXTURE_2D);
glActiveTextureARB(GL_TEXTURE1_ARB);
glDisable(GL_TEXTURE_2D);
}

You need to make GL_TEXTURE0_ARB the active texture again. It’s best to disable your textures backwards…like GL_TEXTURE3_ARB then GL_TEXTURE2_ARB then GL_TEXTURE1_ARB then GL_TEXTURE0_ARB.

Thanks, Whatever.

The order made the difference.

Originally posted by Archimedes:
[b]Thanks, Whatever.

The order made the difference.[/b]

I’m glad it solved your problem, but this doesn’t make any sense. The order shouldn’t make any difference.

Is it possible that some subsequent code was expecting that the active unit was texture zero? In other words, if you put ‘ActiveTexture(TEXTURE0)’ after disabling texture units zero and one, does this also fix your problem?

secnuop, even though I’m using single texturing for the other objects in the scene, you appear to be right.

If I activate the 0th texture at the end of the renderTerrain() function, that seems to allow the other objects to be textured.

I guess they are tied together.

State in GL persists until you change it. There is no “memory” (except for the Push stuff, which I try to avoid where possible).

Thus, if you have two render functions; one doing:

render1() {
BindTexture( 1 );

DrawGeometry();
}

render2() {
ActiveTexture( TEXTURE0 );
Enable( TEXTURE_2D );
BindTexture( 2 );
ActiveTexture( TEXTURE1 );
Enable( TEXTURE_2D );
BindTexture( 3 );

DrawGeometry();
}

There’s no way for the GL to know that you want TEXTURE0 to be active at the start of render1(). If you’re executed render2(), it will leave TEXTURE1 active.

There are two coding paradigms to fix this:

  1. always re-set the state after you’re done to some default state, which you can expect everywhere else

  2. always explicitly set up all state you know you need

I prefer 2) (coupled with an application-level state cache).

Note that render1() not only needs to call ActiveTexture( TEXTURE0 ) to get what it wants; it also needs to make sure to disable the TEXTURE1 texture target. Thus, it’s usually convenient to wrap everything you need about textures into a texture state block, and call some utility function which takes care of actually make sure that texturing looks like that.

secnuop, the order doesn’t matter. It’s just that if you disable from highest texture to lowest you end up back at texture unit 0 in the end, which is what you want.

Texture unit 0 is OpenGLs default.

The way multitexture works never seemed all that intuitive to me. Here’s how I think of it:

Basically, in an implementation that supports multiple texture units there are ALWAYS n copies of state. They are ALWAYS applied when enabled. If you turn on a texture on unit 3, it will stay on until you turn it off. By default, all units are disabled. If you never update the state for any unit other than zero, you’re basically operating in a 1-texture mode.

ActiveTexture is a piece of state that says which of the <n> copies is updated when you define a texture image, enable a map, update a texture blend mode, or whatever.

ClientActiveTexture works identically, except that it affects only texture coordinate array state and enables.

[[ The reason for the separate “client” call is to simplify matters for client-server implementations (where the client on one machine sends commands to the server on another). If there were only one piece of state, the client would have to track a whole bunch of state to keep its copy consistent with the server’s. This doesn’t seem too hard at first, but you have to handle Push/Pop, and worse, the error semantic that you can’t call ActiveTexture inside a Begin/End. ]]