PDA

View Full Version : when to use glActiveTexture?



shapeare
06-18-2011, 10:34 PM
In the book OpenGL programming guide, Example 9-7 uses two texture objects and it does not call glActiveTexture before calling glBindTexture, while in Example 9-10, it calls glActiveTexture before glBindTexture. What's the difference?

what's the difference between glActiveTexture and glBindTexture? It seems they both can activate a texture.

Alfonse Reinheart
06-18-2011, 11:27 PM
Imagine that OpenGL internally looks like this:



struct TextureUnit
{
GLuint targetTexture1D;
GLuint targetTexture2D;
GLuint targetTexture3D;
GLuint targetTextureCube;
...
};

TextureUnit textureUnits[GL_MAX_TEXTURE_IMAGE_UNITS]
GLuint currentTextureUnit = 0;


glActiveTexture means this:



void glActiveTexture(GLenum textureUnit)
{
currentTextureUnit = GL_TEXTURE0 - textureUnit;
}


And glBindTexture does this:



void glBindTexture(GLenum textureTarget, GLuint textureObject)
{
TextureUnit *texUnit = &textureUnits[currentTextureUnit];
switch(textureTarget)
{
case GL_TEXTURE_1D: texUnit->targetTexture1D = textureObject; break;
case GL_TEXTURE_2D: texUnit->targetTexture2D = textureObject; break;
case GL_TEXTURE_3D: texUnit->targetTexture3D = textureObject; break;
case GL_TEXTURE_CUBEMAP: texUnit->targetTextureCube = textureObject; break;
}
}


Obviously there would be error testing, but that's the idea. All of the functions that modify the texture use the "currentTextureUnit" set by glActiveTexture. The target parameter they take tells which bound texture location within that texture unit to use.

So if you have:



glActiveTexture(GL_TEXTURE0 + 5);
glBindTexture(GL_TEXTURE_2D, object);
glTexImage2D(GL_TEXTURE_2D, ...);


The texture being uploaded to is the one stored in textureUnits[5]->targetTexture2D. Each texture that you bind has a texture target and a texture unit; this specifies its unique location in the context.

I don't have that particular book, but one often binds a texture to the context just to upload some data or to modify it. It doesn't matter at that point which texture unit you bind it to, so there's no need to set the current texture unit. glTexImage2D doesn't care if the current active texture is 0, 1, 40, or whatever.

However, texture units have special meaning to the rendering of objects. When you bind textures for the purpose of rendering with them, you need to bind them to a particular texture unit. Therefore, you need to set the current texture unit before you do the bind.

Aleksandar
06-19-2011, 02:19 AM
Great explanation, Alfonse!


In the book OpenGL programming guide, Example 9-7 uses two texture objects and it does not call glActiveTexture before calling glBindTexture, while in Example 9-10, it calls glActiveTexture before glBindTexture. What's the difference?

Example 9-10 is not complete; maybe that why you are confused. Think in this way: If there is a need for several textures used simultaneously, then glActiveTexture() must be applied in order to setup each texture unit (see previous Alfonse's post). If you need just one texture at a time, only one unit (usually 0) is used.

Be aware that the number of texture units is limited. On mobile devices there are usually only two. On desktop systems it should be at least 8.

Dark Photon
06-19-2011, 01:48 PM
what's the difference between glActiveTexture and glBindTexture? It seems they both can activate a texture.
You got some good answers already. I'll just add one thing to that. glActiveTexture selects the active texture unit, and glBindTexture binds a texture to the active texture unit. So you see they work together hand-in-hand.

Rather than use a behind-the-scenes "active texture unit" selector to help define what BindTexture does, GL could have put the arguments to both APIs in one single stand-alone GL call. And this in-fact is what's done in the EXT_direct_state_access (http://www.opengl.org/registry/specs/EXT/direct_state_access.txt) function glBindMultiTextureEXT:


void BindMultiTextureEXT(enum texunit, enum target, uint texture);


which does exactly what we just discussed. You tell it which "texture" you want to bind, what its texture type is (target), and which "texture unit" you want to bind it to. It's all right there without any behind-the-scenes selectors.

Similar APIs are defined by this extension for many other texture calls, and many other calls besides.

V-man
06-19-2011, 05:38 PM
In the book OpenGL programming guide, Example 9-7 uses two texture objects and it does not call glActiveTexture before calling glBindTexture, while in Example 9-10, it calls glActiveTexture before glBindTexture. What's the difference?

what's the difference between glActiveTexture and glBindTexture? It seems they both can activate a texture.

If you don't call glActiveTexture, then it uses the default, which is 0 (GL_TEXTURE0).

If you need to bind a texture to another tex unit, then you need glActiveTexture.

Despite the name, glActiveTexture does not activate a texture unit. I really don't know why they didn't just create that glBindMultiTexture function in GL 1.2.1

There was this "let's not modify old GL functions and just introduce another one" attitude back then. Got to live with it now.

kRogue
06-20-2011, 12:53 AM
Be aware that the number of texture units is limited. On mobile devices there are usually only two. On desktop systems it should be at least 8.


The GLES2 standard requires atleast 8 texture units, not too sure what GLES1 requires though. As a side note, the N900 which uses a PowerVR SGX supports just that: 8 texture units. The SGX in the N900 is by today's standards pretty low on the totem pole, and newer devices are typically faster than the SGX in the N900 (bit often enough SGX's as well, but higher clock and higher "model number").

shapeare
07-11-2011, 05:51 AM
Be aware that the number of texture units is limited. On mobile devices there are usually only two. On desktop systems it should be at least 8.

I have a NVIDIA GeForce GTS 450 graphics card. I use glGetIntegerv(GL_MAX_TEXTURE_UNITS, ...) in my c++ program and only get 4 texture units. It is really strange.

V-man
07-11-2011, 12:42 PM
There is an app for that
http://www.opengl.org/wiki/Common_Mistakes#Texture_Unit

shapeare
07-11-2011, 08:09 PM
Thank you very much.

The OpenGL Programming Guide is a little misleading.

Aleksandar
07-12-2011, 01:29 AM
The Red book is excellent for the fixed functionality, but gives little to no clues about what is going on in the programmable pipeline. On the other hand, Wiki is oversimplified.

You have six different constants that define how many sampler object you can use:
- GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS,
- GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS,
- GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS,
- GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS,
- GL_MAX_TEXTURE_IMAGE_UNITS and
- GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS.

Each of the first 5 defines the maximal number of texture image units in particular programmable pipeline stage. The last one defines the total number of texture image units that can be used simultaneously in all stages. Theoretically MAX_COMBINED can be the sum of all others, but in practice that number could be smaller since texture units might be shared.

Alfonse Reinheart
07-12-2011, 01:40 AM
On the other hand, Wiki is oversimplified.

Then fix the Wiki. It's a wiki for a reason.

See? It's better now. (http://www.opengl.org/wiki/Common_Mistakes#Texture_Unit)

Aleksandar
07-12-2011, 02:13 AM
Yes, it's better now. ;)

V-man
07-12-2011, 05:25 AM
Isn't it still oversimplified?

Should i use GL_MAX_TEXTURE_IMAGE_UNITS or GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS?

What if my name is mr joe the programmer and my Intel supports GL 2.0. Will GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS works or will I get INVALID_ENUM?

Aleksandar
07-12-2011, 06:31 AM
I wouldn't even dare to use OpenGL 2.0+ on Intel's graphics cards. :D
(Although Intel HD Graphics 2000/3000 should be GL 3.0 compliant, I haven't tried it yet.)

If something is not supported in the drivers you will certainly get invalid enumeration error if you call it. The problem is that drivers shouldn't return such severe error if enumeration is not supported, and furthermore debug output indicates error in totally wrong location (R266.58 for Win7/Vista 32-bit notebook version).

Hint: Try to get GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS on SM4 card.

Alfonse Reinheart
07-12-2011, 11:52 AM
Isn't it still oversimplified?

It's not a dissertation; it's a "Common Mistakes" question. Hence the linking to other pages where more detailed information can be found.