Shader Patch Terrain Materials - PrismaticFlower/shaderpatch GitHub Wiki
Contents
- Intro
- Config Files
- Config.Global
- Config.Global.BlendingMode
- Config.Global.FarTerrain
- Config.Global.UseEnvironmentMapping
- Config.Global.EnvironmentMap
- Config.Global.UseZEStaticLighting
- Config.Global.sRGBDiffuseMaps
- Config.Global.BumpMappingType
- Config.Global.Rendertype
- Config.Global.DiffuseColor
- Config.Global.SpecularColor
- Config.Global.BaseColor
- Config.Global.BaseMetallicness
- Config.Global.BaseRoughness
- Config.Materials
- Config.Global
- Terrain Texture Builtins
- Far Scene Terrain Optimizations
- Triangle Texture Selection
- Example Configs
Intro
As of v1.1 terrain can also now have SP materials applied to it but because terrain isn't drawn in the same way as regular models the process for doing so is different.
First instead of having .mtrl
files each terrain has a single .tmtrl
file. Next terrain materials can not share textures with other materials. (They can both use but the terrain will get it's own copy, more on this later.)
When material_munge
encounters MAP.tmtrl
file it first loads MAP.ter
from the same folder and also loads MAP.terrain
(the munged version MAP.ter
) from _BUILD\Worlds\SPT\PC
.
It will then generate new geometry for the terrain from MAP.ter
. The old terrain geometry from the loaded MAP.terrain
is discarded. (Note that this happens in memory, the original MAP.terrain
on disk is never modified.)
Then the terrain geometry's triangles are sorted into segments on an 8x8 grid. These segments are then sorted into models, one for every 48 segments. Using a defined max of 6 models, but obviously currently only 2 are used. These models are appended to SP's copy of MAP.terrain
.
Finally in order to make the new terrain models show up a world layer is also created and appended to MAP.terrain
. This layer will define an object that references each of the terrain's models. Again up to a limit of 6. Each object will be unnamed and will use com_inv_col_8
as it's class. (However despite using an object class explicitly for the purposes of providing collision none of the terrain objects have collision, the terrain collision comes from the original collision in MAP.terrain
.)
Once all that is done MAP.terrain
is saved into _BUILD\Worlds\SPT\PC_SP
for SP's lvl_pack
to pickup and use instead of the game's regular terrain.
Next the textures for the terrain will be assembled and packed together. The textures referenced in MAP.tmtrl
must have .*.tex
files so that they produce .sptex
files in _BUILD\Worlds\SPT\PC_SP
for this step. If they are only used by the terrain then setting Uncompressed
and the seldom documented NoMips
both to yes
in the texture's .tex
file can save you some time when munging.
Each of the textures will be loaded and assembled arrays with the other textures. This let's the textures being used by the terrain be controlled at a primitive level instead of segment level and reduces GPU state changes while drawing. However it has the downside that all the textures must have the same resolution.
If the texture resolutions do not match (or they are not a power of two) then the size of the largest one will be taken, rounded to the next largest power of two in each direction (1000x400 becomes 1024x512) and all the textures will be resized to that resolution automatically.
Texture types are also packed together to reduce memory requirements. (AO is placed in the alpha channel of the diffuse texture for instance.) But the exact details of this are larger unimportant. But below is high level list of the resulting arrays.
- Color Maps + AO
- Normal Maps + Gloss (or MetallicRoughness)
- Height Maps
Because I'm a lazy busy person I haven't had time to refactor out the texture processing in sp_texture_munge
and make it usable in material_munge
so instead of the usual texture compressor DirectXTex's GPU compressor is used. This will likely cause your GPU usage go up to close to 100%, there is nothing wrong with this obviously (unless something is really wrong with your PC) but I figured I'd leave a note about it so no one gets confused/surprised.
After that the textures are saved. And then as a last step the material files to tie it all together are created for the terrain's models.
Config Files
The format of .tmtrl
files is similar to .mtrl
but very much distinct. Like all modder facing configs in SP it is written in YAML. Below is the documentation for each key. Example config files can be found at the bottom of this page.
Config.Global
The Global
section in the config contains settings that affect all the materials that make up the terrain.
Config.Global.BlendingMode
Blending mode for the terrains textures. Options are.
Height
- Use height maps to blend between textures.Basic
- Simple linear blending like stock terrain has. Cheaper than height based blending.
Defaults to Height
.
Config.Global.FarTerrain
Geometry detail for terrain in the far scene. Options are.
Downsampled
- Downsample the terrain to 64x64 grids. Has the potential for better performance in some cases. But due to the downsampling and the way the far scene works in SWBFII it is only suitable for terrains with no hills/mountains.Fullres
- Use the same geometry for the far scene as the near scene. Works in all cases.
Defaults to Fullres
.
Config.Global.TerrainOffset
Offsets the terrain by specified amount. Can be used to work around misaligned terrain. Provide as an array of three values.
TerrainOffset: [0.0, 0.0, -8.0] # x, y, z
Config.Global.UseEnvironmentMapping
Use an envmap for reflections on the terrain. Currently only supported for normal_ext
terrain and defaults to no
.
Config.Global.EnvironmentMap
The name of the texture to use as the environment map. The texture should be a cubemap and should have it's sRGB
value set to yes
if HDR rendering is being used.
Config.Global.UseZEStaticLighting
Use diffuse lighting baked in ZE editor and mark the terrain as statically lit. Defaults to no
.
Config.Global.sRGBDiffuseMaps
Equivalent of sRGB
value in *.tex
files for terrain diffuse texture array. Only applicable to normal_ext
and defaults to yes
.
Config.Global.BumpMappingType
The type of bump mapping to use. Parallax options may be unsuitable for terrain with widely varying elevation due to problems relating to normal transitions. Options are,
Normal Mapping
- Simple normal mapping.Parallax Offset Mapping
- Parallax Mapping with Offset Limiting, can give the illusion of greater depth to the image at a fraction of the cost ofParallax Occlusion Mapping
.Parallax Occlusion Mapping
- Parallax Occlusion Mapping, see documentation here.
Defaults to Normal Mapping
.
Config.Global.Rendertype
The rendertype to use for the terrain. Can be normal_ext
or pbr
. Defaults to normal_ext
.
Config.Global.DiffuseColor
Diffuse color modifier, multiplied with the blended diffuse map color before calculating lighting. Only applicable to normal_ext
and defaults to [1.0, 1.0, 1.0]
.
Config.Global.SpecularColor
Specular color. Only applicable to normal_ext
and defaults to [1.0, 1.0, 1.0]
.
Config.Global.BaseColor
Base color modifier, multiplied with the blended albedo map color before calculating lighting. Only applicable to pbr
and defaults to [1.0, 1.0, 1.0]
.
Config.Global.BaseMetallicness
Metallicness modifier, multiplied with the blended metallicness map value before calculating lighting. Only applicable to pbr
and defaults to 1.0
.
Config.Global.BaseRoughness
Roughness modifier, multiplied with the blended roughness map value before calculating lighting. Only applicable to pbr
and defaults to 1.0
.
Config.Materials
The Materials
section in the config contains a listing for each material or "game texture" in the terrain. They do not have to be in order but each texture must have an entry. Even though they will be listed as "Config.Materials." all keys listed below for the individual entries and are thus really of the format "Config.Materials.texture_name.".
Config.Materials.HeightScale
Height scale for parallax effects (if used). Defaults to 0.05
. The terrain shaders are coded to recognize 0.0
as meaning skip parallax occlusion mapping for this texture.
Config.Materials.SpecularExponent
Specular exponent for normal_ext
. Defaults to 64.0
.
Config.Materials.AOMap
Texture name for ambient occlusion map.
Config.Materials.HeightMap
Texture name for height map. Used for parallax effects and blending between terrain textures.
Config.Materials.NormalMap
Texture name for normal map.
Config.Materials.DiffuseMap
Texture name for diffuse map. Only applicable for normal_ext
.
Config.Materials.GlossMap
Texture name for gloss map. Only applicable for normal_ext
.
If you want to effectively disable specular lighting for this entry pass $null_glossmap
here.
Config.Materials.AlbedoMap
Texture name for albedo map. Only applicable for pbr
.
Config.Materials.MetallicRoughnessMap
Texture name for metallic roughness map. Only applicable for pbr
.
Terrain Texture Builtins
The texture assembler for terrain recognizes some of SP's builtin textures for materials and will handle them correctly. It also supports some additional ones that regular materials do not.
Name | Description |
---|---|
$null_normalmap |
A normal map that always points directly away from the surface |
$null_ao |
An AO map that never occludes. |
$null_aomap |
An AO map that never occludes. |
$null_detailmap |
A linear texture with the value 0.5 . |
$null_heightmap |
A linear texture with the value 1.0 . |
$null_metallic_roughnessmap |
A texture with the value 1.0 in all channels, causing the metallicness and roughness parameters to always be the BaseMetallicness and BaseRoughness values. |
$null_albedomap |
A white texture. |
$null_diffusemap |
A white texture. |
$null_glossmap |
A texture with the value of 0.0 , effectively removing all specular lighting from the material. |
Far Scene Terrain Optimizations
Far scene terrain has a couple special things happen to it to reduce it's cost. Specifically the BumpMappingType
will be set to Normal Mapping
for it and the BlendingMode
to Basic
.
Triangle Texture Selection
Each triangle on the terrain can only blend between up to three textures at once. The way this is done is intended to be intuitive and just give the right result. So in most cases you shouldn't have to worry about it.
But for those pesky times when you're seeing hard edges with your texture blending it probably pays to know how textures are selected.
First the texture weights of the three terrain points making up the terrain are fetched and then all the weights of all their neighboring points are fetched. The badly made illustration below shows this process for a hypothetical triangle. Each black point is a point on the terrain that texture weights are being fetched from.
The textures to use are then selected by determining what textures have the greatest total contribution across all fetched. So say you're terrain had five textures and these textures each had these hypothetical weights across all the considered points. Then the textures whose weights are bolded would be the one's chosen for use as they had the highest total contribution to the terrain points.
- 0.25
- 0.1
- 0.20
- 0.05
- 0.15
Example Configs
normal_ext
Global:
UseEnvironmentMapping: no
EnvironmentMap: cubemap
UseZEStaticLighting: yes
sRGBDiffuseMaps: yes
BumpMappingType: Parallax Occlusion Mapping
Rendertype: normal_ext
DiffuseColor: [1.0, 1.0, 1.0]
SpecularColor: [1.0, 1.0, 1.0]
Materials:
Ground03_col:
DiffuseMap: Ground03_col
NormalMap: Ground03_nrm
GlossMap: Ground03_gloss
AOMap: $null_ao
HeightMap: Ground03_disp
HeightScale: 0.01
SpecularExponent: 32.0
Ground23_col:
DiffuseMap: Ground23_col
NormalMap: Ground23_nrm
GlossMap: Ground23_gloss
AOMap: Ground23_AO
HeightMap: Ground23_disp
HeightScale: 0.01
SpecularExponent: 96.0
Rocks05_col:
DiffuseMap: Rocks05_col
NormalMap: Rocks05_nrm
GlossMap: Rocks05_gloss
AOMap: Rocks05_AO
HeightMap: Rocks05_disp
HeightScale: 0.05
SpecularExponent: 64.0
pbr
Global:
BumpMappingType: Parallax Occlusion Mapping
Rendertype: pbr
BaseColor: [1.0, 1.0, 1.0]
BaseMetallicness: 0.0
BaseRoughness: 1.0
Materials:
Ground03_col:
AlbedoMap: Ground03_col
NormalMap: Ground03_nrm
MetallicRoughnessMap: Ground03_rgh
AOMap: $null_ao
HeightMap: Ground03_disp
HeightScale: 0.01
Ground23_col:
AlbedoMap: Ground23_col
NormalMap: Ground23_nrm
MetallicRoughnessMap: Ground23_rgh
AOMap: Ground23_AO
HeightMap: Ground23_disp
HeightScale: 0.01
Rocks05_col:
AlbedoMap: Rocks05_col
NormalMap: Rocks05_nrm
MetallicRoughnessMap: Rocks05_rgh
AOMap: Rocks05_AO
HeightMap: Rocks05_disp
HeightScale: 0.05