Materials and Compiled States (.smt_t and .rw4)
Materials define the way an object is rendered in the game. All models have at least one material that will tell the renderer which texture, shader, color, etc to use when rendering.
Materials are actually made of:
- One or multiple compiled states. Compiled states contain most information about the material; usually only one is used, we don't knw what multiple states might be used for.
You can find materials in two places:
.rw4models. There can be more than one material there, and they are called
.smt_tfiles, which are part of material packs. Material packs contain all those general materials that are not used in an specific model (for example, water, creature, etc)
Material packs are stored in the
materials_compiled_states_link~ (0x40212000) folder, in a
.smt file; when unpacked, they finish with the extension
.smt_t. It is possible to create your custom material packs. You can have your own
MyMaterials.smt.unpacked folder (where MyMaterials is whatever name you want, unique to your mod) containing material files.
A .smt_t file contains one or multiple compiled states that will be used by your material. Then, it contains only one
material instruction that follows this structure:
material ID -states stateNames... -textures textureIDs
IDis the exported name of your shader. That will be the ID you have to reference to use this material.
statesyou must specify the names of the compiled states in the file that the material will use.
texturesis optional, you can specify the folder and file name (with no extension) of any textures this material requires.
Example of a
Compiled states are defined with the
compiledState block, they take a name as a parameter. The name of the state only affects the file and so it's not really important. They can have the following attributes:
The color of the material, with opacity; when defined, it can be used in shaders with the
materialColor shader data. Takes an RGBA ArgScript Color.
The ambient color of the material; when defined, it can be used in shaders with the
ambientColor shader data. Takes an RGB ArgScript Color.
Determines the type of primitive used in the model data, generally you don't need to touch this. The value is any of the D3DPRIMITIVETYPE enumeration.
Unknown usage, maybe related with textures. Takes 17 boolean values.
shaderData dataName data...
Compiled states can define Shader Data that will be used when rendering the material. You must specify the name of the data (sometimes it's an hexadecimal number) and then all the values it takes. Unfortunately, values can only be displayed as integers so if you, for example, want to use a floating point number, you will need to convert it beforehand. You can use this instruction multiple times to define more than one data.
Render States are different variables that affect the rendering pipeline. In a material you can specify multiple render states with this instruction:
renderState name value
You must specify the name, which is any in the D3DRENDERSTATETYPE enumeration. The type of value expected depends on the specific render state.
Rende states can be grouped inside a
statesGroup block, which takes an integer as parameter. For example:
statesGroup 0 renderState D3DRS_SRCBLEND D3DBLEND_SRCALPHA renderState D3DRS_DESTBLEND D3DBLEND_INVSRCALPHA renderState D3DRS_ALPHABLENDENABLE TRUE end
Materials can use textures, those are defined through texture slots. Keep in mind, a slot means that a texture could be used there, but it's not the texture itself. This means taht you can't have two texture slots without assigning them any texture, because maybe the game code will add that texture when using the material.
Texture slots are defined using the
textureSlot block, which takes the slot index (starting at 0) as parameter. The block can have the following attributes:
samplerState name value
You must specify the name, which is any in the D3DSAMPLERSTATETYPE enumeration. The type of value expected depends on the specific render state.
stageState name value
You must specify the name, which is any in the D3DTEXTURESTAGESTATETYPE enumeration. The type of value expected depends on the specific render state.
Only available in the materials of a
.rw4 model. This attribute holds the index of the raster object used as a texture.
Example of two texture slots in a
textureSlot 0 samplerState D3DSAMP_ADDRESSU D3DTADDRESS_BORDER samplerState D3DSAMP_ADDRESSV D3DTADDRESS_BORDER samplerState D3DSAMP_MAGFILTER D3DTEXF_LINEAR samplerState D3DSAMP_MINFILTER D3DTEXF_LINEAR end textureSlot 1 samplerState D3DSAMP_ADDRESSU D3DTADDRESS_BORDER samplerState D3DSAMP_ADDRESSV D3DTADDRESS_BORDER samplerState D3DSAMP_MAGFILTER D3DTEXF_LINEAR samplerState D3DSAMP_MINFILTER D3DTEXF_LINEAR end
vertexDescription lock is really important as it defines the elements (e.g. position, normals, UV coordinates, vertex colors, etc) that vertices in the models that use this material must use. Therefore, the vertex description is used to read data from vertices and defines the data that is sent to the shaders.
The vertex description block is made up of multiple element instructions (order is important), which follow this structure:
element type usage shaderUsage -usageIndex int -stream int -method D3DDECLMETHOD
Optionally you can also specify the
-stream, although these are rarely used.
Example of a vertex description:
vertexDescription element position D3DDECLTYPE_FLOAT3 element texcoord0 D3DDECLTYPE_FLOAT2 element texcoord1 D3DDECLTYPE_FLOAT3 element color D3DDECLTYPE_D3DCOLOR end