Texture Map Specifications

The simplest form of a material definition is to only specify the texture map images that compose the material. The previous example, repeated here, was an example for such a simple definition:

    Textures/Kai/3r_metpan01        // Material definitions start with the material name.
    {
        diffusemap  Textures/Kai/3r_metpan01_diff.png     // This line says which texture is used as diffuse-map.
        normalmap   Textures/Kai/3r_metpan01_norm.png
        specularmap Textures/Kai/3r_metpan01_spec.png
        lightmap    $lightmap
    }

A texture map specification starts with a keyword (e.g. diffusemap) and is followed by a “map composition”.

Map compositions are normally just the path plus file name of a texture image relative to the MOD directory, like for example Textures/Kai/3r_metpan01_diff.png. However, map compositions can also be more complex constructs as explained in the next section Map Compositions.

The initial keyword (diffusemap etc.) defines how the texture image is used in dynamic lighting computations during rendering. This is very similar to Doom3 materials, and both Cafu and Doom3 implement in this regard a form of the Phong lighting model.

Here comes a list of all available keywords for texture map specifications, along with a short description of their default meaning. (The default is dynamic Phong lighting, which however can be overridden, as explained at Shader Specifications.)

You can specify arbitrary combinations of these keywords in one material, as only the diffusemap keyword is mandatory. However, if you use the same keyword more than once, only the last occurrence is considered. The order of the keywords occurrences is not relevant.

Map Compositions

Texture map image specifications with the above keywords can not only be simple file names, but also be more powerful Map Compositions. A map composition is a description of how a single texture map image is composited from several source images on disk. Here is an example for a simple material whose normal-map is defined by a complex map composition:

    Textures/Kai/barrel_rst
    {
        diffusemap Textures/Kai/barrel_rst_diff.png
        normalmap  combineNMs(MyNm1.png, hm2nm(add(MyHm2.jpg, MyHm3.tga)))
        lightmap   $lightmap
    }

(This example is overly complex for demonstration purposes, and not really meaningful. Real-life examples are normally much simpler.)

The expressions that are valid to define a map composition are defined as follows. Please note that the arbitrary nesting of expressions is expressly permitted, yielding great freedom for artists.

You can apply map composition expressions to all above mentioned texture map specification keywords, i.e. they work with diffusemap, normalmap, specularmap, cubemap, etc.

Technically, a map composition is completed before the Cafu engine or the graphics board see them. In other words, the engine or the 3D hardware never see the individual images, only the composite result. Everything that is done by these composition steps could also be pre-worked by the artist in an image processing software. There would be no difference for the engine, the hardware, or in the resource (memory) consumption. Note that this feature has nothing to do with dynamic lighting or how a texture map image is combined with images of other texture map specification keywords!

Finally, you can specify several comma-separated options for the map composition:

The meaning of the minFilter, magFilter, wrapS and wrapT options is analogous to their respective meanings in the OpenGL and DirectX APIs. The OpenGL Programming Guide (the “Red Book”) about OpenGL version 1.2 and higher has a good explanation about these options. Although the text is specific to OpenGL, the same concepts apply to the above mentioned options. The “Red Book” for version 1.1 does not address the clampToEdge option, but its text is available online at http://www.rush3d.com/reference/opengl-redbook-1.1/chapter09.html.

The options noScaleDown and minFilter bilinear are often combined, because both scaling down textures for better graphics performance as well as using trilinear filtering for rendering have a tendency to mix the colors of neighboring pixels. In some cases such as font textures, even the bilinear filtering is too much mix-up, requiring us to combine noScaleDown with minFilter nearest.

Options Example 1

Here is an example from Games/DeathMatch/Materials/Fonts.cmat that demonstrates how the options are used:

    Fonts/Arial
    {
        diffusemap ../../Fonts/Arial.png, minFilter nearest, magFilter nearest, noScaleDown
        // ...
    }

Options Example 2

Another example for the noScaleDown and minFilter keywords.

This is a typical skin texture that a modeller has produced for application to one of his model meshes.

A straightforward material definition would look like this:

    Models/Players/Trinity/trinityskin3
    {
        diffusemap Models/Players/Trinity_Skin_diff.png

        red   ambientLightRed
        green ambientLightGreen
        blue  ambientLightBlue
    }

The image to the left shows the result of the this material definition being applied to a model mesh. Notice the small glitch in the image, which is a result of mipmaps being applied to the above shown texture: Mip-mapping mixes black pixels of the hair with adjacent, bright pixels of the skin, yielding the intermediate colors that are marked in the result image to the left. Such glitches are even more disturbing and better visible with animated models, e.g. when the head of the model slightly turns.

Note that these kinds of artifacts are no bugs, they are a normal result from mipmap filtering.

With the noScaleDown and minFilter bilinear keywords applied in the material script, the glitch disappears as shown here:

    Models/Players/Trinity/trinityskin3
    {
        diffusemap Models/Players/Trinity_Skin_diff.png, minFilter bilinear, noScaleDown

        red   ambientLightRed
        green ambientLightGreen
        blue  ambientLightBlue
    }