Difference between revisions of "Materials in Oolite"

From Elite Wiki
(Material attributes dictionaries)
(Updating BB links)
 
(15 intermediate revisions by 4 users not shown)
Line 1: Line 1:
:<small>This page applies to Oolite 1.69 and later.</small>
+
Since v.1.87 (August 2018), more advanced options have become available. See [https://bb.oolite.space/viewtopic.php?f=2&t=19881 A Description of the Improved Lighting and Materials System] (2018), the attached update of Oct 2018 and the clarifications of May 2021.
Traditionally, the surface appearance of ships in Oolite has been defined entirely by textures specified in the ship’s model file and the ''[[#smooth|smooth]]'' attribute. Test release 1.67 added support for [[Shaders in Oolite|shaders]], and test release 1.69 expands this to a more flexible '''material model'''. Under the new model, the texture file names in model files have been repurposed as '''material keys'''. A material key specifies an entry in the ship’s '''material dictionary''', specified in the ship’s ''[[shipdata.plist]]'' entry. For backwards compatibility, if no material of a given name is found, a material is generated using the material key as a diffuse texture name – providing the same functionality as previous versions of Oolite.
 
  
 +
{{OXPNote|This page was last properly edited in 2013, well after the introduction of shaders but before [[User:Another commander|Another commander]]'s work on Oolite introducing specular & gloss maps, the new Oren-Nayar diffuse light model, high-definition graphic resolution ''etc''}}
  
=== The ''materials'' and ''shaders'' dictionary ===
+
Traditionally, the surface appearance of ships in Oolite has been defined entirely by textures specified in the ship’s model file and the ''[[#smooth|smooth]]'' attribute. Test release 1.67 added support for [[Shaders in Oolite|shaders]], and test release 1.69 expanded this to a more flexible '''material model'''. Under the new model, the texture file names in model files have been repurposed as '''material keys'''. A material key specifies an entry in the ship’s '''material dictionary''', specified in the ship’s ''[[shipdata.plist]]'' entry. For backwards compatibility, if no material of a given name is found, a material is generated using the material key as a diffuse texture name – providing the same functionality as previous versions of Oolite.
The '''material dictionary''' is actually specified as two separate dictionaries in the ''shipdata.plist'' entry. The first is called ''materials'', the second ''shaders''. If [[Shaders in Oolite|shader support]] is available and enabled, the entries in ''shaders'' are used in preference to those in ''materials''. Otherwise, ''shaders'' is ignored. The entries in the two dictionaries take exactly the same form, however; it is possible to specify a shader in the ''materials'' dictionary, and it will simply be ignored if shader support is not available. The ''materials'' and ''shaders'' dictionaries, merged together, are known as “the material dictionary”.
 
  
 +
This page documents the material model as of Oolite test release 1.74 (2010), and applies to stable release 1.76 (2011) and later.
 +
 +
== Important concepts ==
 +
The following concepts are important in understanding how materials work and how they interact with lights.
 +
* '''Colour''': Oolite uses a basic low dynamic range lighting model. Colours are considered to be lists of three values, representing red, green and blue colours, each ranging from 0 to 1. These are often encoded as integers ranging from 0 to 255 for technical reasons, but 0 to 1 is the true range of values. There may also be an associated ''alpha channel'', which is traditionally used for blending effects. In shaders, any colour channel can be used for any purpose, and textures often encode values that are not treated as colours.
 +
* '''Fragment''': roughty speaking, an on-screen pixel. When objects are rendered, their geometry is used to generate a fragments, which are then coloured based on lighting and materials.
 +
* '''Modulation''': multiplying two colours together, by channel. For instance, if the calculated light colour for a given fragment is pale yellow – [1, 1, 0.8] – and the corresponding part of the diffuse map is turquoise – [0.2, 0.8, 0.8] – the ''diffuse contribution'' is [0.2, 0.8, 0.64] (a greenish tint). In graphics programs, this blending mode is usually called ''Multiply''.
 +
* '''Additive blending''': adding two colours together, by channel. In Oolite’s low dynamic range lighting model, the result is always clipped to the range 0..1. In graphics programs, this blending mode is usually called ''Lighten''.
 +
* '''Normals''': All lighting calculations require a concept of the orientation of a surface relative to a light and, for reflections, relative to the camera. A surface oriented towards the light will be lighter than a surface oriented away from it. The ''normal'' for any given point on a surface is a vector pointing straight out, which for our purposes ''defines'' the concept of “straight out”.<br />By default, Oolite models have constant normals across each face. By setting the <code>smooth</code> attribute in [[shipdata.plist]], normals are instead interpolated across each face, with each vertex having a normal that is a weighted average of surounding faces’ normals, and each point on a surface getting a weighted average of the normals at the corners of the face. Using ''smooth groups'', a model can be divided into regions which are smoothed but have sharp boundaries between them. As of Oolite 1.74, models can also include explicit per-vertex normals instead of having Oolite calculate them – most 3D modellers export this information.<br />When using smoothing, it is important to understand that Oolite does not add any geometry,and will result in each vertex being lit as if it is locally flat. This is generally inappropriate for any sharp corner. If you set <code>smooth</code> on a basic cube, the result will be badly lit.
 +
* '''Diffuse reflection''': light that is reflected evenly in all directions. A “dull” surface primarily reflects diffusely. Because the light is reflected evenly in all directions, the diffuse term is independent of the camera position; it is a function of the light and the surface normal. The standard diffuse reflection term is the cosine of the angle between the direction to the light and the normal, or zero if this is negative – this is known as the [http://en.wikipedia.org/wiki/Lambertian_reflectance Lambertian reflectance model]. This value is then modulated with the material’s diffuse colour and diffuse map.
 +
* '''Specular reflection''': light that is reflected in a particular direction, producing a shiny effect. In real life, this is simply a mirror reflection which is generally darkened and blurred, leaving an enlarged, blurry reflection of bright light sources, with other objects being washed out so they aren’t noticeable. In Oolite, a simpler mathematical model called the [http://en.wikipedia.org/wiki/Blinn–Phong_shading_model Blinn-Phong shading model] is used.<br />[http://www.youtube.com/watch?v=76jvMmV1ih0 This video] demonstrates the effects of specular lighting and specular mapping on the built-in scarred alloy model.
 +
 +
== The material dictionary ==
 +
The '''material dictionary''' is actually specified as two separate dictionaries in the ''shipdata.plist'' entry. The first is called ''materials'', the second ''shaders''. If [[Shaders in Oolite|shader support]] is available and enabled, the entries in ''shaders'' are used in preference to those in ''materials''. Otherwise, ''shaders'' is ignored. The entries in the two dictionaries take exactly the same form, however; it is possible to specify a shader in the ''materials'' dictionary, and it will simply be ignored if shader support is not available. The ''materials'' and ''shaders'' dictionaries, merged together, are known as a ''material dictionary''.
 +
 +
=== Material specifiers ===
 +
The material dictionary is a [[property list]] dictionary whose keys are ''material keys'' as defined below, and whose values are '''material specifiers''', which are either dictionaries or strings. When a string is used as a material specifier, it is equivalent to a dictionary with that string as the value for '''diffuse_map''', and no other properties. Currently-supported material specifier keys are listed here; “texture specifier” and similar are defined below.
 +
 +
Most of these keys have no effect when a custom shader is in effect.
 +
 +
When shaders are disabled or not available, emission and illumination maps are supported only if reduced detail is disabled and the graphics hardware supports multi-texturing. If '''emission_modulate_color''', '''illumination_map''', or '''emission_and_illumination_map''' are used, Oolite must combine them into a single emission map. It is generally preferable to do this in advance (by modulating the illumination map with the diffuse map and blending it additively with the emission map, after applying any colouring). This is more efficient when using shaders, too.
  
=== Material attributes dictionaries ===
 
The material dictionary is a [[property list]] dictionary whose keys are material keys as defined above, and whose values are '''material attribute dictionaries'''. Currently-supported material attribute dictionary keys are listed here; “texture specifier” and similar are defined below.
 
 
{| class="wikitable" border="1" cellpadding="3" cellspacing="0"
 
{| class="wikitable" border="1" cellpadding="3" cellspacing="0"
 
|+ General material attribues
 
|+ General material attribues
 
! Name !! Type !! Description
 
! Name !! Type !! Description
 
|-
 
|-
| '''ambient''' || colour&nbsp;specifier || The ambient colour of the entity, that is, the colour reflected evenly in all directions by starlight. By default, this is the same as '''diffuse'''.
+
| '''ambient_color''' || [[#Colour specifiers|colour&nbsp;specifier]] || The ambient colour of the entity, that is, the colour reflected evenly in all directions by starlight. If there is a '''diffuse_map''', the '''ambient_color''' is modulated by the '''diffuse_map'''. Default: white (1.0, 1.0, 1.0, 1.0).
 
|-
 
|-
| '''diffuse''' || colour&nbsp;specifier || Overall diffuse colour of the entity; that is, the colour reflected in a “non-shiny” way on the sunlit side of the entity. If both '''diffuse''' and '''diffuse_map''' are specified, the texture is “dyed” with this colour. Default: white (1.0, 1.0, 1.0, 1.0).
+
| '''diffuse_color''' || [[#Colour specifiers|colour&nbsp;specifier]] || Overall diffuse colour of the entity; that is, the colour reflected in a “non-shiny” way on the sunlit side of the entity. If there is a '''diffuse_map''', the '''diffuse_color''' is modulated by the '''diffuse_map'''. Default: white (1.0, 1.0, 1.0, 1.0).
 
|-
 
|-
| '''diffuse_map''' || texture&nbsp;specifier || A texture specifying the basic colour of the material. This is a “normal” texture, the same as you get without a material dictionary. If not specified, the material key will be used. To specify no texture, use an empty string for '''diffuse_map'''. Ignored when using shaders.
+
| '''diffuse_map''' || [[#Texture specifiers|texture&nbsp;specifier]] || A texture specifying the basic colour of the material. This is a “normal” texture, the same as you get without a material dictionary. If not specified, the material key will be used. To specify no texture, use an empty string for '''diffuse_map'''. Ignored when using shaders.
 
|-
 
|-
| '''emission''' || colour&nbsp;specifier || The emitted (glow) colour of the material. Default: black (0.0, 0.0, 0.0, 1.0).
+
| '''emission_color''' || [[#Colour specifiers|colour&nbsp;specifier]] || The emitted (glow) colour of the material. This is ignored when '''emission_map''' is in use (but see also: '''emission_modulate_color'''). Default: black (0.0, 0.0, 0.0, 1.0).
 
|-
 
|-
| '''shininess''' || integer || The “tightness” of specular reflect, ranging from 0 to 128. 0 means no specular highlight. Default: 0 in shader mode and 10 in non-shader mode. From Oolite 1.74, it will default to 128 if '''specular_map''' is used and 10 otherwise.
+
| '''emission_map''' || [[#Texture specifiers|texture&nbsp;specifier]] || A texture specifying emission (glow) colours. This is blended additively with all other colour terms. If '''emission_modulate_color''' is specified, the emission map is modulated by the modulate colour. Emission maps are used when shaders are active, and without shaders on supported hardware.
 
|-
 
|-
| '''specular''' || colour&nbsp;specifier || The specular (shiny reflection) colour of the material. This is ignored if shininess is not 1 or more. Default: black (0.0, 0.0, 0.0, 1.0) in shader mode and (0.2, 0.2, 0.2, 1.0) in non-shader mode. From Oolite 1.74, it will default to white (1.0, 1.0, 1.0, 1.0) if '''specular_map''' is used and (0.2, 0.2, 0.2, 1.0) otherwise.
+
| '''emission_modulate_color''' || [[#Colour specifiers|colour&nbsp;specifier]] || A colour with which to modulate the '''emission_map'''. If the emission map is in full colour, it is best to apply the colouring in advance using a graphics program. However, if the emission map is a single colour, using a greyscale emission map and a modulate colour will reduce memory usage by a factor of four when shaders are in use. Default: white (1.0, 1.0, 1.0, 1.0).
 
|-
 
|-
| '''textures''' || array&nbsp;of&nbsp;texture&nbsp;specifiers || Textures to use in shader program.
+
| '''emission_and_illumination_map''' || [[#Texture specifiers|texture&nbsp;specifier]] || A texture whose RGB channels act like '''emission_map''', and whose alpha channel acts like '''illumination_map''' (and can be coloured with '''illumination_modulate_color'''). This uses less memory (on systems with shaders) than using separate shaders, although blending the emission and illumination maps into a single emission map, as described above, is still preferable.
 
|-
 
|-
|}
+
| '''illumination_map''' || [[#Texture specifiers|texture&nbsp;specifier]] || A texture specifying local illumination colour, which is added to incoming light. It differs from an emission map in that it is modulated with the diffuse colour before being added to the final colour. See example below.
 
+
|-
 
+
| '''illumination_modulate_color''' || [[#Colour specifiers|colour&nbsp;specifier]] || A colour with which to modulate the '''illumination_map'''. Default: white (1.0, 1.0, 1.0, 1.0).
The following attributes are only supported if shader support is active:
 
{| class="wikitable" border="1" cellpadding="3" cellspacing="0"
 
|+ Shader material attribues
 
! Name !! Type !! Description
 
 
|-
 
|-
| '''emission_map''' || texture&nbsp;specifier || A texture specifying emission (glow) colours. If both '''emission''' and '''emission_map''' are specified, the values of the '''emission_map''' will be multiplied by '''emission'''. Emission mapping is available in Oolite 1.70 and later with shaders enabled, for materials with no custom shader.
+
| '''normal_map''' || [[#Texture specifiers|texture&nbsp;specifier]] || A texture modifying [[#Important concepts|normals]]. The red, green and blue channels are the x, y and z coordinates of normals relative to the underlying normal (“[http://en.wikipedia.org/wiki/Normal_mapping tangent-space normal mapping]”), and the alpha channel is ingored. This is only used when shaders are active and no custom shader is used.
 
|-
 
|-
| '''emission_and_illumination_map''' || texture&nbsp;specifier || A texture whose RGB channels act like '''emission_map''', and whose alpha channel acts much like '''illumination_map''', adding white light, for materials with no custom shader.
+
| '''normal_and_parallax_map''' || [[#Texture specifiers|texture&nbsp;specifier]] || Like '''normal_map''', except that the alpha channel is includes a depth value used to add [http://en.wikipedia.org/wiki/Parallax_mapping simulated perspective]. If specified, '''normal_map''' is ignored.
 
|-
 
|-
| '''illumination_map''' || texture&nbsp;specifier || A texture specifying local illumination colour, which is added to incoming light. (This is useful for things like hull spotlights.) Illumination mapping is available in Oolite 1.70 and later with shaders enabled, for materials with no custom shader.
+
| '''parallax_bias''' || number || A value added to the parallax component of '''normal_and_parallax_map''', after multiplying by '''parallax_scale''' (default: 0).
 
|-
 
|-
| '''illumination_color ''' || colour&nbsp;specifier || A colour to modify the illumination map with (available in Oolite 1.74 or later).
+
| '''parallax_scale''' || number || A scale factor for the parallax component of '''normal_and_parallax_map''' (default: 0.01). This value is the depth of the parallax map relative to the size of the texture. For instance, a value of 0.01 on a texture 100 metres wide will produce a maximum indentation of 1 metre. High parallax_scale values tend to lead to unacceptable texture distortion and “creeping” artefacts.
 
|-
 
|-
| '''fragment_shader''' || file&nbsp;name || name of GLSL fragment program to use.
+
| '''specular_color''' || [[#Colour specifiers|colour&nbsp;specifier]] || The colour to use for specular reflection over the entire model when '''specular_map''' is not used. The specular term is added to the diffuse term; for less intense specular highlights, use a darker colour. Default: black (0.0, 0.0, 0.0, 1.0) if '''shininess''' is zero, (0.2, 0.2, 0.2, 1.0) otherwise.  
 
|-
 
|-
| '''normal_map''' || texture&nbsp;specifier || A texture modifying [[normals (3D)|normals]]. The red, green and blue channels are the x, y and z coordinates of tangent-space normals, and the alpha channel is ignored.
+
| '''specular_map''' || [[#Texture specifiers|texture&nbsp;specifier]] || A texture specifying the specular highlight colour in its red, green and blue channels, and '''shininess''' in its alpha channel. 1 (fully opaque) means the value of '''shininess''' is used. 0 means a very low shininess is used. This is only used when shaders are active and no custom shader is used.
 
|-
 
|-
| '''normal_and_parallax_map''' || texture&nbsp;specifier || Like '''normal_map''', except that the alpha channel is includes a depth value. If specified, '''normal_map''' is ignored. The parallax component is ignored in simple shader mode.
+
| '''specular_modulate_color''' || [[#Colour specifiers|colour&nbsp;specifier]] || A colour with which to modulate the '''specular_map'''. Default: white (1.0, 1.0, 1.0, 1.0).
 
|-
 
|-
| '''parallax_bias''' || number || A value added to the parallax component of '''normal_and_parallax_map''', after multiplying by '''parallax_scale''' (default: 0).
+
| '''shininess''' || integer || The “tightness” of specular reflection, ranging from 0 to 128. 0 means no specular highlight. 128 is maximally shiny. Default: 128 if '''specular_map''' is used, 10 otherwise. '''Limitation:''' to use different shininess values with '''specular_map''' or '''specular_color''', you must either use the default or use different “shaders” and “materials” dictionaries. This should be fixed for 1.75.
 
|-
 
|-
| '''parallax_scale''' || number || A scale factor for the parallax component of '''normal_and_parallax_map''' (default: 0.01).
+
| '''vertex_shader''' || file&nbsp;name || name of GLSL vertex program to use.
 
|-
 
|-
| '''specular_map''' || texture&nbsp;specifier || A texture modifying '''specular''' and '''shininess'''. The colour channels of the '''specular''' value are multiplied by the '''specular_map''' colour values, and the '''shininess''' value is scaled by the alpha channel of the '''specular_map'''. Specular mapping is available in Oolite 1.70 and later with shaders enabled, for materials with no custom shader.
+
| '''fragment_shader''' || file&nbsp;name || name of GLSL fragment program to use.
 
|-
 
|-
| '''textures''' || array of texture&nbsp;specifiers || Textures to use in shader program.
+
| '''textures''' || array&nbsp;of&nbsp;[[#Texture specifiers|texture&nbsp;specifier]]s || Textures to use in shader program.
 
|-
 
|-
 
| '''uniforms''' || dictionary of uniform&nbsp;variable&nbsp;specifiers || uniform variables to use in shader program.
 
| '''uniforms''' || dictionary of uniform&nbsp;variable&nbsp;specifiers || uniform variables to use in shader program.
|-
 
| '''vertex_shader''' || file&nbsp;name || name of GLSL vertex program to use.
 
 
|-
 
|-
 
|}
 
|}
 
  
 
==== Illumination mapping vs. emission mapping ====
 
==== Illumination mapping vs. emission mapping ====
Line 71: Line 82:
 
=== Colour specifiers ===
 
=== Colour specifiers ===
 
'''Colour specifiers''' are used to declare colours in material attribute dictionaries, and in other contexts such as lasers in ''[[shipdata.plist]]''. Colour specifiers take any of several forms:
 
'''Colour specifiers''' are used to declare colours in material attribute dictionaries, and in other contexts such as lasers in ''[[shipdata.plist]]''. Colour specifiers take any of several forms:
 
  
 
==== Named colours ====
 
==== Named colours ====
Line 83: Line 93:
 
| darkGrayColor || 1/3, 1/3, 1/3, 1
 
| darkGrayColor || 1/3, 1/3, 1/3, 1
 
|-
 
|-
| lightGrayColor || 1/6, 1/6, 1/6, 1
+
| lightGrayColor || 2/3, 2/3, 2/3, 1
 
|-
 
|-
 
| whiteColor || 1, 1, 1, 1
 
| whiteColor || 1, 1, 1, 1
Line 110: Line 120:
 
|-
 
|-
 
|}
 
|}
 
  
 
==== RGBA tuples ====
 
==== RGBA tuples ====
 
Colours may also be specified in RGB or RGBA (red, green, blue, alpha [transparency]). RGB or RGBA tuples may be specified as arrays or as strings separated by spaces. The values may range from 0 to 1 or 0 to 255. (If no value is greater than 1, 0–1 is assumed, otherwise 0–255.) Examples:
 
Colours may also be specified in RGB or RGBA (red, green, blue, alpha [transparency]). RGB or RGBA tuples may be specified as arrays or as strings separated by spaces. The values may range from 0 to 1 or 0 to 255. (If no value is greater than 1, 0–1 is assumed, otherwise 0–255.) Examples:
* <code>&lt;string>1 1 0&lt;/string> &lt;!-- yellow --></code>
+
* <code>"1 1 0"</code> — yellow
* <code>&lt;string>0 128 0 128&lt;/string> &lt;!-- medium green at 50% opacity --></code>
+
* <code>"0 128 0 128"</code> medium green at 50% opacity
* <code>&lt;array>&lt;real>1&lt;/real> &lt;real>0&lt;/real> &lt;real>0&lt;/real>&lt;/array> &lt;!-- red --></code>
+
* <code>(1, 0, 0)</code> – red
  
  
 
==== RGBA dictionaries ====
 
==== RGBA dictionaries ====
 
Just in case you’re unsure of the order the RGB[A] components come in, you can use a dictionary:
 
Just in case you’re unsure of the order the RGB[A] components come in, you can use a dictionary:
  &lt;dict>
+
  {
    &lt;key>blue&lt;/key> &lt;real>0.8&lt;/real>
+
    blue = 0.8;
    &lt;key>green&lt;/key> &lt;real>0.8&lt;/real>
+
    green = 0.8;
  &lt;/dict>
+
  }
 
Accepted keys are '''red''', '''green''', '''blue''' and '''alpha''' (or '''opacity'''), all optional (default: 0.0 for red, green and blue, 1.0 for alpha).
 
Accepted keys are '''red''', '''green''', '''blue''' and '''alpha''' (or '''opacity'''), all optional (default: 0.0 for red, green and blue, 1.0 for alpha).
 
  
 
==== HSBA dictionaries ====
 
==== HSBA dictionaries ====
 
But wait, there’s more! Colours may also be specified as dictionaries in the [http://en.wikipedia.org/wiki/HSB_colour_space HSB colour space]. Accepted keys are '''hue''' (hue angle in degrees, required), '''saturation''', '''brightness''' (or '''value''') and '''alpha''' (or '''opacity'''). The default for the optional keys is 1.0.
 
But wait, there’s more! Colours may also be specified as dictionaries in the [http://en.wikipedia.org/wiki/HSB_colour_space HSB colour space]. Accepted keys are '''hue''' (hue angle in degrees, required), '''saturation''', '''brightness''' (or '''value''') and '''alpha''' (or '''opacity'''). The default for the optional keys is 1.0.
  &lt;dict>
+
  {
    &lt;!-- Pale magenta -->
+
    // Pale magenta
    &lt;key>hue&lt;/key> &lt;real>300&lt;/real>
+
    hue = 300;
    &lt;key>saturation&lt;/key> &lt;real>0.3&lt;/real>
+
    saturation = 0.3;
  &lt;/dict>
+
  }
  
 
=== Texture specifiers ===
 
=== Texture specifiers ===
'''Texture specifiers''' are used to, er, specify textures. The simplest form of texture specifier is a string: <code>&lt;string>ahruman-example-texture.png&lt;/string></code>. The very simplest texture specifier is the empty string, <code>&lt;string/></code> (or <code>""</code> in OpenStep style property lists), meaning no texture. More complex texture specifiers are dictionaries, which can be used to specify a number of texture options.
+
'''Texture specifiers''' are used to, er, specify textures. The simplest form of texture specifier is a string: <code>"ahruman-example-texture.png"</code>. The very simplest texture specifier is the empty string, <code>""</code>, meaning no texture. More complex texture specifiers are dictionaries, which can be used to specify a number of texture options.
 
{| class="wikitable" border="1" cellpadding="3" cellspacing="0"
 
{| class="wikitable" border="1" cellpadding="3" cellspacing="0"
 
|+ Texture specifier attributes
 
|+ Texture specifier attributes
Line 143: Line 151:
 
|-
 
|-
 
| '''anisotropy''' || real || The degree of [http://en.wikipedia.org/wiki/Anisotropic_filtering anisotropic filtering] to use. Anisotropic filtering is used to reduce blurriness of MIP mapped textures shown at an angle (and thus only applies to textures whose '''min_filter''' is '''mipmap''' or '''default'''). The '''anisotropy''' setting is multiplied by the maximum anisotropy level specified by the system, and anisotropic filtering is used only if the result is greater than 1. (For example, on a GeForce FX 5200 card, the maximum level is 8, so an anisotropy value of 0.5 means an effective anisotropic filtering strength of 4. The precise meaning of this number is hardware-dependant. Fun, eh?) Anisotropic filtering is disabled in Reduced Detail mode and is not available on all hardware. Default: 0.5.
 
| '''anisotropy''' || real || The degree of [http://en.wikipedia.org/wiki/Anisotropic_filtering anisotropic filtering] to use. Anisotropic filtering is used to reduce blurriness of MIP mapped textures shown at an angle (and thus only applies to textures whose '''min_filter''' is '''mipmap''' or '''default'''). The '''anisotropy''' setting is multiplied by the maximum anisotropy level specified by the system, and anisotropic filtering is used only if the result is greater than 1. (For example, on a GeForce FX 5200 card, the maximum level is 8, so an anisotropy value of 0.5 means an effective anisotropic filtering strength of 4. The precise meaning of this number is hardware-dependant. Fun, eh?) Anisotropic filtering is disabled in Reduced Detail mode and is not available on all hardware. Default: 0.5.
 +
|-
 +
| '''cube_map''' || boolean || If this is true, and the texture file is six times as high as it is wide, the texture will be treated as a cube map. If cube maps are not supported, it will be converted to a latitude/longitude map; if used as a diffuse map or emission/illumination map, you must ensure the model has appropriate texture coordinates. Note that cube maps are always available if shaders are supported, so custom shaders do not need to worry about this.
 +
 +
'''cube_map''' is always true for planet textures. To convert textures to and from cube maps, see [[planettool]].
 +
|-
 +
| '''extract_channel''' || string || Indicates that one of the channels of the texture should be extracted into a new greyscale texture. Allowed values: '''r''', '''g''', '''b''' and '''a'''.
 +
 +
This obviously involves extra work for Oolite, which is always a bad thing, but it makes it possible to combine multiple effect maps in a single texture for shaders and then extract channels for use as emission or illumination maps without shipping a redundant texture. If this means nothing to you, you probably don’t want to use '''extract_channel'''.
 
|-
 
|-
 
| '''mag_filter''' || string || Specifies how to scale up the texture when it is near the camera. Either of:
 
| '''mag_filter''' || string || Specifies how to scale up the texture when it is near the camera. Either of:
Line 156: Line 172:
 
Default: '''default'''.
 
Default: '''default'''.
 
|-
 
|-
| '''name''' || string || The file name of the texture to use. Must be a PNG image, in the Textures folder of Oolite or an OXP.
+
| '''name''' || string || The file name of the texture to use. Must be a PNG image, in the Textures folder of Oolite or an OXP. In the specific case of '''diffuse_map''' textures, '''name''' is implicitly the same as the material key; to use no texture, you must specify <code>diffuse_map = ""</code>.
 
|-
 
|-
 
| '''no_shrink''' || boolean || Indicates that Oolite should not scale the texture down, except to meet hardware requirements. Default: false.
 
| '''no_shrink''' || boolean || Indicates that Oolite should not scale the texture down, except to meet hardware requirements. Default: false.
Line 167: Line 183:
 
|-
 
|-
 
|}
 
|}
 
  
 
=== Uniform specifiers ===
 
=== Uniform specifiers ===
 
:''Main article: [[Shaders in Oolite: uniforms]]''
 
:''Main article: [[Shaders in Oolite: uniforms]]''
A ''uniform specifier'' is used to specify game information to pass to a [[Shaders in oolite|shader program]]. As with [[#Texture specifiers|texture specifiers]], the simple case is a string. For instance, <code>&lt;key>uHullHeatLevel&lt;/key> &lt;string>hullHeatLevel&lt;/string></code> will bind a shader’s <code>uHullHeatLevel</code> uniform to a ship’s <code>hullHeatLevel</code> property. Additional properties can be specified in a dictionary.
+
A ''uniform specifier'' is used to specify game information to pass to a [[Shaders in Oolite|shader program]]. As with [[#Texture specifiers|texture specifiers]], the simple case is a string, which is treated as <code>{ binding = "the string" }</code>. For instance, uHullHeatLevel = hullHeatLevel</code> will bind a shader’s <code>uHullHeatLevel</code> uniform to a ship’s <code>hullHeatLevel</code> property. Additional properties can be specified in a dictionary.
 
{| class="wikitable" border="1" cellpadding="3" cellspacing="0"
 
{| class="wikitable" border="1" cellpadding="3" cellspacing="0"
 
|+ Texture specifier attributes
 
|+ Texture specifier attributes
 
! Name !! Type !! Description
 
! Name !! Type !! Description
 
|-
 
|-
| '''asMatrix''' || boolean || For a '''binding''' uniform whose bound property is of type ''quaternion'', setting '''asMatrix''' to true causes the value to be converted to a rotation matrix. If '''asMatrix''' is false, the quaternion will be converted to a vector, whose w, x, y and z values match those of the quaternion. For any other type of uniform, '''clamped''' is ignored. Default: true.
+
| '''asMatrix''' || boolean || For a '''binding''' uniform whose bound property is of type ''quaternion'', setting '''asMatrix''' to true causes the value to be converted to a rotation matrix. If '''asMatrix''' is false, the quaternion will be converted to a vector, whose w, x, y and z values match those of the quaternion. For any other type of uniform, '''asMatrix''' is ignored. Default: true.
 
|-
 
|-
 
| '''binding''' || string || The entity property to bind to, for a '''binding''' uniform. Ignored for other types of uniform.
 
| '''binding''' || string || The entity property to bind to, for a '''binding''' uniform. Ignored for other types of uniform.
 
|-
 
|-
| '''clamped''' || boolean || For a '''binding''' uniform whose bound property is of type ''float'', setting '''clamped''' to true causes the value to be restricted to the range 0 to 1, inclusive. For a binding of type ''int'', causes the value to be set to either 0 or 1; 1 indicates that the underlying property has any value other than 0. For any other type of uniform, '''asMatrix''' is ignored. Default: false.
+
| '''clamped''' || boolean || For a '''binding''' uniform whose bound property is of type ''float'', setting '''clamped''' to true causes the value to be restricted to the range 0 to 1, inclusive. For a binding of type ''int'', causes the value to be set to either 0 or 1; 1 indicates that the underlying property has any value other than 0. For any other type of uniform, '''clamped''' is ignored. Default: false.
 
|-
 
|-
 
| '''normalized''' || boolean || For a '''binding''' uniform whose bound property is of type ''vector'', setting '''normalized''' to true causes the value to be normalized, that is, scaled to a length of 1. For any other type of uniform, '''normalized''' is ignored. The spelling '''normalised''' is also accepted. Default: false.
 
| '''normalized''' || boolean || For a '''binding''' uniform whose bound property is of type ''vector'', setting '''normalized''' to true causes the value to be normalized, that is, scaled to a length of 1. For any other type of uniform, '''normalized''' is ignored. The spelling '''normalised''' is also accepted. Default: false.
Line 188: Line 203:
 
* '''float''' or '''real''': indicates that the '''value''' property is an floating-point number.
 
* '''float''' or '''real''': indicates that the '''value''' property is an floating-point number.
 
* '''int''' or '''integer''': indicates that the '''value''' property is an integer, or whole number.
 
* '''int''' or '''integer''': indicates that the '''value''' property is an integer, or whole number.
* '''texture''': indicates that the '''value''' property is an integer specifying a texture unit, that is, an index in the '''textures''' array. This lets you select an alternative to the standard texture names '''tex0''', '''tex1''' etc.
+
* '''texture''': indicates that the '''value''' property is an integer specifying a texture unit, that is, an index in the '''textures''' array.
 
Default: '''float'''.
 
Default: '''float'''.
 
|-
 
|-
| '''value''' || number || The value to use for a '''float''', '''integer''' or '''texture''' uniform. Ignored for '''binding''' uniforms.
+
| '''value''' || number || The value to use for a '''float''', '''int''' or '''texture''' uniform. Ignored for '''binding''' uniforms.
 
|-
 
|-
 
|}
 
|}
 
  
 
=== Material dictionary example ===
 
=== Material dictionary example ===
Here is an example from the Oolite 1.69 version of [[Freaky Thargoids OXP|Freaky Thargoids]]:
+
Here is an example from the [[Material Test Suite OXP]]:
  <key>shaders</key>
+
  materials =
<dict>
 
    <key>thargoid_redux.png</key><!-- replace this texture -->
 
    <dict>
 
        <key>textures</key>
 
        <array>
 
            <string> thargoid_redux.png</string><!-- passed as tex0 -->
 
            <dict>
 
                <!-- passed as tex1 -->
 
                <key>name</key>
 
                <string>thargoid-glow.png</string>
 
                <key>mag_filter</key><!-- no mip-map (added purely for demonstration purposes) -->
 
                <string>linear</string>
 
            </dict>
 
        </array>
 
        <key>fragment_shader</key>
 
        <string>freaky_thargoid.fragment</string>
 
        <key>vertex_shader</key>
 
        <string>freaky_thargoid.vertex</string>
 
        <key>uniforms</key>
 
        <dict>
 
            <key>uTime</key>
 
            <!-- Alternatively, universalTime may be used, in which case all thargoids will pulse in sync. -->
 
            <string>timeElapsedSinceSpawn</string>
 
            <key>uReciprocalFrequency</key>
 
            <dict>
 
                <key>value</key>
 
                <real>1.0</real>
 
            </dict>
 
        </dict>
 
    </dict>
 
</dict>
 
…or, in OpenStep format:
 
shaders =
 
 
  {
 
  {
     "thargoid_redux.png" = // replace this texture
+
     "cube-face" =
 
     {
 
     {
         textures =
+
         diffuse_map = "oolite_shader_test_suite_7_diffuse.png";
        (
+
        emission_and_illumination_map = "oolite_shader_test_suite_emission_and_illumination.png";
            "thargoid_redux.png",  // passed as tex0
+
        emission_modulate_color = (160, 255, 160);
            {
+
         illumination_modulate_color = (180, 180, 200);
                name = "thargoid-glow.png"; // passed as tex1
 
                mag_filter = linear;        // no mip-map (added purely for demonstration purposes)
 
            }
 
        );
 
         fragment_shader = "freaky_thargoid.fragment";
 
        vertex_shader = "freaky_thargoid.vertex";
 
        uniforms =
 
        {
 
            // Alternatively, universalTime may be used, in which case all thargoids will pulse in sync.
 
            "uTime" = "timeElapsedSinceSpawn";
 
            "uReciprocalFrequency" = { value = 1.0; };
 
        };
 
 
     };
 
     };
 
  };
 
  };
This means that, if shaders are available, the material named “thargon_redux.png” will use a vertex and fragment shader pair called ''freaky_thargoid.vertex'' and ''freaky_thargoid.fragment''; that the textures used by these shaders are ''thargon-base.png'' and ''thargon-glow.png'', and that the latter should use '''linear''' magnification filtering; and that the shaders use two uniform variables, ''uTime'' and ''uReciprocalFrequency''. ''uTime'' is bound to the property ''timeElapsedSinceSpawn'', while ''uReciprocalFrequency'' is a constant float with the value 1.0. A similar configuration is used for the tharglet, but ''uReciprocalFrequency'' is set to 1.5. This allows the same texture to be used by two different ships, animating at different speeds.
+
Here, the “cube-face” material is assigned the diffuse texture “oolite_shader_test_suite_7_diffuse.png” and a combined emission and illumination map (which is a greyscale+alpha texture). The emission and illumination components are then given coloured tints (slightly green and slightly blue, respectively), producing this:
 +
 
 +
[[File:Oolite Material Test Suite 7.png|320px]]
 +
 
 +
[[File:Viper Griff Specgloss.png|thumb|right|640px|Griff's SpecGloss Viper]]
 +
== See also ==
 +
* [[Material Test Suite OXP]] — demonstrates most material properties.
 +
* [[Library OXP]] also has a couple of add-on tools ([[MatFinder]] & DevTools) which enable you to play around with all this and see the effects
 +
* [https://bb.oolite.space/viewtopic.php?p=285081#p285081 Specular Maps Alpha channel]: more by a_c_ (2022)
 +
* [https://bb.oolite.space/viewtopic.php?f=4&t=21170 griff SpecGloss ships]: some q's & a's about colour corrections (2022)
 +
:Also contains Griff's SpecGloss models of the Cobra Mk.1, Gecko, Mamba, Sidewinder & Viper
 +
* [https://bb.oolite.space/viewtopic.php?p=293033#p293033 Is there a (shipdata) variable with which I can reduce the amount of influence an emission or illumination map has?] (2023) Answers involve using the varieties of "_modulate_color" listed above - and shows an example of what happens.
 +
 
  
[[Category: Oolite]]
+
[[Category: Oolite]] [[Category:Oolite_scripting]]
[[Category:Oolite scripting]]
 

Latest revision as of 02:08, 29 February 2024

Since v.1.87 (August 2018), more advanced options have become available. See A Description of the Improved Lighting and Materials System (2018), the attached update of Oct 2018 and the clarifications of May 2021.

Traditionally, the surface appearance of ships in Oolite has been defined entirely by textures specified in the ship’s model file and the smooth attribute. Test release 1.67 added support for shaders, and test release 1.69 expanded this to a more flexible material model. Under the new model, the texture file names in model files have been repurposed as material keys. A material key specifies an entry in the ship’s material dictionary, specified in the ship’s shipdata.plist entry. For backwards compatibility, if no material of a given name is found, a material is generated using the material key as a diffuse texture name – providing the same functionality as previous versions of Oolite.

This page documents the material model as of Oolite test release 1.74 (2010), and applies to stable release 1.76 (2011) and later.

Important concepts

The following concepts are important in understanding how materials work and how they interact with lights.

  • Colour: Oolite uses a basic low dynamic range lighting model. Colours are considered to be lists of three values, representing red, green and blue colours, each ranging from 0 to 1. These are often encoded as integers ranging from 0 to 255 for technical reasons, but 0 to 1 is the true range of values. There may also be an associated alpha channel, which is traditionally used for blending effects. In shaders, any colour channel can be used for any purpose, and textures often encode values that are not treated as colours.
  • Fragment: roughty speaking, an on-screen pixel. When objects are rendered, their geometry is used to generate a fragments, which are then coloured based on lighting and materials.
  • Modulation: multiplying two colours together, by channel. For instance, if the calculated light colour for a given fragment is pale yellow – [1, 1, 0.8] – and the corresponding part of the diffuse map is turquoise – [0.2, 0.8, 0.8] – the diffuse contribution is [0.2, 0.8, 0.64] (a greenish tint). In graphics programs, this blending mode is usually called Multiply.
  • Additive blending: adding two colours together, by channel. In Oolite’s low dynamic range lighting model, the result is always clipped to the range 0..1. In graphics programs, this blending mode is usually called Lighten.
  • Normals: All lighting calculations require a concept of the orientation of a surface relative to a light and, for reflections, relative to the camera. A surface oriented towards the light will be lighter than a surface oriented away from it. The normal for any given point on a surface is a vector pointing straight out, which for our purposes defines the concept of “straight out”.
    By default, Oolite models have constant normals across each face. By setting the smooth attribute in shipdata.plist, normals are instead interpolated across each face, with each vertex having a normal that is a weighted average of surounding faces’ normals, and each point on a surface getting a weighted average of the normals at the corners of the face. Using smooth groups, a model can be divided into regions which are smoothed but have sharp boundaries between them. As of Oolite 1.74, models can also include explicit per-vertex normals instead of having Oolite calculate them – most 3D modellers export this information.
    When using smoothing, it is important to understand that Oolite does not add any geometry,and will result in each vertex being lit as if it is locally flat. This is generally inappropriate for any sharp corner. If you set smooth on a basic cube, the result will be badly lit.
  • Diffuse reflection: light that is reflected evenly in all directions. A “dull” surface primarily reflects diffusely. Because the light is reflected evenly in all directions, the diffuse term is independent of the camera position; it is a function of the light and the surface normal. The standard diffuse reflection term is the cosine of the angle between the direction to the light and the normal, or zero if this is negative – this is known as the Lambertian reflectance model. This value is then modulated with the material’s diffuse colour and diffuse map.
  • Specular reflection: light that is reflected in a particular direction, producing a shiny effect. In real life, this is simply a mirror reflection which is generally darkened and blurred, leaving an enlarged, blurry reflection of bright light sources, with other objects being washed out so they aren’t noticeable. In Oolite, a simpler mathematical model called the Blinn-Phong shading model is used.
    This video demonstrates the effects of specular lighting and specular mapping on the built-in scarred alloy model.

The material dictionary

The material dictionary is actually specified as two separate dictionaries in the shipdata.plist entry. The first is called materials, the second shaders. If shader support is available and enabled, the entries in shaders are used in preference to those in materials. Otherwise, shaders is ignored. The entries in the two dictionaries take exactly the same form, however; it is possible to specify a shader in the materials dictionary, and it will simply be ignored if shader support is not available. The materials and shaders dictionaries, merged together, are known as a material dictionary.

Material specifiers

The material dictionary is a property list dictionary whose keys are material keys as defined below, and whose values are material specifiers, which are either dictionaries or strings. When a string is used as a material specifier, it is equivalent to a dictionary with that string as the value for diffuse_map, and no other properties. Currently-supported material specifier keys are listed here; “texture specifier” and similar are defined below.

Most of these keys have no effect when a custom shader is in effect.

When shaders are disabled or not available, emission and illumination maps are supported only if reduced detail is disabled and the graphics hardware supports multi-texturing. If emission_modulate_color, illumination_map, or emission_and_illumination_map are used, Oolite must combine them into a single emission map. It is generally preferable to do this in advance (by modulating the illumination map with the diffuse map and blending it additively with the emission map, after applying any colouring). This is more efficient when using shaders, too.

General material attribues
Name Type Description
ambient_color colour specifier The ambient colour of the entity, that is, the colour reflected evenly in all directions by starlight. If there is a diffuse_map, the ambient_color is modulated by the diffuse_map. Default: white (1.0, 1.0, 1.0, 1.0).
diffuse_color colour specifier Overall diffuse colour of the entity; that is, the colour reflected in a “non-shiny” way on the sunlit side of the entity. If there is a diffuse_map, the diffuse_color is modulated by the diffuse_map. Default: white (1.0, 1.0, 1.0, 1.0).
diffuse_map texture specifier A texture specifying the basic colour of the material. This is a “normal” texture, the same as you get without a material dictionary. If not specified, the material key will be used. To specify no texture, use an empty string for diffuse_map. Ignored when using shaders.
emission_color colour specifier The emitted (glow) colour of the material. This is ignored when emission_map is in use (but see also: emission_modulate_color). Default: black (0.0, 0.0, 0.0, 1.0).
emission_map texture specifier A texture specifying emission (glow) colours. This is blended additively with all other colour terms. If emission_modulate_color is specified, the emission map is modulated by the modulate colour. Emission maps are used when shaders are active, and without shaders on supported hardware.
emission_modulate_color colour specifier A colour with which to modulate the emission_map. If the emission map is in full colour, it is best to apply the colouring in advance using a graphics program. However, if the emission map is a single colour, using a greyscale emission map and a modulate colour will reduce memory usage by a factor of four when shaders are in use. Default: white (1.0, 1.0, 1.0, 1.0).
emission_and_illumination_map texture specifier A texture whose RGB channels act like emission_map, and whose alpha channel acts like illumination_map (and can be coloured with illumination_modulate_color). This uses less memory (on systems with shaders) than using separate shaders, although blending the emission and illumination maps into a single emission map, as described above, is still preferable.
illumination_map texture specifier A texture specifying local illumination colour, which is added to incoming light. It differs from an emission map in that it is modulated with the diffuse colour before being added to the final colour. See example below.
illumination_modulate_color colour specifier A colour with which to modulate the illumination_map. Default: white (1.0, 1.0, 1.0, 1.0).
normal_map texture specifier A texture modifying normals. The red, green and blue channels are the x, y and z coordinates of normals relative to the underlying normal (“tangent-space normal mapping”), and the alpha channel is ingored. This is only used when shaders are active and no custom shader is used.
normal_and_parallax_map texture specifier Like normal_map, except that the alpha channel is includes a depth value used to add simulated perspective. If specified, normal_map is ignored.
parallax_bias number A value added to the parallax component of normal_and_parallax_map, after multiplying by parallax_scale (default: 0).
parallax_scale number A scale factor for the parallax component of normal_and_parallax_map (default: 0.01). This value is the depth of the parallax map relative to the size of the texture. For instance, a value of 0.01 on a texture 100 metres wide will produce a maximum indentation of 1 metre. High parallax_scale values tend to lead to unacceptable texture distortion and “creeping” artefacts.
specular_color colour specifier The colour to use for specular reflection over the entire model when specular_map is not used. The specular term is added to the diffuse term; for less intense specular highlights, use a darker colour. Default: black (0.0, 0.0, 0.0, 1.0) if shininess is zero, (0.2, 0.2, 0.2, 1.0) otherwise.
specular_map texture specifier A texture specifying the specular highlight colour in its red, green and blue channels, and shininess in its alpha channel. 1 (fully opaque) means the value of shininess is used. 0 means a very low shininess is used. This is only used when shaders are active and no custom shader is used.
specular_modulate_color colour specifier A colour with which to modulate the specular_map. Default: white (1.0, 1.0, 1.0, 1.0).
shininess integer The “tightness” of specular reflection, ranging from 0 to 128. 0 means no specular highlight. 128 is maximally shiny. Default: 128 if specular_map is used, 10 otherwise. Limitation: to use different shininess values with specular_map or specular_color, you must either use the default or use different “shaders” and “materials” dictionaries. This should be fixed for 1.75.
vertex_shader file name name of GLSL vertex program to use.
fragment_shader file name name of GLSL fragment program to use.
textures array of texture specifiers Textures to use in shader program.
uniforms dictionary of uniform variable specifiers uniform variables to use in shader program.

Illumination mapping vs. emission mapping

This image demonstrates the distinction between illumination mapping (top row) and emission mapping (bottom row).

Emission-vs-illumination.png

Colour specifiers

Colour specifiers are used to declare colours in material attribute dictionaries, and in other contexts such as lasers in shipdata.plist. Colour specifiers take any of several forms:

Named colours

The simplest form of colour specifier is a string containing a colour name. The following names are supported:

Colour names
Name RGBA value
blackColor 0, 0, 0, 1
darkGrayColor 1/3, 1/3, 1/3, 1
lightGrayColor 2/3, 2/3, 2/3, 1
whiteColor 1, 1, 1, 1
grayColor 1/2, 1/2, 1/2, 1
redColor 1, 0, 0, 1
greenColor 0, 1, 0, 1
blueColor 0, 0, 1, 1
cyanColor 0, 1, 1, 1
yellowColor 1, 1, 0, 1
magentaColor 1, 0, 1, 1
orangeColor 1, 1/2, 0, 1
purpleColor 1/2, 0, 1/2, 1
brownColor 0.6, 0.4, 0.2, 1
clearColor 0, 0, 0, 0

RGBA tuples

Colours may also be specified in RGB or RGBA (red, green, blue, alpha [transparency]). RGB or RGBA tuples may be specified as arrays or as strings separated by spaces. The values may range from 0 to 1 or 0 to 255. (If no value is greater than 1, 0–1 is assumed, otherwise 0–255.) Examples:

  • "1 1 0" — yellow
  • "0 128 0 128" — medium green at 50% opacity
  • (1, 0, 0) – red


RGBA dictionaries

Just in case you’re unsure of the order the RGB[A] components come in, you can use a dictionary:

{
   blue = 0.8;
   green = 0.8;
}

Accepted keys are red, green, blue and alpha (or opacity), all optional (default: 0.0 for red, green and blue, 1.0 for alpha).

HSBA dictionaries

But wait, there’s more! Colours may also be specified as dictionaries in the HSB colour space. Accepted keys are hue (hue angle in degrees, required), saturation, brightness (or value) and alpha (or opacity). The default for the optional keys is 1.0.

{
   // Pale magenta
   hue = 300;
   saturation = 0.3;
}

Texture specifiers

Texture specifiers are used to, er, specify textures. The simplest form of texture specifier is a string: "ahruman-example-texture.png". The very simplest texture specifier is the empty string, "", meaning no texture. More complex texture specifiers are dictionaries, which can be used to specify a number of texture options.

Texture specifier attributes
Name Type Description
anisotropy real The degree of anisotropic filtering to use. Anisotropic filtering is used to reduce blurriness of MIP mapped textures shown at an angle (and thus only applies to textures whose min_filter is mipmap or default). The anisotropy setting is multiplied by the maximum anisotropy level specified by the system, and anisotropic filtering is used only if the result is greater than 1. (For example, on a GeForce FX 5200 card, the maximum level is 8, so an anisotropy value of 0.5 means an effective anisotropic filtering strength of 4. The precise meaning of this number is hardware-dependant. Fun, eh?) Anisotropic filtering is disabled in Reduced Detail mode and is not available on all hardware. Default: 0.5.
cube_map boolean If this is true, and the texture file is six times as high as it is wide, the texture will be treated as a cube map. If cube maps are not supported, it will be converted to a latitude/longitude map; if used as a diffuse map or emission/illumination map, you must ensure the model has appropriate texture coordinates. Note that cube maps are always available if shaders are supported, so custom shaders do not need to worry about this.

cube_map is always true for planet textures. To convert textures to and from cube maps, see planettool.

extract_channel string Indicates that one of the channels of the texture should be extracted into a new greyscale texture. Allowed values: r, g, b and a.

This obviously involves extra work for Oolite, which is always a bad thing, but it makes it possible to combine multiple effect maps in a single texture for shaders and then extract channels for use as emission or illumination maps without shipping a redundant texture. If this means nothing to you, you probably don’t want to use extract_channel.

mag_filter string Specifies how to scale up the texture when it is near the camera. Either of:
  • nearest (use nearest-neighbour sampling, which produces a pixellated effect)
  • linear (use linear interpolation, which produces a blurry effect).

Default: linear.

min_filter string Specifies how to scale down the texture when it is far from the camera. One of:
  • nearest: nearest-neighbour sampling; generally very ugly, but sometimes useful for shaders using textures for special purposes.
  • linear: efficient, but rather ugly for textures with significant contrast or details.
  • mipmap: use trilinear MIP map filtering to improve scaling quality; generally also fast and least ugly, but uses 1/3 more memory, potentially slowing down systems with limited RAM or video memory.
  • default: linear in reduced detail mode, otherwise mipmap.

Default: default.

name string The file name of the texture to use. Must be a PNG image, in the Textures folder of Oolite or an OXP. In the specific case of diffuse_map textures, name is implicitly the same as the material key; to use no texture, you must specify diffuse_map = "".
no_shrink boolean Indicates that Oolite should not scale the texture down, except to meet hardware requirements. Default: false.
repeat_s boolean Whether Oolite should repeat the texture in the s (or u) co-ordinate, rather than clamping it. Default: false.
repeat_t boolean Whether Oolite should repeat the texture in the t (or v) co-ordinate, rather than clamping it. Default: false.
texture_LOD_bias real tweak factor for MIP mapping (which does not apply to other min_filter modes). MIP mapping involves a trade-off between scaling artefacts and blurriness; the LOD (level of detail) bias affects this. Positive values mean more blur, negative ones mean more artefacts. The default value is −0.25 (mostly so people won’t say “hey, why is everything blurrier in the new Oolite?”). Texture LOD bias is not available on all hardware.

Uniform specifiers

Main article: Shaders in Oolite: uniforms

A uniform specifier is used to specify game information to pass to a shader program. As with texture specifiers, the simple case is a string, which is treated as { binding = "the string" }. For instance, uHullHeatLevel = hullHeatLevel will bind a shader’s uHullHeatLevel uniform to a ship’s hullHeatLevel property. Additional properties can be specified in a dictionary.

Texture specifier attributes
Name Type Description
asMatrix boolean For a binding uniform whose bound property is of type quaternion, setting asMatrix to true causes the value to be converted to a rotation matrix. If asMatrix is false, the quaternion will be converted to a vector, whose w, x, y and z values match those of the quaternion. For any other type of uniform, asMatrix is ignored. Default: true.
binding string The entity property to bind to, for a binding uniform. Ignored for other types of uniform.
clamped boolean For a binding uniform whose bound property is of type float, setting clamped to true causes the value to be restricted to the range 0 to 1, inclusive. For a binding of type int, causes the value to be set to either 0 or 1; 1 indicates that the underlying property has any value other than 0. For any other type of uniform, clamped is ignored. Default: false.
normalized boolean For a binding uniform whose bound property is of type vector, setting normalized to true causes the value to be normalized, that is, scaled to a length of 1. For any other type of uniform, normalized is ignored. The spelling normalised is also accepted. Default: false.
type  string One of:
  • binding: indicates that the binding property specifies an entity property to be set dynamically each time the shader is used.
  • float or real: indicates that the value property is an floating-point number.
  • int or integer: indicates that the value property is an integer, or whole number.
  • texture: indicates that the value property is an integer specifying a texture unit, that is, an index in the textures array.

Default: float.

value number The value to use for a float, int or texture uniform. Ignored for binding uniforms.

Material dictionary example

Here is an example from the Material Test Suite OXP:

materials =
{
    "cube-face" =
    {
        diffuse_map = "oolite_shader_test_suite_7_diffuse.png";
        emission_and_illumination_map = "oolite_shader_test_suite_emission_and_illumination.png";
        emission_modulate_color = (160, 255, 160);
        illumination_modulate_color = (180, 180, 200);
    };
};

Here, the “cube-face” material is assigned the diffuse texture “oolite_shader_test_suite_7_diffuse.png” and a combined emission and illumination map (which is a greyscale+alpha texture). The emission and illumination components are then given coloured tints (slightly green and slightly blue, respectively), producing this:

Oolite Material Test Suite 7.png

Griff's SpecGloss Viper

See also

Also contains Griff's SpecGloss models of the Cobra Mk.1, Gecko, Mamba, Sidewinder & Viper