Mod Authors - hakasapl/PGPatcher GitHub Wiki

This page will describe best practices for mod authors packaging their mods to work nicely with PG.

General

File Naming

Always use standard naming conventions for your textures. The following table shows standard conventions for different texture types:

Texture Type Suffix
Diffuse _d.dds or .dds
Normal _n.dds
Model Space Normal _msn.dds
Glow _g.dds
Skin Tint _sk.dds
Height _p.dds
Environment / Cubemap _e.dds
Environment Mask / Complex Material _m.dds, _em.dds, _envmask.dds
RMAOS _rmaos.dds
Fuzz _f.dds
Inner Layer _i.dds
Subsurface Tint _s.dds
Coat Normal Roughness _cnr.dds
Backlight _b.dds, _bl.dds

Packaging

The PG compatible variant of your mod should not contain:

  • Any meshes except those that are custom made for a specific texture (for geometry and UV mapping, not for shader type)
    • Including meshes that could otherwise be patched can prevent users from using the meshes they want.
  • Any plugins that modify TXST or MODL records
    • PG will NOT patch a specific mesh if the user specifies that a non-special-shader mod (not Parallax, CM, or PBR) has higher priority than a special shader mod. This is intended to allow the user to use vanilla mods mixed with special shader mods. If the mod author includes edits to TXST records, it will be left alone and there would be a mismatch between the shader in the mesh and what the actual textures reflect. This is particularly important for PBR.

The mod author could include an optional file on their page that includes the above items if the mod author would like to support non-PG users as well. It is better and cleaner for the users to keep these files separate so PG users do not have to download the extra file.

NOTE: Landscape and decal mods are an exception to the above since landscape isn't meshes. I don't think a user would want a different mod running their dirtcliffs than their landscapes so the above rules can be ignored for landscape mods.

Specific Materials

This section describes instructions for specific materials.

Parallax

Parallax doesn't need anything special, just make height maps and follow correct naming conventions for them.

Complex Material

Some guidelines to follow for Complex Material mods:

  • Follow standard naming conventions (_m.dds) preferred
  • PG will apply a dynamic cubemap on anything CM, keep that in mind while developing your mod
  • PG will set the environment map scale to 1.0 for every mesh patched with complex material. Adjust your texture accordingly.
  • PG will set the specular strength to 1.0 for every mesh patched with complex material. Adjust your texture accordingly.
  • PG will set specular color to white IF you have metalness (blue channel) in your texture

PBR

General rules to follow:

  • PBR texture swap JSONs should not be included in the main file if a corresponding patcher JSON exists.
  • ALL PBR textures must be prefixed with textures/pbr in their path. While it does work without doing this, PG expects this convention and won't work correctly without it.
  • DO NOT include ANY prepatched TXST records in your plugins. PG does this for you and expects existing TXST records to be non-PBR. You can still use TXST records, just don't prepatch them with PBR textures.

Because PBR has many parameters, PG cannot patch for PBR from texture information only. This is why JSON files can be created to tell PG how to patch something for PBR.

You should create a JSON file named whatever you want in the PBRNIFPatcher folder. The file should be a list of JSON objects. An example is below.

[
    {
        "texture": "fern01", "emissive": false, "parallax": false, "subsurface_foliage":false, "subsurface": false, 
        "specular_level" : 0.04, "subsurface_color": [1,1,1], "roughness_scale" : 1, "subsurface_opacity" : 1, "displacement_scale" : 1
    },
    {
        "texture": "fern02", "emissive": false, "parallax": false, "subsurface_foliage":false, "subsurface": false, 
        "specular_level" : 0.04, "subsurface_color": [1,1,1], "roughness_scale" : 1, "subsurface_opacity" : 1, "displacement_scale" : 1
    },
    {
        "texture": "mushroom01", "emissive": false, "parallax": false, "subsurface_foliage":false, "subsurface": false, 
        "specular_level" : 0.04, "subsurface_color": [1,1,1], "roughness_scale" : 1, "subsurface_opacity" : 1, "displacement_scale" : 1
    }
]

You can also define defaults which will be applied to every entry unless also defined in the entry like so:

{
"default": {
    "vertex_color_lum_mult": 1.5
},
"entries": [
    {
        "texture": "fern01", "emissive": false, "parallax": false, "subsurface_foliage":false, "subsurface": false, 
        "specular_level" : 0.04, "subsurface_color": [1,1,1], "roughness_scale" : 1, "subsurface_opacity" : 1, "displacement_scale" : 1
    },
    {
        "texture": "fern02", "emissive": false, "parallax": false, "subsurface_foliage":false, "subsurface": false, 
        "specular_level" : 0.04, "subsurface_color": [1,1,1], "roughness_scale" : 1, "subsurface_opacity" : 1, "displacement_scale" : 1
    },
    {
        "texture": "mushroom01", "emissive": false, "parallax": false, "subsurface_foliage":false, "subsurface": false, 
        "specular_level" : 0.04, "subsurface_color": [1,1,1], "roughness_scale" : 1, "subsurface_opacity" : 1, "displacement_scale" : 1
    }
]
}

NOTE: PG will NOT patch a shape if any texture set from the result of your combined JSON objects in a given match does not exist.

The following fields are available for each JSON object:

Matching Fields

Matching fields are used to match a given JSON object to an existing shape. If more than one rule matches, they will be executed sequentially in the order they are in the JSON file. PG will NOT allow matches across JSON files, only one JSON file can match a given shape.

"texture": "" or "match_diffuse": ""

Match an existing diffuse. It will match any diffuse that ends with what you specify in this field. Partial file names are not allowed, it must be at least a full file, or a path, where each component is a full filename.

"match_normal": ""

Same rules as above but match normal instead of diffuse.

"path_contains": ""

This will match any diffuse that contains the string specified in this field anywhere in the diffuse path.

"nif_filter": ""

If this field is specified, only NIFs that contain this string in their path will be patched.

General Fields

"delete": true/false

If delete: true is specified, the matching shape will be deleted from the result mesh.

"smooth_angle": true/false

Smooths the normals (and removes doubled vertices) where the angle is less extreme (flatter) than the given number in degrees, useful when sharp edges look bad with high resolution textures.

"vertex_colors": true/false

Enable or disable vertex colors, useful if the mesh used vertex colors to change the colors of the old textures

"vertex_color_lum_mult": 0.0

First convert RGB of vertex color to HSV, then apply the formula 1-(1-ORIGINAL_L)*vertex_color_lum_mult

"vertex_color_sat_mult": 0.0

First convert RGB of vertex color to HSV, then apply the formula ORIGINAL_S * vertex_color_sat_mult. Result is clamped between 0.0 and 1.0

"zbuffer_write": true/false

Apples the zbuffer_write shader flag if true

"specular_level": 0.0

Set the specular level in the shader.

"roughness_scale": 0.0

Set the roughness scale in the shader.

"auto_uv": true/false

Experimental, scales the uvs to keep the pixel density constant on average

"uv_scale": [0.0, 0.0, 0.0]

Set the UV scale for the shader.

PBR Texture Fields

By default the patcher will add textures to the set based on parameters set in the JSON. If you do not want the patcher to modify a given slot, you can use lock fields:

"lock_diffuse": true/false
"lock_normal": true/false
"lock_emissive": true/false
"lock_parallax": true/false
"lock_cubemap": true/false
"lock_rmaos": true/false
"lock_cnr": true/false
"lock_subsurface": true/false

In addition, the mod author can explicitly specify a given slot using slot commands (note that the full path must be specified for slots: textures\\PBR\\bla.dds for example):

"slot1": ""
"slot2": ""
"slot3": ""
"slot4": ""
"slot5": ""
"slot6": ""
"slot7": ""
"slot8": ""

"rename": ""

Rename can be used to rename the matching part (from match_diffuse or match_normal) of the JSON entry with the defined rename string. This will apply to all textures while preserving correct suffixes (except if lock_X is specified for any slot).

Emissive

"emissive": true/false

Enabling this will enable glow and add <prefix>_g.dds to slot 3.

"emissive_scale": 0.0

Set the emissive scale in the shader.

"emissive_color": [0, 0, 0, 0]

Set the emissive color in the shader.

Parallax

"parallax": true/false

Enabling this will enable parallax and add <prefix>_p.dds to slot 4.

"displacement_scale": 0.0

Set the displacement scale in the shader.

Subsurface

"subsurface": true/false

Enabling this will enable subsurface and add <prefix>_s.dds to slot 8

"subsurface_color": [0, 0, 0]

Set the subsurface color in the shader.

"subsurface_opacity": 0.0

Set the subsurface opacity in the shader.

Multilayer PBR

"coat_normal": true/false

Enabling this will enable multilayer PBR and add <prefix>_cnr.dds to slot 7.

"coat_strength": 0.0

Set the coat strength

"coat_roughness": 0.0

Set the coat roughness

"coat_specular_level": 0.0

Set the coat specular level

"coat_diffuse": true/false

Enabling this will add <prefix>_s.dds to slot 8

"coat_parallax": true/false

Enables parallax for inner layer

Fuzz

To enable fuzz add this:

"fuzz": {
}

Then, the following parameters are valid if used inside the fuzz JSON object.

"texture": true/false

If true, <prefix>_f.dds will be added to slot 7.

"color": [ 1, 1, 1 ]

Set fuzz color (if texture is true this is a multiplier)

"weight": 1.0

Set fuzz weight (if texture is true this is a multiplier)

Hair

"hair": true/false

Enabling this will enable the PBR hair shader.

Glint

To enable glint add this:

"glint": {
}

Then, the following parameters are valid if used inside the glint JSON object.

"screen_space_scale": 0.0

Set screen space scale for glint

"log_microfacet_density": 0.0

Set log microfacet density for glint

"microfacet_roughness": 0.0

Set microfacet roughness for glint

"density_randomization": 0.0

Set density randomization for glint

⚠️ **GitHub.com Fallback** ⚠️