next up previous contents
Next: 5.2 MIPmap Generation Up: 5.1 Review Previous: 5.1.1 Filtering

5.1.2 Texture Environment

The process by which the final fragment color value is derived is called the texture environment function (glTexEnv()) Several methods exist for computing the final color, each capable of producing a particular effect. One of the most commonly used is the modulate function. For all practical purposes the modulate function multiplies or modulates the original fragment color with the texel color. Typically, applications generate white polygons, light them, and then use this lit value to modulate the texture image to effectively produce a lit, textured surface. Unfortunately when the lit polygon includes a specular highlight, the resulting modulated texture will not look correct since the specular highlight simply changes the brightness of the texture at that point rather than the desired effect of adding in some specular illumination. Some vendors have tried to address this problem with extensions to perform specular lighting after texturing. We will discuss some other techniques that can be used to address this problem later on.

The decal environment function performs simple alpha-blending between the fragment color and an RGBA texture; for RGB textures it simply replaces the fragment color. Decal mode is undefined for luminance (L) and luminance alpha (LA) textures. The blend environment function uses the texture value to control the mix of the incoming fragment color and a constant texture environment color. OpenGL 1.1 adds a replace texture environment which substitutes the texel color for the incoming fragment color. This effect can be achieved using the modulate environment, but replace has a lower computational burden.

Another useful (and sometimes misunderstood) feature of OpenGL is the texture border. OpenGL supports either a constant texture border color or a border that is a portion of the edge of the texture image. The key to understanding texture borders is understanding how textures are sampled when the texture coordinate values are near the edges of the [0,1] range and the texture wrap mode is set to GL_CLAMP. For point sampled filters, the computation is quite simple: the border is never sampled. However, when the texture filter is linear and the texture coordinate reaches the extremes (0.0 or 1.0), however, the resulting texel value is a 50% mix of the border color and the outer texel of the texture image at that edge.

This is most useful when attempting to use a single high resolution texture image which is too large for the OpenGL implementation to support as a single texture map. For this case, the texture can be broken up into multiple tiles, each with a 1 pixel wide border from the neighboring tiles. The texture tiles can then be loaded and used for rendering in several passes. For example, if a 1K by 1K texture is broken up into 4 512 by 512 images, the 4 images would correspond to the texture coordinate ranges (0-0.5,0-0.5), (0.5,1.0,0-0.5), (0-0.5,0.5,1.0) and (.5-1.0,.5-1.0). As each tile is loaded, only the portions of the geometry that correspond to the appropriate texture coordinate ranges for a given tile should be drawn. If we had a single triangle whose texture coordinates were (.1,.1), (.1,.7), and (.8,.8) we would clip the triangle against the 4 tile regions and draw only the portion of the triangle that intersects with that region as shown in Figure 11. At the same time, the original texture coordinates need to be adjusted to correspond to the scaled and translated texture space represented by the tile. This transformation can be easily performed by loading the appropriate scale and translation onto the texture matrix stack.

 

table764

Unfortunately, OpenGL doesn't provide much assistance for performing the clipping operation. If the input primitives are quads and they are appropriately aligned in object space with the texture, then the clipping operation is trivial; otherwise, it is substantially more work. One method to assist with the clipping would involve using stenciling to control which textured fragments are kept. Then we are left with the problem of setting the stencil bits appropriately. The easiest way to do this is to produce alpha values that are proportional to the texture coordinate values and use glAlphaFunc() to reject alpha values that we do not wish to keep. Unfortunately, we can't easily map a multidimensional texture coordinate value (e.g. s,t) to an alpha value by simply interpolating the original vertex alpha values, so it would be best to use a multidimensional texture itself which has some portion of the texture with zero alpha and some portion with it equal to one. The texture coordinates are then scaled so that the textured polygon map to texels with an alpha of 1.0 for pixels to be retained and 0.0 for pixels to be rejected.


next up previous contents
Next: 5.2 MIPmap Generation Up: 5.1 Review Previous: 5.1.1 Filtering

David Blythe
Thu Jul 17 21:24:28 PDT 1997