Overview

A Material Target declares which material to modify and exactly what to do to it when its parent Skin Group is active on a gear. Each target lives in its own .mattarget.json file placed anywhere inside the skin group’s folder tree — the mod discovers them recursively.

For a easy way to create Material Target manifest files, check out Editing Material Targets.

Warning

Multiple Material Targets with different configurations that target the same material within the same Skin Group is undefined behavior! There is no guarantee as to which material target definition will be used. If you want to provide different versions of a gear part (say for different guns), you NEED to do so in different Skin Groups!

File Naming & Folder Structure

Files must have the extension .mattarget.json. The filename itself is free-form.

my-skin/
  manifest.skingroup.json
  rifle.mattarget.json            ← any name is fine
  details/
    scope.mattarget.json          ← nesting is fine too

Manifest Schema

{
  "material_name": "Front_Pistol_4",
  "match_groups": [ /* optional variant filter */ ], // legacy: matchGroups
  "shader": "Cell/Player/CustomGearShader", // optional shader override
  "properties": {
    "_MainTex": {
      "type": "Texture2D",
      "data": { "src": "textures/albedo.png" }
    }
  }
}

Fields

FieldTypeRequiredDescription
material_namestring✓Exact name of the material to match. Must match the in-game material name precisely (case-sensitive).
match_groupsarray of match group objects—Optional variant filter used to disambiguate materials that share a name. See Variant Matching. When absent or empty, all variants of the named material are matched.
shaderstring—If set, the material’s shader is replaced with this shader before any properties are applied.
propertiesobject (property map)—Dictionary of shader property name → property definition. See Properties.

Variant Matching

Some materials in GTFO share the same name (for example, "Spear" exists on multiple unrelated items). matchGroups lets you add additional texture-name conditions to narrow down the match.

The structure mirrors the filter system on Skin Groups: it is a DNF. The target matches when any group in matchGroups matches, and a group matches when all of its conditions match.

Each condition checks whether a specific texture slot on the material carries an expected in-game texture name:

"matchGroups": [
  {
    "conditions": [
      { "slot": "_MainTex", "value": "mat_spear_playerMain" }
    ]
  }
]

When matchGroups is empty or omitted, the target matches all variants of the material (wildcard).

Condition Object Fields

FieldTypeDescription
slotstringThe shader texture slot to inspect (e.g. _MainTex).
valuestringThe expected in-game texture name currently assigned to that slot.

Use the Select Material dialog in the SkinGroup Editor, or check the gear dump, to find and fill in the correct in-game texture names.

Properties

The properties map is keyed by shader property name (e.g. _MainTex, _Glossiness). Each value is an object with a type discriminator and a data payload:

"properties": {
  "_MainTex": { "type": "Texture2D", "data": { "src": "albedo.png" } },
  "_Glossiness": { "type": "Float",  "data": { "value": 0.5 } }
}

If a property name does not exist on the material’s current shader, or the type does not match, the property is skipped and a warning is logged — it will not cause a crash.

Property Types

Texture2D

Sets a texture slot.

{
  "type": "Texture2D",
  "data": {
    "src": "textures/albedo.png",
    "options": "Albedo"
  }
}
FieldTypeRequiredDescription
srcstring✓Path to the texture file, relative to the .mattarget.json file’s directory. Can also be a Texture Macro expression (e.g. @WHITE).
optionsstring or object—Import options. When omitted, options are inferred from the slot name automatically (see below).

Import Options

ValueLinearMipmapsUse for
"Albedo"falsetrueColor/albedo maps
"Data"truetrueNormal maps, metallic-smoothness, masks
"AlbedoNoMips"falsefalseUI / decal textures that should not be mipmapped
"DataNoMips"truefalseData maps that should not be mipmapped

You can also supply a custom object (this is the most canonical form):

"options": { "linear": true, "mipmaps": false }

When options is omitted the mod infers sensible defaults from the slot name — for example, slots containing normal or bump default to linear + no mipmaps, while color slots default to non-linear + no mipmaps. It is fine to rely on our inference for standard Unity shader slots.

Mipmaps

The base game will not create mipmaps for the custom textures that we load. To include mipmaps, set the mipmaps key to true for import options as mentioned above.


Internally we initialize textures using the provided options by calling the following

	new Texture2D(..., mipChain: options.Mipmaps, linear: options.Linear);

Special Cases

Emissive Maps

When the property name is _EmissiveMap, the mod automatically enables the ENABLE_EMISSIVE material keyword so the emissive actually renders.

Float

Sets a float or range shader property.

{
  "type": "Float",
  "data": { "value": 0.75 }
}
FieldTypeDescription
valuefloatThe float value to set.

Color

Sets a color shader property. Each channel is a float in the 0–1 range.

{
  "type": "Color",
  "data": { "r": 1.0, "g": 0.2, "b": 0.2, "a": 1.0 }
}
FieldTypeDefaultDescription
rfloat0Red channel (0–1)
gfloat0Green channel (0–1)
bfloat0Blue channel (0–1)
afloat1Alpha channel (0–1)

Vector

Sets a Vector4 shader property (commonly used for tiling/offset or custom packed data).

{
  "type": "Vector",
  "data": { "x": 2.0, "y": 2.0, "z": 0.0, "w": 0.0 }
}
FieldTypeDefaultDescription
xfloat0X component
yfloat0Y component
zfloat0Z component
wfloat0W component

Full Example

{
  "material_name": "Head_Hammer_5",
  "matchGroups": [
    {
      "conditions": [
        { "slot": "_MainTex", "value": "Head_Hammer_5_Albedo" }
      ]
    }
  ],
  "properties": {
    "_MainTex": {
      "type": "Texture2D",
      "data": { "src": "textures/albedo.png", "options": "Albedo" }
    },
    "_NormalMap": {
      "type": "Texture2D",
      "data": { "src": "textures/normal.png", "options": "Data" }
    },
    "_EmissiveMap": {
      "type": "Texture2D",
      "data": { "src": "textures/em.png" } // options inferred to be "AlbedoNoMips" for _Em
    },
    "_MetallicGlossMap": {
      "type": "Texture2D",
      "data": { "src": "@METALLIC_SMOOTHNESS(0.8,0.6)" }
    },
    "_Glossiness": {
      "type": "Float",
      "data": { "value": 0.6 }
    }
  }
}