VRML Tech Talk

Last time around, we looked at the Material node and how it's used to define the surface properties of a virtual object. This issue we're going to see how to further increase the realism of our worlds by using texture mapping.

by Bernie Roehl

Texture maps are basically just flat (two-dimensional) images that are applied to the surface of three-dimensional objects, in order to make them appear to be more detailed than they actually are. Texture maps can be scanned photographs, computer-generated images, captured video, or any other kind of picture. They can be stored in any of a number of formats; VRML supports PNG (Portable Network Graphics) and JPEG (Joint Photographic Experts Group). Most VRML browsers will also support GIF (Graphics Interchange Format), but its use is discouraged since it's plagued by licensing restrictions.

The way to specify a texture map in VRML is with a Texture2 node. It takes a single field, called ``filename'', which gives the URL of an image file somewhere on the net or on your local machine:

Texture2 {
  filename "http://somewhere.someplace.com/Textures/brick.bmp"
} 

This brick texture might be applied to the large, flat polygons you use to define the walls of your building. Other uses for texture maps include putting a painting inside a frame, giving a ``grassy'' look to an empty field, or putting a wood-grain finish on a coffee table.

How Textures Are Applied to Objects

Depending on the shape of the object the texture is being applied to, the texture may be wrapped in a variety of different ways. In a VRML Cube node, the texture is applied separately to each of the six faces of the cube. In the case of a Cylinder, it's wrapped around the sides like a soup can label; a circle is also cut out from the texture and applied to the end caps.

This wrapping is done internally by generating ``texture coordinates''. Texture coordinates are pairs of numbers in the range of 0.0 to 1.0 inclusive, that are used to specify locations within the image. Note that they're independent of the image dimensions; if you have a 128 by 256 image, the horizontal coordinates still range from 0.0 through 1.0 (where a value of 1.0 means 127 in one direction and 255 in the other).

In the case of an IndexedFaceSet, the texture is applied to the entire object. The texture coordinates are specified explicitly, using a TextureCoordinate2 node. The node has a single field, ``point'', which contains a list of coordinate pairs:

TextureCoordinate2 {
    point [ 0 0, 1 0, 1 1, 0 1 ]
} 

These coordinates are referred to inside the IndexedFaceSet using a textureCoordinateIndex field.

Texture Transformations

The texture coordinates can be transformed in several different ways. For example, you can scale the coordinates to ``stretch'' or ``shrink'' the texture relative to the surface, as well as rotating or shifting it. This is done using the Texture2Transform node; for example, the following:

Texture2Transform {
    scaleFactor 5 3
    translation 0.2 0.3
    rotation 1.5708
} 

would scale up the horizontal texture coordinates by a factor of five and the vertical coordinates by a factor of three. It would also rotate the coordinates by 90 degrees (1.5708 radians), and shift them by 0.2 and 0.3 radians in the horizontal and vertical directions respectively.

Wrapping of Textures

The example above raises an interesting question. What happens when a texture map coordinate goes outside of the 0 through 1 range? It turns out there are two answers:

Each of the axes of the texture has a ``wrapping'' flag associated with it, specified as the wrapS and wrapT fields in the Texture2 node. The names wrapS and wrapT refer to the S (horizontal) and T (vertical) axes of a texture map.

If the wrapS flag is set to REPEAT, the texture will be repeated horizontally across the surface as often as necessary to fill it out to the texture coordinate value. The same thing is done with the vertical axis if the wrapT flag is set to REPEAT.

For example, if the texture coordinates are scaled by a factor of 16, and the wrapS and wrapT flags are both left at their default value of REPEAT, the texture will be replicated 16 times across and down the surface.

If either flag is set to CLAMP, the transformed coordinate values along that axis will be clamped (truncated) at zero and one. In effect, the edgemost row or column of the texture map will be extended along the surface.

Transparent Textures

Textures stored using the PNG format can have an ``alpha'' channel associated with them. This alpha channel corresponds one-to-one with the pixels (or ``texels'') in the image, and controls their transparency. Wherever the alpha value is set to transparency, you'll ``see through'' the texture to whatever lies beyond. This can be handy for creating trees, picket fences, or other complex-looking objects that don't have a solid outline.

Limitations

At the moment, VRML supports only a single texture map per object. This is more limited than most other 3D graphics systems, which allow each face of an object to be assigned a different texture. This limitation will probably be fixed in a future release of the VRML specification.

In the meantime, there are two solutions. The first is to break your object into a number of separate objects, each of which uses just one texture. The other approach is to combine all the required texture maps into one large map, and set up the texture map coordinates on each face to select the appropriate ``sub-map'' within the montage.

If you need more details about VRML, a good starting point is the * VRML Repository, which has links to software, documentation and more. You may also want to check out Special Edition: Using VRML, a book I've co-authored with Stephen Matsuba. It discusses VRML in considerable detail, and gives you everything you need to start building complex and interesting worlds.


Bernie Roehl is probably best known for REND386, a freeware VR library for PCs. He is also the author of two books on virtual reality, including the popular Playing God: Creating Virtual Worlds. Bernie is currently a regular columnist for both VR Special Report and VR News. He's also active on the VRML mailing lists, and is maintaining a collection of proposed changes to the VRML spec. As always, you can reach him by e-mail at broehl@sunee.uwaterloo.ca.