GL_MAX_TEXTURE_UNITS_ARB = 4 ?

When I do

glGetIntegerv (GL_MAX_TEXTURE_UNITS_ARB, &tmu_num);

on a geforcefx5900ultra, I get the result 4.

Should it not be 8 for this card?

/mfugl

No that is the correct result. To access more than four textures you’ll need to use fragment programs (NV_fragment_program or ARB_fragment_program).

Take a look at this thread: http://www.opengl.org/discussion_boards/ubb/Forum3/HTML/009119.html for more information.

Ok thanks, but why is the geforcefx limited in this way?

OpenGL multitexturing can use up to 32 textures.

How about the Radeon cards, are they able to make it right?

/mfugl

The R3xx reports 8 texture units and 16 image units.

I still don’t quite understand the difference between a texture unit and a texture image unit.
How do I bind textures to the other image units?

-Mezz

Wasn’t there all that flak about the NV30 and NV35 really having only 4 pixel pipelines (though with 2 TMUs each)? With that as the case, shouldn’t the number of texture units reported should be the same as for a Geforce 3 or 4ti or a Radeon 8500?

The traditional notion of a “texture unit” means a texture image unit plus a texture coordinate interpolator. Texture coordinates and texture images units have been separated though in recent hardware. You bind may bind a texture to texture image unit 0, but texture coordinate 0 need not be connected to this texture at all as plain GL_ARB_multitexture. Instead you may use the texture coordinate 3 to lookup in texture 0 if you so prefer. Thus the Radeon 9700 has 16 texture image unit and consequently can bind up to 16 textures. But it only has 8 texture coordinate interpolators. Thus you can only call glMultiTexCoord() with at most GL_TEXTURE7. The same texture coordinate can be used for many textures though, for instance is it common to use the same coordinates for base, bump and gloss maps in perpixel lighting.

“I still don’t quite understand the difference between a texture unit and a texture image unit.”

Here’s an explanation taken from the NV_fragment_program spec:

The fragment program execution environment accesses textures via
arbitrarily computed texture coordinates. As such, there is no necessary
correspondence between the texture coordinates and texture maps previously
lumped into a single “texture unit”. This extension separates the notion
of “texture coordinate sets” and “texture image units” (texture maps and
associated parameters), allowing implementations with a different number
of each. The initial implementation of this extension will support 8
texture coordinate sets and 16 texture image units.

“How do I bind textures to the other image units?”

Just like usual:

glActiveTexture(GL_TEXTURE5);
glBindTexture(GL_TEXTURE_2D, texobj);
glActiveTexture(GL_TEXTURE6);
glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap);

Note that you do not need to call glEnable(texture target) when using fragment programs (ARB_fragment_program or NV_fragment_program) or if you are using texture shaders.

Originally posted by Ostsol:
Wasn’t there all that flak about the NV30 and NV35 really having only 4 pixel pipelines (though with 2 TMUs each)? With that as the case, shouldn’t the number of texture units reported should be the same as for a Geforce 3 or 4ti or a Radeon 8500?
Nope, it really needn’t be this way.
As ARB_fp is quite obviously a functional superset of classic multitexturing, and, by using it, you can do eight textures (with eight texcoord sets), this limitation must be artificial.

If we wanted to get real paranoid, we could speculate that NVIDIA did this to stifle adoption of multitexturing beyond quad (because R200 supports six and R300 supports eight).

Being a little less paranoid, it seems that classic multitexturing is still done with register combiner (integer) hardware, which is a seperate functional block on the chip.

But this may all be wrong. Kyro OpenGL drivers limit themselves to four textures, too, while the same driver exposes eight textures in D3D. Maybe there’s a reason for that, and the same reason applies here?

see what Mark Kilgard has said about this: http://www.cgshaders.org/forums/viewtopic.php?t=1041&highlight=

haha, davepermen got owned!

So what this means is that we can bind a texture to each of the texture image units (16 for the FX)

and in our fp, we can sample any of those 16 images using any of the 8 tex coords we wish. So we have a 1:2 ratio.

I think that it`s unlikely that anyone will be using ALL 16 images.

However, it does happen that the same tex coords is used for multiple textures.

It`s so simple that even I can understand it!

I wonder what the next generatio will have? Maybe the ratio will be 1:1 (tex coords and tex images)

Shaders give you enough flexibility to compute more texture coords, if you wish to do so.

This is just the same tradeoff between fixed function hardware and programmable hardware that we’ve come to know and love (in this case texcoord interpolators vs shader ALUs).
You can’t use FF hardware for anything else besides what they were meant to do. ALUs can also be used for something else, if you don’t need the extra texcoords.

> and in our fp, we can sample any of those 16 images using any of the 8 tex coords we wish. So we have a 1:2 ratio.

I’m not sure computing a simple ratio such as 1:2 makes sense.

GeForce FX provides 8 texture coordinate sets. That is 32 texture coordinates (4 texture coordinates per texture coordinate set, ie. s,t,r,q).

Because swizzling is “free” in fragment (and vertex) programs, you could use the X & Y components of the 8 texture coordinate sets to access the first 8 texture image units (as non-projective 2D textures) and the Z & W components of the 8 texture coordinate sets to access the second 8 texture image units (again, as non-projective 2D textures.

My point is really that you no longer need to think about texture coordinate sets as having a direct mapping from 4-component vectors to accessing a single texture image unit.

It makes a lot more sense to think of GeForce FX as providing 32 interpolated texture coordinates (rather than 8 texture coordinate sets) between your vertex and fragment program. How you use these texture coordinate sets is up to you.

And if you count the other more limited interpolants (the 1-component floating-point fog coordinate, the two 4-component [0,1] fixed-point colors, and the 3-component window-space position and inverse eye-space W), you really have a large number of available interpolants.

  • Mark

It should also be noted that a texture coordinate interpolator doesn’t neccesarily need to be used for texture lookup at all. I frequently use texture coordinates to pass normals, tangent vectors, light and view vectors, fragment position in world space etc. This is also the reason why GL2 calls it “varying” rather than “texCoord” or something along that line. Texture access is just one use of many of an interpolator.

Originally posted by Mark Kilgard:
[BBecause swizzling is “free” in fragment (and vertex) programs, you could use the X & Y components of the 8 texture coordinate sets to access the first 8 texture image units (as non-projective 2D textures) and the Z & W components of the 8 texture coordinate sets to access the second 8 texture image units (again, as non-projective 2D textures.[/b]

Possible, but it requires more work.
I think it would go something like this:

#For Tex0 and Tex1
TEMP R1;

MOV R1.xy, fragment.texcoord[0];
MOV R1.w, fragment.position;
TXP …;

MOV R1.xy, fragment.texcoord[0].zwzw;
MOV R1.w, fragment.position;
TXP …;

Also, computing tex coords in the fp ourselves justifies it some more.