Skip to content

Shaders

Bad Dog edited this page Nov 19, 2024 · 12 revisions

PyNifly will import and export shaders. On import, we do our best to duplicate the shader attributes in Blender, setting up a material and node tree for the shape. On export, we analyze the node tree and export the equivalent to the nif. Any attributes that don't have a Blender equivalent are stored in custom properties on the material and written out on export. You can edit them directly if you know what you're doing.

Texture files: Blender has limited support for DDS files. So when setting up shader nodes on import, it will look for PNG files to use by preference. The filepath in the nif is relative--in the game it's relative to the "textures" folder in the game directory. The importer searches for textures as follows:

  • First, it looks for a PNG file in Blender's own textures directory, which you can set up through Preferences > File Paths > Data > Textures. This should point to a folder that has a "textures" folder in it, and that is the base for the relative filepath in the nif. If there's a PNG, that's imported; if only a DDS, that is used. This is useful if you're working with nifs that are not in the game's directories, e.g. a Bodyslide nif.

  • Second, it looks in the nif's own file tree. If the nif is under a "meshes" directory, it will look for a "textures" directory at that same level and use that as the base for the relative path. Again, PNGs are chosen in preference to DDS files. This is useful if you're just working on nifs in the game directory.

Materials files: Fallout4 keeps most shader properties in a separate materials file, under the top-level "Materials" folder. On import, pyNifly reads this file and uses its settings to override settings from the nif. The file must be in the same file tree as the nif--so the importer climbs the nif path to the "Meshes" folder, finds a sibling "Materials" folder, and uses that as the base for the materials file path.

On export, the shader node in the nif is written. There is no materials file export.

The importer uses group nodes in the shader to implement the nif shader properties. Input values to the nodes match the values in the nif. Alpha property nodes have their own shader node in Blender, with input values that behave like the ones in the nif.

The exporter will look at the Blender shader node tree and Blender attributes and set the values in the output nif accordingly. If you change the shader nodes or property values, the output will change (and it's not hard to confuse the exporter completely). So be careful what you do. If things aren't behaving as you expect, import a good nif and copy the material the importer created.

Shaders use flags and magic values. These will be translated into text by the importer, and back again by the exporter. See below for the possible values. For flags, where more than one may be set, the values will be separated by " | ", e.g. "SPECULAR | SKINNED | ZBUFFER_TEST".

BSLightingShaderProperty, BSEffectShaderProperty, and BSShaderPPLightingProperty nodes are supported. The first is general use; the second is used by FO4 for glass in eyeglasses and helmet visors.

BSLightingShaderProperty

For BSLightingShaderProperty nodes the properties are used as follows:

  • Shader node name -- The node's name. In FO4, the shader node name is the path to the materials file to use. This is stored and can be set as Blender custom property BSLSP_Shader_Name on the Blender object's material.
  • Shader Type (see BSLSPShaderType below) -- Read and written. Stored in a Blender property. Not used in Blender.
  • Shader_Flags_1 (see ShaderFlags1) -- Read and written, also stored in a Blender property. On read, if model_space_normal is set, the Blender normal map is set to object mode and the green and blue channels are swapped to match Blender's convention. On write, the model_space_normal bit is overwritten to match Blender's normal map.
  • Shader_Flags_2 (see ShaderFlags2) -- Read and written, and stored in a blender property. On write, vertex_colors bit is set or cleared depending on whether the shape has vertex colors.
  • UV_Offset_U, UV_Offset_V -- Stored in blender properties and exported, not otherwise used.
  • UV_Scale_U, UV_Scale_V -- Stored in blender properties and exported, not otherwise used.
  • Emissive_Color -- Used for the "Emission" color of the Blender shader node. Exported.
  • Emissive_Mult -- Used for the "Emission Strength" setting of the Blender shader node. Exported.
  • Tex_Clamp_Mode -- Not used, not stored. Always 'WRAP_S WRAP_T' on export.
  • Alpha -- Used for the "Alpha" property of the Blender shader node and written on export. Not clear this is ever used.
  • Refraction_Str -- Stored in Blender properties and exported, not otherwise used.
  • Glossiness -- Used for the "Metallic" property of the Blender shader node, and exported. A scale factor is applied so the appearance in Blender more-or-less matches what you see in game.
  • Specular Color -- Stored in Blender properties and exported, not otherwise used.
  • Specular Strength -- Stored in Blender properties and exported, not otherwise used.
  • Soft_Lighting, aka "Lighting Effect 1" -- Stored in Blender properties and exported, not otherwise used.
  • Rim_Light_Power, aka "Lighting Effect 2" -- Stored in Blender properties and exported, not otherwise used.
  • Skin Tint Color -- Stored in Blender properties and exported, not otherwise used. Note this does appear to be used in-game when the "Skin Tint" shader is used. (But not when the face tint shader is used, which limits its usefulness.) If you want to set the skin tint value, set the custom property directly.

BSEffectShaderProperty

Shader_Flags_1
Shader_Flags_2
UV_Offset_U
UV_Offset_V
UV_Scale_U
UV_Scale_V
Tex_Clamp_Mode
Lighting_Influence
Env_Map_Min_LOD
Falloff_Start_Angle
Falloff_Stop_Angle
Falloff_Start_Opacity
Falloff_Stop_Opacity
Emissive_Color_R
Emissive_Color_G
Emissive_Color_B
Emissive_Color_A
Emissive_Mult
Soft_Falloff_Depth
Env_Map_Scale

Texture paths

  • Texture paths are relative to their parent nif, if possible. They are absolute paths in Blender, but truncated to the "textures" folder on export.
  • The diffuse texture provides the color in Blender. If there's an alpha property, it also supplies the alpha value, and the material is set up to show transparency.
  • The normal texture provides the normal map. A normal map node is created in the Blender shader. Tangent vs. model space normals are set by the shader_flags_1 bit, not by the "_msn" or "_n" extension.
  • If it's a tangent space normal for Skyrim, the alpha channel is used as the specular input to the Blender shader.
  • For model space normals, blue and green channels are swapped to conform with Blender's conventions.
  • For Skyrim, the SK texture is used for the subsurface input of the Blender shader.
  • For Skyrim, the specular texture is used for specular input if it's provided. (Even if there's a tangent space normal. It's not clear what the game does in this situation.)
  • For FO4, the specular texture provides both specular (red channel) and glossiness/metallic (green channel). The importer separates the channels and feeds the appropriate inputs to the Blender shader. On export, the specular input to the shader sets the specular texture slot in the nif.
  • If a texture file can't be found the shader nodes are still created in Blender to make it easier to set things up later.
  • On export, the texture file paths are truncated to the leading "textures" so they'll be relative to the game directory.

Special Values

BSLSPShaderType

Default = 0
Environment_Map = 1
Glow_Shader = 2
Parallax = 3
Face_Tint = 4
Skin_Tint = 5
Hair_Tint = 6
Parallax_Occ = 7
Multitexture_Landscape = 8
LOD_Landscape = 9
Snow = 10
MultiLayer_Parallax = 11
Tree_Anim = 12
LOD_Objects = 13
Sparkle_Snow = 14
LOD_Objects_HD = 15
Eye_Envmap = 16
Cloud = 17
LOD_Landscape_Noise = 18
Multitexture_Landscape_LOD_Blend = 19
FO4_Dismemberment = 20

ShaderFlags1

SPECULAR = 1 << 0
SKINNED = 1 << 1
TEMP_REFRACTION = 1 << 2
VERTEX_ALPHA = 1 << 3
GREYSCALE_COLOR = 1 << 4
GREYSCALE_ALPHA = 1 << 5
USE_FALLOFF = 1 << 6
ENVIRONMENT_MAPPING = 1 << 7
RECEIVE_SHADOWS = 1 << 8
CAST_SHADOWS = 1 << 9
FACEGEN_DETAIL_MAP = 1 << 10
PARALLAX = 1 << 11
MODEL_SPACE_NORMALS = 1 << 12
NON_PROJECTIVE_SHADOWS = 1 << 13
LANDSCAPE = 1 << 14
REFRACTION = 1 << 15
FIRE_REFRACTION = 1 << 16
EYE_ENVIRONMENT_MAPPING = 1 << 17
HAIR_SOFT_LIGHTING = 1 << 18
SCREENDOOR_ALPHA_FADE = 1 << 19
LOCALMAP_HIDE_SECRET = 1 << 20
FACEGEN_RGB_TINT = 1 << 21
OWN_EMIT = 1 << 22
PROJECTED_UV = 1 << 23
MULTIPLE_TEXTURES = 1 << 24
REMAPPABLE_TEXTURES = 1 << 25
DECAL = 1 << 26
DYNAMIC_DECAL = 1 << 27
PARALLAX_OCCLUSION = 1 << 28
EXTERNAL_EMITTANCE = 1 << 29
SOFT_EFFECT = 1 << 30
ZBUFFER_TEST = 1 << 31

Note FACEGEN_RGB_TINT on Skyrim is the same as SKIN_TINT on FO4.

ShaderFlags2

ZBUFFER_WRITE = 1
LOD_LANDSCAPE = 1 << 1
LOD_OBJECTS = 1 << 2
NO_FADE = 1 << 3
DOUBLE_SIDED = 1 << 4
VERTEX_COLORS = 1 << 5
GLOW_MAP = 1 << 6
ASSUME_SHADOWMASK = 1 << 7
PACKED_TANGENT = 1 << 8
MULTI_INDEX_SNOW = 1 << 9
VERTEX_LIGHTING = 1 << 10
UNIFORM_SCALE = 1 << 11
FIT_SLOPE = 1 << 12
BILLBOARD = 1 << 13
NO_LOD_LAND_BLEND = 1 << 14
ENVMAP_LIGHT_FADE = 1 << 15
WIREFRAME = 1 << 16
WEAPON_BLOOD = 1 << 17
HIDE_ON_LOCAL_MAP = 1 << 18 
PREMULT_ALPHA = 1 << 19
CLOUD_LOD = 1 << 20
ANISOTROPIC_LIGHTING = 1 << 21
NO_TRANSPARENCY_MULTISAMPLING = 1 << 22
UNUSED01 = 1 << 23
MULTI_LAYER_PARALLAX = 1 << 24
SOFT_LIGHTING = 1 << 25
RIM_LIGHTING = 1 << 26
BACK_LIGHTING = 1 << 27
UNUSED02 = 1 << 28
TREE_ANIM = 1 << 29
EFFECT_LIGHTING = 1 << 30
HD_LOD_OBJECTS = 1 << 31