Difference between revisions of "FMDL (File Format)"

From MK8
Jump to navigation Jump to search
(Shader Control -> Shader Assign, document it's name offset meanings, redirect user data links to main BFRES page.)
m (→‎Header (FSHP): this is kind of annoying)
(42 intermediate revisions by 3 users not shown)
Line 1: Line 1:
The '''FMDL''' model format is a format for models which appears as a subfile of a '''[[BFRES (File Format)|BFRES file]]''' in the '''0'''th file group. Typically a BFRES file has one FMDL but some have none and some have more than one.
+
The '''FMDL''' (ca'''F'''e '''M'''o'''D'''e'''L''') model format is a format for models which appears as a subfile of a '''[[BFRES (File Format)|BFRES file]]''' in the '''0'''th file group. Typically a BFRES file has one FMDL but some have none and some have more than one.
  
 
__TOC__
 
__TOC__
Line 8: Line 8:
  
 
{| class="wikitable"
 
{| class="wikitable"
! Section
+
! Section !! Purpose
! Purpose
 
 
|-
 
|-
| [[#FVTX|FVTX]]
+
| [[#FVTX|FVTX]] || Describes an array of array of vertices which can have a number of attributes including position, normal, colour and texture coordinates.
| Describes an array of array of vertices which can have a number of attributes including position, normal, colour and texture coordinates.
 
 
|-
 
|-
| [[#FMAT|FMAT]]
+
| [[#FMAT|FMAT]] || Describes the properties of a surface necessary to draw it including texture information.
| Describes the properties of a surface necessary to draw it including texture information.
 
 
|-
 
|-
| [[#FSKL|FSKL]]
+
| [[#FSKL|FSKL]] || Describes a skeleton for the model which may be used in animations.
| Describes a skeleton for the model which may be used in animations.
 
 
|-
 
|-
| [[#FSHP|FSHP]]
+
| [[#FSHP|FSHP]] || Selects triples of vertices from one [[#FVTX|FVTX]] section to draw triangles between. Also specifies the [[#FMAT|FMAT]] material and the [[#FSKL|FSKL]] attachment of the triangles.
| Selects triples of vertices from one [[#FVTX|FVTX]] section to draw triangles between. Also specifies the [[#FMAT|FMAT]] material and the [[#FSKL|FSKL]] attachment of the triangles.
 
|-
 
| [[#Parameter|Parameter]]
 
| Sets a named paramter for the model.
 
 
|}
 
|}
  
Line 32: Line 24:
  
 
{| class="wikitable"
 
{| class="wikitable"
! Offset
+
! Offset !! Size !! Type !! Description
! Size
 
! Description
 
 
|-
 
|-
| 0x00
+
| 0x00 || 4 || Char[4] || "'''FMDL'''" file identifier, ASCII string.
| 4
 
| "'''FMDL'''" file identifier, ASCII string.
 
 
|-
 
|-
| 0x04
+
| 0x04 || 4 || Int32 || '''File name''' offset (without file extension).
| 4
 
| '''File name''' offset (without file extension).
 
 
|-
 
|-
| 0x08
+
| 0x08 || 4 || Int32 || '''File path''' offset, the path of the file this data was originally created from. Stripped in [[Mario Kart 8]] files, always pointing to an empty string at the end of the BFRES [[BFRES (File Format)#String Table|string table]].
| 4
 
| '''End of BFRES string table''' offset. Points to just after the last string in the string table. Originally pointed to a string being the file path of the file the FMDL data was created from, which has been removed in the released game.
 
 
|-
 
|-
| 0x0C
+
| 0x0C || 4 || Int32 || '''[[#FSKL|FSKL]]''' offset. Offset to the '''FSKL Header'''.
| 4
 
| '''[[#FSKL|FSKL]]''' offset. Offset to the '''FSKL Header'''.
 
 
|-
 
|-
| 0x10
+
| 0x10 || 4 || Int32 || '''[[#FVTX|FVTX]] array''' offset. Offset to the first element in an array of '''FVTX Header'''s.
| 4
 
| '''[[#FVTX|FVTX]] array''' offset. Offset to the first element in an array of '''FVTX Header'''s.
 
 
|-
 
|-
| 0x14
+
| 0x14 || 4 || Int32 || '''[[#FSHP|FSHP]] [[index group]]''' offset. Offset to an index group which contains named pointers to '''FSHP Header'''s.
| 4
 
| '''[[#FSHP|FSHP]] [[BFRES (File Format)#Index Group|index group]]''' offset. Offset to an index group which contains named pointers to '''FSHP Header'''s.
 
 
|-
 
|-
| 0x18
+
| 0x18 || 4 || Int32 || '''[[#FMAT|FMAT]] [[index group]]''' offset. Offset to an index group which contains named pointers to '''FMAT Header'''s.
| 4
 
| '''[[#FMAT|FMAT]] [[BFRES (File Format)#Index Group|index group]]''' offset. Offset to an index group which contains named pointers to '''FMAT Header'''s.
 
 
|-
 
|-
| 0x1C
+
| 0x1C || 4 || Int32 || '''[[User Data]] [[index group]]''' offset. It is only used in a handful of [[Mario Kart 8]] models to set the value of "ParticleLimit".
| 4
 
| '''[[#Parameter|Parameter]] [[BFRES (File Format)#Index Group|index group]]''' offset. Offset to an index group which contains named pointers to parameter values. May be '''0''' if no parameters exist (common).
 
 
|-
 
|-
| 0x20
+
| 0x20 || 2 || UInt16 || '''[[#FVTX|FVTX]] count''': number of FVTX sections in the '''FVTX array'''.
| 2
 
| '''[[#FVTX|FVTX]] count''': number of FVTX sections in the '''FVTX array'''.
 
 
|-
 
|-
| 0x22
+
| 0x22 || 2 || UInt16 || '''[[#FSHP|FSHP]] count''': number of FSHP sections in the the '''FSHP index group'''.
| 2
 
| '''[[#FSHP|FSHP]] count''': number of FSHP sections in the the '''FSHP index group'''.
 
 
|-
 
|-
| 0x24
+
| 0x24 || 2 || UInt16 || '''[[#FMAT|FMAT]] count''': number of FMAT sections in the the '''FMAT index group'''.
| 2
 
| '''[[#FMAT|FMAT]] count''': number of FMAT sections in the the '''FMAT index group'''.
 
 
|-
 
|-
| 0x26
+
| 0x26 || 2 || UInt16 || '''[[User Data]] entry count'''.
| 2
 
| '''[[#Parameter|Parameter]] count''': number of parameters in the '''Parameter index group'''.
 
 
|-
 
|-
| 0x28
+
| 0x28 || 4 || UInt32 || '''Total number of vertices''' to process.
| 4
 
| '''Total number of vertices''' to process.
 
 
|-
 
|-
| 0x2C
+
| 0x2C || 4 || UInt32 || '''User pointer''', can be set at runtime, '''0''' in files.
| 4
 
| '''[[BFRES (File Format)#User Data|User data]] [[index group]]''' offset. Never used in [[Mario Kart 8]] FMDL subfiles and thus '''0'''.
 
 
|-
 
|-
| 0x30
+
| 0x30 || colspan="3" {{Unknown|End of FMDL header}}
| colspan="2" {{Unknown|End of FMDL header}}
 
 
|}
 
|}
  
 
== FVTX ==
 
== FVTX ==
  
The model may have one or more '''FVTX''' sections which describe the vertices for one polygon (e.g. the road of a track). The section describes a series of buffers and attributes. Buffers are arrays of arbitrary elements which contain the actual values of the vertices and are passed directly to the graphics card. Attributes are properties of vertices (e.g. position, texture coordinate, vertex colours) and they describe the format and layout of the elements in the buffers.
+
The model may have one or more '''FVTX''' (ca'''F'''e '''V'''er'''T'''e'''X''') sections which describe the vertices for one polygon (e.g. the road of a track). The section describes a series of buffers and attributes. Buffers are arrays of arbitrary elements which contain the actual values of the vertices and are passed directly to the graphics card. Attributes are properties of vertices (e.g. position, texture coordinate, vertex colours) and they describe the format and layout of the elements in the buffers.
  
 
=== Header (FVTX) ===
 
=== Header (FVTX) ===
Line 105: Line 66:
  
 
{| class="wikitable"
 
{| class="wikitable"
! Offset
+
! Offset !! Size !! Type !! Description
! Size
 
! Description
 
 
|-
 
|-
| 0x00
+
| 0x00 || 4 || Char[4] || "'''FVTX'''" section identifier, ASCII string.
| 4
 
| "'''FVTX'''" section identifier, ASCII string.
 
 
|-
 
|-
| 0x04
+
| 0x04 || 1 || Byte || '''[[#Attributes|Attribute]] count''': number of different attributes (position, normal, colour, etc) in the attribute array.
| 1
 
| '''[[#Attributes|Attribute]] count''': number of different attributes (position, normal, colour, etc) in the attribute array.
 
 
|-
 
|-
| 0x05
+
| 0x05 || 1 || Byte || '''[[#Buffers|Buffer]] count''': number of attribute buffers in the buffer array.
| 1
 
| '''[[#Buffers|Buffer]] count''': number of attribute buffers in the buffer array.
 
 
|-
 
|-
| 0x06
+
| 0x06 || 2 || UInt16 || '''Section index''': index into FVTX array of this entry.
| 2
 
| '''Section index''': index into FVTX array of this entry.
 
 
|-
 
|-
| 0x08
+
| 0x08 || 4 || UInt32 || '''Number of vertices'''. This is also the number of elements in each buffer.
| 4
 
| '''Number of vertices'''. This is also the number of elements in each buffer.
 
 
|-
 
|-
| 0x0C
+
| 0x0C || 1 || Byte || '''Vertex skin count''', the number of bones influencing a vertex. Depending on the value, vertex positions are stored in different coordinate systems:
| 1
+
* '''2+''' indicates smooth skinning. Coordinates are relative to the model coordinate system of a rest pose.
| '''Vertex skin count''', values seen are between '''0''' and '''4''' (normally '''0''').
+
* '''1''' indicates rigid skinning. Coordinates are relative to the local coordinate system of the bone at the index given by the ''blendindex0'' vertex attribute.
 +
* '''0''' indicates rigid bodies using no skinning. Coordinates are relative to the local coordinate system of the bone at the index given by the ''FSKL Bone skin index'' field in the FSHP header.
 
|-
 
|-
| 0x0D
+
| 0x0D || 3 || — || Padding.
| 3
 
| '''Padding'''.
 
 
|-
 
|-
| 0x10
+
| 0x10 || 4 || Int32 || '''[[#Attributes|Attribute]] array''' offset. Offset to the first element in the Attribute array.
| 4
 
| '''[[#Attributes|Attribute]] array''' offset. Offset to the first element in the Attribute array.
 
 
|-
 
|-
| 0x14
+
| 0x14 || 4 || Int32 || '''[[#Attributes|Attribute]] [[index group]]''' offset. Named pointers to the members of the '''Attribute array''' to allow named lookups.
| 4
 
| '''[[#Attributes|Attribute]] [[BFRES (File Format)#Index Group|index group]]''' offset. Named pointers to the members of the '''Attribute array''' to allow named lookups.
 
 
|-
 
|-
| 0x18
+
| 0x18 || 4 || Int32 || '''[[#Buffers|Buffer]] array''' offset. Offset to the first element in the Buffer array.
| 4
 
| '''[[#Buffers|Buffer]] array''' offset. Offset to the first element in the Buffer array.
 
 
|-
 
|-
| 0x1C
+
| 0x1C || 4 || UInt32 || '''User pointer''', can be set at runtime, '''0''' in files.
| 4
 
| '''[[BFRES (File Format)#User Data|User data]] [[index group]]''' offset. Never used in [[Mario Kart 8]] FVTX sections and thus '''0'''.
 
 
|-
 
|-
| 0x20
+
| 0x20 || colspan="3" {{Unknown|End of FVTX header}}
| colspan="2" {{Unknown|End of FVTX header}}
 
 
|}
 
|}
  
Line 162: Line 101:
  
 
{| class="wikitable"
 
{| class="wikitable"
! Offset
+
! Offset !! Size !! Type !! Description
! Size
 
! Description
 
 
|-
 
|-
| 0x00
+
| 0x00 || 4 || Int32 || '''Attribute name''' offset (s. below).
| 4
 
| '''Attribute name''' offset.
 
 
|-
 
|-
| 0x04
+
| 0x04 || 1 || Byte || '''Buffer index''' in the ''[[#FVTX|FVTX]] Buffer array'' of the buffer storing the data of this attribute (s. below).
| 1
 
| '''Buffer index''' of the buffer containing this attribute.
 
 
|-
 
|-
| 0x05
+
| 0x05 || 1 || — || Padding.
| 3
 
| '''Buffer offset''' of the attribute in each element in the buffer.
 
 
|-
 
|-
| 0x08
+
| 0x05 || 2 || UInt16 || '''Buffer offset''' of the attribute in each element in the buffer (in bytes).
| 4
 
| '''Format''' of the attribute's data in the buffer.
 
 
|-
 
|-
| 0x0C
+
| 0x08 || 4 || UInt32 || '''Format''' of the attribute's data in the buffer, maps to '''GX2AttribFormat''' (s. below).
| colspan="2" {{Unknown|End of attribute}}
+
|-
 +
| 0x0C || colspan="3" {{Unknown|End of attribute}}
 
|}
 
|}
  
The following formats are known, mapping to the '''GX2AttribFormat''' enum:
+
==== Attribute Name ====
 +
 
 +
Based on some of the shader code in [[Filesystem/content/mapobj/PackunMusic#Files|/vol/content/mapobj/PackunMusic/PackunMusic.bfres]] the following naming convention seems to be used for attributes.
 +
 
 +
{| class="wikitable"
 +
! Attribute Name !! Friendly Name !! Description
 +
|-
 +
| _p0 || position0 || The position of the vertex.
 +
|-
 +
| _n0 || normal0 || The normal of the vertex used in lighting calculations.
 +
|-
 +
| _t0 || tangent0 || The tangent of the vertex used in advanced lighting calculations.
 +
|-
 +
| _b0 || binormal0 || The binormal of the vertex used in advanced lighting calculations.
 +
|-
 +
| _w0 || blendweight0 || Influence amount of the smooth skinning matrix at the index given in ''blendindex0''.
 +
|-
 +
| _i0 || blendindex0 || Index of influencing smooth skinning matrix.
 +
|-
 +
| _u0 || uv0 || rowspan="4" | Texture coordinates used for texture mapping.
 +
|-
 +
| _u1 || uv1
 +
|-
 +
| _u2 || uv2
 +
|-
 +
| _u3 || uv3
 +
|-
 +
| _c0 || color0 || rowspan="2" | Vertex colours used for simple shadow mapping.
 +
|-
 +
| _c1 || color1
 +
|}
 +
 
 +
==== Buffer Index ====
 +
 
 +
Original files typically store all attributes into one buffer or each attribute into a separate buffer. Rarely more than 1 attribute is stored in one and remaining attributes in another buffer. The condition determining which way is chosen seems arbitrary and does not follow specific rules.
 +
 
 +
==== Format ====
 +
 
 +
The following formats are available in the '''GX2AttribFormat''' enum:
  
 
{|class="wikitable"
 
{|class="wikitable"
Line 232: Line 200:
 
|-
 
|-
 
| 0x0813 || float_32_32_32_32 || Four floats || — || — || Represents four [http://en.wikipedia.org/wiki/Single-precision_floating-point_format 32 bit floating point] numbers.
 
| 0x0813 || float_32_32_32_32 || Four floats || — || — || Represents four [http://en.wikipedia.org/wiki/Single-precision_floating-point_format 32 bit floating point] numbers.
|}
 
 
Based on the some of the shader code in [[Filesystem/content/mapobj/PackunMusic#Files|/vol/content/mapobj/PackunMusic/PackunMusic.bfres]] the following naming convention seems to be used for attributes.
 
 
{| class="wikitable"
 
! Attribute Name !! Friendly Name !! Description
 
|-
 
| _p0 || position0 || The position of the vertex.
 
|-
 
| _n0 || normal0 || The normal of the vertex used in lighting calculations.
 
|-
 
| _t0 || tangent0 || The tangent of the vertex used in advanced lighting calculations.
 
|-
 
| _b0 || binormal0 || The binormal of the vertex used in advanced lighting calculations.
 
|-
 
| _w0 || blendweight0 || {{Unknown}}
 
|-
 
| _i0 || blendindex0 || {{Unknown}}
 
|-
 
| _u0 || uv0 || rowspan="4" | Texture coordinates used for texture mapping.
 
|-
 
| _u1 || uv1
 
|-
 
| _u2 || uv2
 
|-
 
| _u3 || uv3
 
|-
 
| _c0 || color0 || rowspan="2" | Vertex colours used for simple shadow mapping.
 
|-
 
|| _c1 || color1
 
 
|}
 
|}
  
Line 269: Line 207:
  
 
{| class="wikitable"
 
{| class="wikitable"
! Offset
+
! Offset !! Size !! Type !! Description
! Size
 
! Description
 
 
|-
 
|-
| 0x00
+
| 0x00 || 4 || UInt32 || '''Data pointer''' filled at runtime, always '''0''' in files.
| 4
 
| '''Data pointer''' filled at runtime, always '''0''' in files.
 
 
|-
 
|-
| 0x04
+
| 0x04 || 4 || UInt32 || '''Size''' of the buffer in bytes.
| 4
 
| '''Size''' of the buffer in bytes.
 
 
|-
 
|-
| 0x08
+
| 0x08 || 4 || UInt32 || '''Buffer handle''', filled at runtime, always '''0''' in files.
| 4
 
| '''Buffer handle''', filled at runtime, always '''0''' in files.
 
 
|-
 
|-
| 0x0C
+
| 0x0C || 2 || UInt16 || '''Stride''', the size of each element in the buffer (always '''0''' for index buffers).
| 2
 
| '''Stride''', the size of each element in the buffer.
 
 
|-
 
|-
| 0x0E
+
| 0x0E || 2 || UInt16 || '''Buffering count''', always '''1'''. Multiplicator for the number of bytes reserved as buffer data at runtime.
| 2
 
| '''Buffering count''', always '''1'''. Multiplicator for the number of bytes reserved as buffer data at runtime.
 
 
|-
 
|-
| 0x10
+
| 0x10 || 4 || UInt32 || '''Context pointer''' filled at runtime as a pointer to '''GX2StreamOutContext''', always '''0''' in files.
| 4
 
| '''Context pointer''' filled at runtime, always '''0''' in files.
 
 
|-
 
|-
| 0x14
+
| 0x14 || 4 || Int32 || '''Data offset'''.
| 4
 
| '''Data offset'''.
 
 
|-
 
|-
| 0x18
+
| 0x18 || colspan="3" {{Unknown|End of buffer}}
| colspan="2" {{Unknown|End of buffer}}
 
 
|}
 
|}
  
 
== FMAT ==
 
== FMAT ==
  
The model may have one or more '''FMAT''' sections which describe surface properties of a polygon such as textures. Every polygon is rendered using a vertex shader and a pixel shader. These are pieces of code which run on the graphics card. Like any code, these have parameters which is principally what the '''FMAT''' section controls. There are many different ways for the '''FMAT''' section to set variables in the shader code, but it remains '''unknown''' what the reason for this is. All shader parameters are either uniform or attributes. Attribute parameters vary per vertex or pixel, whereas uniform parameters are global. The '''FMAT''' must specify values for all uniform parameters, and specifies a mapping between vertex attributes in the corresponding '''[[#FVTX|FVTX]] sections''' and attribute parameters for both the pixel and vertex shader. In [[Mario Kart 8]] most models reference the same pixel shader and the same vertex shader, both called Turbo_UBER. Turbo_UBER is totally generic and has hundreds of parameters to configure the rendering. The source code for Turbo_UBER seems to be available in [[Filesystem/content/mapobj/PackunMusic#Files|/vol/content/mapobj/PackunMusic/PackunMusic.bfres]].
+
The model may have one or more '''FMAT''' (ca'''F'''e '''MAT'''erial) sections which describe surface properties of a polygon such as textures. Every polygon is rendered using a [https://www.khronos.org/opengl/wiki/Vertex_Shader vertex shader] and a [https://www.khronos.org/opengl/wiki/Fragment_Shader fragment shader]. A [https://www.khronos.org/opengl/wiki/Geometry_Shader geometry shader] is optional. These are pieces of code which run on the GPU. Like any code, these have parameters which is principally what the '''FMAT''' section controls. There are many different ways for the '''FMAT''' section to set variables in the shader code. All shader parameters are either [https://www.khronos.org/opengl/wiki/Uniform_(GLSL) uniforms] or attributes. Attribute parameters vary per vertex or pixel, whereas uniform parameters are global. The '''FMAT''' must specify values for all uniform parameters, and specifies a mapping between vertex attributes in the corresponding '''[[#FVTX|FVTX]] sections''' and attribute parameters for both the fragment and vertex shader. In [[Mario Kart 8]] the shader file is called Turbo_UBER. The name is the same for most files but the rendering code varies. All shaders are generic and has many parameters to configure. A GLSL shader for a shader file is available in [[Filesystem/content/mapobj/PackunMusic#Files|/vol/content/mapobj/PackunMusic/PackunMusic.bfres]].
  
 
=== Header (FMAT) ===
 
=== Header (FMAT) ===
Line 314: Line 235:
  
 
{| class="wikitable"
 
{| class="wikitable"
! Offset
+
! Offset !! Size !! Type !! Description
! Size
+
|-
! Description
+
| 0x00 || 4 || Char[4] || "'''FMAT'''" section identifier, ASCII string.
 +
|-
 +
| 0x04 || 4 || Int32 || '''Material name''' offset.
 
|-
 
|-
| 0x00
+
| 0x08 || 4 || UInt32 || '''Material flags'''. Only bit 0 has a meaning, controlling the visibility of the material (visible if set).
| 4
 
| "'''FMAT'''" section identifier, ASCII string.
 
 
|-
 
|-
| 0x04
+
| 0x0C || 2 || UInt16 || '''Section index''' of this material.
| 4
 
| '''Material name''' offset.
 
 
|-
 
|-
| 0x08
+
| 0x0E || 2 || UInt16 || '''[[#Render Info Parameter|Render info parameter]] count'''. Number of elements in the Render Info Parameter index group.
| 4
 
| '''Material flags'''. Only bit 0 has a meaning, controlling the visibility of the material (visible if set).
 
 
|-
 
|-
| 0x0C
+
| 0x10 || 1 || Byte || '''Texture Reference count'''. Number of elements in ''Texture Reference array''.  
| 2
 
| '''Section Index''' of this material.
 
 
|-
 
|-
| 0x0E
+
| 0x11 || 1 || Byte || '''[[#Texture Sampler|Texture Sampler]] count'''. Number of elements in the Texture Sampler array. Always equal to the number of elements in the Texture Selector array.
| 2
 
| '''[[#Render Info Parameter|Render Info Parameter]] Count'''. Number of elements in the Render Info Parameter index group.
 
 
|-
 
|-
| 0x10
+
| 0x12 || 2 || UInt16 || '''[[#Material Parameter|Material Parameter]] count'''. Number of elements in the Material Parameter array.
| 1
 
| '''[[#Texture Selector|Texture Selector]] Count'''. Number of elements in the Texture Selector array.
 
 
|-
 
|-
| 0x11
+
| 0x14 || 2 || UInt16 || '''Volatile Parameter count'''. Number of parameters handled as volatile, unknown purpose.
| 1
 
| '''[[#Texture Sampler|Texture Sampler]]  Count'''. Number of elements in the Texture Sampler array. Always equal to the number of elements in the Texture Selector array.
 
 
|-
 
|-
| 0x12
+
| 0x16 || 2 || UInt16 || '''[[#Material Parameter|Material Parameter]] data length'''. The size of the Material Parameter Data section in bytes.
| 2
 
| '''[[#Material Parameter|Material Parameter]] Count'''. Number of elements in the Material Parameter array.
 
 
|-
 
|-
| 0x14
+
| 0x18 || 2 || UInt16 || '''Raw Parameter data length''', unknown purpose.
| 4
 
| '''[[#Material Parameter|Material Parameter]] Data Size''' in bytes. The size of the Material Parameter Data section.
 
 
|-
 
|-
| 0x18
+
| 0x1A || 2 || UInt16 || '''[[User Data]] entry count'''. User data in FMAT sections is apparently used to assign values to a shadow variable in the shader code. Shadow variables are always uniform variables.
| 4
 
| '''[[#Shadow Parameter|Shadow Parameter]] count'''. Number of elements in the Shadow Parameter array.
 
 
|-
 
|-
| 0x1C
+
| 0x1C || 4 || Int32 || '''[[#Render Info Parameter|Render Info Parameter]] [[index group]]''' offset. Offset to the index group defining render info parameters.
| 4
 
| '''[[#Render Info Parameter|Render Info Parameter]] [[BFRES (File Format)#Index Group|index group]]''' offset. Offset to the index group defining render info parameters.
 
 
|-
 
|-
| 0x20
+
| 0x20 || 4 || Int32 || '''[[#Render State|Render State]]''' offset. Offset to the render state structure.
| 4
 
| '''[[#Render State|Render State]]''' offset. Offset to the render state structure.
 
 
|-
 
|-
| 0x24
+
| 0x24 || 4 || Int32 || '''[[#Shader Assign|Shader Assign]]''' offset. Offset to the shader assign structure.
| 4
 
| '''[[#Shader Assign|Shader Assign]]''' offset. Offset to the shader assign structure.
 
 
|-
 
|-
| 0x28
+
| 0x28 || 4 || Int32 || '''Texture Reference array''' offset. Each element points to [[FTEX]] file names and [[FTEX]] headers.
| 4
 
| '''[[#Texture Selector|Texture Selector]]''' offset. Offset to the first element in the Texture Selector array.
 
 
|-
 
|-
| 0x2C
+
| 0x2C || 4 || Int32 || '''[[#Texture Sampler|Texture Sampler]]''' offset. Offset to the first element in the Texture Sampler array.
| 4
 
| '''[[#Texture Sampler|Texture Sampler]]''' offset. Offset to the first element in the Texture Sampler array.
 
 
|-
 
|-
| 0x30
+
| 0x30 || 4 || Int32 || '''[[#Texture Sampler|Texture Sampler]] [[index group]]''' offset.  Offset to an index group which references the Texture Sampler array, to allow named value lookups.
| 4
 
| '''[[#Texture Sampler|Texture Sampler]] [[BFRES (File Format)#Index Group|index group]]''' offset.  Offset to an index group which references the Texture Sampler array, to allow named value lookups.
 
 
|-
 
|-
| 0x34
+
| 0x34 || 4 || Int32 || '''[[#Material Parameter|Material Parameter]]''' array offset. Offset to the first element in the Material Parameter array.
| 4
 
| '''[[#Material Parameter|Material Parameter]]''' array offset. Offset to the first element in the Material Parameter array.
 
 
|-
 
|-
| 0x38
+
| 0x38 || 4 || Int32 || '''[[#Material Parameter|Material Parameter]] [[index group]]''' offset. Offset to an index group which references the Material Parameter array, to allow named value lookups.
| 4
 
| '''[[#Material Parameter|Material Parameter]] [[BFRES (File Format)#Index Group|index group]]''' offset. Offset to an index group which references the Material Parameter array, to allow named value lookups.
 
 
|-
 
|-
| 0x3C
+
| 0x3C || 4 || Int32 || '''[[#Material Parameter|Material Parameter]] data''' offset. Offset to the beginning of the values for Material Parameters. The Material Parameter array references this data.
| 4
 
| '''[[#Material Parameter|Material Parameter]] Data''' offset. Offset to the beginning of the values for Material Parameters. The '''Material Parameter array''' references this data.
 
 
|-
 
|-
| 0x40
+
| 0x40 || 4 || Int32 || '''[[User Data]] [[index group]]''' offset.
| 4
 
| '''[[#Shadow Parameter|Shadow Parameter]] [[BFRES (File Format)#Index Group|index group]]''' offset. May be '''0''' if not needed.
 
 
|-
 
|-
| 0x44
+
| 0x44 || 4 || Int32 || '''Volatile Flags data''' offset. Points to an array of '''Ceil((Material Parameter count) / 8)''' bytes, representing bits determining if a parameter is volatile. Unknown purpose.
| 4
 
| {{Unknown|'''Unknown''' offset. Always points to 12 bytes, all 0. Offset may be '''0''' if not needed.}}
 
 
|-
 
|-
| 0x48
+
| 0x48 || 4 || Int32 || '''User pointer''', can be set at runtime, '''0''' in files.
| 4
 
| '''[[BFRES (File Format)#User Data|User data]] [[index group]]''' offset. Never used in [[Mario Kart 8]] FMAT sections and thus '''0'''.
 
 
|-
 
|-
| 0x4C
+
| 0x4C || colspan="3" {{Unknown|End of FMAT Header}}
| colspan="2" {{Unknown|End of FMAT Header}}
 
 
|}
 
|}
  
 
=== Render Info Parameter ===
 
=== Render Info Parameter ===
  
A '''Render Info Parameter''' is a repeating structure of at least 0x08 bytes, each of which describes an array of values to assign to a render info variable in the shader code. Render info variables are always uniform variables. The '''Render Info Parameter''' structures are referenced by the '''Render Info Parameter index group''' in the corresponding '''[[#Header (FMAT)|FMAT Header]]'''.
+
A '''Render Info Parameter''' is a repeating structure of at least 0x08 bytes, each of which describes an array of values to assign to a render info variable in the shader code. Render info variables are always uniform variables and are used to set how the shader should render the graphics. The '''Render Info Parameter''' structures are referenced by the '''Render Info Parameter index group''' in the corresponding '''[[#Header (FMAT)|FMAT Header]]'''.
  
 
{| class="wikitable"
 
{| class="wikitable"
! Offset
+
! Offset !! Size !! Type !! Description
! Size
 
! Description
 
|-
 
| 0x00
 
| 2
 
| '''Array length''', number of elements in the array. Always '''0''' or '''1''' in [[Mario Kart 8]] files.
 
|-
 
| 0x02
 
| 1
 
| '''Type''' of each array element.
 
|-
 
| 0x03
 
| 1
 
| '''Padding'''.
 
|-
 
| 0x04
 
| 4
 
| '''Variable Name''' offset.
 
 
|-
 
|-
| 0x08
+
| 0x00 || 2 || UInt16 || '''Array length''', number of elements in the array. Always '''0''' or '''1''' in [[Mario Kart 8]] files.
| Varies
 
| '''Array''' data.
 
 
|-
 
|-
| Varies
+
| 0x02 || 1 || Byte || '''Type''' of each array element.
| colspan="2" {{Unknown|End of Render Info Parameter}}
 
|}
 
 
 
The '''Type''' field describes the type each element in the array has, which can be one of the following:
 
 
 
 
{| class="wikitable"
 
{| class="wikitable"
 
! Type !! Element Size !! Element Type
 
! Type !! Element Size !! Element Type
 
|-
 
|-
| 0x00 || 8 || Vector of 2 signed integers.
+
| 0 || 8 || Vector of 2 signed integers.
 
|-
 
|-
| 0x01 || 8 || Vector of 2 floats.
+
| 1 || 8 || Vector of 2 floats.
 
|-
 
|-
| 0x02 || 4 || Offset to a string.
+
| 2 || 4 || Offset to a string.
 
|}
 
|}
 
=== Texture Selector ===
 
 
A '''Texture Selector''' is a repeating 0x08 byte structure each of which references a single '''[[FTEX (File Format)|FTEX texture]]'''. The length and position of the '''Texture Selector''' array is specified by the corresponding '''[[#Header (FMAT)|FMAT Header]]'''.
 
 
{| class="wikitable"
 
! Offset
 
! Size
 
! Description
 
 
|-
 
|-
| 0x00
+
| 0x03 || 1 || — || '''Padding'''.
| 4
+
|-
| '''Texture Name''' offset. The same as the '''FTEX''' name.
+
| 0x04 || 4 || Int32 || '''Variable name''' offset.
 
|-
 
|-
| 0x04
+
| 0x08 || Varies || Varies || '''Array data'''.
| 4
 
| '''[[FTEX (File Format)|FTEX]]''' offset. Points to the header of the '''FTEX'''.
 
 
|-
 
|-
| 0x08
+
| Varies || colspan="3" {{Unknown|End of Render Info Parameter}}
| colspan="2" {{Unknown|End of Texture Selector}}
 
 
|}
 
|}
  
 
=== Texture Sampler ===
 
=== Texture Sampler ===
  
An '''Texture Sampler''' is a repeating 0x18 byte structure each of which describes one of the inputs to the pixel shader from the selected textures. The length and position of the '''Texture Sampler''' array is specified by the corresponding '''[[#Header (FMAT)|FMAT Header]]'''.
+
A '''Texture Sampler''' is a repeating 0x18 byte structure each of which is used to assign a texture to the shader. The length and position of the '''Texture Sampler''' array is specified by the corresponding '''[[#Header (FMAT)|FMAT Header]]'''.
  
 
{| class="wikitable"
 
{| class="wikitable"
! Offset
+
! Offset !! Size !! Type !! Description
! Size
 
! Description
 
 
|-
 
|-
| 0x00
+
| 0x00 || 4 || UInt32 || First value of '''GX2Sampler''' structure. Bits packed as '''xxxJJJxx IIHHHGGF FxEExDDC CCBBBAAA'''.
| 12
+
* '''AAA''' maps to '''GX2TexClamp''' (line 880 [https://pastebin.com/DCrP1w9x here]) and sets the clamping / repetition of the texture on the U axis.
| '''GX2Sampler''' structure (consisting of 3 unsigned integers).
+
* '''BBB''' maps to '''GX2TexClamp''' (line 880 [https://pastebin.com/DCrP1w9x here]) and sets the clamping / repetition of the texture on the V axis.
 +
* '''CC C''' maps to '''GX2TexClamp''' (line 880 [https://pastebin.com/DCrP1w9x here]) and sets the clamping / repetition of the texture on the W axis (for 3D textures).
 +
* '''DD''' maps to '''GX2TexXYFilterType''' (line 910 [https://pastebin.com/DCrP1w9x here]) and sets the texture filtering on the U and V axes when the texture is drawn larger than the actual texture's resolution.
 +
* '''EE''' maps to '''GX2TexXYFilterType''' (line 910 [https://pastebin.com/DCrP1w9x here]) and sets the texture filtering on the U and V axes when the texture is drawn smaller than the actual texture's resolution.
 +
* '''F F''' maps to '''GX2TexZFilterType''' (line 920 [https://pastebin.com/DCrP1w9x here]) and sets the texture filtering on the W axis (for 3D textures).
 +
* '''GG''' maps to '''GX2TexMipFilterType''' (line 931 [https://pastebin.com/DCrP1w9x here]) and sets the texture filtering for mipmaps.
 +
* '''HHH''' maps to '''GX2TexAnisoRatio''' (line 976 [https://pastebin.com/DCrP1w9x here]) and controls the maximum anisotropic filtering level to use.
 +
* '''II''' maps to '''GX2TexBorderType''' (line 896 [https://pastebin.com/DCrP1w9x here]) and determines what color to draw at places not reached by a texture if the clamp mode does not repeat it.
 +
* '''JJJ''' maps to '''GX2CompareFunction''' (line 105 [https://pastebin.com/DCrP1w9x here]) and sets the depth comparison function.
 
|-
 
|-
| 0x0C
+
| 0x04 || 4 || UInt32 || Second value of '''GX2Sampler''' structure. Bits packed as '''CCCCCCCC CCCCBBBB BBBBBBAA AAAAAAAA'''.
| 4
+
* '''AA AAAAAAAA''' is a 10-bit floating point value controlling the minimum LOD level.
| '''Handle''' of the sampler, filled at runtime.
+
* '''BBBB BBBBBB''' is a 10-bit floating point value controlling the maximum LOD level.
 +
* '''CCCCCCCC CCCC''' is a 12-bit floating point value controlling the LOD bias.
 +
10-bit values are stored unsigned. To get a float value, divide it by 64. 12-bit values are stored signed. To get the float value, divide the signed value by 64. 10-bit values have a range between 0 – 32 and 12-bit values have a range between -32 – 31.984375.
 
|-
 
|-
| 0x10
+
| 0x08 || 4 || UInt32 || Third value of '''GX2Sampler''' structure. Bits packed as '''xAxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx'''.
| 4
+
* '''A''' is a boolean controlling whether depth comparison is enabled. This should never be set on a real console.
| '''Attribute Name''' offset.
 
 
|-
 
|-
| 0x14
+
| 0x0C || 4 || UInt32 || '''Handle''' of the sampler, set at runtime.
| 1
 
| '''Index''' of this element.
 
 
|-
 
|-
| 0x15
+
| 0x10 || 4 || Int32 || '''Attribute name''' offset.
| 3
 
| '''Padding'''.
 
 
|-
 
|-
| 0x18
+
| 0x14 || 1 || Byte || '''Index''' of this element.
| colspan="2" {{Unknown|End of Texture Sampler}}
+
|-
 +
| 0x15 || 3 || — || Padding.
 +
|-
 +
| 0x18 || colspan="3" {{Unknown|End of Texture Sampler}}
 
|}
 
|}
  
Line 512: Line 359:
  
 
{| class="wikitable"
 
{| class="wikitable"
! Attribute Name
+
! Attribute Name !! Friendly Name !! Description
! Friendly Name
 
! Description
 
 
|-
 
|-
| _a0
+
| _a0 || albedo0 || rowspan="4" | Ordinary colour textures for surface albedo.
| albedo0
 
| rowspan="4" | Ordinary colour textures for surface albedo.
 
 
|-
 
|-
| _a1
+
| _a1 || albedo1
| albedo1
 
 
|-
 
|-
| _a2
+
| _a2 || albedo2
| albedo2
 
 
|-
 
|-
| _a3
+
| _a3 || albedo3
| albedo3
 
 
|-
 
|-
| _s0
+
| _n0 || normal0 || rowspan="2" | Normal map texture for altering surface normals.
| specular0
 
| Specular highlight texture.
 
 
|-
 
|-
| _n0
+
| _n1 || normal1
| normal0
 
| rowspan="2" | Normal map texture for altering surface normals.
 
 
|-
 
|-
| _n1
+
| _s0 || specular0 || Specular highlight texture.
| normal1
 
 
|-
 
|-
| _e0
+
| _e0 || emission0 || Emissive lighting texture.
| emission0
 
| Emissive lighting texture.
 
 
|-
 
|-
| _b0
+
| _b0 || bake0 || rowspan="2" | Bake textures.
| bake0
 
| rowspan="2" | Shadow textures.
 
 
|-
 
|-
| _b1
+
| _b1 || bake1
| bake1
 
 
|}
 
|}
  
 
=== Material Parameter ===
 
=== Material Parameter ===
  
A '''Material Parameter''' is a repeating 0x14 byte structure each of which describes the value to assign to a material variable in the shader code. Material variables are always uniform variables. The length and position of the '''Material Parameter''' array is controlled by the corresponding '''[[#Header (FMAT)|FMAT Header]]'''.
+
A '''Material Parameter''' is a repeating 0x14 byte structure each of which describes the value to assign to a uniform variable in the shader code. The length and position of the '''Material Parameter''' array is controlled by the corresponding '''[[#Header (FMAT)|FMAT Header]]'''.
 
 
In some '''BFRES Files''' which do not have 0x03040004 after the '''FRES''' identifier, the '''Material Parameter''' structure is shorter or longer than 0x14 bytes. This seems to be consistent across entire model files. This is presumably a different verson of the '''FMDL''' format. It is rare in [[Mario Kart 8]] (affecting only 6 models).
 
  
 
{| class="wikitable"
 
{| class="wikitable"
! Offset
+
! Offset !! Size !! Type !! Description
! Size
 
! Description
 
|-
 
| 0x00
 
| 1
 
| '''Type''' of the variable.
 
|-
 
| 0x01
 
| 1
 
| '''Size''' of the value in bytes.
 
|-
 
| 0x02
 
| 2
 
| '''Offset''' relative to the start of the '''Material Parameter Data''' section to the value.
 
|-
 
| 0x04
 
| 4
 
| '''Uniform Variable Offset''', filled at runtime, always '''-1''' in files.
 
|-
 
| 0x08
 
| 4
 
| '''Conversion Callback Pointer''', filled at runtime, always '''0''' in files.
 
 
|-
 
|-
| 0x0C
+
| 0x00 || 1 || Byte || '''Type''' of the variable (s. below).
| 2
 
| '''Parameter Index''' into the Material Parameter array.
 
 
|-
 
|-
| 0x0E
+
| 0x01 || 1 || Byte || '''Size''' of the value in bytes.
| 2
 
| Same value as '''Parameter Index''' again.
 
 
|-
 
|-
| 0x10
+
| 0x02 || 2 || UInt16 || '''Offset''' relative to the start of the '''Material Parameter Data''' section to the value.
| 4
 
| '''Variable Name''' offset.
 
 
|-
 
|-
| 0x14
+
| 0x04 || 4 || Int32 || '''Uniform variable offset''', set at runtime, always '''-1''' in files.
| colspan="2" {{Unknown|End of Material Parameter}}
+
|- bgcolor="#FFAAAA"
 +
| colspan="4" align="center" | '''if BFRES version >= 3.4.0.0'''
 +
|- bgcolor="#FFDDDD"
 +
| 0x08 || 4 || UInt32 || '''Conversion callback pointer''', set at runtime, always '''0''' in files.
 +
|- bgcolor="#FFDDDD"
 +
| 0x0C || 2 || UInt16 || '''Parameter index''' into the Material Parameter array.
 +
|- bgcolor="#FFDDDD"
 +
| 0x0E || 2 || UInt16 || Same value as '''Parameter index''' again.
 +
|- bgcolor="#FFDDDD"
 +
| 0x10 || 4 || Int32 || '''Variable name''' offset.
 +
|- bgcolor="#AAFFAA"
 +
| colspan="4" align="center" | '''if BFRES version = 3.3.X.X'''
 +
|- bgcolor="#DDFFDD"
 +
| 0x08 || 4 || UInt32 || '''Conversion callback pointer''', set at runtime, always '''0''' in files.
 +
|- bgcolor="#DDFFDD"
 +
| 0x0C || 2 || UInt16 || '''Parameter index''' into the Material Parameter array.
 +
|- bgcolor="#DDFFDD"
 +
| 0x0E || 2 || UInt16 || Same value as '''Parameter index''' again.
 +
|- bgcolor="#DDFFDD"
 +
| 0x10 || 4 || Int32 || [[#FMAT|FMAT]] offset.
 +
|- bgcolor="#DDFFDD"
 +
| 0x14 || 4 || Int32 || '''Variable name''' offset.
 +
|- bgcolor="#AAAAFF"
 +
| colspan="4" align="center" | '''if BFRES version < 3.3.0.0'''
 +
|- bgcolor="#DDDDFF"
 +
| 0x08 || 4 || Int32 || '''Variable name''' offset.
 
|}
 
|}
  
The '''Type''' field has values as follows.
+
The '''Type''' field can be one of the following:
 
 
 
{| class="wikitable"
 
{| class="wikitable"
! Type
+
! Type !! Size !! Description
! Size
 
! Description
 
 
|-
 
|-
 
| 0 || 4 || 1 boolean value.
 
| 0 || 4 || 1 boolean value.
Line 656: Line 478:
 
| 27 || 64 || 4&times;4 floating point matrix.
 
| 27 || 64 || 4&times;4 floating point matrix.
 
|-
 
|-
| 28 || 20 || ?&times;? 2D SRT matrix.
+
| 28 || 20 || 2D SRT data.
 +
{| class="wikitable"
 +
! Offset !! Size !! Type !! Description
 +
|-
 +
| 0x00 || 8 || Single[2] || XY scaling
 +
|-
 +
| 0x08 || 4 || Single || Rotation
 +
|-
 +
| 0x0C || 8 || Single[2] || XY translation
 +
|}
 +
|-
 +
| 29 || 36 || 3D SRT data.
 +
{| class="wikitable"
 +
! Offset !! Size !! Type !! Description
 +
|-
 +
| 0x00 || 12 || Single[3] || XYZ scaling
 +
|-
 +
| 0x0C || 12 || Single[3] || XYZ rotation
 +
|-
 +
| 0x18 || 12 || Single[3] || XYZ translation
 +
|}
 +
|-
 +
| 30 || 24 || Texture SRT data.
 +
{| class="wikitable"
 +
! Offset !! Size !! Type !! Description
 +
|-
 +
| 0x00 || 4 || UInt32 || SRT mode
 +
* 0 specifies Maya SRT method.
 +
* 1 specifies 3ds Max SRT method.
 +
* 2 specifies Softimage SRT method.
 +
|-
 +
| 0x04 || 8 || Single[2] || XY scaling
 +
|-
 +
| 0x0C || 4 || Single || Rotation
 +
|-
 +
| 0x10 || 8 || Single[2] || XY translation
 +
|}
 
|-
 
|-
| 29 || 36 || 3&times;3 3D SRT matrix.
+
| 31 || 28 || Texture SRT data which is then multiplied by a 3x4 matrix referenced by the matrix pointer. The structure is the same as above, but with a field added to store the pointer to the matrix in at runtime:
 +
{| class="wikitable"
 +
! Offset !! Size !! Type !! Description
 
|-
 
|-
| 30 || 24 || 2&times;3 Texture SRT matrix.
+
| 0x18 || 4 || UInt32 || 3x4 matrix pointer, set at runtime.
 +
|}
 
|}
 
|}
  
Line 667: Line 528:
 
=== Render State ===
 
=== Render State ===
  
A '''Render State''' structure is a 0x30 byte structure controlling if and how polygons are drawn. A '''Render State''' structure is referenced by the corresponding '''[[#Header (FMAT)|FMAT Header]]'''.
+
A '''Render State''' structure is a 0x30 byte structure controlling if and how polygons are drawn. The structure is referenced by the corresponding '''[[#Header (FMAT)|FMAT Header]]'''.
  
 
{| class="wikitable"
 
{| class="wikitable"
! Offset
+
! Offset !! Size !! Type !! Description
! Size
 
! Description
 
 
|-
 
|-
| 0x00
+
| 0x00 || 4 || UInt32 || '''Flags'''. Controls how polygons are affecting the depth buffer and how they are blended / composed. A mode and blend value have to be combined to form valid flags.
| 4
 
| '''Flags'''. Controls how polygons are affecting the depth buffer and how they are blended / composed. A mode and blend value have to be combined to form valid flags.
 
 
{| class="wikitable"
 
{| class="wikitable"
 
! Type !! Bits (0-based) !! Description
 
! Type !! Bits (0-based) !! Description
Line 695: Line 552:
 
|}
 
|}
 
|-
 
|-
| 0x04
+
| 0x04 || 4 || UInt32 || '''Polygon control''', maps to '''GX2PolygonControlReg''', a bitset packed as '''xxxxxxxx xxxxxxxx xxIHGFFF EEEDDCBA'''. Beyond other features, it most prominently controls culling and cull order of polygons.
| 4
+
* '''A''' controls whether front faces are culled.
| '''Polygon Control''', maps to '''GX2PolygonControlReg'''. Beyond other features, it most prominently controls culling and cull order of polygons.
+
* '''B''' controls whether back faces are culled.
Always '''0x00280240''', '''0x00280242''' or '''0x00280243''' in [[Mario Kart 8]] files.
+
* '''C''' maps to '''GX2FrontFaceMode''' and determines the order in which vertices have to form the triangle to be handled as a front rather than back face. The order can be clockwise ('''1''') or counter-clockwise ('''0''').
 +
* '''DD''' configures whether polygons are drawn at all ('''1''') or not ('''0''')
 +
* '''EEE''' maps to '''GX2PolygonMode''' and determines how front facing polygons are drawn. This can be set to draw only points ('''0'''), lines ('''1''') or full triangles ('''2''').
 +
* '''FFF''' is the same as ''EEE'', but for back facing polygons.
 +
* '''G''' configures polygon depth offsets for front facing polygons (useful to create decals without Z fighting).
 +
* '''H''' is the same as ''G'' but for back facing polygons.
 +
* '''I''' is the same as ''G'' but for lines and points.
 
|-
 
|-
| 0x08
+
| 0x08 || 4 || UInt32 || '''Depth control''', maps to '''GX2DepthStencilControlReg''', a bitset packed as '''MMMLLLKK KJJJIIIH HHGGGFFF EDDDxCBA'''. Controls depth and stencil buffer value comparison and action before writing new data to buffers.
| 4
+
* '''A''' controls whether stencil testing is enabled ('''1''') or not ('''0''').
| '''Depth Control''', maps to '''GX2DepthStencilControlReg'''. Controls depth buffer value comparison before writing new data to buffers.
+
* '''B''' controls whether depth testing is enabled ('''1''') or not ('''0''').
Always '''0x49749732''' or '''0x49749736''' in [[Mario Kart 8]] files.
+
* '''C''' controls whether writing to the depth buffer is enabled ('''1''') or not ('''0''').
 +
* '''DDD''' maps to '''GX2CompareFunction''' and configures when a fragment is allowed to overwrite the old value in the depth buffer with a new one (the depth buffer comparison function) (line 105 [https://pastebin.com/DCrP1w9x here]).
 +
* '''E''' controls whether back faces can write to the stencil buffer ('''1''') or not ('''0''').
 +
* '''FFF''' controls the front face stencil buffer comparison function, maps to '''GX2CompareFunction''' aswell (s. ''DDD'').
 +
* '''GGG''' maps to '''GX2StencilFunction''' and configures what to do with the existing stencil value when the stencil comparison function fails for front facing polygons (line 121 [https://pastebin.com/DCrP1w9x here]).
 +
* '''HH H''' is the same as ''GGG'', but taking effect when the stencil test passes with the depth buffer.
 +
* '''III''' is the same as ''GGG'', but taking effect when the stencil test fails with the depth buffer.
 +
* '''JJJ''' is the same as ''FFF'', but for back faces.
 +
* '''K KK''' is the same as ''GGG'', but taking effect when the stencil test fails for back faces.
 +
* '''LLL''' is the same as ''GGG'', but taking effect when the stencil test passes for back faces with the depth buffer.
 +
* '''MMM''' is the same as ''GGG'', but taking effect when the stencil test fails for back faces with the depth buffer.
 
|-
 
|-
| 0x0C
+
| 0x0C || 8 || UInt32 / Single || '''Alpha test''', maps to '''GX2AlphaTestReg''', a structure of an unsigned integer and a floating point value. Controls how alpha colors are written to buffers. The unsigned integer is a bitset packed as '''xxxxxxxx xxxxxxxx xxxxxxxx xxxxBAAA'''.
| 8
+
* '''AAA''' maps to '''GX2CompareFunction''' and determines when alpha fragments should be written.
| '''Alpha Test''', maps to '''GX2AlphaTestReg'''. Controls how alpha colors are written to buffers. Consists of an unsigned integer and a floating point reference value.
+
* '''B''' determines whether alpha testing is enabled at all (line 105 [https://pastebin.com/DCrP1w9x here]).
Always less than or equal '''0x0E''', Floating point reference value always less than '''1.0f''' in [[Mario Kart 8]] files.
+
Floating point reference value always less than '''1.0f''' in [[Mario Kart 8]] files.
 
|-
 
|-
| 0x14
+
| 0x14 || 4 || UInt32 || '''Color control''', maps to '''GX2ColorControlReg''', a bitset packed as '''xxxxxxxx DDDDDDDD CCCCCCCC xBBBxxxA'''. Controls how colors are written to buffers.
| 4
+
* '''A''' controls whether multiwrites are enabled ('''1''') or not ('''0''').
| '''Color Control''', maps to '''GX2ColorControlReg'''. Controls how colors are written to buffers.
+
* '''BBB''' controls a special operation and is used to enable a color buffer with unknown purpose.
Always '''0x00CC0000''' or '''0x00CC0100''' in [[Mario Kart 8]] files.
+
* '''CCCCCCCC''' controls the bitmask used for blending.
 +
* '''DDDDDDDD''' maps to '''GX2LogicOp''' and determines the ROP3 color logic operation (line 161 [https://pastebin.com/DCrP1w9x here])
 +
Defaults to Copy operation and nothing else enabled. Some files set a bitmask of 00000001.
 
|-
 
|-
| 0x18
+
| 0x18 || 8 || UInt32[2] || '''Blend control''', maps to '''GX2BlendControlReg''', a structure of two unsigned integers. Controls how and to which target blending is performed. The first unsigned integer describes the target index (always '''0''' in [[Mario Kart 8]] files), the second is a bitset packed as '''xxGFFFFF EEEDDDDD xxxCCCCC BBBAAAAA'''.
| 8
+
* '''AAAAA''' maps to '''GX2BlendFunction'''and sets the color source blend operation (line 189 [https://pastebin.com/DCrP1w9x here]).
| '''Blend Control''', maps to '''GX2BlendControlReg'''. Controls how and to which target blending is performed.
+
* '''BBB''' maps to '''GX2BlendCombine''' and sets the color combine operation (line 231 [https://pastebin.com/DCrP1w9x here]).
Target always '''0''', blend value always '''0x20010101''', '''0x20010104''', '''0x20010501''' or '''0x20010504''' in [[Mario Kart 8]] files.
+
* '''CCCCC''' is the same as ''AAAAA'' but sets the color destination blend operation.
 +
* '''DDDDD''' is the same as ''AAAAA'', but sets the alpha source blend operation.
 +
* '''EEE''' is the same as ''BBB'', but sets the alpha combine operation.
 +
* '''FFFFF''' is the same as ''AAAAA'', but sets the alpha destination blend operation.
 +
* '''G''' apparently controls whether to separate the alpha from color blending.
 +
Blend value always '''0x20010101''', '''0x20010104''', '''0x20010501''' or '''0x20010504''' in [[Mario Kart 8]] files.
 
|-
 
|-
| 0x20
+
| 0x20 || 16 || Single[4] || '''Blend color''', maps to '''GX2BlendConstantColorReg'''. Controls the blend color as 4 RGBA floating point values.
| 16
+
Defaults to '''(0f, 0f, 0f, 0f)'''.
| '''Blend Color''', maps to '''GX2BlendConstantColorReg'''. Controls the blend color as 4 RGBA floating point values.
 
Always '''(0f, 0f, 0f, 0f)''' in [[Mario Kart 8]] files.
 
 
|-
 
|-
| 0x30
+
| 0x30 || colspan="3" {{Unknown|End of Render State}}
| colspan="2" {{Unknown|End of Render State}}
 
 
|}
 
|}
  
Line 734: Line 611:
  
 
{| class="wikitable"
 
{| class="wikitable"
! Offset
+
! Offset !! Size !! Type !! Description
! Size
 
! Description
 
 
|-
 
|-
| 0x00
+
| 0x00 || 4 || Int32 || '''Shader archive name''' offset.
| 4
 
| '''Shader Archive Name''' offset.
 
 
|-
 
|-
| 0x04
+
| 0x04 || 4 || Int32 || '''Shading model name''' offset.
| 4
 
| '''Shading Model Name''' offset.
 
 
|-
 
|-
| 0x08
+
| 0x08 || 4 || UInt32 || '''Revision'''. Apparently unused, always '''0''' or '''1'''.
| 4
 
| '''Revision'''. Apparently unused, always '''0''' or '''1'''.
 
 
|-
 
|-
| 0x0C
+
| 0x0C || 1 || Byte || '''Vertex Shader Input count'''. Number of elements in the Vertex Shader Input index group.
| 1
 
| '''Vertex Shader Input Count'''. Number of elements in the Vertex Shader Input index group.
 
 
|-
 
|-
| 0x0D
+
| 0x0D || 1 || Byte || '''Fragment Shader Input count'''. Number of elements in the Fragment Shader Input index group.
| 1
 
| '''Pixel Shader Input Count'''. Number of elements in the Pixel Shader Input index group.
 
 
|-
 
|-
| 0x0E
+
| 0x0E || 2 || UInt16 || '''Parameter count'''. Number of elements in the Parameter index group.
| 2
 
| '''Parameter Count'''. Number of elements in the Parameter index group.
 
 
|-
 
|-
| 0x10
+
| 0x10 || 4 || Int32 || '''Vertex Shader Input [[index group]]''' offset. Offset to the index group which forms a mapping between strings, mapping an '''FVTX''' attribute to a vertex shader variable. Normally the names are always the same in [[Mario Kart 8]], so this mapping is just ["_p0": "_p0", "_n0": "_n0", ...]?
| 4
 
| '''Vertex Shader Input [[BFRES (File Format)#Index Group|index group]]''' offset. Offset to the index group which forms a mapping between strings, mapping an '''FVTX''' attribute to a vertex shader variable. Normally the names are always the same in [[Mario Kart 8]], so this mapping is just ["_p0": "_p0", "_n0": "_n0", ...]?
 
 
|-
 
|-
| 0x14
+
| 0x14 || 4 || Int32 || '''Fragment Shader Input [[index group]]''' offset. Offset to the index group which forms a mapping between strings, mapping an '''FVTX''' attribute to a fragment shader variable. Normally the names are always the same in [[Mario Kart 8]], so this mapping is just ["_p0": "_p0", "_n0": "_n0", ...]?
| 4
 
| '''Pixel Shader Input [[BFRES (File Format)#Index Group|index group]]''' offset. Offset to the index group which forms a mapping between strings, mapping an '''FVTX''' attribute to a pixel shader variable. Normally the names are always the same in [[Mario Kart 8]], so this mapping is just ["_p0": "_p0", "_n0": "_n0", ...]?
 
 
|-
 
|-
| 0x18
+
| 0x18 || 4 || Int32 || '''Parameter [[index group]]''' offset. Offset to the index group which forms a mapping between strings, mapping a uniform shader variable to a value. The values are always strings, even for numeric parameters. The values are used to specify the shader program used for rendering.
| 4
 
| '''Parameter [[BFRES (File Format)#Index Group|index group]]''' offset. Offset to the index group which forms a mapping between strings, mapping a uniform shader variable to a value. The values are always strings, even for numeric parameters.
 
 
|-
 
|-
| 0x1C
+
| 0x1C || colspan="3" {{Unknown|End of Shader Assign}}
| colspan="2" {{Unknown|End of Shader Assign}}
 
 
|}
 
|}
  
=== Shadow Parameter ===
+
== FSKL ==
  
A '''Shadow Parameter''' is a repeating 0xc byte structure, each of which describes the value to assign to a shadow variable in the shader code. Shadow variables are always uniform variables. The '''Shadow Parameter''' structures are referenced by the '''Shadow Parameter index group''' in the corresponding '''[[#Header (FMAT)|FMAT Header]]'''.
+
Each model has one '''FSKL''' (ca'''F'''e '''SK'''e'''L'''eton) section which describes one or more bones. The bones form a skeleton and give a transformation to apply to any attached polygon. Every '''[[#FSHP|FSHP polygon]]''' is attached to at least one bone. The '''FSKL''' format is somewhat different in '''BFRES''' files with values other than 0x03040004 after the '''FRES''' identifier, which may indicate an alternative version of the format. These are rare in [[Mario Kart 8]] and not documented here.
 +
 
 +
=== Header (FSKL) ===
 +
 
 +
The FSKL section always starts with an 0x24 byte header. The location of this header is given by the offset in the '''FMDL header'''.
  
 
{| class="wikitable"
 
{| class="wikitable"
! Offset
+
! Offset !! Size !! Type !! Description
! Size
 
! Description
 
 
|-
 
|-
| 0x00
+
| 0x00 || 4 || Char[4] || "'''FSKL'''" section identifier, ASCII string.
| 4
 
| '''Variable Name''' offset.
 
 
|-
 
|-
| 0x04
+
| 0x04 || 4 || UInt32 || '''Flags'''. Controls how scaling and rotation is performed. Encoded as '''xxxxxxxx xxxxxxxx xxxRxxSS xxxxxxxx''' bits.
| 2
+
* SS specifies how the bone matrix is calculated:
| {{Unknown|'''Unknown''' always '''1'''.}}
+
{| class="wikitable"
 +
! Value !! Description
 
|-
 
|-
| 0x06
+
| 0 || No scaling
| 1
 
| {{Unknown|'''Type''' or '''Index'''?}}
 
 
|-
 
|-
| 0x07
+
| 1 || Standard scaling. Results in a "default" scaling method.
| 1
 
| {{Unknown|'''Unknown''' always '''0'''.}}
 
 
|-
 
|-
| 0x08
+
| 2 || Maya scaling. Respects [http://download.autodesk.com/us/fbx/FBX_Maya_online/files/WS73099cc142f48755-3d114b751181c40f14b1283.htm Maya's segment scale compensation] which offsets child bones rather than scaling them with the parent.
| 4
 
| '''Value''' of the variable.
 
 
|-
 
|-
| 0x0C
+
| 3 || Softimage scaling. Respects the scaling method of Softimage.
| colspan="2" {{Unknown|End of Shadow Parameter}}
+
|}
 +
* R controls the rotation mode, either euler XYZ rotation (bit set) or quaternion (bit unset).
 +
Always '''0x00001100''' (standard scaling & euler XYZ rotation) or '''0x00001200''' (Maya scaling & euler XYZ rotation) in [[Mario Kart 8]] files.
 +
|-
 +
| 0x08 || 2 || UInt16 || '''[[#Bone|Bone]] array count'''. Number of elements in the Bone array.
 +
|-
 +
| 0x0A || 2 || UInt16 || '''[[#Smooth Matrix|Smooth Index]] array count'''. Number of elements in the Smooth Matrix array for smooth skinning (shape vertices are influenced by multiple bones).
 +
|-
 +
| 0x0C || 2 || UInt16 || '''[[#Rigid Matrix|Rigid Index]] array count'''. Number of elements in the Rigid Matrix array at the end of the '''[[#Smooth Matrix|Smooth Index]] array''' for rigid skinning (shape vertices are influenced by a single bone).
 +
|-
 +
| 0x0E || 2 || &mdash; || Padding.
 +
|-
 +
| 0x10 || 4 || Int32 || '''[[#Bone|Bone]] [[index group]]''' offset. Named pointers to the members of the '''Bone array''' to allow named lookups.
 +
|-
 +
| 0x14 || 4 || Int32 || '''[[#Bone|Bone]] array''' offset. Offset to the first element in the Bone array.
 +
|-
 +
| 0x18 || 4 || Int32 || '''[[#Smooth Matrix|Smooth Index]] array''' offset. Offset to the first element in the Smooth Index array. Always given even if the array is empty.
 +
|-
 +
| 0x1C || 4 || Int32 || '''[[#Smooth Matrix|Smooth Matrix]] array''' offset. Offset to the first element in the Smooth Matrix array. Always given even if the array is empty.
 +
|-
 +
| 0x20 || 4 || UInt32 || '''User pointer''', can be set at runtime, '''0''' in files.
 +
|-
 +
| 0x24 || colspan="3" {{Unknown|End of FSKL header}}
 
|}
 
|}
  
== FSKL ==
+
=== Bone ===
  
Each model has one '''FSKL''' section which describes one or more bones. The bones form a skeleton and give a transformation to apply to any attached polygon. Every '''[[#FSHP|FSHP polygon]]''' is attached to at least one bone. The '''FSKL''' format is somewhat different in '''BFRES''' files with values other than 0x03040004 after the '''FRES''' identifier, which may indicate an alternative version of the format. These are rare in [[Mario Kart 8]] and not documented here.
+
A '''Bone''' is a repeating 0x40 byte structure which descibes a transformation to apply to a polygon. Each bone has up to four parents, which form a tree called a skeleton. To compute the final transformation of a point, apply the transformation required by the bone it is attached to, then that bone's parent recursively up until no parents remain. The '''Bone''' tree is stored as an array with offset and length specified by the '''[[#Header (FSKL)|FSKL header]]'''.
 
 
=== Header (FSKL) ===
 
 
 
The FSKL section always starts with an 0x24 byte header. The location of this header is given by the offset in the '''FMDL header'''.
 
  
 
{| class="wikitable"
 
{| class="wikitable"
! Offset
+
! Offset !! Size !! Type !! Description
! Size
 
! Description
 
 
|-
 
|-
| 0x00
+
| 0x00 || 4 || Int32 || '''Name offset''' for this bone.
| 4
 
| "'''FSKL'''" section identifier, ASCII string.
 
 
|-
 
|-
| 0x04
+
| 0x04 || 2 || UInt16 || '''Bone index''' of this bone into the bone array.
| 2
 
| {{Unknown|'''Unknown''' always '''0'''.}}
 
 
|-
 
|-
| 0x06
+
| 0x06 || 2 || UInt16 || '''Parent index''' of the parents to this bone. '''0xFFFF''' for no parent.
| 2
 
| {{Unknown|'''Unknown''' always '''0x1100''' or '''0x1200'''.}}
 
 
|-
 
|-
| 0x08
+
| 0x08 || 2 || Int16 || '''Smooth Matrix index''' to reverse the transformation of this bone. '''-1''' for no smooth matrix.
| 2
 
| '''[[#Bone|Bone]] array count'''. Number of elements in the Bone array.
 
 
|-
 
|-
| 0x0A
+
| 0x0A || 2 || Int16 || '''Rigid Matrix index''' with unknown purpose. '''-1''' for no rigid matrix.
| 2
 
| '''[[#Inverse Matrix|Inverse Index]] array count'''. Number of elements in the Inverse Matrix array.
 
 
|-
 
|-
| 0x0C
+
| 0x0C || 2 || Int16 || '''Billboard index''' to control how billboarded bones are affected in a hierarchy. '''-1''' if no billboarded bones are affected.
| 2
 
| '''Extra Index count'''. Count of the number of extra indices at the end of the '''[[#Inverse Matrix|Inverse Index]] array'''. These serve '''unknown''' purpose.
 
 
|-
 
|-
| 0x0E
+
| 0x0E || 2 || UInt16 || '''[[User Data]] entry count'''.
| 2
 
| {{Unknown|'''Unknown''' always '''0'''.}}
 
 
|-
 
|-
| 0x10
+
| 0x10 || 4 || UInt32 || '''Flags''', encoded as '''CCCCTTTT TxxxxBBB xxxRxxxx xxxxxxxV''' bits.
| 4
+
* V controls the visibility of the influenced shape.
| '''[[#Bone|Bone]] [[BFRES (File Format)#Index Group|index group]]''' offset. Named pointers to the members of the '''Bone array''' to allow named lookups.
+
* R controls the rotation mode, either euler XYZ rotation (bit set) or quaternion (bit unset).
 +
* BBB controls how billboarded bones are projected:
 +
{| class="wikitable"
 +
! Value !! Description
 
|-
 
|-
| 0x14
+
| 0 || No billboarding. The influenced shape is not transformed for billboarding.
| 4
 
| '''[[#Bone|Bone]] array''' offset. Offset to the first element in the Bone array.
 
 
|-
 
|-
| 0x18
+
| 1 || Child billboarding.
| 4
 
| '''[[#Inverse Matrix|Inverse Index]] array''' offset. Offset to the first element in the Inverse Index array. Always given even if the array is empty.
 
 
|-
 
|-
| 0x1C
+
| 2 || World View Vector. The Z axis is parallel to the camera.
| 4
 
| '''[[#Inverse Matrix|Inverse Matrix]] array''' offset. Offset to the first element in the Inverse Matrix array. Always given even if the array is empty.
 
 
|-
 
|-
| 0x20
+
| 3 || World View Point. The Z axis is equal to the direction the camera is pointing to.
| 4
 
| Padding, always '''0'''.
 
 
|-
 
|-
| 0x24
+
| 4 || Screen View Vector. The Z axis is parallel to the camera, the Y axis is equal to the up vector of the camera.
| colspan="2" {{Unknown|End of FSKL header}}
+
|-
 +
| 5 || Screen View Point. The Z axis is equal to the direction the camera is pointing to, the Y axis is equal to the up vector of the camera.
 +
|-
 +
| 6 || Y-Axis View Vector. The Z axis has been made parallel to the camera view by rotating the Y axis.
 +
|-
 +
| 7 || Y-Axis View Point. The Z axis has been made equal to the direction the camera is pointing to by rotating the Y axis.
 
|}
 
|}
 
+
* T TTTT are combinable flags controlling how bones are transformed.
=== Bone ===
 
 
 
A '''Bone''' is a repeating 0x40 byte structure which descibes a transformation to apply to a polygon. Each bone has up to four parents, which form a tree called a skeleton. To compute the final transformation of a point, apply the transformation required by the bone it is attached to, then that bone's parent recursively up until no parents remain. The '''Bone''' tree is stored as an array with offset and length specified by the '''[[#Header (FSKL)|FSKL header]]'''.
 
 
 
 
{| class="wikitable"
 
{| class="wikitable"
! Offset
+
! Value !! Description
! Size
 
! Description
 
 
|-
 
|-
| 0x00
+
| 1 || Segment scale compensation. Set for bones scaled in Maya whose scale is not applied to child bones.
| 4
 
| '''Name offset''' for this bone.
 
 
|-
 
|-
| 0x04
+
| 2 || Scale uniformly.
| 2
 
| '''Bone index''' of this bone into the bone array.
 
 
|-
 
|-
| 0x06
+
| 4 || Scale volume by 1.
| 8
 
| '''Parent indices''' of up to four parents for this bone. '''0xFFFF''' for no parent.
 
 
|-
 
|-
| 0x0E
+
| 8 || No rotation.
| 2
 
| {{Unknown|'''Unknown''' always '''0'''.}}
 
 
|-
 
|-
| 0x10
+
| 16 || No translation.
| 2
+
|}
| '''Flags''' controlling this bone. '''Unknown''' purpose.
+
* CCCC controls the same but for a hierarchy of bones.
 +
{| class="wikitable"
 +
! Value !! Description
 
|-
 
|-
| 0x12
+
| 1 || Scale uniformly.
| 2
 
| {{Unknown|'''Unknown''' always '''0x1001'''.}}
 
 
|-
 
|-
| 0x14
+
| 2 || Scale volume by 1.
| 12
 
| '''Scale Vector''' 3 floats. The amount to scale the vertices by.
 
 
|-
 
|-
| 0x20
+
| 4 || No rotation.
| 16
 
| '''Rotation Vector''', normally stored as euler rotation (X, Y, Z in radians) but it can be stored as a quaternion. The last float is not used by euler rotation and is therefor set to 1f.
 
 
|-
 
|-
| 0x30
+
| 8 || No translation.
| 12
+
|}
| '''Translation Vector''' 3 floats. The amount to translate the vertices by.
+
Always '''0x00001001''' (visible & euler XYZ rotation) in [[Mario Kart 8]] files.
 
|-
 
|-
| 0x3C
+
| 0x14 || 12 || Single[3] || '''Scale Vector''' 3 floats. The amount to scale the vertices by.
| 4
 
| Padding, always '''0'''.
 
 
|-
 
|-
| 0x40
+
| 0x20 || 16 || Single[4] || '''Rotation Vector''', either stored as euler rotation (X, Y, Z in radians) or a quaternion, depending on the bone ''Flags''. Mario Kart 8 always uses euler XYZ rotation, so the last float is always set to 1f.
| colspan="2" {{Unknown|End of Bone}}
+
|-
 +
| 0x30 || 12 || Single[3] || '''Translation Vector''' 3 floats. The amount to translate the vertices by.
 +
|-
 +
| 0x3C || 4 || Int32 || '''[[User Data]] [[index group]]''' offset. Never used in [[Mario Kart 8]] FSKL sections and thus '''0'''.
 +
|-
 +
| 0x40 || colspan="3" {{Unknown|End of Bone}}
 
|}
 
|}
  
=== Inverse Matrix ===
+
=== Smooth Matrix ===
  
The '''FSKL''' may specify an '''Inverse Matrix''' for any '''[[#Bone|Bone]]'''. It does this by creating an entry in the '''Invese Index''' array which is the index of the bone, and in the corresponding place in the '''Inverse Matrix array''' it places a 4&times;3 transformation matrix which reverses the full transformation of the bone and all its parents. Inverse Matricies are optional, it is '''Unknown''' if they are ever referenced. The position of and number of elements in the '''Inverse Matrix array''' and the '''Inverse Index array''' are given in the [[#Header (FSKL)|FSKL Header]]. At the end of the '''Inverse Index array''' are a number of extra indices, which have '''Unknown''' purpose. The number of such extra indices is also present in the [[#Header (FSKL)|FSKL Header]].
+
The '''FSKL''' may specify an '''Smooth Matrix''' for any '''[[#Bone|Bone]]'''. It does this by creating an entry in the '''Inverse Index''' array which is the index of the bone, and in the corresponding place in the '''Smooth Matrix array''' it places a 4&times;3 transformation matrix which reverses the full transformation of the bone and all its parents. Smooth Matrices are optional, it is '''Unknown''' if they are ever referenced. The position of and number of elements in the '''Smooth Matrix array''' and the '''Smooth Index array''' are given in the [[#Header (FSKL)|FSKL Header]].
 +
 
 +
=== Rigid Matrix ===
 +
 
 +
At the end of the '''Smooth Index array''' are a number of indices for Rigid Matrices, which have '''Unknown''' purpose. The number of such Rigid Matrices is also present in the [[#Header (FSKL)|FSKL Header]].
  
 
== FSHP ==
 
== FSHP ==
  
The model may have one or more '''FSHP''' sections which describe the one polygon (e.g. the road of a track). The FSHP section consists of an 0x40 byte header, which references an '''[[#FVTX|FVTX]]''' section and indices of the polygons to draw. A basic '''FSHP''' amounts to a list of indices into the corresponding '''FVTX''' indicating which points to draw triangles between. The '''FSHP''' also references an '''[[#FMAT|FMAT]]''' to describe the material of the triangles, and an '''[[#FSKL|FSKL]]''' to indicate the bone structure of the model used in animation.
+
The model may have one or more '''FSHP''' (ca'''F'''e '''SH'''a'''P'''e) sections which describe the one polygon (e.g. the road of a track). The FSHP section consists of an 0x40 byte header, which references an '''[[#FVTX|FVTX]]''' section and indices of the polygons to draw. A basic '''FSHP''' amounts to a list of indices into the corresponding '''FVTX''' indicating which points to draw triangles between. The '''FSHP''' also references an '''[[#FMAT|FMAT]]''' to describe the material of the triangles, and an '''[[#FSKL|FSKL]]''' to indicate the bone structure of the model used in animation.
  
 
The triangles in an '''FSHP''' are organised by two systems; [[#LoD Model|LoD Models]] and [[#Visibility Group|Visibility Groups]]. No model in Mario Kart 8 uses both of these features non-trivially simultaneously. LoD stands for Level of Detail, which is a standard performance technique used across many 3d rendering systems. Each LoD model is a simpler version of the one before it, with extraneous triangles removed, and finer detail simplified. As the camera in the game moves away from a polygon, the simpler version of the model is rendered instead, which should look the same as the fine detailed version at a distance. A trivial polygon will only have one LoD model, which will be rendered no matter what distance the camera is. Separately, the Visibility Group system allows parts of the model to not be rendered if they are off-screen. This allows an polygon which is partially off-screen to be rendered faster, by skipping the off-screen components. A trivial polygon will only have one Visibility Group, which will always be rendered.
 
The triangles in an '''FSHP''' are organised by two systems; [[#LoD Model|LoD Models]] and [[#Visibility Group|Visibility Groups]]. No model in Mario Kart 8 uses both of these features non-trivially simultaneously. LoD stands for Level of Detail, which is a standard performance technique used across many 3d rendering systems. Each LoD model is a simpler version of the one before it, with extraneous triangles removed, and finer detail simplified. As the camera in the game moves away from a polygon, the simpler version of the model is rendered instead, which should look the same as the fine detailed version at a distance. A trivial polygon will only have one LoD model, which will be rendered no matter what distance the camera is. Separately, the Visibility Group system allows parts of the model to not be rendered if they are off-screen. This allows an polygon which is partially off-screen to be rendered faster, by skipping the off-screen components. A trivial polygon will only have one Visibility Group, which will always be rendered.
Line 944: Line 786:
  
 
{| class="wikitable"
 
{| class="wikitable"
! Offset
+
! Offset !! Size !! Type !! Description
! Size
+
|-
! Description
+
| 0x00 || 4 || Char[4] || "'''FSHP'''" section identifier, ASCII string.
 +
|-
 +
| 0x04 || 4 || Int32 || '''Polygon name''' offset.
 +
|-
 +
| 0x08 || 4 || UInt32 || '''Flags''' with only the following meaning:
 +
{| class="wikitable"
 +
! Bit (0-based) !! Description
 
|-
 
|-
| 0x00
+
| 1 || Has vertex buffer.
| 4
+
|}
| "'''FSHP'''" section identifier, ASCII string.
+
Always set (thus '''2''') in [[Mario Kart 8]] files.
 
|-
 
|-
| 0x04
+
| 0x0C || 2 || UInt16 || '''Section index'''.
| 4
 
| '''Polygon name''' offset.
 
 
|-
 
|-
| 0x08
+
| 0x0E || 2 || UInt16 || '''[[#FMAT|FMAT]] index'''. Index of the material for this polygon.
| 4
 
| {{Unknown|'''Unknown''' always '''2'''.}}
 
 
|-
 
|-
| 0x0C
+
| 0x10 || 2 || UInt16 || '''[[#FSKL|FSKL]] index''' of the bone for this polygon.
| 2
 
| '''Section Index''' or '''[[#FVTX|FVTX]] Index'''. In every [[Mario Kart 8]] model these numbers are the same.
 
 
|-
 
|-
| 0x0E
+
| 0x12 || 2 || UInt16 || '''[[#FVTX|FVTX]] index''' of the vertex buffer this polygon uses.
| 2
 
| '''[[#FMAT|FMAT]] Index'''. Index of the material for this polygon.
 
 
|-
 
|-
| 0x10
+
| 0x14 || 2 || UInt16 || '''FSKL Bone skin index'''. Specifies the index of the bone to which local coordinate matrix vertices are relative in case of rigid bodies using no skinning.
| 2
 
| '''[[#FSKL|FSKL]] Index''' of the bone for this polygon.
 
 
|-
 
|-
| 0x12
+
| 0x16 || 1 || Byte || '''Vertex skin count''', the number of bones influencing a vertex. Depending on the value, vertex positions are stored in different coordinate systems:
| 2
+
* '''2+''' indicates smooth skinning. Coordinates are relative to the model coordinate system of a rest pose.
| '''Section Index''' or '''[[#FVTX|FVTX]] Index'''. In every [[Mario Kart 8]] model these numbers are the same.
+
* '''1''' indicates rigid skinning. Coordinates are relative to the local coordinate system of the bone at the index given by the ''blendindex0'' vertex attribute.
 +
* '''0''' indicates rigid bodies using no skinning. Coordinates are relative to the local coordinate system of the bone at the index given by the ''FSKL Bone skin index'' field.
 
|-
 
|-
| 0x14
+
| 0x17 || 1 || Byte || '''[[#LoD Model|LoD Model]] count'''. Number of elements in the array.
| 2
 
| '''FSKL Index Array Count'''. Often zero, '''Unknown''' purpose but seems to be related to '''FSKL'''.
 
 
|-
 
|-
| 0x16
+
| 0x18 || 1 || Byte || '''Key Shape count'''. This feature is not used in [[Mario Kart 8]], thus always '''0'''.
| 1
 
| {{Unknown|'''Unknown''': If '''FSKL Index Array''' is present this tends to be non-zero. Zero otherwise.}}
 
 
|-
 
|-
| 0x17
+
| 0x19 || 1 || Byte || '''Target Attribute count'''. This feature is not used in [[Mario Kart 8]], thus always '''0'''.
| 1
 
| '''[[#LoD Model|LoD Model]] count'''. Number of elements in the array.
 
 
|-
 
|-
| 0x18
+
| 0x1A || 2 || UInt16 || '''[[#Visibility Group Tree|Visibility Group Tree Node]] count'''.
| 4
 
| '''[[#Visibility Group Tree|Visibility Group Tree Node]] count'''.
 
 
|-
 
|-
| 0x1C
+
| 0x1C || 4 || Single || '''Radius''' of spherical bounding box.
| 4
 
| {{Unknown|'''Unknown''' floating point.}}
 
 
|-
 
|-
| 0x20
+
| 0x20 || 4 || Int32 || '''[[#FVTX|FVTX]]''' offset to the vertex buffer for this polygon.
| 4
 
| '''[[#FVTX|FVTX]] offset''' to the vertex buffer for this polygon.
 
 
|-
 
|-
| 0x24
+
| 0x24 || 4 || Int32 || '''[[#LoD Model|LoD Model]]''' offset. Offset to the first element in the array.
| 4
 
| '''[[#LoD Model|LoD Model]] offset'''. Offset to the first element in the array.
 
 
|-
 
|-
| 0x28
+
| 0x28 || 4 || Int32 || '''FSKL Index array''' offset. Each element of this array is a 16 bit index.
| 4
 
| '''FSKL Index Array Offset'''. Each element of this array is a 16 bit index.
 
 
|-
 
|-
| 0x2C
+
| 0x2C || 4 || Int32 || '''Key Shape [[index group]]''' offset. Never used in [[Mario Kart 8]] and thus '''0'''.
| 4
 
| {{Unknown|'''Unknown''' always '''0'''.}}
 
 
|-
 
|-
| 0x30
+
| 0x30 || 4 || Int32 || '''[[#Visibility Group Tree|Visibility Group Tree Nodes]]''' offset.
| 4
 
| '''[[#Visibility Group Tree|Visibility Group Tree Nodes]] offset'''.
 
 
|-
 
|-
| 0x34
+
| 0x34 || 4 || Int32 || '''[[#Visibility Group Tree|Visibility Group Tree Ranges]]''' offset.
| 4
 
| '''[[#Visibility Group Tree|Visibility Group Tree Ranges]] offset'''.
 
 
|-
 
|-
| 0x38
+
| 0x38 || 4 || Int32 || '''[[#Visibility Group Tree|Visibility Group Tree Indices]]''' offset.
| 4
 
| '''[[#Visibility Group Tree|Visibility Group Tree Indices]] offset'''.
 
 
|-
 
|-
| 0x3C
+
| 0x3C || 4 || UInt32 || '''User pointer''', can be set at runtime, '''0''' in files.
| 4
 
| {{Unknown|'''Unknown''' always '''0'''.}}
 
 
|-
 
|-
| 0x40
+
| 0x40 || colspan="3" {{Unknown|End of FSHP header}}
| colspan="2" {{Unknown|End of FSHP header}}
 
 
|}
 
|}
  
 
=== LoD Model ===
 
=== LoD Model ===
  
An '''LoD Model''' is a repeating 0x1C byte structure which are stored in a sequential array with location and size specified by the '''[[#Header (FSHP)|FSHP Header]]'''. Their purpose is described at the beginning of this section.
+
A '''LoD Model''' is a repeating 0x1C byte structure which are stored in a sequential array with location and size specified by the '''[[#Header (FSHP)|FSHP Header]]'''. Their purpose is described at the beginning of this section.
  
 
{| class="wikitable"
 
{| class="wikitable"
! Offset
+
! Offset !! Size !! Type !! Description
! Size
 
! Description
 
 
|-
 
|-
| 0x00
+
| 0x00 || 4 || UInt32 || '''Primitive Type''', maps to '''GX2PrimitiveType''' (line 527 [https://pastebin.com/DCrP1w9x here]). Determines how index lists are interpreted to form triangles.
| 4
+
Always '''GX2_PRIMITIVE_TRIANGLES''' (thus '''4''') in [[Mario Kart 8]] files.
| {{Unknown|'''Unknown''' Always '''4'''.}}
 
 
|-
 
|-
| 0x04
+
| 0x04 || 4 || UInt32 || '''Index Format''', maps to '''GX2IndexFormat''' (line 515 [https://pastebin.com/DCrP1w9x here]). The data type of indices.
| 4
+
Always '''GX2_INDEX_FORMAT_U16''' (thus '''4''') in [[Mario Kart 8]] files.
| {{Unknown|'''Unknown''' Always '''4'''.}}
 
 
|-
 
|-
| 0x08
+
| 0x08 || 4 || UInt32 || '''Count of points''' drawn in all [[#Visibility Group|Visibility Group]]s, thus the maximum number of points drawn at this LoD.
| 4
 
| '''Count''' of points drawn in all [[#Visibility Group|Visibility Group]]s, thus the maximum number of points drawn at this LoD.
 
 
|-
 
|-
| 0x0C
+
| 0x0C || 2 || UInt16 || '''[[#Visibility Group|Visibility Group]] count'''. The number of elements in the array.
| 2
 
| '''[[#Visibility Group|Visibility Group]] count'''. The number of elements in the array.
 
 
|-
 
|-
| 0x0E
+
| 0x0E || 2 || &mdash; || '''Padding'''.
| 2
 
| {{Unknown|'''Unknown'''.}}
 
 
|-
 
|-
| 0x10
+
| 0x10 || 4 || Int32 || '''[[#Visibility Group|Visibility Group]]''' offset to the first element in the array.
| 4
 
| '''[[#Visibility Group|Visibility Group]] offset'''. Offset to the first element in the array.
 
 
|-
 
|-
| 0x14
+
| 0x14 || 4 || Int32 || '''[[#Index Buffer|Index Buffer]]''' offset.
| 4
 
| '''[[#Index Buffer|Index Buffer]] offset'''.
 
 
|-
 
|-
| 0x18
+
| 0x18 || 4 || UInt32 || '''Skip vertices''', the number of elements to skip in the corresponding '''FVTX''' buffer.
| 4
 
| '''Skip Vertices''': the number of elements to skip in the corresponding '''FVTX''' buffer.
 
 
|-
 
|-
| 0x1C
+
| 0x1C || colspan="3" {{Unknown|End of LoD Model}}
| colspan="2" {{Unknown|End of LoD Model}}
 
 
|}
 
|}
  
Line 1,082: Line 877:
  
 
{| class="wikitable"
 
{| class="wikitable"
! Offset
+
! Offset !! Size !! Type !! Description
! Size
 
! Description
 
 
|-
 
|-
| 0x00
+
| 0x00 || 4 || UInt32 || '''Offset''' into index buffer in bytes.
| 4
 
| '''Offset''' into index buffer in bytes.
 
 
|-
 
|-
| 0x04
+
| 0x04 || 4 || UInt32 || '''Count''' of the points to draw.
| 4
 
| '''Count''' of the points to draw.
 
 
|-
 
|-
| 0x08
+
| 0x08 || colspan="3" {{Unknown|End of Visibility Group}}
| colspan="2" {{Unknown|End of Visibility Group}}
 
 
|}
 
|}
  
 
=== Index Buffer ===
 
=== Index Buffer ===
  
An '''Index Buffer''' is an 0x18 byte structure which describes a list of 16 bit values which are used to index the '''FVTX''' section when drawing the polygon. Index Buffers are referenced by [[#LoD Model|LoD Model]]s. The format is very similar to the [[#Buffers|FVTX Buffer]] format, which may indicate they are instances of the same structure.
+
An '''Index Buffer''' is an 0x18 byte structure which describes a list of values (of type as given in the header) which are used to index the '''FVTX''' section when drawing the polygon. Index Buffers are referenced by [[#LoD Model|LoD Model]]s. They are instances of the same structure as [[#Buffers|FVTX Buffers]] and thus have the same layout.
 
 
{| class="wikitable"
 
! Offset
 
! Size
 
! Description
 
|-
 
| 0x00
 
| 4
 
| {{Unknown|'''Unknown''' Always '''0'''.}}
 
|-
 
| 0x04
 
| 4
 
| '''Size''' of index data in bytes.
 
|-
 
| 0x08
 
| 4
 
| {{Unknown|'''Unknown''' Always '''0'''.}}
 
|-
 
| 0x0C
 
| 2
 
| {{Unknown|'''Unknown''' Always '''0'''.}}
 
|-
 
| 0x0E
 
| 2
 
| {{Unknown|'''Unknown''' Always '''1'''.}}
 
|-
 
| 0x10
 
| 4
 
| {{Unknown|'''Unknown''' Always '''0'''.}}
 
|-
 
| 0x14
 
| 4
 
| '''Index data offset'''.
 
|-
 
| 0x18
 
| colspan="2" {{Unknown|End of Index Buffer}}
 
|}
 
  
 
=== Visibility Group Tree ===
 
=== Visibility Group Tree ===
Line 1,148: Line 899:
  
 
{| class="wikitable"
 
{| class="wikitable"
! Offset
+
! Offset !! Size !! Description
! Size
 
! Description
 
 
|-
 
|-
| 0x00
+
| 0x00 || 2 || '''Left child''' index. The current node's index if it has no left child.
| 2
 
| '''Left Child''' index. The current node's index if it has no left child.
 
 
|-
 
|-
| 0x02
+
| 0x02 || 2 || '''Right child''' index. The current node's index if it has no right child.
| 2
 
| '''Right Child''' index. The current node's index if it has no right child.
 
 
|-
 
|-
| 0x04
+
| 0x04 || 2 || {{Unknown|'''Unknown''', always the same as '''Left child''' index.}}
| 2
 
| '''Unknown''' always the same as '''Left Child''' index.
 
 
|-
 
|-
| 0x06
+
| 0x06 || 2 || '''Next sibling''' index. For left children, always the current node's parent's right child (the current node's index if it has no right child).
| 2
 
| '''Next Sibling''' index. For left children, always the current node's parent's right child (the current node's index if it has no right child).
 
 
|-
 
|-
| 0x08
+
| 0x08 || 2 || '''[[#Visibility Group|Visibility Group]] index''' selects a range of Visibility Groups along with the count.
| 2
 
| '''[[#Visibility Group|Visibility Group]] Index''' selects a range of Visibility Groups along with the count.
 
 
|-
 
|-
| 0x0A
+
| 0x0A || 2 || '''[[#Visibility Group|Visibility Group]] count''' selects a range of Visibility Groups along with the index.
| 2
 
| '''[[#Visibility Group|Visibility Group]] Count''' selects a range of Visibility Groups along with the index.
 
 
|-
 
|-
| 0x0C
+
| 0x0C || colspan="2" {{Unknown|End of Node}}
| colspan="2" {{Unknown|End of Node}}
 
 
|}
 
|}
  
 
==== Ranges ====
 
==== Ranges ====
  
The '''Visibility Group Tree Range''' is a repeating 0x18 byte structure. There are exactly as many Ranges as Nodes. The range appears to contain two 3D positions, which are not necessarily distinct, but seem to represent a center value and a maximum range (possibly a bounding box) in a 3D frustum.
+
The '''Visibility Group Tree Range''' is a repeating 0x18 byte structure. There are exactly as many Ranges as Nodes. The range contains two 3D vectors defining a bounding box.
  
 
{| class="wikitable"
 
{| class="wikitable"
! Offset
+
! Offset !! Size !! Type !! Description
! Size
 
! Description
 
 
|-
 
|-
| 0x00
+
| 0x00 || 12 || Single[3] || '''Center''' 3D position (X,Y,Z float).
| 12
 
| {{Unknown|Seems to be a '''center''' 3D position (X,Y,Z float).}}
 
 
|-
 
|-
| 0x0C
+
| 0x0C || 12 || Single[3] || '''Extent''' from the center position (X,Y,Z float).
| 12
 
| '''Maximum''' 3D position (X,Y,Z float).
 
 
|-
 
|-
| 0x18
+
| 0x18 || colspan="3" {{Unknown|End of Range}}
| colspan="2" {{Unknown|End of Range}}
 
 
|}
 
|}
 +
 +
Note that in older BFRES versions, the vectors specify minimum and maximum points of the bounding boxes rather than center and extent.
  
 
==== Indices ====
 
==== Indices ====
  
 
The '''Visibility Group Tree Index''' array is an array of 16 bit values which appear to be the index of the leaf node of the '''Visibility Group Tree''' which contains the corresponding '''[[#Visibility Group|Visibility Group]]'''. Therefore this array has length equal to the number of [[#Visibility Group|Visibility Group]]s in the '''FSHP''' section.
 
The '''Visibility Group Tree Index''' array is an array of 16 bit values which appear to be the index of the leaf node of the '''Visibility Group Tree''' which contains the corresponding '''[[#Visibility Group|Visibility Group]]'''. Therefore this array has length equal to the number of [[#Visibility Group|Visibility Group]]s in the '''FSHP''' section.
 
== Parameter ==
 
 
A '''Parameter''' is an 0x0C byte structure which describes the value of some model parameter. It is only used in a handful of [[Mario Kart 8]] models to set the value of "ParticleLimit". A '''Parameter''' structure is referenced by the '''Parameter index group''' in the '''[[#Header (FMDL)|FMDL Header]]'''.
 
 
{| class="wikitable"
 
! Offset
 
! Size
 
! Description
 
|-
 
| 0x00
 
| 4
 
| '''Variable Name''' offset.
 
|-
 
| 0x04
 
| 2
 
| {{Unknown|'''Unknown''' always '''1'''.}}
 
|-
 
| 0x06
 
| 2
 
| {{Unknown|'''Unknown''' always '''0'''.}}
 
|-
 
| 0x08
 
| 4
 
| '''Value''' of the variable (floating point).
 
|-
 
| 0x0C
 
| colspan="2" {{Unknown|End of Parameter}}
 
|}
 
  
 
[[Category:File Format]]
 
[[Category:File Format]]

Revision as of 16:56, 22 January 2018

The FMDL (caFe MoDeL) model format is a format for models which appears as a subfile of a BFRES file in the 0th file group. Typically a BFRES file has one FMDL but some have none and some have more than one.

Format

An FMDL file begins with an FMDL header. This is then followed by a number of sections pointed to by the header, many of which can occur multiple times. The purpose of these sections is described in the table below. Unless otherwise noted, all offsets in BFRES files are relative to themselves, not the beginning of the file which is more common in other formats.

Section Purpose
FVTX Describes an array of array of vertices which can have a number of attributes including position, normal, colour and texture coordinates.
FMAT Describes the properties of a surface necessary to draw it including texture information.
FSKL Describes a skeleton for the model which may be used in animations.
FSHP Selects triples of vertices from one FVTX section to draw triangles between. Also specifies the FMAT material and the FSKL attachment of the triangles.

Header (FMDL)

Every FMDL begins with an 0x30 byte FMDL header.

Offset Size Type Description
0x00 4 Char[4] "FMDL" file identifier, ASCII string.
0x04 4 Int32 File name offset (without file extension).
0x08 4 Int32 File path offset, the path of the file this data was originally created from. Stripped in Mario Kart 8 files, always pointing to an empty string at the end of the BFRES string table.
0x0C 4 Int32 FSKL offset. Offset to the FSKL Header.
0x10 4 Int32 FVTX array offset. Offset to the first element in an array of FVTX Headers.
0x14 4 Int32 FSHP index group offset. Offset to an index group which contains named pointers to FSHP Headers.
0x18 4 Int32 FMAT index group offset. Offset to an index group which contains named pointers to FMAT Headers.
0x1C 4 Int32 User Data index group offset. It is only used in a handful of Mario Kart 8 models to set the value of "ParticleLimit".
0x20 2 UInt16 FVTX count: number of FVTX sections in the FVTX array.
0x22 2 UInt16 FSHP count: number of FSHP sections in the the FSHP index group.
0x24 2 UInt16 FMAT count: number of FMAT sections in the the FMAT index group.
0x26 2 UInt16 User Data entry count.
0x28 4 UInt32 Total number of vertices to process.
0x2C 4 UInt32 User pointer, can be set at runtime, 0 in files.
0x30 End of FMDL header

FVTX

The model may have one or more FVTX (caFe VerTeX) sections which describe the vertices for one polygon (e.g. the road of a track). The section describes a series of buffers and attributes. Buffers are arrays of arbitrary elements which contain the actual values of the vertices and are passed directly to the graphics card. Attributes are properties of vertices (e.g. position, texture coordinate, vertex colours) and they describe the format and layout of the elements in the buffers.

Header (FVTX)

Each FVTX section has a 0x20 byte header. These headers are stored sequentially in an array at the offset given in the FMDL header. The length of this array is also given in that header.

Offset Size Type Description
0x00 4 Char[4] "FVTX" section identifier, ASCII string.
0x04 1 Byte Attribute count: number of different attributes (position, normal, colour, etc) in the attribute array.
0x05 1 Byte Buffer count: number of attribute buffers in the buffer array.
0x06 2 UInt16 Section index: index into FVTX array of this entry.
0x08 4 UInt32 Number of vertices. This is also the number of elements in each buffer.
0x0C 1 Byte Vertex skin count, the number of bones influencing a vertex. Depending on the value, vertex positions are stored in different coordinate systems:
  • 2+ indicates smooth skinning. Coordinates are relative to the model coordinate system of a rest pose.
  • 1 indicates rigid skinning. Coordinates are relative to the local coordinate system of the bone at the index given by the blendindex0 vertex attribute.
  • 0 indicates rigid bodies using no skinning. Coordinates are relative to the local coordinate system of the bone at the index given by the FSKL Bone skin index field in the FSHP header.
0x0D 3 Padding.
0x10 4 Int32 Attribute array offset. Offset to the first element in the Attribute array.
0x14 4 Int32 Attribute index group offset. Named pointers to the members of the Attribute array to allow named lookups.
0x18 4 Int32 Buffer array offset. Offset to the first element in the Buffer array.
0x1C 4 UInt32 User pointer, can be set at runtime, 0 in files.
0x20 End of FVTX header

Attributes

The attributes of each FVTX section are stored as a simple repeating 0xc byte structure. These are stored in an array with location and length specified by the FVTX header. They are also referenced by the attribute index group, presumably to allow both index and name based lookup of attributes.

Offset Size Type Description
0x00 4 Int32 Attribute name offset (s. below).
0x04 1 Byte Buffer index in the FVTX Buffer array of the buffer storing the data of this attribute (s. below).
0x05 1 Padding.
0x05 2 UInt16 Buffer offset of the attribute in each element in the buffer (in bytes).
0x08 4 UInt32 Format of the attribute's data in the buffer, maps to GX2AttribFormat (s. below).
0x0C End of attribute

Attribute Name

Based on some of the shader code in /vol/content/mapobj/PackunMusic/PackunMusic.bfres the following naming convention seems to be used for attributes.

Attribute Name Friendly Name Description
_p0 position0 The position of the vertex.
_n0 normal0 The normal of the vertex used in lighting calculations.
_t0 tangent0 The tangent of the vertex used in advanced lighting calculations.
_b0 binormal0 The binormal of the vertex used in advanced lighting calculations.
_w0 blendweight0 Influence amount of the smooth skinning matrix at the index given in blendindex0.
_i0 blendindex0 Index of influencing smooth skinning matrix.
_u0 uv0 Texture coordinates used for texture mapping.
_u1 uv1
_u2 uv2
_u3 uv3
_c0 color0 Vertex colours used for simple shadow mapping.
_c1 color1

Buffer Index

Original files typically store all attributes into one buffer or each attribute into a separate buffer. Rarely more than 1 attribute is stored in one and remaining attributes in another buffer. The condition determining which way is chosen seems arbitrary and does not follow specific rules.

Format

The following formats are available in the GX2AttribFormat enum:

Value Format Data Min Max Description
0x0000 unorm_8 One u8 0f 1f Represents one u8 that is converted to one float.
0x0004 unorm_8_8 Two u8s 0f 1f Represents two u8 that is converted to two floats.
0x0007 unorm_16_16 Two u16s 0f 1f Represents two u16 that is converted to two floats.
0x000A unorm_8_8_8_8 Four u8 0f 1f Represents four u8 that is converted to four floats.
0x0100 uint_8 One u8 0x00 0xFF Represents one u8 that is converted to one u32.
0x0104 uint_8_8 Two u8 0x00 0xFF Represents two u8 that is converted to two u32.
0x010A uint_8_8_8_8 Four u8 0x00 0xFF Represents four u8 that is converted to four u32.
0x0200 snorm_8 One s8 -1f 1f Represents one s8 that is converted to one float.
0x0204 snorm_8_8 Two s8 -1f 1f Represents two s8 that is converted to two floats.
0x0207 snorm_16_16 Two s16 -1f 1f Represents two s16 that is converted to two floats.
0x020A snorm_8_8_8_8 Four s8 -1f 1f Represents four s8 that is converted to four floats.
0x020B snorm_10_10_10_2 Three s10 -1f 1f Represents three s10 that is converted to three floats. The top two bits are always 0b01.
0x0300 sint_8 One s8 Represents one s8.
0x0304 sint_8_8 Two s8 Represents two s8.
0x030A sint_8_8_8_8 Four s8 Represents four s8.
0x0806 float_32 One float Represents one 32 bit floating point number.
0x0808 float_16_16 Two halfs Represents two 16 bit floating point numbers that is converted to two floats.
0x080D float_32_32 Two floats Represents two 32 bit floating point numbers.
0x080F float_16_16_16_16 Four halfs Represents four 16 bit floating point numbers that is converted to four floats.
0x0811 float_32_32_32 Three floats Represents three 32 bit floating point numbers.
0x0813 float_32_32_32_32 Four floats Represents four 32 bit floating point numbers.

Buffers

The buffers of each FVTX section are stored as a repeating 0x18 byte header structure which references the actual data stored later in the BFRES file. The headers are stored in an array with location and length specified by the FVTX header.

Offset Size Type Description
0x00 4 UInt32 Data pointer filled at runtime, always 0 in files.
0x04 4 UInt32 Size of the buffer in bytes.
0x08 4 UInt32 Buffer handle, filled at runtime, always 0 in files.
0x0C 2 UInt16 Stride, the size of each element in the buffer (always 0 for index buffers).
0x0E 2 UInt16 Buffering count, always 1. Multiplicator for the number of bytes reserved as buffer data at runtime.
0x10 4 UInt32 Context pointer filled at runtime as a pointer to GX2StreamOutContext, always 0 in files.
0x14 4 Int32 Data offset.
0x18 End of buffer

FMAT

The model may have one or more FMAT (caFe MATerial) sections which describe surface properties of a polygon such as textures. Every polygon is rendered using a vertex shader and a fragment shader. A geometry shader is optional. These are pieces of code which run on the GPU. Like any code, these have parameters which is principally what the FMAT section controls. There are many different ways for the FMAT section to set variables in the shader code. All shader parameters are either uniforms or attributes. Attribute parameters vary per vertex or pixel, whereas uniform parameters are global. The FMAT must specify values for all uniform parameters, and specifies a mapping between vertex attributes in the corresponding FVTX sections and attribute parameters for both the fragment and vertex shader. In Mario Kart 8 the shader file is called Turbo_UBER. The name is the same for most files but the rendering code varies. All shaders are generic and has many parameters to configure. A GLSL shader for a shader file is available in /vol/content/mapobj/PackunMusic/PackunMusic.bfres.

Header (FMAT)

Every FMAT begins with an 0x4C byte header structure. This references the other structures documented here to describe the material.

Offset Size Type Description
0x00 4 Char[4] "FMAT" section identifier, ASCII string.
0x04 4 Int32 Material name offset.
0x08 4 UInt32 Material flags. Only bit 0 has a meaning, controlling the visibility of the material (visible if set).
0x0C 2 UInt16 Section index of this material.
0x0E 2 UInt16 Render info parameter count. Number of elements in the Render Info Parameter index group.
0x10 1 Byte Texture Reference count. Number of elements in Texture Reference array.
0x11 1 Byte Texture Sampler count. Number of elements in the Texture Sampler array. Always equal to the number of elements in the Texture Selector array.
0x12 2 UInt16 Material Parameter count. Number of elements in the Material Parameter array.
0x14 2 UInt16 Volatile Parameter count. Number of parameters handled as volatile, unknown purpose.
0x16 2 UInt16 Material Parameter data length. The size of the Material Parameter Data section in bytes.
0x18 2 UInt16 Raw Parameter data length, unknown purpose.
0x1A 2 UInt16 User Data entry count. User data in FMAT sections is apparently used to assign values to a shadow variable in the shader code. Shadow variables are always uniform variables.
0x1C 4 Int32 Render Info Parameter index group offset. Offset to the index group defining render info parameters.
0x20 4 Int32 Render State offset. Offset to the render state structure.
0x24 4 Int32 Shader Assign offset. Offset to the shader assign structure.
0x28 4 Int32 Texture Reference array offset. Each element points to FTEX file names and FTEX headers.
0x2C 4 Int32 Texture Sampler offset. Offset to the first element in the Texture Sampler array.
0x30 4 Int32 Texture Sampler index group offset. Offset to an index group which references the Texture Sampler array, to allow named value lookups.
0x34 4 Int32 Material Parameter array offset. Offset to the first element in the Material Parameter array.
0x38 4 Int32 Material Parameter index group offset. Offset to an index group which references the Material Parameter array, to allow named value lookups.
0x3C 4 Int32 Material Parameter data offset. Offset to the beginning of the values for Material Parameters. The Material Parameter array references this data.
0x40 4 Int32 User Data index group offset.
0x44 4 Int32 Volatile Flags data offset. Points to an array of Ceil((Material Parameter count) / 8) bytes, representing bits determining if a parameter is volatile. Unknown purpose.
0x48 4 Int32 User pointer, can be set at runtime, 0 in files.
0x4C End of FMAT Header

Render Info Parameter

A Render Info Parameter is a repeating structure of at least 0x08 bytes, each of which describes an array of values to assign to a render info variable in the shader code. Render info variables are always uniform variables and are used to set how the shader should render the graphics. The Render Info Parameter structures are referenced by the Render Info Parameter index group in the corresponding FMAT Header.

Offset Size Type Description
0x00 2 UInt16 Array length, number of elements in the array. Always 0 or 1 in Mario Kart 8 files.
0x02 1 Byte Type of each array element.
Type Element Size Element Type
0 8 Vector of 2 signed integers.
1 8 Vector of 2 floats.
2 4 Offset to a string.
0x03 1 Padding.
0x04 4 Int32 Variable name offset.
0x08 Varies Varies Array data.
Varies End of Render Info Parameter

Texture Sampler

A Texture Sampler is a repeating 0x18 byte structure each of which is used to assign a texture to the shader. The length and position of the Texture Sampler array is specified by the corresponding FMAT Header.

Offset Size Type Description
0x00 4 UInt32 First value of GX2Sampler structure. Bits packed as xxxJJJxx IIHHHGGF FxEExDDC CCBBBAAA.
  • AAA maps to GX2TexClamp (line 880 here) and sets the clamping / repetition of the texture on the U axis.
  • BBB maps to GX2TexClamp (line 880 here) and sets the clamping / repetition of the texture on the V axis.
  • CC C maps to GX2TexClamp (line 880 here) and sets the clamping / repetition of the texture on the W axis (for 3D textures).
  • DD maps to GX2TexXYFilterType (line 910 here) and sets the texture filtering on the U and V axes when the texture is drawn larger than the actual texture's resolution.
  • EE maps to GX2TexXYFilterType (line 910 here) and sets the texture filtering on the U and V axes when the texture is drawn smaller than the actual texture's resolution.
  • F F maps to GX2TexZFilterType (line 920 here) and sets the texture filtering on the W axis (for 3D textures).
  • GG maps to GX2TexMipFilterType (line 931 here) and sets the texture filtering for mipmaps.
  • HHH maps to GX2TexAnisoRatio (line 976 here) and controls the maximum anisotropic filtering level to use.
  • II maps to GX2TexBorderType (line 896 here) and determines what color to draw at places not reached by a texture if the clamp mode does not repeat it.
  • JJJ maps to GX2CompareFunction (line 105 here) and sets the depth comparison function.
0x04 4 UInt32 Second value of GX2Sampler structure. Bits packed as CCCCCCCC CCCCBBBB BBBBBBAA AAAAAAAA.
  • AA AAAAAAAA is a 10-bit floating point value controlling the minimum LOD level.
  • BBBB BBBBBB is a 10-bit floating point value controlling the maximum LOD level.
  • CCCCCCCC CCCC is a 12-bit floating point value controlling the LOD bias.

10-bit values are stored unsigned. To get a float value, divide it by 64. 12-bit values are stored signed. To get the float value, divide the signed value by 64. 10-bit values have a range between 0 – 32 and 12-bit values have a range between -32 – 31.984375.

0x08 4 UInt32 Third value of GX2Sampler structure. Bits packed as xAxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx.
  • A is a boolean controlling whether depth comparison is enabled. This should never be set on a real console.
0x0C 4 UInt32 Handle of the sampler, set at runtime.
0x10 4 Int32 Attribute name offset.
0x14 1 Byte Index of this element.
0x15 3 Padding.
0x18 End of Texture Sampler

Based on the some of the shader code in /vol/content/mapobj/PackunMusic/PackunMusic.bfres the following naming convention seems to be used for texture attributes.

Attribute Name Friendly Name Description
_a0 albedo0 Ordinary colour textures for surface albedo.
_a1 albedo1
_a2 albedo2
_a3 albedo3
_n0 normal0 Normal map texture for altering surface normals.
_n1 normal1
_s0 specular0 Specular highlight texture.
_e0 emission0 Emissive lighting texture.
_b0 bake0 Bake textures.
_b1 bake1

Material Parameter

A Material Parameter is a repeating 0x14 byte structure each of which describes the value to assign to a uniform variable in the shader code. The length and position of the Material Parameter array is controlled by the corresponding FMAT Header.

Offset Size Type Description
0x00 1 Byte Type of the variable (s. below).
0x01 1 Byte Size of the value in bytes.
0x02 2 UInt16 Offset relative to the start of the Material Parameter Data section to the value.
0x04 4 Int32 Uniform variable offset, set at runtime, always -1 in files.
if BFRES version >= 3.4.0.0
0x08 4 UInt32 Conversion callback pointer, set at runtime, always 0 in files.
0x0C 2 UInt16 Parameter index into the Material Parameter array.
0x0E 2 UInt16 Same value as Parameter index again.
0x10 4 Int32 Variable name offset.
if BFRES version = 3.3.X.X
0x08 4 UInt32 Conversion callback pointer, set at runtime, always 0 in files.
0x0C 2 UInt16 Parameter index into the Material Parameter array.
0x0E 2 UInt16 Same value as Parameter index again.
0x10 4 Int32 FMAT offset.
0x14 4 Int32 Variable name offset.
if BFRES version < 3.3.0.0
0x08 4 Int32 Variable name offset.

The Type field can be one of the following:

Type Size Description
0 4 1 boolean value.
1 8 2-component boolean vector.
2 12 3-component boolean vector.
3 16 4-component boolean vector.
4 4 1 signed integer value.
5 8 2-component signed integer vector.
6 12 3-component signed integer vector.
7 16 4-component signed integer vector.
8 4 1 unsigned integer value.
9 8 2-component unsigned integer vector.
10 12 3-component unsigned integer vector.
11 16 4-component unsigned integer vector.
12 4 1 floating point value.
13 8 2-component floating point vector.
14 12 3-component floating point vector.
15 16 4-component floating point vector.
17 16 2×2 floating point matrix.
18 24 2×3 floating point matrix.
19 32 2×4 floating point matrix.
21 24 3×2 floating point matrix.
22 36 3×3 floating point matrix.
23 48 3×4 floating point matrix.
25 32 4×2 floating point matrix.
26 48 4×3 floating point matrix.
27 64 4×4 floating point matrix.
28 20 2D SRT data.
Offset Size Type Description
0x00 8 Single[2] XY scaling
0x08 4 Single Rotation
0x0C 8 Single[2] XY translation
29 36 3D SRT data.
Offset Size Type Description
0x00 12 Single[3] XYZ scaling
0x0C 12 Single[3] XYZ rotation
0x18 12 Single[3] XYZ translation
30 24 Texture SRT data.
Offset Size Type Description
0x00 4 UInt32 SRT mode
  • 0 specifies Maya SRT method.
  • 1 specifies 3ds Max SRT method.
  • 2 specifies Softimage SRT method.
0x04 8 Single[2] XY scaling
0x0C 4 Single Rotation
0x10 8 Single[2] XY translation
31 28 Texture SRT data which is then multiplied by a 3x4 matrix referenced by the matrix pointer. The structure is the same as above, but with a field added to store the pointer to the matrix in at runtime:
Offset Size Type Description
0x18 4 UInt32 3x4 matrix pointer, set at runtime.

Matrices are encoded down columns then along rows, so a 2×3 identity matrix would be encoded 1, 0, 0, 1, 0, 0.

Render State

A Render State structure is a 0x30 byte structure controlling if and how polygons are drawn. The structure is referenced by the corresponding FMAT Header.

Offset Size Type Description
0x00 4 UInt32 Flags. Controls how polygons are affecting the depth buffer and how they are blended / composed. A mode and blend value have to be combined to form valid flags.
Type Bits (0-based) Description
Mode - Custom
Mode 0 Opaque
Mode 1 Alpha Mask
Mode 0 & 1 Translucent
Blend - None
Blend 4 Color
Blend 5 Logical
0x04 4 UInt32 Polygon control, maps to GX2PolygonControlReg, a bitset packed as xxxxxxxx xxxxxxxx xxIHGFFF EEEDDCBA. Beyond other features, it most prominently controls culling and cull order of polygons.
  • A controls whether front faces are culled.
  • B controls whether back faces are culled.
  • C maps to GX2FrontFaceMode and determines the order in which vertices have to form the triangle to be handled as a front rather than back face. The order can be clockwise (1) or counter-clockwise (0).
  • DD configures whether polygons are drawn at all (1) or not (0)
  • EEE maps to GX2PolygonMode and determines how front facing polygons are drawn. This can be set to draw only points (0), lines (1) or full triangles (2).
  • FFF is the same as EEE, but for back facing polygons.
  • G configures polygon depth offsets for front facing polygons (useful to create decals without Z fighting).
  • H is the same as G but for back facing polygons.
  • I is the same as G but for lines and points.
0x08 4 UInt32 Depth control, maps to GX2DepthStencilControlReg, a bitset packed as MMMLLLKK KJJJIIIH HHGGGFFF EDDDxCBA. Controls depth and stencil buffer value comparison and action before writing new data to buffers.
  • A controls whether stencil testing is enabled (1) or not (0).
  • B controls whether depth testing is enabled (1) or not (0).
  • C controls whether writing to the depth buffer is enabled (1) or not (0).
  • DDD maps to GX2CompareFunction and configures when a fragment is allowed to overwrite the old value in the depth buffer with a new one (the depth buffer comparison function) (line 105 here).
  • E controls whether back faces can write to the stencil buffer (1) or not (0).
  • FFF controls the front face stencil buffer comparison function, maps to GX2CompareFunction aswell (s. DDD).
  • GGG maps to GX2StencilFunction and configures what to do with the existing stencil value when the stencil comparison function fails for front facing polygons (line 121 here).
  • HH H is the same as GGG, but taking effect when the stencil test passes with the depth buffer.
  • III is the same as GGG, but taking effect when the stencil test fails with the depth buffer.
  • JJJ is the same as FFF, but for back faces.
  • K KK is the same as GGG, but taking effect when the stencil test fails for back faces.
  • LLL is the same as GGG, but taking effect when the stencil test passes for back faces with the depth buffer.
  • MMM is the same as GGG, but taking effect when the stencil test fails for back faces with the depth buffer.
0x0C 8 UInt32 / Single Alpha test, maps to GX2AlphaTestReg, a structure of an unsigned integer and a floating point value. Controls how alpha colors are written to buffers. The unsigned integer is a bitset packed as xxxxxxxx xxxxxxxx xxxxxxxx xxxxBAAA.
  • AAA maps to GX2CompareFunction and determines when alpha fragments should be written.
  • B determines whether alpha testing is enabled at all (line 105 here).

Floating point reference value always less than 1.0f in Mario Kart 8 files.

0x14 4 UInt32 Color control, maps to GX2ColorControlReg, a bitset packed as xxxxxxxx DDDDDDDD CCCCCCCC xBBBxxxA. Controls how colors are written to buffers.
  • A controls whether multiwrites are enabled (1) or not (0).
  • BBB controls a special operation and is used to enable a color buffer with unknown purpose.
  • CCCCCCCC controls the bitmask used for blending.
  • DDDDDDDD maps to GX2LogicOp and determines the ROP3 color logic operation (line 161 here)

Defaults to Copy operation and nothing else enabled. Some files set a bitmask of 00000001.

0x18 8 UInt32[2] Blend control, maps to GX2BlendControlReg, a structure of two unsigned integers. Controls how and to which target blending is performed. The first unsigned integer describes the target index (always 0 in Mario Kart 8 files), the second is a bitset packed as xxGFFFFF EEEDDDDD xxxCCCCC BBBAAAAA.
  • AAAAA maps to GX2BlendFunctionand sets the color source blend operation (line 189 here).
  • BBB maps to GX2BlendCombine and sets the color combine operation (line 231 here).
  • CCCCC is the same as AAAAA but sets the color destination blend operation.
  • DDDDD is the same as AAAAA, but sets the alpha source blend operation.
  • EEE is the same as BBB, but sets the alpha combine operation.
  • FFFFF is the same as AAAAA, but sets the alpha destination blend operation.
  • G apparently controls whether to separate the alpha from color blending.

Blend value always 0x20010101, 0x20010104, 0x20010501 or 0x20010504 in Mario Kart 8 files.

0x20 16 Single[4] Blend color, maps to GX2BlendConstantColorReg. Controls the blend color as 4 RGBA floating point values.

Defaults to (0f, 0f, 0f, 0f).

0x30 End of Render State

Shader Assign

A Shader Assign structure is a 0x1C byte structure which describe the shader to be used by a material. A Shader Assign structure is referenced by the corresponding FMAT Header.

Offset Size Type Description
0x00 4 Int32 Shader archive name offset.
0x04 4 Int32 Shading model name offset.
0x08 4 UInt32 Revision. Apparently unused, always 0 or 1.
0x0C 1 Byte Vertex Shader Input count. Number of elements in the Vertex Shader Input index group.
0x0D 1 Byte Fragment Shader Input count. Number of elements in the Fragment Shader Input index group.
0x0E 2 UInt16 Parameter count. Number of elements in the Parameter index group.
0x10 4 Int32 Vertex Shader Input index group offset. Offset to the index group which forms a mapping between strings, mapping an FVTX attribute to a vertex shader variable. Normally the names are always the same in Mario Kart 8, so this mapping is just ["_p0": "_p0", "_n0": "_n0", ...]?
0x14 4 Int32 Fragment Shader Input index group offset. Offset to the index group which forms a mapping between strings, mapping an FVTX attribute to a fragment shader variable. Normally the names are always the same in Mario Kart 8, so this mapping is just ["_p0": "_p0", "_n0": "_n0", ...]?
0x18 4 Int32 Parameter index group offset. Offset to the index group which forms a mapping between strings, mapping a uniform shader variable to a value. The values are always strings, even for numeric parameters. The values are used to specify the shader program used for rendering.
0x1C End of Shader Assign

FSKL

Each model has one FSKL (caFe SKeLeton) section which describes one or more bones. The bones form a skeleton and give a transformation to apply to any attached polygon. Every FSHP polygon is attached to at least one bone. The FSKL format is somewhat different in BFRES files with values other than 0x03040004 after the FRES identifier, which may indicate an alternative version of the format. These are rare in Mario Kart 8 and not documented here.

Header (FSKL)

The FSKL section always starts with an 0x24 byte header. The location of this header is given by the offset in the FMDL header.

Offset Size Type Description
0x00 4 Char[4] "FSKL" section identifier, ASCII string.
0x04 4 UInt32 Flags. Controls how scaling and rotation is performed. Encoded as xxxxxxxx xxxxxxxx xxxRxxSS xxxxxxxx bits.
  • SS specifies how the bone matrix is calculated:
Value Description
0 No scaling
1 Standard scaling. Results in a "default" scaling method.
2 Maya scaling. Respects Maya's segment scale compensation which offsets child bones rather than scaling them with the parent.
3 Softimage scaling. Respects the scaling method of Softimage.
  • R controls the rotation mode, either euler XYZ rotation (bit set) or quaternion (bit unset).

Always 0x00001100 (standard scaling & euler XYZ rotation) or 0x00001200 (Maya scaling & euler XYZ rotation) in Mario Kart 8 files.

0x08 2 UInt16 Bone array count. Number of elements in the Bone array.
0x0A 2 UInt16 Smooth Index array count. Number of elements in the Smooth Matrix array for smooth skinning (shape vertices are influenced by multiple bones).
0x0C 2 UInt16 Rigid Index array count. Number of elements in the Rigid Matrix array at the end of the Smooth Index array for rigid skinning (shape vertices are influenced by a single bone).
0x0E 2 Padding.
0x10 4 Int32 Bone index group offset. Named pointers to the members of the Bone array to allow named lookups.
0x14 4 Int32 Bone array offset. Offset to the first element in the Bone array.
0x18 4 Int32 Smooth Index array offset. Offset to the first element in the Smooth Index array. Always given even if the array is empty.
0x1C 4 Int32 Smooth Matrix array offset. Offset to the first element in the Smooth Matrix array. Always given even if the array is empty.
0x20 4 UInt32 User pointer, can be set at runtime, 0 in files.
0x24 End of FSKL header

Bone

A Bone is a repeating 0x40 byte structure which descibes a transformation to apply to a polygon. Each bone has up to four parents, which form a tree called a skeleton. To compute the final transformation of a point, apply the transformation required by the bone it is attached to, then that bone's parent recursively up until no parents remain. The Bone tree is stored as an array with offset and length specified by the FSKL header.

Offset Size Type Description
0x00 4 Int32 Name offset for this bone.
0x04 2 UInt16 Bone index of this bone into the bone array.
0x06 2 UInt16 Parent index of the parents to this bone. 0xFFFF for no parent.
0x08 2 Int16 Smooth Matrix index to reverse the transformation of this bone. -1 for no smooth matrix.
0x0A 2 Int16 Rigid Matrix index with unknown purpose. -1 for no rigid matrix.
0x0C 2 Int16 Billboard index to control how billboarded bones are affected in a hierarchy. -1 if no billboarded bones are affected.
0x0E 2 UInt16 User Data entry count.
0x10 4 UInt32 Flags, encoded as CCCCTTTT TxxxxBBB xxxRxxxx xxxxxxxV bits.
  • V controls the visibility of the influenced shape.
  • R controls the rotation mode, either euler XYZ rotation (bit set) or quaternion (bit unset).
  • BBB controls how billboarded bones are projected:
Value Description
0 No billboarding. The influenced shape is not transformed for billboarding.
1 Child billboarding.
2 World View Vector. The Z axis is parallel to the camera.
3 World View Point. The Z axis is equal to the direction the camera is pointing to.
4 Screen View Vector. The Z axis is parallel to the camera, the Y axis is equal to the up vector of the camera.
5 Screen View Point. The Z axis is equal to the direction the camera is pointing to, the Y axis is equal to the up vector of the camera.
6 Y-Axis View Vector. The Z axis has been made parallel to the camera view by rotating the Y axis.
7 Y-Axis View Point. The Z axis has been made equal to the direction the camera is pointing to by rotating the Y axis.
  • T TTTT are combinable flags controlling how bones are transformed.
Value Description
1 Segment scale compensation. Set for bones scaled in Maya whose scale is not applied to child bones.
2 Scale uniformly.
4 Scale volume by 1.
8 No rotation.
16 No translation.
  • CCCC controls the same but for a hierarchy of bones.
Value Description
1 Scale uniformly.
2 Scale volume by 1.
4 No rotation.
8 No translation.

Always 0x00001001 (visible & euler XYZ rotation) in Mario Kart 8 files.

0x14 12 Single[3] Scale Vector 3 floats. The amount to scale the vertices by.
0x20 16 Single[4] Rotation Vector, either stored as euler rotation (X, Y, Z in radians) or a quaternion, depending on the bone Flags. Mario Kart 8 always uses euler XYZ rotation, so the last float is always set to 1f.
0x30 12 Single[3] Translation Vector 3 floats. The amount to translate the vertices by.
0x3C 4 Int32 User Data index group offset. Never used in Mario Kart 8 FSKL sections and thus 0.
0x40 End of Bone

Smooth Matrix

The FSKL may specify an Smooth Matrix for any Bone. It does this by creating an entry in the Inverse Index array which is the index of the bone, and in the corresponding place in the Smooth Matrix array it places a 4×3 transformation matrix which reverses the full transformation of the bone and all its parents. Smooth Matrices are optional, it is Unknown if they are ever referenced. The position of and number of elements in the Smooth Matrix array and the Smooth Index array are given in the FSKL Header.

Rigid Matrix

At the end of the Smooth Index array are a number of indices for Rigid Matrices, which have Unknown purpose. The number of such Rigid Matrices is also present in the FSKL Header.

FSHP

The model may have one or more FSHP (caFe SHaPe) sections which describe the one polygon (e.g. the road of a track). The FSHP section consists of an 0x40 byte header, which references an FVTX section and indices of the polygons to draw. A basic FSHP amounts to a list of indices into the corresponding FVTX indicating which points to draw triangles between. The FSHP also references an FMAT to describe the material of the triangles, and an FSKL to indicate the bone structure of the model used in animation.

The triangles in an FSHP are organised by two systems; LoD Models and Visibility Groups. No model in Mario Kart 8 uses both of these features non-trivially simultaneously. LoD stands for Level of Detail, which is a standard performance technique used across many 3d rendering systems. Each LoD model is a simpler version of the one before it, with extraneous triangles removed, and finer detail simplified. As the camera in the game moves away from a polygon, the simpler version of the model is rendered instead, which should look the same as the fine detailed version at a distance. A trivial polygon will only have one LoD model, which will be rendered no matter what distance the camera is. Separately, the Visibility Group system allows parts of the model to not be rendered if they are off-screen. This allows an polygon which is partially off-screen to be rendered faster, by skipping the off-screen components. A trivial polygon will only have one Visibility Group, which will always be rendered.

Header (FSHP)

Every FSHP begins with an 0x40 byte header. This references other data structures which describe the polygon.

Offset Size Type Description
0x00 4 Char[4] "FSHP" section identifier, ASCII string.
0x04 4 Int32 Polygon name offset.
0x08 4 UInt32 Flags with only the following meaning:
Bit (0-based) Description
1 Has vertex buffer.

Always set (thus 2) in Mario Kart 8 files.

0x0C 2 UInt16 Section index.
0x0E 2 UInt16 FMAT index. Index of the material for this polygon.
0x10 2 UInt16 FSKL index of the bone for this polygon.
0x12 2 UInt16 FVTX index of the vertex buffer this polygon uses.
0x14 2 UInt16 FSKL Bone skin index. Specifies the index of the bone to which local coordinate matrix vertices are relative in case of rigid bodies using no skinning.
0x16 1 Byte Vertex skin count, the number of bones influencing a vertex. Depending on the value, vertex positions are stored in different coordinate systems:
  • 2+ indicates smooth skinning. Coordinates are relative to the model coordinate system of a rest pose.
  • 1 indicates rigid skinning. Coordinates are relative to the local coordinate system of the bone at the index given by the blendindex0 vertex attribute.
  • 0 indicates rigid bodies using no skinning. Coordinates are relative to the local coordinate system of the bone at the index given by the FSKL Bone skin index field.
0x17 1 Byte LoD Model count. Number of elements in the array.
0x18 1 Byte Key Shape count. This feature is not used in Mario Kart 8, thus always 0.
0x19 1 Byte Target Attribute count. This feature is not used in Mario Kart 8, thus always 0.
0x1A 2 UInt16 Visibility Group Tree Node count.
0x1C 4 Single Radius of spherical bounding box.
0x20 4 Int32 FVTX offset to the vertex buffer for this polygon.
0x24 4 Int32 LoD Model offset. Offset to the first element in the array.
0x28 4 Int32 FSKL Index array offset. Each element of this array is a 16 bit index.
0x2C 4 Int32 Key Shape index group offset. Never used in Mario Kart 8 and thus 0.
0x30 4 Int32 Visibility Group Tree Nodes offset.
0x34 4 Int32 Visibility Group Tree Ranges offset.
0x38 4 Int32 Visibility Group Tree Indices offset.
0x3C 4 UInt32 User pointer, can be set at runtime, 0 in files.
0x40 End of FSHP header

LoD Model

A LoD Model is a repeating 0x1C byte structure which are stored in a sequential array with location and size specified by the FSHP Header. Their purpose is described at the beginning of this section.

Offset Size Type Description
0x00 4 UInt32 Primitive Type, maps to GX2PrimitiveType (line 527 here). Determines how index lists are interpreted to form triangles.

Always GX2_PRIMITIVE_TRIANGLES (thus 4) in Mario Kart 8 files.

0x04 4 UInt32 Index Format, maps to GX2IndexFormat (line 515 here). The data type of indices.

Always GX2_INDEX_FORMAT_U16 (thus 4) in Mario Kart 8 files.

0x08 4 UInt32 Count of points drawn in all Visibility Groups, thus the maximum number of points drawn at this LoD.
0x0C 2 UInt16 Visibility Group count. The number of elements in the array.
0x0E 2 Padding.
0x10 4 Int32 Visibility Group offset to the first element in the array.
0x14 4 Int32 Index Buffer offset.
0x18 4 UInt32 Skip vertices, the number of elements to skip in the corresponding FVTX buffer.
0x1C End of LoD Model

Visibility Group

A Visibility Group is a repeating 0x08 byte structure describing an offset and a count in the corresponding Index Buffer. Visibility Groups are stored in a sequential array with location and count indicated by the corresponding LoD Model. This allows multiple visibility groups to use the same Index Buffer. In many cases, a single group is used which simply draws the entire Index Buffer.

Offset Size Type Description
0x00 4 UInt32 Offset into index buffer in bytes.
0x04 4 UInt32 Count of the points to draw.
0x08 End of Visibility Group

Index Buffer

An Index Buffer is an 0x18 byte structure which describes a list of values (of type as given in the header) which are used to index the FVTX section when drawing the polygon. Index Buffers are referenced by LoD Models. They are instances of the same structure as FVTX Buffers and thus have the same layout.

Visibility Group Tree

The Visibility Group Tree is some sort of tree structure that occurs in all FSHP sections. In all Mario Kart 8 files, when the FSHP has multiple LoD Models, the Visibility Group Tree is a trivial one node tree. The Visibility Group Tree is used to control which Visibility Groups need to be drawn as described at the beginning of this section. The workings of the structure are however unknown.

Nodes

The Visibility Group Tree Node is a repeating 0x0C byte structure. The nodes form a binary tree. The FSHP header contains a pointer to node array, as well as specifying its length. The root node is the first node in this array. Each node specifies a range of Visibility Groups, with the root node always covering all nodes, and the children of each node always selecting disjoint subsets of that node's range.

Offset Size Description
0x00 2 Left child index. The current node's index if it has no left child.
0x02 2 Right child index. The current node's index if it has no right child.
0x04 2 Unknown, always the same as Left child index.
0x06 2 Next sibling index. For left children, always the current node's parent's right child (the current node's index if it has no right child).
0x08 2 Visibility Group index selects a range of Visibility Groups along with the count.
0x0A 2 Visibility Group count selects a range of Visibility Groups along with the index.
0x0C End of Node

Ranges

The Visibility Group Tree Range is a repeating 0x18 byte structure. There are exactly as many Ranges as Nodes. The range contains two 3D vectors defining a bounding box.

Offset Size Type Description
0x00 12 Single[3] Center 3D position (X,Y,Z float).
0x0C 12 Single[3] Extent from the center position (X,Y,Z float).
0x18 End of Range

Note that in older BFRES versions, the vectors specify minimum and maximum points of the bounding boxes rather than center and extent.

Indices

The Visibility Group Tree Index array is an array of 16 bit values which appear to be the index of the leaf node of the Visibility Group Tree which contains the corresponding Visibility Group. Therefore this array has length equal to the number of Visibility Groups in the FSHP section.