Creating Textures and Texture WADs for Half-Life

Overview

Texture map creation for 3D games has taken a big leap forward with Half-Life, and artists and designers who wish to push themselves in creating entirely new game worlds have virtually unlimited flexibility in the Half-Life engine. This tutorial explains the technical and artistic considerations of texture mapping for Half-Life. It by no means attempts to teach how to paint, but rather how to use your painting skills to best effect in the creation of texture maps.

Painting Textures

Texture painting is a very specific technique of painting that requires a significantly different way of thinking as opposed to simply painting a traditional scene. Textures usually tile in all directions, and they need to look good doing so: painting a big splotch onto a texture may look good when you see just a single instance of it, but when you see that texture repeated a dozen times in a row, it begins to look ridiculous. A great technique when painting in PhotoShop (I’m sure there’s a similar method of doing this in other programs), is to have two images open while painting: one of the texture, and one of the texture on a much larger page tiled. If you occasionally select all in the single-texture image, define your selection as a pattern, then in the large image do a fill with pattern, you can easily see as you work how your texture will look tiled. Using the Offset filter helps a great deal when making tileable edges, but actually tiling your image in a large window allows you to see whatever latent tiling feature that may be lurking in your texture but is not apparent when viewed singly: you think the texture is a nice jumble of rocks until you tile it 10x10 on a large page and see that one white highlight standing out like a beacon, an avoidable grid that detracts from your texture considerably. Using this technique with two image canvases helps solve these problems before you ever compile the texture into a WAD.

It’s best to think of textures less as individual images, but as members of a texture family. If you paint a set that is designed to work well together, then it changes for the better the way you go about painting each individual texture. Constructing a texture family along the following lines is a good basic start:

Two basic, simple wall types
Two detailed variants of each of the simple walls
Two different floors, slightly lighter or darker than the walls
Two different ceilings, darker than the walls
One or two light fixture textures
One door texture with accompanying doorframe
One stair top texture, and one stair riser texture
One switch texture (well, at least two: on and off)
One "glue" texture
The last entry, what we call the "glue" texture, is one of the most critical. It is usually a small, simple texture that can be used to fill in odd spaces: thin slices of walls, edges of floors, or whatever other nooks and crannies that no other texture really works in. Even when your map is very simple, there will still be all sorts of places where a good glue texture saves it from looking sloppy: carpets seldom give way to hard floors without a little protective strip at the edge, door edges and railings often benefit from different textures on their various faces, etc. The glue texture can do a lot of this work for you, saving you from spending inordinate amounts of time creating specific textures for each and every bit of architecture.

If you create a set of textures according to that outline, then you have some structure to decide where you need to go with further textures. Signs, for instance, can be made that look appropriate for your area: more walls, lights, doors, technical devices, what have you. Your map will look less like a jumble of random textures and look more like a place with a purpose. The texture artist should work closely with the map maker to insure that textures are used appropriately, and to see where the designer has used perhaps an adequate generic texture when a specific texture for that feature might be warranted.

Realize also that the lighting of the level is going to play a large part in how the textures come out. Think about what sort of lighting is appropriate for the texture family, and work with lighting within the level to keep you from making too many textures: often two rooms can be given very different feels by using a warm light in one versus a cool light in the other, even if they share the same wall, floor, and ceiling textures. Don’t make the textures do all of the work: it helps map performance to keep the number of textures relatively low. Find the best balance for a texture family, and work in concert with the designer to insure that the right amount of effort is going in from their end as well as yours.

Technical Specifications

Textures must be increments of 16 pixels in size: the smallest texture possible is 16x16. The largest possible texture is 256x256. Any dimension of X and Y where both values are divisible by 16 is acceptable: 16x256, 48x80, 128x32, whatever. Any texture with bad dimensions will cause qlumpy to abort the WAD compiling process when it reaches that texture.

Textures are painted ordinarily as 24-bit images, and each one then must be reduced down to an individual palette of 256 colors. No two textures need to share the same palette, and nothing is gained in performance or memory by having textures share the same palette. They are saved as 8-bit BMP files. Any non-paletted texture will cause qlumpy to abort the WAD compiling process when it reaches that texture.

The final WAD may be of any size, but keep in mind that the larger the WAD, the more memory required to run Worldcraft acceptably. Worldcraft can read from multiple WADs, so making separate WADs according to style or use is a perfectly acceptable thing to do (it also serves as a good self-organizing feature, preventing designers from using drastically inappropriate textures together, if they limit themselves to certain WADs meant to work together.)

A texture name can be 15 contiguous characters long, before the .bmp extension. No spaces are allowed. The characters ! + - { all have special uses, described below, and should not be part of a simple texture name.

Types of Textures

Regular Tiling

The regular tiling texture is just that: one that tiles with itself when placed on a brush. It will tile in both the X and the Y, so keep that in mind when creating it and using it. A wall done, for instance, with a wainscoting painted in should not be used to tile vertically up a tall wall: it should only be used on walls one texture unit high. If there are taller walls, a secondary texture to go with that first one would be in order, where the wall could then go infinitely high without the wainscoting repeating inappropriately.

Regular tiling textures can be named anything.

Randomly Tiling

A Half-Life innovation is the randomly tiling texture set. This texture is very useful for organic materials or for organic damage to regular textures. With a random texture family, each texture is designed to tile seamlessly with any other member of the family, and by applying the first member of the random set to a wall, the engine will display that wall with a randomly tiled assortment of all members of that random set.

For instance, if you were to do a regular tiling texture of bricks, in a 64x64 pixel texture, and you colored the bricks naturally such that some were darker and some lighter than others, when you see that texture on a large wall, the darkest brick will likely stand out readily, forming a 64x64 grid on that wall. The tiling will be apparent and ugly. If, however, you were to do four 32x32 textures of bricks for a random set (which would take up the same memory as one 64x64 texture), and you applied that random set to the large wall, the bricks that stand out would not be noticeably tiling in any particular pattern: one of the 32x32 textures could have the darkest brick, and the instances of that particular texture along the wall would be random, not forming any particular pattern that calls attention to itself. One texture could have a little water stain, or crack in the mortar, and this sort of organic damage will not tile in an immediately obvious pattern.

There can be up to ten members of a randomly tiling set. The naming convention is that all members of the family have the same name, preceded by –X, where X is a digit from 0 to 9, in ascending order. For example, a six texture random set would be named –0texname.bmp to –5texname.bmp.

Other uses for a random texture set: have five textures that look nearly identical, with one member that has a wall socket, and this will give you walls for offices where occasionally a wall socket will be placed. Or half a dozen plain concrete textures with one that has a crack in it will allow for an infrequent crack to appear on an otherwise regular concrete wall. A rocky cliff face is helped immeasurably by doing four or five rock textures that tile together, so when seen from a distance the mip-mapping of the textures doesn’t reduce the cliff to a very ugly simple grid of color.

Intelligent use of random textures can breathe a lot of life into an otherwise standard area. Be careful, however, because often a poorly utilized random set can cause you to use five textures when one would do, so don’t overuse this feature. Note that by applying the first member (the –0 texture) of the set to a brush, you apply the whole set. If you apply any other member of the set, then the wall appears with only that member and no other, so it behooves the texture artist to arrange the set members so that the texture that tiles best by itself is not the –0 texture: that way, if the designer has used the random set but discovers a need to pare his map down memory-wise, he can substitute another –X texture for the –0, do no other texture alignment work, have his level automatically reduced in memory footprint, and have a decent single regular tiling texture in place of the luxurious randomly tiling set.

Random textures work in software, but not GL.

Regular Animating

Textures can animate as well. Creating a set of animating textures merely means naming them in the sequence order you wish them to animate in. They animate at a 10hz rate, and this cannot be changed. Name the first texture of the sequence +0texname.bmp, then proceed on up to +9texname.bmp (you can have a maximum of 10 frames of animation.) The textures will loop endlessly during the game.

Switchable Animating

These are animating textures that have a switchable state: they can either be animating or they can be off. To create a switchable animating set, create a regular animating set as described above, but also add a frame called +Atexname.bmp. This will be the off state for the texture. If a button is textured with the switchable animating set, it changes according to the button state. If a func_wall is textured with a switchable animating set and is the target of a trigger or button, it will change textures upon triggering.

You cannot switch from one animating state to a different animating state. Brushes can start off textured either with the +0texname texture or the +Atexname texture, and will toggle appropriately.

Masked Textures

Masked textures are textures that have transparent sections to them, with other sections that are opaque. In Half-Life, most of the ladders, grates, and railings were done with masked textures. Anything requiring fine detail that you can see through is a likely candidate for using a masked texture instead of brushwork.

To create a masked texture, paint the texture as you would normally, then paint in the "holes" in the texture by using the color 0 0 255 (pure blue). Any pixel of pure blue will become transparent in the engine. Note that a pixel of color 0 1 255 (amazingly indistinguishably close to pure blue) will not be transparent, so it is vital that you not paint the image with the blue in it from the beginning: more than likely, your visible portions will anti-alias to the background, and your texture will have a blue halo around it. Apply the blue as your last step.

Masked texture brushes need to be brush entities for them to be transparent: if they are standard world geometry, the blue will appear normally. Make them func_wall or func_illusionary entities, give them a rendermode of "solid" and a renderamount of "255", and they will appear correctly. Note that you can’t shoot through func_walls, so if you have a railing, for instance, it should probably be a func_illusionary with a corresponding clip brush to make it impassable to the player, but not block bullets.

The name of a masked texture must start with a {.

Liquid Procedural

Creating good water textures takes experimentation. Liquid textures can be 64x64 or 128x128 in size, and are designated as liquids by placing a "!" before their name, thus !texname.bmp is automatically understood by the engine to mean a water brush. The texture will have a water-droplet procedure added to it to create random ripple effects, so the basic texture data should be smooth and serve as a good background for the busier procedural effect, but with a decent dynamic range of color to allow the procedure sufficient colors to look good.

Fog color is handled by certain color registers in the texture: a color register is a palette location. Color register 0 is the first color of the palette, color register 255 is the last. Fog color is handled by color register 3 in a water texture, and the fog density is handled by color register 4. The density value is drawn from the R value of that register (G and B are ignored), so pure red is the densest fog and black is the least dense fog.

Qrad Textures

Textures in Half-Life can be specified to throw light, as if they were _light entities. To do so, they must be referenced in a RAD file. A texture thus referenced will always throw light: every example of that texture in the level will throw identical light. Further, this light cannot be turned off, so creating on/off textures for lights that one expects to switch should not be given qrad values: those lights need to be _light entities.

There are three types of RAD file: lights.rad, a global RAD file; designer.rad, a specifiable RAD file; and levelname.rad, a RAD file that is automatically parsed if it exists in the map directory when compiling a map of the same name. The designer.rad supersedes the lights.rad, and the levelname.rad supersedes the designer.rad, in case a texture is specified in multiple files. Qrad will not run if lights.rad is not present in the \valve directory.

A texture can be given an RGB value in the RAD file, or an RGBV value. RGBV values are a little easier to understand sometimes, but you may use either. The amount of light a texture throws off is directly proportional to how much of that texture is visible, so TexlightA on a 4x4 pixel face may throw off very little light, while the same texture on a 128x128 pixel face may flood a room completely with light. It’s best to decide on a light value for a texture and use that texture similarly under all circumstances: that’s the best way to know what things will look like in the engine. A designer usually handles the RAD file for a map, but the texture artist should know how textures get used in this way.

A RAD file is a text file that looks like this:

TexlightA     255     0     0
TexlightB     25500     36000     1000
TexlightC     128     128     0     10000
TexlightD     100     128     225     1000
<…>
 

The first texture is just RGB values, the second is RGB where the texture needs to be really powerfully bright: perhaps it will always appear on very small faces but be asked to throw a lot of light, like a small halogen bulb. As you can see, with three values like that, it can be tough to know exactly what color light the thing is, because there’s no paint program that will show you what the values 25500 36000 1000 work out to. The better way is to add the V number, so you can more readily understand the exact color (by bringing up a paint program and generating the color you want, and writing down the RGB values). Increasing or decreasing the strength of the light is merely a matter of adjusting the final number up or down. Given an RGBV sequence, the RGB values must be between 0 and 255. The V can be anything. Given just RGB, they can be any value, but again, it’s tougher to predict what the light will be, and tougher to adjust the texture to be brighter or darker while maintaining the same hue.
 

WAD Creation

WAD3 format

The WAD3 format is similar to the WAD format of Quake, except that each texture entry is followed by a short (number of palette entries), then 256 RGB entries describing its palette. The old Quake WAD just used one overall palette, but each texture in Half-Life has an individual palette, thus the format change. Writers of WAD utilities should be able to parse the file format given the above information.

Makels.exe

Makels.exe is a simple program that generates a script file for easy compiling of textures into a WAD. With Quake, multiple textures would be referenced on a single 320x200 page, and the script file had to be written by hand to give ripping coordinates, etc. Slow process.

Now each texture is an individual BMP file, utilizing the whole space (no non-texture areas of the canvas), so no hand input of coordinates is necessary. Makels creates the script by looking into the specified directory, and writing the script referencing all the BMPs it finds in that directory. Simple and painless. The command line is thus:

Makels <directory of BMPs name> <output WAD name> <scriptname>

The output will be scriptname.ls. This file can then be fed to qlumpy, which grabs the BMPs according to the script and builds the WAD file. Included is a batch file that will compile the sample textures.

Qlumpy.exe

Qlumpy.exe rips all the BMP files and makes mip-maps out of them, and compiles them into a WAD file. It uses the .ls file to know what to do. Just typing "qlumpy scriptname.ls" should be all you need to do.

Makewad.bat

Makewad.bat is a simple batch file that should compile the sample texture folder into a sample WAD file, suitable for Worldcraft. It shows you what to do when running the utilities, and can of course be duplicated and renamed, rewritten to make different WADs from different directories of textures, etc.
 


This is Wavelength's html version of Valve's Texture and WAD Tutorial for Half-Life.