Welcome back! We've covered quite a bit of ground so far already, and we're about to take another another chunk in the world of cross-graphics API. In this installment of the series, I was struggling between either discussing Camera Control or Texture Mapping. I decided that either one would work at this time period, so I flipped a coin and Camera Control lost (sorry dude).
What is texture mapping?
I guess it would be remiss to have a tutorial on Texture Mapping without actually explaining what it is.
In case you've been living in a cave for several years now, Texture Mapping is the art (or process) of taking an image and putting it onto a vertex defined surface. (ie. a side of a cube, or a triangle or even a 3d model). Texture Mapping is more commonly known as a way of representing an object within a three dimensional world without the overhead of several hundred polygons. A case in point is to think of your favorite FPS game (mine happens to be Unreal Tournament). Enter a level and just start to look around before you begin fragging everyone; the wall is nothing more than a plain surface with a texture map applied to it. The floor is nothing more than some granite looking artwork, and the sky contains not much more than a starfield image.
Even though the majority of graphics programming is done with two dimensional texture images, there can also be one or three dimensional textures mapped onto objects as well.
One dimensional textures are basically just a pixel wide and N pixels high (where N is a power of 2). They're used in a variety of interesting ways, such as in cel shading, or in applying a height-based color in terrain mapping.
Three dimensional textures are another story. Also known as "volume textures", 3d textures are represented (naturally) by 3 coordinates, and can maybe be thought of as a collection of thin slices of textures to create a 3d image map. Wherever the volume map intersects with our game world, the texture vertex (or texel) is applied. A few years ago, volume textures were once theoretical in application, as they were considered too hidiously expensive in terms of performance to apply them within the arena of game programming. However, that trend seems to be disappearing. With the release of Direct3D8.0 from Microsoft, Volume Textures are supported in hardware while on the OpenGL side, they were included in the 1.2 Specification.
(Note that with the Direct3D8.0, the Direct3D team has created support for DXVC - DirectX Volume Compression - support. This can greatly help our engine performance with volume textures as they can be compressed by our DirectX Texture Tool before we shove them into memory.)
We can do quite a few usefull things involving Texture Mapping, and so it would be worth mentioning a few of them below:
Since the dawn of 3d engines, the level of detail (or LOD) has always been a necessary consideration in terms of presenting your scene. Because we need to keep our engine performance high, it's a waste to have our 3d pipeline process/render a model containing a few hundred vertices when it is too far from our camera to see it properly. Likewise, nothing's more painfull than having a beautifully crafted castle (from far away) appear all blotchy and pixelated when we move the camera closer.
Enter Mip Mapping. Mip Mapping is a process of generating different levels of your texture image, so that the pipeline can use the highest resolution image for when the object is up close, and a lower resolution image when that object is further away from the viewer.
As with 2d mip maps, we can create volumetric mip maps to support our 3d textures. Again, if our simple volume texture takes up a lot of memory, then creating a mip map chain for our 3d texture quietly procurs even more memory available to our hardware.
Although for this tutorial we are using basic texture mapping, we should be aware of the MultiTexturing capability of 3d engines available today. Up until recently, most hardware only supported single pass texture mapping. This meant that if you wanted to present some blood on the walls for the player, you would have to implement a "two pass" system in software. eg. First set our wall texture, render the vertices, then set the blood texture and render our vertices again.
Because of our newer specifications, for both OpenGL and Direct3D, our graphics pipeline can support multiple passes through our texture processing stage/area of our pipeline. Back to our example with the blood on the walls, we can now set our wall texture in one stage, set our blood texture on another stage, and then when we render the vertices of our object, both textures will be blended onto its surface.
Another common use of Texture Mapping is for the use of applying our own lighting information to each pixel in our scene. Although both Direct3D and OpenGL have support for dynamic lighting within their pipelines, it doesn't come for free, and the calculations get increasingly more complex as the number of lights increase within the scene.
One approach, or workaround, to this problem that works very well for static lighting is to use a texture map to contain the lighting (or alpha) information. The elements of a lightmap are usually known as "lumels" as they refer to the luminosity of the desired coordinate.
Using our mulitexturing capabilities of our hardware (as explained above), we can then have our original texture in one stage, along with our lightmap in another stage. The final blended result will contain the final effect for that vertex.
Yet another use of Texture Maps is what's known as Environment Mapping. This is a procedure where you take an entire scene and store it into a texture. You can then apply this texture to any object within your scene, giving the impression that you have a reflection of the surrounding environment on your texture. There are other types of environment mapping, but by far the two most popular are: cubic and spherical.
Cubic Environment Mapping (or cube maps) involves creating 6 textures which represents the surrounding scene as if the object in question were in the center of a cube. In most cases, the environment is mapped upon curved objects (ie. a silver bullet, or car, etc..) so we don't really need too much detail within these images to make them appear as if they're reflecting the environment.
Spherical Environment Mapping (or sphere maps) involves taking a 2d texture image of the full 360 degrees surrounding the object as if taken through a fish eye lens. One of the downsides towards using a sphere map, is that the sphere map's texture is taken from one position in the scene and applied to every object in the scene (no matter what its position). This means that objects closer to the camera won't have the proper looking reflection mapped to it.