Difference between revisions of "Materials (Metroid Prime)"

From Retro Modding Wiki
Jump to: navigation, search
(Texgen)
(Flags)
 
(62 intermediate revisions by 4 users not shown)
Line 1: Line 1:
The format for '''materials''' is seen in both the [[CMDL (Metroid Prime)|CMDL]] and [[MREA (File Format)|MREA]] formats, and is identical in both. This particular material format appears in both Metroid Prime and Metroid Prime 2, with minor differences.
+
The format for '''materials''' is seen in both the [[CMDL (Metroid Prime)|CMDL]] and [[MREA (File Format)|MREA]] formats and is identical in both. This particular material format appears in both Metroid Prime and Metroid Prime 2 with minor differences.
  
{{researchmoderate|reason=There are a few unknown values, and some unknown settings in known values; there are also a few unknown material animation modes. Also, basically everything that was introduced in Echoes (two general settings and a vertex attribute) is unknown.}}
+
{{research|minor|MP1's materials are completely understood, but MP2 introduced two new values that are both unknown.}}
  
 
__TOC__
 
__TOC__
  
== GX Explanation ==
+
== GX Overview ==
  
 
The materials system in Metroid Prime is heavily dependent on the GameCube and Wii's graphics system, GX. GX is a fixed-function graphics pipeline, similar to old versions of OpenGL. In GX, rendering is done through a series of steps called '''T'''exture '''E'''n'''V'''ironment Stages, or or TEV stages for short.
 
The materials system in Metroid Prime is heavily dependent on the GameCube and Wii's graphics system, GX. GX is a fixed-function graphics pipeline, similar to old versions of OpenGL. In GX, rendering is done through a series of steps called '''T'''exture '''E'''n'''V'''ironment Stages, or or TEV stages for short.
  
Prior to TEV stages, per-vertex calculations are performed. Lighting calculations are performed, and passed to GX as a rasterized vertex color; texture coordinate generation (texgen) is also performed and made available to TEV.
+
Lighting calculations and tex coord generation are done per-vertex and passed along to TEV; the results of the lighting calculations are saved into up to two color channels that can be used as TEV inputs (as the rasterized vertex color). Each TEV stage takes in four color inputs and four alpha inputs, from one of eight sources. Then these four input colors are combined into one output color, and the output is saved into one of four registers, which can subsequently be used as input in the next TEV stages. The final stage must always save its output into the "previous TEV stage" register; that register is used as the final pixel color that gets displayed onscreen.
 
+
How TEV stages actually work: Each TEV stage takes in four color (RGB) inputs, and four alpha inputs, from one of eight sources. Then these four input colors are combined into one output color, and the output is saved into one of four registers, which can subsequently be used as input in the next TEV stages. The final stage must always save its output into the "previous TEV stage" register; that register is used as the final pixel color that gets displayed onscreen.
+
  
 
== Material Set Format ==
 
== Material Set Format ==
Line 78: Line 76:
 
| long
 
| long
 
| 1
 
| 1
| {{unknown|'''Unknown'''}}
+
| '''Group index'''
 
|-
 
|-
 
| long
 
| long
Line 98: Line 96:
 
| long
 
| long
 
| 1
 
| 1
| {{unknown|'''Unknown''' ''(note: only present if flag 0x400 is set!)''}}
+
| '''Reflection indirect texture slot index''' ''(note: only present if flag 0x400 is set!)''
 
|-
 
|-
 
| long
 
| long
 
| 1
 
| 1
| '''Color channel flag count''' (CC)
+
| '''Color channel count''' (CC)
 
|-
 
|-
 
| long
 
| long
 
| CC
 
| CC
| '''Color channel flags'''
+
| '''Color channel flags''' ''(note: only one flag value, but you must advance 4*CC bytes instead of 4 for some reason)''
 
|-
 
|-
 
| long
 
| long
Line 115: Line 113:
 
==== Flags ====
 
==== Flags ====
  
These are the known flag settings:
+
These are simple boolean settings that can be toggled on and off on each material. These are the known flag settings:
  
 
{| class="wikitable"
 
{| class="wikitable"
Line 124: Line 122:
 
| 0
 
| 0
 
| 0x1
 
| 0x1
| Appears unused, but always set
+
| Unused, always set ''(never set in Echoes)''
 
|-
 
|-
 
| 1
 
| 1
 
| 0x2
 
| 0x2
| Appears unused, but always set
+
| Unused, always set
 
|-
 
|-
 
| 2
 
| 2
 
| 0x4
 
| 0x4
| Appears unused, but always unset
+
| Unused, never set
 
|-
 
|-
 
| 3
 
| 3
 
| 0x8
 
| 0x8
| Enable Konstant values
+
| Has Konst values
 
|-
 
|-
 
| 4
 
| 4
 
| 0x10
 
| 0x10
| Mark transparent material
+
| Transparent
 
|-
 
|-
 
| 5
 
| 5
 
| 0x20
 
| 0x20
| Enable punchthrough alpha
+
| Masked alpha (compare threshold is hardcoded at 0.25)
 
|-
 
|-
 
| 6
 
| 6
Line 152: Line 150:
 
| 7
 
| 7
 
| 0x80
 
| 0x80
| Enable depth writing
+
| Enable Z-writes
 
|-
 
|-
 
| 8
 
| 8
 
| 0x100
 
| 0x100
| {{unknown|Unknown}}
+
| Enable Samus's reflection, using the eye position and projection direction from the surface header
 
|-
 
|-
 
| 9
 
| 9
 
| 0x200
 
| 0x200
| Don't draw
+
| Shadow occluder mesh; meshes using this material are not rendered, but can be used to cast dynamic shadows on actors
 
|-
 
|-
 
| 10
 
| 10
 
| 0x400
 
| 0x400
| Enable second unknown value
+
| Enable indirect texture stage for reflections
 
|-
 
|-
 
| 11
 
| 11
 
| 0x800
 
| 0x800
| {{unknown|Unknown}}
+
| Indicates a lightmap is present; no ingame effect
 
|-
 
|-
 
| 12
 
| 12
 
| 0x1000
 
| 0x1000
| {{unknown|Unknown}}
+
| Unused, always set ''(never set in Echoes)''
 
|-
 
|-
 
| 13
 
| 13
 
| 0x2000
 
| 0x2000
| Enable lightmaps; first UV coordinate uses short array instead of float array
+
| Enable first UV coordinate to use short array instead of float array (used for world lightmaps)
 
|-
 
|-
 
| 14
 
| 14
 
| 0x4000
 
| 0x4000
| Appears to do the same thing as bit 14
+
| {{unknown|In MP1, unused, never set; in Echoes, unknown}}
 
|-
 
|-
 
| 15
 
| 15
 
| 0x8000
 
| 0x8000
| {{unknown|Unknown}}
+
| {{unknown|In MP1, unused, never set; in Echoes, unknown}}
 
|-
 
|-
| 16
+
| 16-31
| 0x10000
+
| 0xFFFF0000
| {{unknown|Unknown}}
+
| TEV texture flags; a bit set indicates that the corresponding TEV stage uses a texture. No ingame effect.
|-
+
| 17
+
| 0x20000
+
| {{unknown|Unknown}}
+
|-
+
| 18
+
| 0x40000
+
| {{unknown|Unknown}}
+
|-
+
| 19
+
| 0x80000
+
| {{unknown|Unknown}}
+
|-
+
| 20+
+
| 0x100000+
+
| Unused; never set
+
 
|}
 
|}
  
 
==== Vertex Attribute Flags ====
 
==== Vertex Attribute Flags ====
  
These flags are generally toggled in pairs, with each pair corresponding to a vertex attribute; if a pair is set, then vertices using this material will have the corresponding attribute. This is vital for reading geometry.
+
These flags are generally toggled in pairs, with each pair corresponding to a vertex attribute; if a pair is set, then vertices using this material will have the corresponding attribute. This is vital for reading geometry. Starting in Echoes, each pair is used to indicate the size of the attribute indices in the geometry data, with 3 meaning a 16-bit index and 2 meaning an 8-bit index. (This isn't actually used, though; the original game data always uses 16-bit indices.)
  
An important note is that while the leftmost byte is not used in Prime 1, in Echoes there's occasionally a value there that toggles an extra vertex attribute preceding position. This needs research to determine what the new attribute actually is. Also, GX supports up to 8 texture coords per vertex, but the game doesn't seem to allow you to assign more than 7 (though this could do with some double-checking).
+
GX supports up to 8 texture coords per vertex, but the game doesn't seem to allow you to assign more than 7 (though this could do with some double-checking).
  
 
These are the possible attributes:
 
These are the possible attributes:
Line 240: Line 222:
 
| Tex 2
 
| Tex 2
 
|-
 
|-
| 0xC0000
+
| 0xC000
 
| Tex 3
 
| Tex 3
 
|-
 
|-
| 0x300000
+
| 0x30000
 
| Tex 4
 
| Tex 4
 
|-
 
|-
| 0xC00000
+
| 0xC0000
 
| Tex 5
 
| Tex 5
 
|-
 
|-
| 0x3000000
+
| 0x300000
 
| Tex 6
 
| Tex 6
 
|}
 
|}
 +
 +
Echoes introduces some new attributes using the top byte of the flags value; unlike the other flags, these are not set in pairs. Each individual bit indicates the presence of a different attribute. The indices in the geometry data are always 8 bits.
 +
 +
{| class="wikitable"
 +
! Bit
 +
! Attribute
 +
|-
 +
| 0x1
 +
| Position Matrix Index
 +
|-
 +
| 0x2
 +
| Tex0 Matrix Index
 +
|-
 +
| 0x4
 +
| Tex1 Matrix Index
 +
|-
 +
| 0x8
 +
| Tex2 Matrix Index
 +
|-
 +
| 0x10
 +
| Tex3 Matrix Index
 +
|-
 +
| 0x20
 +
| Tex4 Matrix Index
 +
|-
 +
| 0x40
 +
| Tex5 Matrix Index
 +
|-
 +
| 0x80
 +
| Tex6 Matrix Index
 +
|}
 +
 +
==== Group Index ====
 +
 +
The group index marks groups of materials that all have the same settings, but different textures. The game will check the value after loading the textures (but prior to the vertex attribute flags), and check whether the group index set on the material matches the material currently set up. If it does, it will skip the rest of the material setup. The value typically starts at 0 on the first material and increments by 1 on each new group with different settings.
  
 
==== Konst Colors ====
 
==== Konst Colors ====
Line 292: Line 309:
 
==== Color Channels ====
 
==== Color Channels ====
  
There's an odd quirk with how these values work; although there's a count value listed, the game will only actually read the first value listed, and then skip the rest. There's no reason to ever have more than one flag value. Aside from that, how this works is unknown and needs research.
+
The color channels data consists of a count value indicating the number of color channels, and then one set of flags that controls the COLOR0 channel. The flags correspond to arguments passed to [http://libogc.devkitpro.org/gx_8h.html#a87d79cf2375217d06237c887ba027cc2 GX_SetChanCtrl()]. These are the settings:
 +
 
 +
{| class="wikitable"
 +
! Bits
 +
! Hex
 +
! Description
 +
|-
 +
| 0
 +
| 0x1
 +
| '''Enable lighting''' (enable)
 +
|-
 +
| 1
 +
| 0x2
 +
| '''Ambient color source''' (ambsrc)
 +
|-
 +
| 2
 +
| 0x4
 +
| '''Material color source''' (matsrc)
 +
|-
 +
| 3-10
 +
| 0x7F8
 +
| '''Light mask'''; always 0, filled in at runtime ([http://libogc.devkitpro.org/group__lightid.html litmask])
 +
|-
 +
| 11-12
 +
| 0x1800
 +
| '''Diffuse function''' ([http://libogc.devkitpro.org/group__difffn.html diff_fn])
 +
|-
 +
| 13-14
 +
| 0x6000
 +
| '''Attenuation function''' ([http://libogc.devkitpro.org/group__attenfunc.html attn_fn])
 +
|}
 +
 
 +
There's only one set of flags, which operates on COLOR0. COLOR1 is reserved for dynamic shadows (terrain casting shadows on actors), so its settings can't be directly modified. Here's how the other color channel settings work.
 +
 
 +
COLOR1A1's settings vary depending on whether shadowmaps are enabled:
 +
 
 +
* No processing will be done if the count value is 0. Otherwise, the count value is ignored; the game will always set up both color channels.
 +
* COLOR1A1's ambient color is black, and its material color is white.
 +
* COLOR1 will use the diffuse function GX_DF_CLAMP and the attenuation function GX_AF_SPOT. It will have lighting disabled entirely if there are no lights in range
 +
 
 +
If shadowmaps are disabled:
 +
 
 +
* COLOR1 is disabled if the count value is not 2. If it is 2, then its ambient color will be black and its material color will be white.
 +
 
 +
COLOR0 is set up the same way either way:
 +
 
 +
* COLOR0 will use the flags from the material, with the light mask merged in. It will also have lighting disabled if there are no lights in range.
 +
* If there are no lights in range, COLOR0A0 will have its material color set to match its ambient color. Otherwise, its material color will be set to white.
 +
 
 +
Finally, an important note is that the formatting of the color channel info is bugged. There is always a color channel count and a single set of flags; 8 bytes total. However, for some reason the game is expecting one set of flags per color channel. To reach the TEV stages, you need to advance (4 * count) bytes past the count value, rather than 4. A likely explanation is that there was one set of flags per channel earlier in development, and the material loading code wasn't fully updated when this was changed. It's not normally an issue because the count is always 1 in every file the game uses, but beware for experimentation/custom materials.
  
 
=== TEV Stages ===
 
=== TEV Stages ===
Line 325: Line 391:
 
| 0x11
 
| 0x11
 
| 1
 
| 1
| '''Konst Alpha Input'''
+
| '''Konst Alpha Input''' ([http://libogc.devkitpro.org/group__tevkalphasel.html possible values])
 
|-
 
|-
 
| 0x12
 
| 0x12
 
| 1
 
| 1
| '''Konst Color Input'''
+
| '''Konst Color Input''' ([http://libogc.devkitpro.org/group__tevkcolorsel.html possible values])
 
|-
 
|-
 
| 0x13
 
| 0x13
 
| 1
 
| 1
| '''Rasterized Color Input'''
+
| '''Rasterized Color Input''' ([http://libogc.devkitpro.org/group__channelid.html possible values])
 
|-
 
|-
 
| 0x14
 
| 0x14
Line 440: Line 506:
 
==== Alpha Input Flags ====
 
==== Alpha Input Flags ====
  
Similar to the color input flags, these set the four alpha inputs used by the TEV stage. Each value is allocated 5 bits, although only 3 are used. The main difference with alpha is there's only 8 possible sources instead of 16:
+
Similar to the color input flags, these set the four alpha inputs used by the TEV stage. Each value is allocated 5 bits, although only 3 are used. The main difference with alpha is that there are only 8 possible sources instead of 16:
  
 
{| class="wikitable"
 
{| class="wikitable"
Line 497: Line 563:
 
| 0-3
 
| 0-3
 
| 0xF
 
| 0xF
| tevop; [http://libogc.devkitpro.org/group__tevop.html there are ten accepted values.]
+
| '''Combiner operator''' ([http://libogc.devkitpro.org/group__tevop.html tevop])
 
|-
 
|-
 
| 4-5
 
| 4-5
 
| 0x30
 
| 0x30
| tevbias. 00 does nothing; 01 adds 0.5; 10 subtracts 0.5; 11 does nothing.
+
| '''Bias''' ([http://libogc.devkitpro.org/group__tevbias.html tevbias]); 00 does nothing; 01 adds 0.5; 10 subtracts 0.5; 11 does nothing.
 
|-
 
|-
 
| 6-7
 
| 6-7
 
| 0xC0
 
| 0xC0
| tevscale. 00 does nothing; 01 multiples by 2; 10 multiplies by 4; 11 divides by 2.
+
| '''Scale''' ([http://libogc.devkitpro.org/group__tevscale.html tevscale]); 00 does nothing; 01 multiples by 2; 10 multiplies by 4; 11 divides by 2.
 
|-
 
|-
 
| 8
 
| 8
 
| 0x100
 
| 0x100
| clamp; enabling this will clamp the output color between 0 and 1.
+
| '''Clamp flag'''; enabling this will clamp the output color between 0 and 1.
 
|-
 
|-
 
| 9-10
 
| 9-10
 
| 0x600
 
| 0x600
| tevrigid; this sets the register that the output color is saved into. 00 is the previous stage register; 01 is Color 0; 10 is Color 1; 11 is Color 2.
+
| '''Output register''' ([http://libogc.devkitpro.org/group__tevcoloutreg.html tevrigid]); can be Previous Stage or Color 0/1/2
 
|-
 
|-
 
| 11+
 
| 11+
Line 544: Line 610:
 
|}
 
|}
  
The flags largely correspond to arguments passed to [http://libogc.devkitpro.org/gx_8h.html#a55a426a3ff796db584302bddd829f002 GX_SetTexCoordGen2()]. These are the settings:
+
The flags correspond to arguments passed to [http://libogc.devkitpro.org/gx_8h.html#a55a426a3ff796db584302bddd829f002 GX_SetTexCoordGen2()]. These are the settings:
  
 
{| class="wikitable"
 
{| class="wikitable"
Line 553: Line 619:
 
| 0-3
 
| 0-3
 
| 0xF
 
| 0xF
| {{unknown|Unknown}}
+
| '''Texture coord generation type''' ([http://libogc.devkitpro.org/group__texgentyp.html tgen_typ])
 
|-
 
|-
 
| 4-8
 
| 4-8
 
| 0x1F0
 
| 0x1F0
| Attribute input. [http://libogc.devkitpro.org/group__texgensrc.html These are the accepted inputs.]
+
| '''Texture coord source''' ([http://libogc.devkitpro.org/group__texgensrc.html tgen_src])
 
|-
 
|-
 
| 9-13
 
| 9-13
 
| 0x3E00
 
| 0x3E00
| {{unknown|Unknown; appear to be unused?}}
+
| '''Texture matrix index''' ([http://libogc.devkitpro.org/group__texmtx.html mtxsrc] - add 30)
 
|-
 
|-
 
| 14
 
| 14
 
| 0x4000
 
| 0x4000
| Toggle whether the coordinate is normalized after being multiplied by the texture matrix.
+
| '''Normalize flag''' - normalizes texture coord after it's multiplied by the texture matrix (normalize)
 
|-
 
|-
 
| 15-20
 
| 15-20
 
| 0x1F8000
 
| 0x1F8000
| This sets the index into the post-transform matrix used for the final calculations.
+
| '''Post-transform texture matrix index''' ([http://libogc.devkitpro.org/group__dttmtx.html postmtx] - add 64)
 
|-
 
|-
 
| 21+
 
| 21+
Line 576: Line 642:
 
|}
 
|}
  
=== Material Animations ===
+
=== UV Animations ===
  
The material animations section immediately follows the texgen flags. It starts with this short header:
+
'' See [[UV Animations]]''
 +
 
 +
The UV animations section immediately follows the texgen flags. Its purpose is to generate texture matrices and post-transform matrices, which are then used to transform UV coordinates. This is commonly used to animate textures via simple UV scrolls, but it's also often used to simulate reflective surfaces that move with the camera. Materials can have multiple UV animations; in that case, each animation generates a separate texture/post-transform matrix and are loaded into GX sequentially. Texgen is used to set which matrices are used by which UV coordinates (if any).
 +
 
 +
The section starts with this short header:
  
 
{| class="wikitable"
 
{| class="wikitable"
Line 594: Line 664:
 
|}
 
|}
  
The structure of the animations themselves is somewhat simple. Each animation has a 32-bit ''mode'' setting, followed by a number of float parameters. The number and usage of these float parameters varies depending on what mode is set. There are 7 possible modes, but only 2-5 are known.
+
For info on how to read the animation data and how each animation mode works, see [[UV Animations]].
 
+
For all of the following modes, let ''s'' be equal to ''seconds mod 900''.
+
 
+
==== Mode 2: UV Offset ====
+
 
+
This mode is used to scroll both U and V at the same time. It has four float parameters: ''offsetA'', ''offsetB'', ''scaleA'', and ''scaleB''.
+
 
+
<pre>uOffset = (s * scaleA) + offsetA;
+
vOffset = (s * scaleB) + offsetB;</pre>
+
 
+
==== Mode 3: Rotation ====
+
 
+
This mode rotates the material. It has two float parameters: ''offset'' and ''scale''.
+
 
+
<pre>angle = (s * scale) + offset;</pre>
+
 
+
The material is then rotated by ''angle'' degrees.
+
 
+
==== Mode 4/5: U/V Offset ====
+
 
+
This mode can be used to scroll U and V independently from each other. It has four float parameters. The offset calculation for these modes is unknown; however, the same code is used for both modes, with the only difference being whether the calculated offset is applied to U or V.
+
  
 
[[Category:File Formats]]
 
[[Category:File Formats]]
 
[[Category:Metroid Prime]]
 
[[Category:Metroid Prime]]
 
[[Category:Metroid Prime 2: Echoes]]
 
[[Category:Metroid Prime 2: Echoes]]

Latest revision as of 13:41, 4 March 2018

The format for materials is seen in both the CMDL and MREA formats and is identical in both. This particular material format appears in both Metroid Prime and Metroid Prime 2 with minor differences.


Morphball render.png This file format is almost completely documented
MP1's materials are completely understood, but MP2 introduced two new values that are both unknown.


GX Overview

The materials system in Metroid Prime is heavily dependent on the GameCube and Wii's graphics system, GX. GX is a fixed-function graphics pipeline, similar to old versions of OpenGL. In GX, rendering is done through a series of steps called Texture EnVironment Stages, or or TEV stages for short.

Lighting calculations and tex coord generation are done per-vertex and passed along to TEV; the results of the lighting calculations are saved into up to two color channels that can be used as TEV inputs (as the rasterized vertex color). Each TEV stage takes in four color inputs and four alpha inputs, from one of eight sources. Then these four input colors are combined into one output color, and the output is saved into one of four registers, which can subsequently be used as input in the next TEV stages. The final stage must always save its output into the "previous TEV stage" register; that register is used as the final pixel color that gets displayed onscreen.

Material Set Format

Materials come as part of a set; often there will only be one set per file, but many CMDLs can have more than one. The set begins with a short header before the actual material data begins.

Type Count Description
long 1 Texture count (TC)
long TC Texture file IDs
long 1 Material count (MC)
long MC Material end offsets (relative to the start of the first material)
Materials begin

Material Format

General Settings

Each material begins with a flags value, followed by a list of texture indices:

Type Count Description
long 1 Flags
long 1 Texture count (TC)
long TC Texture indices (these are indices into the material set texture array)
long 1 Vertex attribute flags
long 1 Unknown (note: only in Echoes)
long 1 Unknown (note: only in Echoes)
long 1 Group index
long 1 Konst count (KC); max setting is 4. (note: only present if flag 0x8 is set!)
long KC Konst colors - 32-bit RGBA colors (note: not present if the Konst count isn't)
short 1 Blend destination factor
short 1 Blend source factor
long 1 Reflection indirect texture slot index (note: only present if flag 0x400 is set!)
long 1 Color channel count (CC)
long CC Color channel flags (note: only one flag value, but you must advance 4*CC bytes instead of 4 for some reason)
long 1 TEV stage count

Flags

These are simple boolean settings that can be toggled on and off on each material. These are the known flag settings:

Bit Hex Description
0 0x1 Unused, always set (never set in Echoes)
1 0x2 Unused, always set
2 0x4 Unused, never set
3 0x8 Has Konst values
4 0x10 Transparent
5 0x20 Masked alpha (compare threshold is hardcoded at 0.25)
6 0x40 Enable Samus's reflection
7 0x80 Enable Z-writes
8 0x100 Enable Samus's reflection, using the eye position and projection direction from the surface header
9 0x200 Shadow occluder mesh; meshes using this material are not rendered, but can be used to cast dynamic shadows on actors
10 0x400 Enable indirect texture stage for reflections
11 0x800 Indicates a lightmap is present; no ingame effect
12 0x1000 Unused, always set (never set in Echoes)
13 0x2000 Enable first UV coordinate to use short array instead of float array (used for world lightmaps)
14 0x4000 In MP1, unused, never set; in Echoes, unknown
15 0x8000 In MP1, unused, never set; in Echoes, unknown
16-31 0xFFFF0000 TEV texture flags; a bit set indicates that the corresponding TEV stage uses a texture. No ingame effect.

Vertex Attribute Flags

These flags are generally toggled in pairs, with each pair corresponding to a vertex attribute; if a pair is set, then vertices using this material will have the corresponding attribute. This is vital for reading geometry. Starting in Echoes, each pair is used to indicate the size of the attribute indices in the geometry data, with 3 meaning a 16-bit index and 2 meaning an 8-bit index. (This isn't actually used, though; the original game data always uses 16-bit indices.)

GX supports up to 8 texture coords per vertex, but the game doesn't seem to allow you to assign more than 7 (though this could do with some double-checking).

These are the possible attributes:

Bit pair Attribute
0x3 Position
0xC Normal
0x30 Color 0
0xC0 Color 1
0x300 Tex 0
0xC00 Tex 1
0x3000 Tex 2
0xC000 Tex 3
0x30000 Tex 4
0xC0000 Tex 5
0x300000 Tex 6

Echoes introduces some new attributes using the top byte of the flags value; unlike the other flags, these are not set in pairs. Each individual bit indicates the presence of a different attribute. The indices in the geometry data are always 8 bits.

Bit Attribute
0x1 Position Matrix Index
0x2 Tex0 Matrix Index
0x4 Tex1 Matrix Index
0x8 Tex2 Matrix Index
0x10 Tex3 Matrix Index
0x20 Tex4 Matrix Index
0x40 Tex5 Matrix Index
0x80 Tex6 Matrix Index

Group Index

The group index marks groups of materials that all have the same settings, but different textures. The game will check the value after loading the textures (but prior to the vertex attribute flags), and check whether the group index set on the material matches the material currently set up. If it does, it will skip the rest of the material setup. The value typically starts at 0 on the first material and increments by 1 on each new group with different settings.

Konst Colors

These values are only present when flag 0x8 is enabled. These allow you to set Konstant values, which can subsequently be used as inputs in TEV stages. The maximum number of Konst values you can set on one material is 4. The colors themselves are simply 32-bit RGBA values.

Blend Mode

The two blend factors set the blending mode used. The most common values you'll see are 0/1, which is used on opaque materials; transparent materials will usually have either 1/1, for additive blending, or 5/4, for alpha blending. Here's the full range of possible settings for each value:

Value Blend factor
0 GX_BL_ZERO
1 GX_BL_ONE
2 GX_BL_SRCCLR / GX_BL_DSTCLR
3 GX_BL_INVSRCCLR / GX_BL_INVSRCCLR
4 GX_BL_SRCALPHA
5 GX_BL_INVSRCALPHA
6 GX_BL_DSTALPHA
7 GX_BL_INVDSTALPHA

Color Channels

The color channels data consists of a count value indicating the number of color channels, and then one set of flags that controls the COLOR0 channel. The flags correspond to arguments passed to GX_SetChanCtrl(). These are the settings:

Bits Hex Description
0 0x1 Enable lighting (enable)
1 0x2 Ambient color source (ambsrc)
2 0x4 Material color source (matsrc)
3-10 0x7F8 Light mask; always 0, filled in at runtime (litmask)
11-12 0x1800 Diffuse function (diff_fn)
13-14 0x6000 Attenuation function (attn_fn)

There's only one set of flags, which operates on COLOR0. COLOR1 is reserved for dynamic shadows (terrain casting shadows on actors), so its settings can't be directly modified. Here's how the other color channel settings work.

COLOR1A1's settings vary depending on whether shadowmaps are enabled:

  • No processing will be done if the count value is 0. Otherwise, the count value is ignored; the game will always set up both color channels.
  • COLOR1A1's ambient color is black, and its material color is white.
  • COLOR1 will use the diffuse function GX_DF_CLAMP and the attenuation function GX_AF_SPOT. It will have lighting disabled entirely if there are no lights in range

If shadowmaps are disabled:

  • COLOR1 is disabled if the count value is not 2. If it is 2, then its ambient color will be black and its material color will be white.

COLOR0 is set up the same way either way:

  • COLOR0 will use the flags from the material, with the light mask merged in. It will also have lighting disabled if there are no lights in range.
  • If there are no lights in range, COLOR0A0 will have its material color set to match its ambient color. Otherwise, its material color will be set to white.

Finally, an important note is that the formatting of the color channel info is bugged. There is always a color channel count and a single set of flags; 8 bytes total. However, for some reason the game is expecting one set of flags per color channel. To reach the TEV stages, you need to advance (4 * count) bytes past the count value, rather than 4. A likely explanation is that there was one set of flags per channel earlier in development, and the material loading code wasn't fully updated when this was changed. It's not normally an issue because the count is always 1 in every file the game uses, but beware for experimentation/custom materials.

TEV Stages

There'll be one of these structures per TEV stage:

Offset Size Description
0x0 4 Color Input Flags
0x4 4 Alpha Input Flags
0x8 4 Color Combine Flags
0xC 4 Alpha Combine Flags
0x10 1 Padding
0x11 1 Konst Alpha Input (possible values)
0x12 1 Konst Color Input (possible values)
0x13 1 Rasterized Color Input (possible values)
0x14 End of TEV stage

After looping through each TEV stage, there will be one of these structures per stage:

Offset Size Description
0x0 2 Padding
0x2 1 Texture TEV Input
0x3 1 Tex Coord TEV Input
0x4 End of structure

Color Input Flags

These flags set the four color inputs that are used by the TEV stage. Each color is allocated 5 bits, even though only 4 are actually used; the lower bits correspond to the lower input numbers (eg. the bottom 5 bits refer to the first input).

There are 16 possible color sources:

Binary Hex Color Source
00000 0x0 Previous stage RGB
00001 0x1 Previous stage AAA
00010 0x2 Color 0 RGB
00011 0x3 Color 0 AAA
00100 0x4 Color 1 RGB
00101 0x5 Color 1 AAA
00110 0x6 Color 2 RGB
00111 0x7 Color 2 AAA
01000 0x8 Texture RGB
01001 0x9 Texture AAA
01010 0xA Rasterized RGB
01011 0xB Rasterized AAA
01100 0xC One
01101 0xD Half
01110 0xE Konstant RGB
01111 0xF Zero

Alpha Input Flags

Similar to the color input flags, these set the four alpha inputs used by the TEV stage. Each value is allocated 5 bits, although only 3 are used. The main difference with alpha is that there are only 8 possible sources instead of 16:

Binary Hex Alpha Source
00000 0x0 Previous stage alpha
00001 0x1 Color 0 alpha
00010 0x2 Color 1 alpha
00011 0x3 Color 2 alpha
00100 0x4 Texture alpha
00101 0x5 Rasterized alpha
00110 0x6 Konstant alpha
00111 0x7 Zero

Color Combine Flags

These flags specify how the operation that combines the four input colors into one output color is performed.

This is the combiner function:

tevrigid = (d (tevop) ((1.0-c)*a + c*b) + tevbias) * tevscale;

The values set in the color operation flags correspond to the parameters passed to GX_SetTevColorOp(). These are the settings:

Bits Hex Description
0-3 0xF Combiner operator (tevop)
4-5 0x30 Bias (tevbias); 00 does nothing; 01 adds 0.5; 10 subtracts 0.5; 11 does nothing.
6-7 0xC0 Scale (tevscale); 00 does nothing; 01 multiples by 2; 10 multiplies by 4; 11 divides by 2.
8 0x100 Clamp flag; enabling this will clamp the output color between 0 and 1.
9-10 0x600 Output register (tevrigid); can be Previous Stage or Color 0/1/2
11+ 0xFFFFF800 Unused.

Note that the vast majority of materials in the game, if not all of them, don't really bother with any of this; they enable clamping, set an output register, and leave everything else at their defaults of 0.

Alpha Combine Flags

This is exactly the same as the color combine flags; the only difference is it operates on alpha instead of color.

Texgen

After the TEV stages comes a sequence of flags determining how texgen is executed. Texgen is the process of taking input values and using them to generate texture coordinates (or UV coordinates), which can then be used by the TEV stages. It's important to note that any vertex attribute can be used as a texgen input; in fact, it's rather common for materials to use the vertex normal as an input to simulate reflections. That means the number of texture coords present on each vertex is not the same as the number of texture coords available to TEV.

Type Count Description
long 1 Texgen count (TC)
long TC Texgen flags

The flags correspond to arguments passed to GX_SetTexCoordGen2(). These are the settings:

Bits Hex Description
0-3 0xF Texture coord generation type (tgen_typ)
4-8 0x1F0 Texture coord source (tgen_src)
9-13 0x3E00 Texture matrix index (mtxsrc - add 30)
14 0x4000 Normalize flag - normalizes texture coord after it's multiplied by the texture matrix (normalize)
15-20 0x1F8000 Post-transform texture matrix index (postmtx - add 64)
21+ 0xFFE00000 Unused

UV Animations

See UV Animations

The UV animations section immediately follows the texgen flags. Its purpose is to generate texture matrices and post-transform matrices, which are then used to transform UV coordinates. This is commonly used to animate textures via simple UV scrolls, but it's also often used to simulate reflective surfaces that move with the camera. Materials can have multiple UV animations; in that case, each animation generates a separate texture/post-transform matrix and are loaded into GX sequentially. Texgen is used to set which matrices are used by which UV coordinates (if any).

The section starts with this short header:

Offset Size Description
0x0 4 Material animations section size (includes animation count, so will be 4 at minimum)
0x4 4 Animation count

For info on how to read the animation data and how each animation mode works, see UV Animations.