-
Notifications
You must be signed in to change notification settings - Fork 6
True PBR
PBR (physically based rendering) approximates how real materials react to light and is used in most modern games. True PBR is a (work in progress) part of Community Shaders that has several benefits:
- It allows the usage of PBR materials which are widely available online, many for free
- Those materials can be used easily in standard tools like Blender and exported in a simple way
- The materials will look the same way in Skyrim as in those tools so it is easy to create a consistent visuals. There is no need to experiment to adjust brightness according to Skyrim's very unique levels
To use PBR you will need to obtain Community Shaders with True PBR feature (current dev build) and True PBR texture packs. Those are currently available only on the Discord. But remember, those texture packs will not work without Community Shaders enabled. If you are not a texture creator you can safely ignore everything else described below.
All the followings sections are only relevant to you if are creating textures for Skyrim yourself. To generate a set of True PBR textures you need to do two things:
- Update the meshes where those textures are being used to enable PBR for those meshes: True PBR only cares about meshes marked with a specific flag, everything else is rendered as usual. True PBR mods therefore contain meshes marked for PBR and a set of PBR textures.
- Create True PBR textures: The base textures for True PBR are albedo, normal, roughness, metallic, ambient occlusion and specular. Parallax and emission (if emissive color map is provided) are also supported. Additionally the material can use
two-sided foliage orsubsurface shading, which require subsurface color map and multilayer Parallax which approximates a semitransparent surface above a hard surface (also following Unreal).
The following flags of BSShaderProperty are used to tag a mesh for PBR rendering:
- Byte 55 (Unused01 in NifSkope) - enables PBR for this BSGeometry
Byte 57 (Soft_Lighting in NifSkope) - enables two-sided foliage shading- Byte 58 (Rim_Lighting in Nifskope) - enables subsurface shading in NifSkope
For a mesh to be recognized as PBR, it must have in BSLightingShaderProperty:
- Default shader type
- In Shader Flags 2 have Unused01 (or PBR) flag set
To tweak PBR settings for the mesh the following parameters of BSShaderProperty can be used:
- Specular Level (replaces Glossiness) - linear multiplier for nonmetal reflectance. Should be 0.04 for meshes which do not have specular map (and have 1 in alpha of RMAOS map) or 0.08 for meshes which have specular map created for Unreal.
- Subsurface Color (replaces Specular Color) - used in Two-Sided Foliage and Subsurface models. If subsurface map is provided it's used as linear multiplier for its RGB.
- Roughness Scale (replaces Specular Strength) - linear multiplier for roughness.
- Subsurface Opacity (replaces Lighting Effect 1) - used in Subsurface model. If subsurface map is provided it's used as linear multiplier for its alpha. Higher opacity makes the effect weaker - lower opacity allows more light through the surface.
- Displacement Scale (replaces Lighting Effect 2) - linear multiplier for displacement.
Enabled by: MultilayerParallax flag + MultilayerParallax shader type
Base parameters:
- Coat strength - strength of coat layer contribution from 0 to 1. Equals to subsurface opacity field * alpha of slot 8 texture (if present)
- Coat roughness - roughness of coat layer. Equals to parallax inner layer thickness * alpha of slot 7 texture (if present)
- Coat specular level - reflectance of coat layer. Equals to parallax refraction scale (just set to 0.04)
Three more flags are used:
- EffectLighting - enables diffuse contribution. Color of top layer is then taken from specular color field * rgb of slot 8 texture (if present)
- SoftLighting - enables interlayer parallax. I.e. with it enabled displacement works as displacement between upper and lower layer to simulate vanilla multilayer parallax
- BackLighting - enables own normal map for coat layer. It's then taken from rgb of slot 7 texture
To set up PBR meshes in batch, you can use PbrNifPatcher. It is useful especially when remaking vanilla textures that are used in many meshes.
To get descriptions for PBR properties and correct rendering of PBR in Nifscope, add these files into your Nifscope folder
- Base color in RGB, opacity in A.
- Normal in RGB, A unused.
- OPTIONAL Emissive color in RGB, A unused.
- OPTIONAL Displacement in R, GBA unused.
- Unused.
- RMAOS - Roughness in R, metallic in G, AO in B, specular in A.
- OPTIONAL Multilayer normal in RGB, roughness in A.
- OPTIONAL Subsurface color in RGB, subsurface opacity in A. Multilayer coat color in RGB, opacity/strength in A.
Color maps are assumed to be in SRGB format. If the actual colors are sRGB (gamma in Mixer), use sRGB flagged dds. If the actual colors are linear, use linear dds.
Landscape texture is assumed to be PBR if a json file with the same name as the texture set record's EDID is found in 'data\PBRTextureSets'. For 'LandscapeDirt02 [TXST:00000C0F]' it would be 'LandscapeDirt02.json' The texture paths are defined in the texture set record:
- TX00: 'PBR\Landscape\Dirt02.dds' Base color in RGB (assumed to be in SRGB format), transparency in A.
- TX01: 'PBR\Landscape\Dirt02_n.dds' Normal in RGB, A unused.
- TX02: 'PBR\Landscape\Dirt02_rmaos.dds' RMAOS - Roughness in R, metallic in G, AO in B, specular in A.
- TX03: 'PBR\Landscape\Dirt02_g.dds' Glow in RGB, A unused. (assumed to be in SRGB format) (unused for landscape)
- TX04: 'PBR\Landscape\Dirt02_p.dds' Displacement in R, GBA unused. (use a greyscale image and save as BC4)
- TX05: Unused
- TX06: 'PBR\Landscape\Dirt02_crn.dds' Coat normal in RGB, coat roughness in A. (only used for multilayer parallax - not used for landscape)
- TX07: 'PBR\Landscape\Dirt02_s.dds' Subsurface colour in RGB, subsurface opacity in A (assumed to be in SRGB format); OR coat colour in RBG, coat strength in A (assumed to be in SRGB format) (both unused for landscape)
Usually, your record will look like this for landscape:
- TX00: 'PBR\Landscape\Dirt02.dds'
- TX01: 'PBR\Landscape\Dirt02_n.dds'
- TX02: 'PBR\Landscape\Dirt02_rmaos.dds'
- TX03: -
- TX04: 'PBR\Landscape\Dirt02_p.dds'
The json file contains the values that are normally defined in the mesh:
{
'"roughnessScale" : 1.0,'
'"displacementScale" : 0.25,'
'"specularLevel" : 0.04,'
'"subsurfaceColor" : [1.0, 1.0, 1.0],' (currently unused)
'"subsurfaceOpacity" : "0.1"' (currently unused)
}
You can tweak the values to your needs, but be aware that landscape textures get also applied to a lot of meshes via texture set swaps - dirtcliffs, for example. In those cases, the settings in the mesh are used (and it also needs to be set up for PBR). But because many different textures are used on these meshes, your landscape textures should use similar values for parallax scale for your landscape textures. A texture that's made for a scale of 0.1 being applied to a mesh with a scale of 0.25 will have much stronger parallax than you intended.
If any of the textures in a quad is PBR, then the entire quad is rendered as PBR. So in order to avoid issues with blending between PBR and non-PBR textures, all landscape textures in a worldspace need to be converted to PBR together. That is to be okay since mods replacing land textures usually replace them all. Also, landscape LOD will not be rendered as PBR (blends together in the distance).
Many programs can be used to work with PBR textures. To generate textures from scratch, you can use for example Substance Designer or Material Maker (free). To edit, mix and apply materials to meshes, you can use Quixel Mixer (free), ArmorPaint (free) or Substance Painter. In this short guide I will show the workflow I use to retexture vanilla meshes. The following workflow is based on Quixel Mixer and Chainner:
- When installing, you can select the sample packs, which contain textures you can freely use. Do NOT select the Unlimited Megascans option - it is only free if your end product is in Unreal Engine. Though do inform yourself, I am not a lawyer.
- Get some free PBR textures for example from polyhaven.com or ambientcg.com, or make your own. Import them using Library -> Import Custom Asset.
- Make sure to fill out the correct albedo - one is for specular and one for metalness workflow. Most available textures use metalness workflow.
- Make sure to use the correct normal map - Mixer uses the OpenGL variant. If you use the DirectX variant, normals may look wrong in Mixer.
- You can add texture names to autofil in Edit -> Configure Autoload Map Names
- Edit and mix textures however you want. Mixer has official tutorials on Youtube.
- Export the PBR textures. You can create a preset that exports according to your needs.
- Pick image format according to preference. I use PNG.
- Export albedo as _Albedo.png, RMAOS as _RMAOS.png, normal as _Normal.png, and displacement textures as _Displacement.png.
- Take note if you export albedo in Gamma or Linear space. This will be important later.
- You can directly export a RMAOS (roughness, metallic, ambient occlusion, specular) texture. In most cases you won't need specular and can save as RGB.
- If you indeed worked with opengl normal maps, set Normal Y (green channel) to be inverted. This transforms it into DirectX format which Skyrim uses.
- Use Chainner and load the following workflow to automatically convert the textures towards the structure Skyrim needs them.
Please note, if you exported your albedo as Gamma, you need to select compression with sRGB. This is the 'Save Image' node in the topright corner of the workflow.
Optionally change percentages of Resize nodes to downscale your textures before saving.
What about Complex Materials?
Complex materials are totally separate from True PBR and there would be no point in combining them. You can still use complex materials on non-pbr objects as usual.Can I convert vanilla shaded textures to True PBR?
If you originally had PBR textures that you somehow converted for Skyrim, you can use those easily. Otherwise it is impossible to do without assumptions, because Skyrim textures contain fundamentally different data. For example, many objects using enviornment mapping are metallic, but not all of them. You can do manual work or use some AI to make the necessary textures, but it is unlikely that it will be a meaningful visual improvement over vanilla.My materials ingame look wrong?
There is many possibilities for this, I will list the common ones. If the material is really shiny, the mesh probably isn't marked for PBR, so is vanilla shaded with specularity 1. If the material is too dark in the shadows, you might have too dark ambient occlusion. If the material gets black when you walk to it with a torch, your normal maps might be wrong - either flipped, or wrong format (opengl).About Texture Compression
There is a number of compression format for DDS textures with various properties such as number of channels, quality and file size. Not all of them are supported by Skyrim. The following list should be sufficient in most situations:- BC1: RGB + 1bit alpha (fully opaque or fully transparent). It has reasonable file size and quality. Use for opaque or cutout albedo textures, and RMAOS textures if you don't need specular. In case of visible banding or squarish artifacts, use BC7.
- BC4: One channel (grayscale). Has the same file size as BC1, but only one channel with better quality. Use for parallax textures.
- BC7: RGBA. Has good quality and twice the file size of BC1. Use for normal maps and albedo with full transparency.
- BC3: RGBA. The RGB part uses BC1, alpha uses BC4. The file size is the same as BC7. This can be useful when you need to preserve a quality alpha channel, for example in complex materials or landscape textures with parallax in alpha channel.
For more details I recommend this article.
Linear vs sRGB because it bears repeating
- You can find discussions online about linear, sRGB, non-color data etc. The details are above my paygrade, here we just hope that stuff works.
- Extremely simplified: Math is easier with linear data, but using sRGB files allows them to store more detail human eyes can actually see (this only makes sense for colors).
- All non-color data such as normals or roughness should be flagged as linear when saving to dds.
- Color data is more complicated - you need to know whether the data (the colors) itself is in sRGB or linear space. AFAIK, albedo/diffuse textures from sites like polyhaven are in sRGB and it is more common on general. If this is the case, you should use the sRGB flag when saving to dds. The flag will allow to the texture to be converted to linear automatically on the gpu. If your data (the colors) is already in linear space, use the linear flag when saving to dds. As you can imagine, if you use the wrong flag, the texture will either be superfluously transformed to linear or not transformed when it should be, which will cause the texture to look wrong.
- BUT WAIT! That applies to True PBR. If you are making textures for vanilla Skyrim... make sure your data is sRGB and use the linear flag. WHAT? Skyrim uses linear-flagged dds that actually contain sRGB data. I'm not sure if they convert the colors to linear manually in shaders or just calculate lighting in sRGB space. So yes, it is weird but it works this way (blame Bethesda).
Do I use rmaos or rmao textures?
You use the specular layer for surfaces like glass, gems, perhaps snow. If there is only one type of surface in your texture you can use rmao and set the specular scale in the nif/json configuration. If you have different surfaces with specular properties, only then it makes sense to use rmaos with a specular map in the alpha channel.
What is the best way to adjust parallax scale?
If you want to change the parallax scale of your texture because it looks to flat instead of changing the displacement map better try to adjust parallax scale in the json for the nif patcher. This usually creates good results.
Is there any best practice how to define the specular maps and strength?
Most materials should use the default value of 0.04 (in the mesh & json settings). That means your alpha would be white and you can save the texture as BC1. Snow has half the specular strength of most other stuff, so you could use a full 128 grey image for the alpha channel or reduce the specular strength in the json & patcher files to 0.02