Texture Modding: Difference between revisions

From OpenMW Wiki
Jump to navigation Jump to search
No edit summary
m (Darklocq moved page TextureModding to Texture Modding: This isn't a CamelCase wiki.)
 
(10 intermediate revisions by 2 users not shown)
Line 1: Line 1:
= Objects =
OpenMW supports new texture mapping techniques that were not available in the vanilla MW engine.


== NIFs ==
"Normal mapping" is a technique used to fake lighting of bumps, cracks and other small details.


NIFs are unfortunately a bit limited in that they don't allow specifying material properties (such as a bump map) externally, meaning that after creating a bump map for a color texture you'd usually have to edit all meshes that use this texture and distribute the meshes with your mod.
"Specular mapping" is used to vary the shininess / specularity along the surface of an object.


With OpenMW, there is an alternate way:
The prerequisite to using these techniques are [https://en.wikipedia.org/wiki/Shader shaders]. OpenMW automatically uses shaders for objects with these mapping techniques.


'''Material overrides'''
== Normal mapping ==


Create a file called material-overrides.cfg and place it in one of the following locations:
To plug in a normal map, you can edit the NIF mesh file(s) using NifSkope and assign the normal map texture to the BumpTexture slot in the NiTexturingProperty.


- Windows: <OpenMW installation root>
Note that while the original MW engine does support the BumpTexture slot, it is using a strange form of normal mapping that applies to an environment map. OpenMW uses standard normal mapping which can achieve much better results. This difference can however result in incompatibilities. Some mods e.g. [http://www.nexusmods.com/morrowind/mods/42406/? Redoran Bump Mapped] look much darker compared to the vanilla engine and will have to be recalibrated.
- Linux: /etc/openmw or build folder for a local build
- Mac: ?


The file must be a simple INI file. For each base texture, a list of overrides can be specified.
== Specular mapping ==


The base textures (INI sections) '''must be in all lowercase'''.
The RGB channels of the specular map are used as the specular color. The alpha channel specifies shininess in range [0, 255]. If a specular map is used, it will override the shininess and specular color set in the NiMaterialProperty / osg::Material.


<pre>
NIF files do not support specular maps. In order to use them anyway, see the next paragraph.
[textures\tx_hlaalu_wall2_01.dds]
normalMap = textures\tx_hlaalu_normal.dds
specular = 1 1 1 64
</pre>


The full list of override keys can be found in the [https://github.com/zinnschlag/openmw/blob/master/files/materials/objects.mat objects.mat] file.
== Automatic use ==


=== Normal mapping ===
In addition to editing mesh files, there is another way of plugging in these texture maps. Simply create the textures with appropriate naming convention (e.g. when the base texture is called foo.dds, the normal map would have to be called foo_n.dds). To enable this automatic use based on filename pattern, you will have to add the following to your user [[settings]]:
<pre>
[Shaders]
auto use object normal maps = true


If using material overrides, use a 'normalMap = <Path to normal map>' line.
auto use object specular maps = true
You can also edit meshes and assign the normal map to the BumpTexture slot of the NiTexturingProperty.


=== Parallax ===
normal map pattern = _n
normal height map pattern = _nh


Parallax mapping requires height information being stored in the normal map's alpha channel.
specular map pattern = _spec
To tell OpenMW that height information is available, make sure your normal map filename contains "_nh." (stands for ''normalHeight''). Example: Tx_BM_snow_01_nh.dds
</pre>


Please note that the strength of the parallax effect is not globally adjustable at the moment. However, to reduce the effect you can simply scale the heights. Height 0.5 is the base level where no view dependent offset is performed.
A normal map with the _nh pattern additionally enables use of the normal map's alpha channel as height information. This can be used by a [https://en.wikipedia.org/wiki/Parallax_mapping parallax mapping] shader to offset the texture depending on the viewing angle and height, creating a fake 3d effect.


=== Specular ===
The above settings are not enabled by default, to prevent incompatibilities with mods that may be inadvertently using these naming schemes.


First, make sure that specular is enabled in general.  
On the topic of shader settings, you may be interested in these three settings as well. In particular, 'clamp lighting = false' makes normal maps look much better!
 
<pre>
If using material overrides, add this line:
[Shaders]
# Force rendering with shaders. By default, only bump-mapped objects will use shaders.
# Enabling this option may cause slightly different visuals if the "clamp lighting" option
# is set to false. Otherwise, there should not be a visual difference.
force shaders = false


<pre>
# Force the use of per pixel lighting. By default, only bump mapped objects use per-pixel lighting.
specular = <R> <G> <B> <S>
# Has no effect if the 'force shaders' option is false.
</pre>
# Enabling per-pixel lighting can result in visual differences to the original MW engine. It is not
RGB is the specular color and S is the shininess.
# recommended to enable this option when using vanilla Morrowind files, because certain lights in Morrowind
# rely on vertex lighting to look as intended.
force per pixel lighting = false


Example:
# Restrict the amount of lighting that an object can receive to a maximum of (1,1,1).
<pre>
# Only affects objects that render with shaders (see 'force shaders' option). Always affects terrain.
specular = 1 1 1 64
# Setting this option to 'true' results in fixed-function compatible lighting, but the lighting
# may appear 'dull' and there might be color shifts.
# Setting this option to 'false' results in more realistic lighting.
clamp lighting = true
</pre>
</pre>


If editing the mesh:
== Terrain ==
* Add a NiSpecularProperty and make sure the 'flags' field is set to '1'.
* In the NiMaterialProperty, make sure the specular color is set properly and glossiness is valid.


==== Shininess/glossiness ====
The terrain shader also supports normal, normal-height and specular maps, with one difference compared to objects: the specular value must be packed into the layer texture's alpha channel.


Valid shininess values are from 1-128. Values higher than 128 may work, but are not supported on all graphics cards. The higher the shininess, the 'sharper' the specular effects will look.
For example, if you wanted to add specular mapping to a terrain layer called <i>rock.dds</i>, you would copy this texture to a new file called <i>rock_diffusespec.dds</i>, and then edit its alpha channel to set the specular intensity.
==== Specular mapping ====


Specular maps allow variations in specular along the texture of the object.
The relevant settings are:
There are two possible ways to do specular mapping:


'''Diffuse alpha channel'''
<pre>
 
[Shaders]
Unless a separate specular map is used (see below), the alpha channel of the diffuse texture will act as a multiplier for the specular color.
auto use terrain normal maps = true
 
'''Separate specular map'''


You can also create a new texture and use it as a specular map. In this case, RGB will be used as a multiplier to the specular color and the alpha channel as a multiplier to the shininess value.
auto use terrain specular maps = true


This method will cost some performance, since an additional texture must be sampled.
terrain specular map pattern = _diffusespec


The material override for this is 'specMap':
# Also used for terrain normal maps
 
normal map pattern = _n
<pre>
normal height map pattern = _nh
[textures\tx_hlaalu_wall2_01.dds]
normalMap = textures\tx_hlaalu_normal.dds
specular = 1 1 1 64
specMap = textures\specular_test.tga
</pre>
</pre>


== Native format ==
== OSG native files ==


We plan to have native mesh/material formats in the future, but this is still in the planning stages.  
OpenMW supports all the above shader features for meshes in the [[Native Mesh Format]]. To have the shader generator recognize specific textures, the osg::Texture2D must be named appropriately.  


= Terrain =
Available texture types are the following (most of which also have NIF equivalents):


=== Specular mapping ===
* diffuseMap: base texture
* normalMap: normal map, as described earlier
* normalHeightMap: same as normal map, but including height information in alpha channel to be used for parallax effects
* emissiveMap: controls the material's emission, useful for objects that glow in the dark
* darkMap: multiplied onto the base texture
* detailMap: multiplied by 2 and then multiplied onto the base texture
* envMap: spherical environment map
* specularMap: specular map, as described earlier


For performance reasons, the specular information is stored in the alpha channel of the color texture.
The first texture unit automatically acts as <i>diffuseMap</i> if no recognized type is specified.


Since Morrowind's vanilla textures are not supposed to have specularity, you need to create a specular-mapped texture with a "_diffusespec" postfix, to indicate that specular information is available for this texture.
<i>Example: .osgt file excerpt of a normal mapped mesh</i>
 
<pre>
For example, for the TX_BM_snow_01.dds layer, a diffuse-specular map would be called TX_BM_snow_01_diffusespec.dds.
                  TextureModeList 2 {
 
                    Data 1 {
=== Normal mapping ===
                      GL_TEXTURE_2D ON
 
                    }
Normal maps need to be named with an _n postfix. For example, for a color texture ''Tx_BM_snow_01.dds'', OpenMW will look for a normal map called ''Tx_BM_snow_01_n.dds''.
                    Data 1 {
 
                      GL_TEXTURE_2D ON
=== Parallax mapping ===
                    }
 
                  }
Parallax mapping requires height information being stored in the normal map's alpha channel.
                  TextureAttributeList 2 {
alpha = 1 -> highest, alpha = 0 -> lowest.
                    Data 1 {
                      osg::Texture2D {
                        UniqueID 37
                        Name "diffuseMap"
                        WRAP_S REPEAT
                        WRAP_T REPEAT
                        WRAP_R REPEAT
                        MIN_FILTER LINEAR_MIPMAP_LINEAR
                        MAG_FILTER LINEAR
                        Image TRUE {
                          UniqueID 60
                          FileName "textures/BuddhaStatue_Dif.jpg"
                          WriteHint 2 2
                        }
                      }
                      Value OFF
                    }
                    Data 1 {
                      osg::Texture2D {
                        UniqueID 38
                        Name "normalMap"
                        WRAP_S REPEAT
                        WRAP_T REPEAT
                        WRAP_R REPEAT
                        MIN_FILTER LINEAR_MIPMAP_LINEAR
                        MAG_FILTER LINEAR
                        Image TRUE {
                          UniqueID 61
                          FileName "textures/BuddhaStatue_Nor.jpg"
                          WriteHint 2 2
                        }
                      }
                      Value OFF
                    }
                  }
</pre>


Also, the filename postfix you need to use becomes _nh (e.g. Tx_BM_snow_01_nh.dds) so that OpenMW knows that height information is available.
[[Category:Modding]]

Latest revision as of 16:27, 5 February 2019

OpenMW supports new texture mapping techniques that were not available in the vanilla MW engine.

"Normal mapping" is a technique used to fake lighting of bumps, cracks and other small details.

"Specular mapping" is used to vary the shininess / specularity along the surface of an object.

The prerequisite to using these techniques are shaders. OpenMW automatically uses shaders for objects with these mapping techniques.

Normal mapping

To plug in a normal map, you can edit the NIF mesh file(s) using NifSkope and assign the normal map texture to the BumpTexture slot in the NiTexturingProperty.

Note that while the original MW engine does support the BumpTexture slot, it is using a strange form of normal mapping that applies to an environment map. OpenMW uses standard normal mapping which can achieve much better results. This difference can however result in incompatibilities. Some mods e.g. Redoran Bump Mapped look much darker compared to the vanilla engine and will have to be recalibrated.

Specular mapping

The RGB channels of the specular map are used as the specular color. The alpha channel specifies shininess in range [0, 255]. If a specular map is used, it will override the shininess and specular color set in the NiMaterialProperty / osg::Material.

NIF files do not support specular maps. In order to use them anyway, see the next paragraph.

Automatic use

In addition to editing mesh files, there is another way of plugging in these texture maps. Simply create the textures with appropriate naming convention (e.g. when the base texture is called foo.dds, the normal map would have to be called foo_n.dds). To enable this automatic use based on filename pattern, you will have to add the following to your user settings:

[Shaders]
auto use object normal maps = true

auto use object specular maps = true

normal map pattern = _n
normal height map pattern = _nh

specular map pattern = _spec

A normal map with the _nh pattern additionally enables use of the normal map's alpha channel as height information. This can be used by a parallax mapping shader to offset the texture depending on the viewing angle and height, creating a fake 3d effect.

The above settings are not enabled by default, to prevent incompatibilities with mods that may be inadvertently using these naming schemes.

On the topic of shader settings, you may be interested in these three settings as well. In particular, 'clamp lighting = false' makes normal maps look much better!

[Shaders]
# Force rendering with shaders. By default, only bump-mapped objects will use shaders.
# Enabling this option may cause slightly different visuals if the "clamp lighting" option
# is set to false. Otherwise, there should not be a visual difference.
force shaders = false

# Force the use of per pixel lighting. By default, only bump mapped objects use per-pixel lighting.
# Has no effect if the 'force shaders' option is false.
# Enabling per-pixel lighting can result in visual differences to the original MW engine. It is not
# recommended to enable this option when using vanilla Morrowind files, because certain lights in Morrowind
# rely on vertex lighting to look as intended.
force per pixel lighting = false

# Restrict the amount of lighting that an object can receive to a maximum of (1,1,1).
# Only affects objects that render with shaders (see 'force shaders' option). Always affects terrain.
# Setting this option to 'true' results in fixed-function compatible lighting, but the lighting
# may appear 'dull' and there might be color shifts.
# Setting this option to 'false' results in more realistic lighting.
clamp lighting = true

Terrain

The terrain shader also supports normal, normal-height and specular maps, with one difference compared to objects: the specular value must be packed into the layer texture's alpha channel.

For example, if you wanted to add specular mapping to a terrain layer called rock.dds, you would copy this texture to a new file called rock_diffusespec.dds, and then edit its alpha channel to set the specular intensity.

The relevant settings are:

[Shaders]
auto use terrain normal maps = true

auto use terrain specular maps = true

terrain specular map pattern = _diffusespec

# Also used for terrain normal maps
normal map pattern = _n
normal height map pattern = _nh

OSG native files

OpenMW supports all the above shader features for meshes in the Native Mesh Format. To have the shader generator recognize specific textures, the osg::Texture2D must be named appropriately.

Available texture types are the following (most of which also have NIF equivalents):

  • diffuseMap: base texture
  • normalMap: normal map, as described earlier
  • normalHeightMap: same as normal map, but including height information in alpha channel to be used for parallax effects
  • emissiveMap: controls the material's emission, useful for objects that glow in the dark
  • darkMap: multiplied onto the base texture
  • detailMap: multiplied by 2 and then multiplied onto the base texture
  • envMap: spherical environment map
  • specularMap: specular map, as described earlier

The first texture unit automatically acts as diffuseMap if no recognized type is specified.

Example: .osgt file excerpt of a normal mapped mesh

                  TextureModeList 2 {
                    Data 1 {
                      GL_TEXTURE_2D ON
                    }
                    Data 1 {
                      GL_TEXTURE_2D ON
                    }
                  }
                  TextureAttributeList 2 {
                    Data 1 {
                      osg::Texture2D {
                        UniqueID 37
                        Name "diffuseMap"
                        WRAP_S REPEAT
                        WRAP_T REPEAT
                        WRAP_R REPEAT
                        MIN_FILTER LINEAR_MIPMAP_LINEAR
                        MAG_FILTER LINEAR
                        Image TRUE {
                          UniqueID 60
                          FileName "textures/BuddhaStatue_Dif.jpg"
                          WriteHint 2 2
                        }
                      }
                      Value OFF
                    }
                    Data 1 {
                      osg::Texture2D {
                        UniqueID 38
                        Name "normalMap"
                        WRAP_S REPEAT
                        WRAP_T REPEAT
                        WRAP_R REPEAT
                        MIN_FILTER LINEAR_MIPMAP_LINEAR
                        MAG_FILTER LINEAR
                        Image TRUE {
                          UniqueID 61
                          FileName "textures/BuddhaStatue_Nor.jpg"
                          WriteHint 2 2
                        }
                      }
                      Value OFF
                    }
                  }