While multipass rendering has been around for years, it really became mainstream when id Software release GLQuake in December 1996. At the time, only one consumer-class chipset (Voodoo) had a sufficient pixel fill-rate to run GLQuake at acceptable fill rates. Why was GLQuake so fill-rate hungry? Because the majority of pixels in each frame were rendered twice; once with a base texture, and again with a light map.
What GLQuake really needed was a way to render with two separate textures in a single pass.
In september of 1998, after several iterations and much debate, the ARB approved the first-ever ARB extension: ARB_multitexture. An ARB extension differs from an EXT extension in that the ARB has formally reviewed and approved the extension. (This is not to say that EXT extensions are somehow inferior, just that the ARB hasn't formally reviewed them.)
Unlike the half-baked and partially-implemented SGIS_multitexture extension, the ARB_multitexture extension has a conformance test and must be fully implemented on any hardware which advertises the extension string. So use ARB_multitexture with confidence, and please don't write new code to the SGIS_multitexture spec.
Somewhere along the line another variant appeared; EXT_multitexture was simply a renaming of SGIS_multitexture, since only SGI is supposed to implemented SGIS extensions. EXT_multitexture was only implemented in Mesa, and its use is discouraged now that ARB_multitexture has been adopted by all multitexture-capable implementations.
| Texture |
Cf ---> | Env | ---> C'f
Multitexture is similar, except that multitexture texture environments (up to 32) are present:
| Texture | | Texture |
Cf ---> | Env 0 | ---> | Env 1 | ---> C'f
To program a particular texture environment, use the command
glActiveTextureARB(GLenum texture);Where texture is GL_TEXTUREn_ARB, 0 <= n < GL_MAX_TEXTURE_UNITS_ARB.
When you call glBindTexture(), the texture object is bound to the active texture unit specified by texture. Likewise, enabling and disabling textures and modifying texture environment, texture matrix and texgen modes affect only the active texture unit. Modifying a texture array or parameters affects the texture object bound to the active texture unit, but such changes are visible to other texture units if the texture is bound to multiple texture units simultaneously.
For example, to bind and enable textures tex0 and tex1 on the first two texture units, use the following sequence:
glActiveTextureARB(GL_TEXTURE0_ARB);Each texture unit uses a seperate set of texture coordinates. To specify texture coordinates for multiple texture units, use the command
glMultiTexCoord[sifd][v](GLenum texture, ...);where texture is GL_TEXTUREn_ARB. You can still use glTexCoord*() for texture unit 0 if you prefer, as it might be slightly faster. For example, to draw a triangle with two textures:
glBegin(GL_TRIANGLES);If you are using vertex arrays, you can set multiple sets of texture coordinates with the commandglMultiTexCoord2fvARB(GL_TEXTURE0_ARB, &t0);glEnd();
glClientActiveTextureARB(GLenum target);which is the client state analog of glActiveTextureARB(). When manipulating vertex array state, glTexCoordPointer() and glEnableClientState() affect the client active texture indicated by target. For example, to set up two texture coordinate arrays:
glClientActiveTextureARB(GL_TEXTURE0_ARB);Now calls to glDrawArrays(), glDrawElements() or glArrayElement() will issue both sets of texture coordinates for each vertex.
glTexCoordPointer(2, GL_FLOAT, 0, tp0);
glTexCoordPointer(2, GL_FLOAT, 0, tp1);
C'f = Cf * Ct0 * Ct1More sophisticated blending capabilities do exist in current hardware, and will be exposed through a new set of extensions which are currently under development.