Eng 591 - VR Programming - Class Outline 12

General Topics: Textures ( WTK chapter 10 )

Textures - What are They, and Why are They Important?

Textures ( a.k.a. texture mapping ) are a method for adding a lot of detail to a geometrical object without using large numbers of polygons. The basic idea behind texture mapping is to take an image ( such as a photograph ), and "paint" it over one or more polygons.

Consider, for example, a simulation involving a bookshelf, on which there are many books. In order to model each book individually using ordinary polygons would require a large number of polygons - at least one for each book on the shelf. The books would also be flat and featureless, with no writing on the spines.

A better approach is to build a geometry that is a simple rectangular box the same size and shape as the desired bookshelf. Then take a photograph of a real bookshelf, and convert the photograph into a computer graphics image. The computer image of the bookshelf is applied as a texture to the front of the box, and the viewer sees the shelf as being full of books with lots of detail. In addition, a computer image of wood grain can be applied to the sides of the box as wallpaper to improve the overall effect of the bookshelf.

Other typical uses of texture mapping include carpeting, ceiling tiles, grass, roadways, distant buildings, signs ( billboards ), and trees and foliage. The latter application is usually accomplished using transparent textures and/or billboarding, as explained below. Textured polygons appear more realistic than regular polygons, BUT they are also more expensive computationally than untextured polygons. Often the cost is worth while, due to either the amount of improvement afforded by the texturing, or by the number of regular polygons that can be replaced with one textured polygon. Computer graphics hardware is also improving to the point where the computational cost of texture mapping is no longer as serious a constraint as it once was.

Different Kinds of Textures

  • Vanilla ( Plain ): A plain vanilla texture covers the polygon with the image. No lighting effects are considered, and the entire polygon is covered with the texture.
  • Shaded: Shaded textures are like vanilla textures, except that lighting effects are also applied, which may diminish the overall brightness of the textured polygon.
  • Transparent: Transparent textures allow some parts of the image to be either completely or partially transparent. More details are provided below.
  • Shaded and Transparent: Combines the features of shading and transparency.

Details of Transparent Textures

Classic Example - A Tree

The classic example of transparent textures involves trees or other foliage. An image of a tree is captured, and all of the pixels in the image outside of the tree itself are set to pure black ( 0, 0, 0 ). This creates a tree-shaped green image in the middle of a black background. The image is applied to a polygon as a transparent texture, meaning that none of the black pixels will be drawn for this polygon. The original polygon color is not drawn either for these pixels, allowing whatever is behind the polygon to show through around the edges of the tree. There are two methods for preventing the user from walking around the polygon to see the edge of the tree. One approach is to get two or more tree polygons, and inter-connect them in an orthogonal ( crossed ) fashion. As the user walks around the tree, there is always at least one polygon that faces him or her. The other approach is to "billboard", or rotate, the polygon, so that it always faces the user. A simplistic to billboarding in WTK is to create the polygon so that it originally lies in the Z=0 plane, and then set the orientation of the polygon to match that of the viewpoint:

WTp3 direction;
WTq orientation;
WTnode *treeBillboard;
.
.
.
WTviewpoint_getorientation( Viewpoint, orientation );
WTnode_setorientation( treeBillboard, orientation );

Note that the above code will also tilt the billboard up and down, and may twist it also. In order to restrict the movement to rotating about the Y axis only, the last two lines can be modified as:

WTviewpoint_getorientation( Viewpoint, orientation );
WTq2dir( orientation, direction ); /* Discards twist information */
direction[ Y ] = 0.0;              /* Discards tilt */
WTdir2q( direction, orientation ); /* Converts back to a quaternion */
WTnode_setorientation( treeBillboard, orientation );
Alpha Channels

A relatively new twist to transparent textures is the addition of an "alpha" channel to the traditional red, green, and blue color components. In the "rgba" format of a graphics image file, each pixel of the image is represented by 32 bits - eight each for red, green, blue, and alpha information ( as opposed to 24 bits in the more traditional rgb format. ) The alpha value is treated like the "opacity" discussed earlier under materials, ranging from 0 ( completely transparent ) to 255 ( completely transparent ) on a pixel by pixel basis. Depending on the platform and software in use, this allows each pixel of an image to have a variable transparency, to be combined with whatever lies behind the image.

WorldToolKit supports the use of alpha channel, in a somewhat limited fashion:

  • All images are stored in memory with 32 bit ( rgba ) information.
  • If an image is loaded that does not have alpha information, then all purely black pixels ( rgb = 0, 0, 0 ) are set to an alpha value of 0, and all other pixels are set to an alpha value of 255.
  • If the polygon on which the texture is applied has opacity greater than 0.996, then the alpha information is treated as an either-or transparency switch, when compared against the threshhold limit WTKALPHATEST, which by default has value 78. If the texture is applied as a transparent texture, then all pixels with alpha below this limit are completely transparent, and all pixels with alpha values above this value are completely opaque. ( This is the "cookie cutter" method described above. )
  • If, however, the polygon has an opacity less than 0.996, then the alpha component of each pixel is multiplied by the opacity of the polygon to determine the overall opacity to use for that particular pixel.

U-V Texture Mapping ( Texture Draping )

UV texture mapping, aka texture draping, involves stretching and/or compressing a texture so that it fits over polygon(s) in very specific ways. Consider the image to be printed on a flexible ( rubber ) sheet, and to be overlaid with a grid of u and v coordinates. ( Such that the origin of the u-v coordinate system is the lower left corner of the image, the u dimension stretchs from left to right, the v dimension stretchs from bottom to top, and the upper right corner of the image is at coordinate 1.0, 1.0 ). Then consider the geometry's collection of vertices and polygons to be like a wire mesh framework. The practice of u-v texture mapping effectively glues specific points of the image ( given by u-v coordinates ) onto specific vertices of the wire mesh framework. The image then stretches as needed to span the polygon(s).

The classic use of texture draping is to apply an image of terrain over a rough wire mesh surface. The example that has recently been added to looploop involves wrapping a texture of a coke can around a cylindrical object.

There are two methods illustrated in this example for applying a draped texture. One is to specify the u-v coordinates and the texture files in the nff file, as shown in cokecan.nff. The other approach illustrated here is to use a set of functions to calculate the u and v coordinates from the vertex coordinates in 3-D space, as illustrated by the following lines extracted from looploop.c:

#define RADIUS 10.0f
#define HEIGHT 37.0f
#define HEIGHT2 18.5f
   
float cokeU( WTp3 );    /* Two function prototypes */
float cokeV( WTp3 );
   
	WTp3 canOffset = { 0.0f, -HEIGHT2, 0.0f };
   
	WTpoly *poly;
	WTgeometry *geo;
	WTnode *node;
   
	geo = WTgeometry_newcylinder( HEIGHT, RADIUS, 42, TRUE, FALSE );
	WTgeometry_translate( geo, canOffset );
   
	WTgeometry_settextureuv( geo, "cokelabl.tga", cokeU, cokeV, FALSE, FALSE );
   
	for( poly = WTgeometry_getpolys( geo ); poly; poly = WTpoly_next( poly ) )
		if( WTpoly_numvertices( poly ) > 4 )
			WTpoly_deletetexture( poly );
   
/*****************************************************************************/
   
/* The following two routines calculate the uv texture coordinates for the coke
   can. */
   
float cokeU( WTp3 p ) {
   
           double x;
   
        x = p[ X ] / RADIUS;        /* Beware of round-off errors */
        if( x > 1.0 ) x = 1.0;
        if( x < -1.0 ) x = -1.0;
   
        if( p[ Z ] > 0.0f )
                return acos( x ) / PIT2;
        else
                return 1.0f - acos( p[ X ] / RADIUS ) / PIT2;
   }
   
float cokeV( WTp3 p ) {
   
    if( p[ Y ] < -HEIGHT2 )
	        return 1.0f;
	else
	        return 0.0f;
}

Applying Textures in an NFF File

Textures are applied to polygons in NFF files by providing the name of the file containing the texture, prepended by either "_V_" for vanilla textures, "_S_" for shaded textures, "_T_" for transparent textures, or "_U_" for shaded transparent textures. E.g. "4 8 9 3 2 matid 4 both _V_vanillaTexture.tga". If u-v coordinates are not provided for the vertices ( see example above ), then the texture can be scaled, translated, and/or rotated on the polygon when it is applied. See chapter 10 and appendix F for more details.

Applying and Modifying Textures During a Simulation ( Using Function Calls )

The following WTK function calls can be used to apply and modify textures during a simulation:
Adding a New Texture to an Object
  • WTpoly_settexture
  • WTgeometry_settexture
  • WTpoly_settextureuv
  • WTgeometry_settextureuv
Replacing an Existing Texture ( Can be Useful for Animation )
  • WTgeometry_changetexture
  • WTtexture_replace
  • WTtexture_load
  • WTtexture_cache
  • WTtexture_iscached
  • WTtexture_getmemory
Modifying an Existing Texture
  • WTpoly_rotatetexture
  • WTpoly_scaletexture
  • WTpoly_translatetexture
  • WTpoly_mirrortexture
  • WTpoly_stretchtexture
  • WTpoly_gettextureinfo
  • WTpoly_setuv
  • WTpoly_getuv
  • WTgeometry_setuv
  • WTpoly_settexturestyle
  • WTpoly_gettexturestyle
  • WTtexture_setfilter
  • Wttexture_getfilter
Deleting Textures and Special Functions
  • WTpoly_deletetexture
  • WTgeometry_deletetexture
  • WTscreen_load
  • WTwindow_getimage