Materials (Metroid Prime): Difference between revisions

>Aruki
>Aruki
 
(45 intermediate revisions by 3 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.


{{research|moderate|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
| {{unknown|Unknown}}
| {{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
| 0x10000
| {{unknown|Unknown}}
|-
| 17
| 0x20000
| {{unknown|Unknown}}
|-
| 18
| 0x40000
| {{unknown|Unknown}}
|-
|-
| 19
| 16-31
| 0x80000
| 0xFFFF0000
| {{unknown|Unknown}}
| TEV texture flags; a bit set indicates that the corresponding TEV stage uses a texture. No ingame effect.
|-
| 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 578: Line 644:
=== UV Animations ===
=== UV Animations ===


The UV 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:
|}
|}


A material can have multiple animations; each animation will generate a separate texture matrix, which can then be used by texgen to transform the texture coordinates accordingly. 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 8 possible modes.
For info on how to read the animation data and how each animation mode works, see [[UV Animations]].
 
Note that despite the name, the UV animations section is meant for transforming UV coordinates in general; they don't necessarily have to be actual animations.
 
For all of the following modes, ''s'' refers to ''seconds mod 900''.
 
==== Mode 0: Inverse ModelView Matrix (No Translation) ====
 
This mode is commonly used with vertex normals to simulate reflective surfaces using spheremaps that move with the camera. It takes no parameters, and will generate both a texture matrix and a post-transform matrix. Translation is ignored.
 
The texture matrix is calculated like this. Note that the multiplication of the view matrix by the model matrix should be modified slightly rather than being a straight multiplication to ignore translation on the model matrix. (The game uses a function called MultiplyIgnoreTranslation for this.)
 
<pre>texmtx = inverse(ViewMatrix) * ModelMatrix;
texmtx[0][3] = texmtx[1][3] = texmtx[2][3] = 0;</pre>
 
The post-transform matrix is a constant value. [1][1] and [1][2] may need to be swapped around for correct playback.
 
<pre>0.5, 0.0, 0.0, 0.5,
0.0, 0.0, 0.5, 0.5,
0.0, 0.0, 0.0, 1.0</pre>
 
==== Mode 1: Inverse ModelView Matrix ====
 
This mode is nearly identical to mode 0; the only difference is that translation is left as-is. The multiplication of the view matrix by the model matrix actually is a straight multiplication in this mode, and the translation values on the texture matrix aren't set to 0.
 
==== 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 texture. It has two float parameters: ''offset'' and ''scale''.
 
<pre>float angle = (s * scale) + offset;
float acos = cos(angle);
float asin = sin(angle);
float translateX = (1.0 - (acos - asin)) * 0.5;
float translateY = (1.0 - (asin + acos)) * 0.5;</pre>
 
The resulting texture matrix is laid out as:
 
<pre>acos, -asin, 0.0, translateX,
asin,  acos, 0.0, translateY,
0.0,  0.0, 1.0,        0.0</pre>
 
==== Mode 4/5: U/V Offset ====
 
These modes can be used to scroll U and V independently from each other; they can also be used to have more advanced . The same calculation is done for both modes, with the only difference being whether the calculated offset is applied to U or V. There are four float parameters: ''scale'', ''numFrames'', ''step'', and ''offset''.
 
The animation is made up of a number of pseudo-frames, where ''step'' controls the amount that the texture scrolls by each frame, and ''numFrames'' sets how many frames are iterated through before resetting back to 0. ''scale'' roughly controls animation playback speed, and ''offset'' modifies the time input value.
 
<pre>float value = step * scale * (offset + s);
float uv_offset = (float)(short)(float)(numFrames * fmod(value, 1.0f)) * step;</pre>
 
==== Mode 6: Model Matrix ====
 
This mode is similar to modes 0 and 1 in that it simulates reflective surfaces, but it only takes the model matrix into account, which means camera movement doesn't affect the reflection. It takes no parameters and it generates both a texture matrix and a post-transform matrix.
 
The texture matrix is simply the model matrix, with the translation values ([0][3], [1][3], and [2][3]) set to 0. The post-transform matrix is set to the following:
 
<pre>0.5, 0.0, 0.0, ModelMatrix[0][3] * 0.50000001,
0.0, 0.0, 0.5, ModelMatrix[1][3] * 0.50000001,
0.0, 0.0, 0.0, 1.0</pre>
 
==== Mode 7: Unknown ====
 
Mode 7 operates on both the model and view matrices, like modes 0 and 1, and it takes two float parameters. it generates both a texture matrix and a post-transform matrix. It's unknown how this mode works.


[[Category:File Formats]]
[[Category:File Formats]]
[[Category:Metroid Prime]]
[[Category:Metroid Prime]]
[[Category:Metroid Prime 2: Echoes]]
[[Category:Metroid Prime 2: Echoes]]
Anonymous user