Quick and Dirty Material Shader Primer
Introduction
In Doom 3 textures are usually composed of several images. These images are blended using different techniques to form a material. These materials are what you see as "textures" in game.
What these images do is define the asthetics of a surface. By combining the efforts of multiple images, each reacting differently to the light surrounding it, you can convey more realism than by using a single image.
The problem with using multiple images is that you need a way to associate them with one another. This is where material shaders come into play.
A material shader is nothing more than a list of commands enclosed in curly brackets with a given name. These commands define what images to use, where to locate them, how they should behave, and how the surface should react to different events in game.
Naming Convention
If you've ever used Doom 3's level editor, you've probably seen the media browser and how it appears to be a directory tree. If you take anything away from this tutorial please note that this menu while it is a directory tree, is not a reflection of actual directories on your hard drive or inside pak files.
In order to help explain this I'm going to have to throw a material shader in your face real quick.
Here is a material shader found in vehicles.mtr...
Code:
models/mapobjects/buggy/buggy
{
renderbump -size 512 512 -aa 2 models/md5/vehicles/buggy/buggy_local.tga models/md5/vehicles/buggy/buggy_hi.lwo
diffusemap models/mapobjects/base/chairs/chair1_bmp.tga
specularmap models/mapobjects/base/chairs/chair1_bmp.tga
bumpmap models/md5/vehicles/buggy/buggy_local.tga
}
Now what's important to note here is the very first line. It says models/mapobjects/buggy/buggy. This is the name of the material. Yes, I am aware that there are forward slashes and it looks like it's pointing to a directory.
And to help prove my point we're going to look for this mysterious directory. First, it says models so that means we should look in pak002.pk4. Now try to browse to models\mapobjects\buggy\buggy.
What's that? There is no buggy directory? Well that can't be right because clearly models/mapobjects/buggy/buggy is a path because it has slashes. Now you can search the other pak files if you want but I'm telling you right now that you're not going to find a buggy directory anywhere unless you're a smart ass and create one yourself.
So, now you've got to be wondering, if models/mapobjects/buggy/buggy is a material name then why are there slashes?
Well, I'll explain that with an example. Remember how the media browser displays a directory tree? Well, if you were to open the editor and go to the media browser. Then browse to models/mapobjects/ you'd see that in the media browser a buggy folder exists and inside this folder is a material named buggy. Coinsidence?
Note: If you have the clean shaders pak that you won't find this shader in the editor.
So, while models/mapobjects/buggy/buggy does not point to a directory inside the pak files it does point to a location inside the media browser.
What does this mean? That you can name your material shaders whatever the hell you want. I can name a material shader foo/dee/dum/wee and it won't matter if my images are stored in the models, or textures folder. All the shader name applies to is the location of the material in the media browser.
Stages and Curly BracketsNow that we know how to name a material shader we need to define where the shader begins and ends. Let's look at that buggy shader again...
Code:
models/mapobjects/buggy/buggy
{
renderbump -size 512 512 -aa 2 models/md5/vehicles/buggy/buggy_local.tga models/md5/vehicles/buggy/buggy_hi.lwo
diffusemap models/mapobjects/base/chairs/chair1_bmp.tga
specularmap models/mapobjects/base/chairs/chair1_bmp.tga
bumpmap models/md5/vehicles/buggy/buggy_local.tga
}
If you look at the shader above you'll see two curly brackets. These brackets define where models/mapobjects/buggy/buggy begins and ends. Opening curly brackets define the start and closing curly brackets define the end.
Now, in this material shader there are three stages. What are stages? Well, you can think of them as layers in Photoshop where each layer could act as it's own separate image. They are in a stack and in some cases the order in which you code them has an effect on the outcome.
For instance, if I had a opaque image on one stage and an image with an alpha blend on another, I would have to ensure that the alpha blended stage was the top most stage so you could see through the transparent parts to the opaque stage below. If it were the other way around, I would not be able to see the alpha blended stage because the opaque stage would obscure it.
The good news is that the three most common blend modes do not have to be in a certain order to render properly.
Don't breathe a sigh of relief yet. There is more to talk about in regards to stages but we'll get back to that later.
Three Most Common Blend ModesNow that we can name a material shader and understand the basic structure we can actually start with the important stuff, blend modes. And since this is just a primer we're only going to bother with the three most common. They are diffusemap, bumpmap, and specularmap.
Diffuse maps define the color of a surface. Diffuse maps do not effect lighting.
Normal maps define the slope of a surface. Normal maps are the most influential in regards to how light effects a surface.
Specular maps define the specular intensity and color of highlights on a surface. Brightness effects the intensity. Hue and saturation effects color.
As for how to use these blend modes let's yet again look at an example shader...
Code:
models/mapobjects/buggy/buggy
{
renderbump -size 512 512 -aa 2 models/md5/vehicles/buggy/buggy_local.tga models/md5/vehicles/buggy/buggy_hi.lwo
diffusemap models/mapobjects/base/chairs/chair1_bmp.tga
specularmap models/mapobjects/base/chairs/chair1_bmp.tga
bumpmap models/md5/vehicles/buggy/buggy_local.tga
}
Now you can see above that each command diffusemap, specularmap, and bumpmap is followed by a reference to an image file. These file paths are relative to the Doom 3 base directory, a mod directory, or the structure of a pak file. In this case they refer to pak002.pk4 because that is the pak with a models folder.
Just to wrap this section up I want to spend a bit of time on the command qer_editorimage. It's not a blend mode but it's format is the same. So, if it's not a blend mode then why is it important?
Well, the editor relies on this command so it knows what to display on the face of your brushes in the camera window. If you leave it out, like it is missing from this shader, then whenever you apply a new material to a brush it will be solid black.
What image you point it to is not important since it has no effect in game but generally it's a good idea to point it at the diffuse map just for the sake of asthetics.
Stages with Special ParametersHere's an example shader I wrote using what we've talked about up to this point...
Code:
textures/custom/mask
{
qer_editorimage textures\custom\mask_d.tga
diffusemap textures\custom\mask_d.tga
specularmap textures\custom\grey.tga
}
Let's say I want my specular map to scroll. Well, the command for that is called translate. But where would I put this command? How would the game know what stage I want to apply this effect to?
Well, without adding new curly brackets it won't. But there's more to it then just wrapping the specularmap command in a set of curly brackets.
Here's how my shader would look after adding the translate command to the specularmap stage...
Code:
textures/custom/mask
{
qer_editorimage textures\custom\mask_d.tga
diffusemap textures\custom\mask_d.tga
{
blend specularmap
map textures\custom\grey.tga
translate 1, 0
}
}
So, what's happening here is a curly bracket defines where this new stage starts. Then it's followed by a blend command that informs the game that this stage will be a specular map stage. Then it's followed by a map command that tells the game what image I intend to use as my specular map. And finally I have my translate command followed by a closing bracket to let the game know that this is the end of the specular stage.
General Material ParametersThe last thing I want to talk about is general material parameters. These are commands that do not affect individual stages but rather the entire material as a whole.
For instance, one of these parameters is metal, and if I added it to my example material it would look like this...
Code:
textures/custom/mask
{
metal
qer_editorimage textures\custom\mask_d.tga
diffusemap textures\custom\mask_d.tga
{
blend specularmap
map textures\custom\grey.tga
translate 1, 0
}
}
What this parameter does is tell the game that when this material is shot it should react as if it were made of metal.
One thing to keep in mind though is that we are not limited to defining the behavior of a material with these commands. There are also commands that effect the way a material is rendered.
An example is the command twosided. This command is best used with decals when you want both sides to be rendered. An example would be all those non-patch hanging wires you see in game. Those are just decals that are set to be two sided.
Conclusion
Now you should have a pretty good idea how to write your own material shaders.
Granted, it's not going to be anything complex but the whole point of this tutorial is just to get the most basic of questions answered and to fill the need for a primer since the SDK is taking longer than I expected.
If you spend a little time examining Doom 3's existing shaders then figuring out what other commands do should be a breeze. And if it's not, the SDK is on the way and there should be a shader manual included.