OGRE  1.10.12
Object-Oriented Graphics Rendering Engine
Material Scripts

Material scripts offer you the ability to define complex materials in a script which can be reused easily. Whilst you could set up all materials for a scene in code using the methods of the Material and TextureLayer classes, in practice it's a bit unwieldy. Instead you can store material definitions in text files which can then be loaded whenever required.

Loading scripts

Material scripts are loaded when resource groups are initialised: OGRE looks in all resource locations associated with the group (see Ogre::ResourceGroupManager::addResourceLocation) for files with the ’.material’ extension and parses them. If you want to parse files manually, use Ogre::MaterialSerializer::parseScript.

It’s important to realise that materials are not loaded completely by this parsing process: only the definition is loaded, no textures or other resources are loaded. This is because it is common to have a large library of materials, but only use a relatively small subset of them in any one scene. To load every material completely in every script would therefore cause unnecessary memory overhead. You can access a ’deferred load’ Material in the normal way (Ogre::MaterialManager::getSingleton().getByName()), but you must call the ’load’ method before trying to use it. Ogre does this for you when using the normal material assignment methods of entities etc.

Another important factor is that material names must be unique throughout ALL scripts loaded by the system, since materials are always identified by name.

Format

Several materials may be defined in a single script. The script format is pseudo-C++, with sections delimited by curly braces (’{’, ’}’), and comments indicated by starting a line with ’//’ (note, no nested form comments allowed). The general format is shown below in the example below (note that to start with, we only consider fixed-function materials which don’t use vertex, geometry or fragment programs, these are covered later):

// This is a comment
material walls/funkywall1
{
// first, preferred technique
technique
{
// first pass
pass
{
ambient 0.5 0.5 0.5
diffuse 1.0 1.0 1.0
// Texture unit 0
texture_unit
{
texture wibbly.jpg
scroll_anim 0.1 0.0
wave_xform scale sine 0.0 0.7 0.0 1.0
}
// Texture unit 1 (this is a multitexture pass)
texture_unit
{
texture wobbly.png
rotate_anim 0.25
colour_op add
}
}
}
// Second technique, can be used as a fallback or LOD level
technique
{
// .. and so on
}
}

Every material in the script must be given a name, which is the line ’material <blah>’ before the first opening ’{’. This name must be globally unique. It can include path characters (as in the example) to logically divide up your materials, and also to avoid duplicate names, but the engine does not treat the name as hierarchical, just as a string. If you include spaces in the name, it must be enclosed in double quotes.

Note
’:’ is the delimiter for specifying material copy in the script so it can’t be used as part of the material name.

A material can inherit from a previously defined material by using a colon **:** after the material name followed by the name of the reference material to inherit from. You can in fact even inherit just parts of a material from others; all this is covered in See Script Inheritance). You can also use variables in your script which can be replaced in inheriting versions, see See Script Variables.

A material can be made up of many techniques (See Techniques)- a technique is one way of achieving the effect you are looking for. You can supply more than one technique in order to provide fallback approaches where a card does not have the ability to render the preferred technique, or where you wish to define lower level of detail versions of the material in order to conserve rendering power when objects are more distant.

Each technique can be made up of many passes (See Passes), that is a complete render of the object can be performed multiple times with different settings in order to produce composite effects. Ogre may also split the passes you have defined into many passes at runtime, if you define a pass which uses too many texture units for the card you are currently running on (note that it can only do this if you are not using a fragment program). Each pass has a number of top-level attributes such as ’ambient’ to set the amount & colour of the ambient light reflected by the material. Some of these options do not apply if you are using vertex programs, See Passes for more details.

Within each pass, there can be zero or many texture units in use (See Texture Units). These define the texture to be used, and optionally some blending operations (which use multitexturing) and texture effects.

You can also reference vertex and fragment programs (or vertex and pixel shaders, if you want to use that terminology) in a pass with a given set of parameters. Programs themselves are declared in separate .program scripts (See Declaring GPU Programs) and are used as described in Using GPU Programs in a Pass.

Top-level material attributes

The outermost section of a material definition does not have a lot of attributes of its own (most of the configurable parameters are within the child sections. However, it does have some, and here they are:

lod_distances (deprecated)

This option is deprecated in favour of lod_values now.

lod_strategy

Sets the name of the LOD strategy to use. Defaults to ’Distance’ which means LOD changes based on distance from the camera. Also supported is ’PixelCount’ which changes LOD based on an estimate of the screen-space pixels affected. Format: lod_strategy <name>
Default: lod_strategy Distance

lod_values

lod_values

This attribute defines the values used to control the LOD transition for this material. By setting this attribute, you indicate that you want this material to alter the Technique that it uses based on some metric, such as the distance from the camera, or the approximate screen space coverage. The exact meaning of these values is determined by the option you select for lod_strategy - it is a list of distances for the ’Distance’ strategy, and a list of pixel counts for the ’PixelCount’ strategy, for example. You must give it a list of values, in order from highest LOD value to lowest LOD value, each one indicating the point at which the material will switch to the next LOD. Implicitly, all materials activate LOD index 0 for values less than the first entry, so you do not have to specify ’0’ at the start of the list. You must ensure that there is at least one Technique with a lod_index value for each value in the list (so if you specify 3 values, you must have techniques for LOD indexes 0, 1, 2 and 3). Note you must always have at least one Technique at lod_index 0. Format: lod_values <value0> <value1> <value2> ...
Default: none

Example:
lod_strategy Distance lod_values 300.0 600.5 1200

The above example would cause the material to use the best Technique at lod_index 0 up to a distance of 300 world units, the best from lod_index 1 from 300 up to 600, lod_index 2 from 600 to 1200, and lod_index 3 from 1200 upwards.

receive_shadows

This attribute controls whether objects using this material can have shadows cast upon them.

Format: receive_shadows <on|off>
Default: on

Whether or not an object receives a shadow is the combination of a number of factors, See Shadows for full details; however this allows you to make a material opt-out of receiving shadows if required. Note that transparent materials never receive shadows so this option only has an effect on solid materials.

transparency_casts_shadows

This attribute controls whether transparent materials can cast certain kinds of shadow.

Format: transparency_casts_shadows <on|off>
Default: off Whether or not an object casts a shadow is the combination of a number of factors, See Shadows for full details; however this allows you to make a transparent material cast shadows, when it would otherwise not. For example, when using texture shadows, transparent materials are normally not rendered into the shadow texture because they should not block light. This flag overrides that.

set_texture_alias

This attribute associates a texture alias with a texture name.

Format: set_texture_alias <alias name> <texture name>

This attribute can be used to set the textures used in texture unit states that were inherited from another material.(See Texture Aliases)

Techniques

A "technique" section in your material script encapsulates a single method of rendering an object. The simplest of material definitions only contains a single technique, however since PC hardware varies quite greatly in it’s capabilities, you can only do this if you are sure that every card for which you intend to target your application will support the capabilities which your technique requires. In addition, it can be useful to define simpler ways to render a material if you wish to use material LOD, such that more distant objects use a simpler, less performance-hungry technique.

When a material is used for the first time, it is ’compiled’. That involves scanning the techniques which have been defined, and marking which of them are supportable using the current rendering API and graphics card. If no techniques are supportable, your material will render as blank white. The compilation examines a number of things, such as:

  • The number of texture_unit entries in each pass
    Note that if the number of texture_unit entries exceeds the number of texture units in the current graphics card, the technique may still be supportable so long as a fragment program is not being used. In this case, Ogre will split the pass which has too many entries into multiple passes for the less capable card, and the multitexture blend will be turned into a multipass blend (See colour_op_multipass_fallback).
  • Whether vertex, geometry or fragment programs are used, and if so which syntax they use (e.g. vs_1_1, ps_2_x, arbfp1 etc.)
  • Other effects like cube mapping and dot3 blending
  • Whether the vendor or device name of the current graphics card matches some user-specified rules


In a material script, techniques must be listed in order of preference, i.e. the earlier techniques are preferred over the later techniques. This normally means you will list your most advanced, most demanding techniques first in the script, and list fallbacks afterwards.

To help clearly identify what each technique is used for, the technique can be named but its optional. Techniques not named within the script will take on a name that is the technique index number. For example: the first technique in a material is index 0, its name would be "0" if it was not given a name in the script. The technique name must be unique within the material or else the final technique is the resulting merge of all techniques with the same name in the material. A warning message is posted in the Ogre.log if this occurs. Named techniques can help when inheriting a material and modifying an existing technique: (See Script Inheritance)

Format: technique name

Techniques have only a small number of attributes of their own:

scheme

Sets the ’scheme’ this Technique belongs to. Material schemes are used to control top-level switching from one set of techniques to another. For example, you might use this to define ’high’, ’medium’ and ’low’ complexity levels on materials to allow a user to pick a performance / quality ratio. Another possibility is that you have a fully HDR-enabled pipeline for top machines, rendering all objects using unclamped shaders, and a simpler pipeline for others; this can be implemented using schemes. The active scheme is typically controlled at a viewport level, and the active one defaults to ’Default’.

Format: scheme <name>
Example: scheme hdr
Default: scheme Default

lod_index

Sets the level-of-detail (LOD) index this Technique belongs to.

Format: lod_index <number>
NB Valid values are 0 (highest level of detail) to 65535, although this is unlikely. You should not leave gaps in the LOD indexes between Techniques.

Example: lod_index 1

All techniques must belong to a LOD index, by default they all belong to index 0, i.e. the highest LOD. Increasing indexes denote lower levels of detail. You can (and often will) assign more than one technique to the same LOD index, what this means is that OGRE will pick the best technique of the ones listed at the same LOD index. For readability, it is advised that you list your techniques in order of LOD, then in order of preference, although the latter is the only prerequisite (OGRE determines which one is ’best’ by which one is listed first). You must always have at least one Technique at lod_index 0. The distance at which a LOD level is applied is determined by the lod_distances attribute of the containing material, See lod_distances for details.

Default: lod_index 0

Techniques also contain one or more passes (and there must be at least one), See Passes.

shadow_caster_material

When using See Texture-based Shadows you can specify an alternate material to use when rendering the object using this material into the shadow texture. This is like a more advanced version of using shadow_caster_vertex_program, however note that for the moment you are expected to render the shadow in one pass, i.e. only the first pass is respected.

shadow_receiver_material

When using See Texture-based Shadows you can specify an alternate material to use when performing the receiver shadow pass. Note that this explicit ’receiver’ pass is only done when you’re not using Integrated Texture Shadows - i.e. the shadow rendering is done separately (either as a modulative pass, or a masked light pass). This is like a more advanced version of using shadow_receiver_vertex_program and shadow_receiver_fragment_program, however note that for the moment you are expected to render the shadow in one pass, i.e. only the first pass is respected.

gpu_vendor_rule and gpu_device_rule

Although Ogre does a good job of detecting the capabilities of graphics cards and setting the supportability of techniques from that, occasionally card-specific behaviour exists which is not necessarily detectable and you may want to ensure that your materials go down a particular path to either use or avoid that behaviour. This is what these rules are for - you can specify matching rules so that a technique will be considered supportable only on cards from a particular vendor, or which match a device name pattern, or will be considered supported only if they don’t fulfil such matches. The format of the rules are as follows:

gpu_vendor_rule <include|exclude> <vendor_name>
gpu_device_rule <include|exclude> <device_pattern> [case_sensitive]

An ’include’ rule means that the technique will only be supported if one of the include rules is matched (if no include rules are provided, anything will pass). An ’exclude’ rules means that the technique is considered unsupported if any of the exclude rules are matched. You can provide as many rules as you like, although <vendor_name> and <device_pattern> must obviously be unique. The valid list of <vendor_name> values is currently ’nvidia’, ’ati’, ’intel’, ’s3’, ’matrox’ and ’3dlabs’. <device_pattern> can be any string, and you can use wildcards (’*’) if you need to match variants. Here’s an example:

gpu_vendor_rule include nvidia
gpu_vendor_rule include intel
gpu_device_rule exclude *950*

These rules, if all included in one technique, will mean that the technique will only be considered supported on graphics cards made by NVIDIA and Intel, and so long as the device name doesn’t have ’950’ in it.

Note that these rules can only mark a technique ’unsupported’ when it would otherwise be considered ’supported’ judging by the hardware capabilities. Even if a technique passes these rules, it is still subject to the usual hardware support tests.

Passes

A pass is a single render of the geometry in question; a single call to the rendering API with a certain set of rendering properties. A technique can have between one and 16 passes, although clearly the more passes you use, the more expensive the technique will be to render.

To help clearly identify what each pass is used for, the pass can be named but its optional. Passes not named within the script will take on a name that is the pass index number. For example: the first pass in a technique is index 0 so its name would be "0" if it was not given a name in the script. The pass name must be unique within the technique or else the final pass is the resulting merge of all passes with the same name in the technique. A warning message is posted in the Ogre.log if this occurs. Named passes can help when inheriting a material and modifying an existing pass: (See Script Inheritance)

Passes have a set of global attributes (described below), zero or more nested texture_unit entries (See Texture Units), and optionally a reference to a vertex and / or a fragment program (See Using Vertex/Geometry/Fragment Programs in a Pass).

Here are the attributes you can use in a ’pass’ section of a .material script:

Attribute Descriptions

ambient

Sets the ambient colour reflectance properties of this pass.

Note
When using shader programs, you have to explicitely forward this property in the Parameter specification

Format: ambient (<red> <green> <blue> [<alpha>]| vertexcolour)
NB valid colour values are between 0.0 and 1.0.

Example: ambient 0.0 0.8 0.0

The base colour of a pass is determined by how much red, green and blue light is reflects at each vertex. This property determines how much ambient light (directionless global light) is reflected. It is also possible to make the ambient reflectance track the vertex colour as defined in the mesh by using the keyword vertexcolour instead of the colour values. The default is full white, meaning objects are completely globally illuminated. Reduce this if you want to see diffuse or specular light effects, or change the blend of colours to make the object have a base colour other than white. This setting has no effect if dynamic lighting is disabled using the ’lighting off’ attribute, or if any texture layer has a ’colour_op replace’ attribute.

Default: ambient 1.0 1.0 1.0 1.0

diffuse

Sets the diffuse colour reflectance properties of this pass.

Note
When using shader programs, you have to explicitely forward this property in the Parameter specification

Format: diffuse (<red> <green> <blue> [<alpha>]| vertexcolour)
NB valid colour values are between 0.0 and 1.0.

Example: diffuse 1.0 0.5 0.5

The base colour of a pass is determined by how much red, green and blue light is reflects at each vertex. This property determines how much diffuse light (light from instances of the Light class in the scene) is reflected. It is also possible to make the diffuse reflectance track the vertex colour as defined in the mesh by using the keyword vertexcolour instead of the colour values. The default is full white, meaning objects reflect the maximum white light they can from Light objects. This setting has no effect if dynamic lighting is disabled using the ’lighting off’ attribute, or if any texture layer has a ’colour_op replace’ attribute.

Default: diffuse 1.0 1.0 1.0 1.0

specular

Sets the specular colour reflectance properties of this pass.

Note
When using shader programs, you have to explicitely forward this property in the Parameter specification

Format: specular (<red> <green> <blue> [<alpha>]| vertexcolour) <shininess>
NB valid colour values are between 0.0 and 1.0. Shininess can be any value greater than 0.

Example: specular 1.0 1.0 1.0 12.5

The base colour of a pass is determined by how much red, green and blue light is reflects at each vertex. This property determines how much specular light (highlights from instances of the Light class in the scene) is reflected. It is also possible to make the diffuse reflectance track the vertex colour as defined in the mesh by using the keyword vertexcolour instead of the colour values. The default is to reflect no specular light. The colour of the specular highlights is determined by the colour parameters, and the size of the highlights by the separate shininess parameter.. The higher the value of the shininess parameter, the sharper the highlight i.e. the radius is smaller. Beware of using shininess values in the range of 0 to 1 since this causes the the specular colour to be applied to the whole surface that has the material applied to it. When the viewing angle to the surface changes, ugly flickering will also occur when shininess is in the range of 0 to 1. Shininess values between 1 and 128 work best in both DirectX and OpenGL renderers. This setting has no effect if dynamic lighting is disabled using the ’lighting off’ attribute, or if any texture layer has a ’colour_op replace’ attribute.

Default: specular 0.0 0.0 0.0 0.0 0.0

emissive

Sets the amount of self-illumination an object has.

Note
When using shader programs, you have to explicitely forward this property in the Parameter specification

Format: emissive (<red> <green> <blue> [<alpha>]| vertexcolour)
NB valid colour values are between 0.0 and 1.0.

Example: emissive 1.0 0.0 0.0

If an object is self-illuminating, it does not need external sources to light it, ambient or otherwise. It’s like the object has it’s own personal ambient light. Unlike the name suggests, this object doesn’t act as a light source for other objects in the scene (if you want it to, you have to create a light which is centered on the object). It is also possible to make the emissive colour track the vertex colour as defined in the mesh by using the keyword vertexcolour instead of the colour values. This setting has no effect if dynamic lighting is disabled using the ’lighting off’ attribute, or if any texture layer has a ’colour_op replace’ attribute.

Default: emissive 0.0 0.0 0.0 0.0

scene_blend

Sets the kind of blending this pass has with the existing contents of the scene. Whereas the texture blending operations seen in the texture_unit entries are concerned with blending between texture layers, this blending is about combining the output of this pass as a whole with the existing contents of the rendering target. This blending therefore allows object transparency and other special effects. There are 2 formats, one using predefined blend types, the other allowing a roll-your-own approach using source and destination factors.

Format1: scene_blend <add|modulate|alpha_blend|colour_blend>

Example: scene_blend add

This is the simpler form, where the most commonly used blending modes are enumerated using a single parameter. Valid <blend_type> parameters are:

add

The colour of the rendering output is added to the scene. Good for explosions, flares, lights, ghosts etc. Equivalent to ’scene_blend one one’.

modulate

The colour of the rendering output is multiplied with the scene contents. Generally colours and darkens the scene, good for smoked glass, semi-transparent objects etc. Equivalent to ’scene_blend dest_colour zero’.

colour_blend

Colour the scene based on the brightness of the input colours, but don’t darken. Equivalent to ’scene_blend src_colour one_minus_src_colour’

alpha_blend

The alpha value of the rendering output is used as a mask. Equivalent to ’scene_blend src_alpha one_minus_src_alpha’


Format2: scene_blend <src_factor> <dest_factor>

Example: scene_blend one one_minus_dest_alpha

This version of the method allows complete control over the blending operation, by specifying the source and destination blending factors. The resulting colour which is written to the rendering target is (texture * sourceFactor) + (scene_pixel * destFactor). Valid values for both parameters are:

one

Constant value of 1.0

zero

Constant value of 0.0

dest_colour

The existing pixel colour

src_colour

The texture pixel (texel) colour

one_minus_dest_colour

1 - (dest_colour)

one_minus_src_colour

1 - (src_colour)

dest_alpha

The existing pixel alpha value

src_alpha

The texel alpha value

one_minus_dest_alpha

1 - (dest_alpha)

one_minus_src_alpha

1 - (src_alpha)


Default: scene_blend one zero (opaque) Also see separate_scene_blend.

separate_scene_blend

This option operates in exactly the same way as scene_blend, except that it allows you to specify the operations to perform between the rendered pixel and the frame buffer separately for colour and alpha components. By nature this option is only useful when rendering to targets which have an alpha channel which you’ll use for later processing, such as a render texture.

Format1: separate_scene_blend <simple_colour_blend> <simple_alpha_blend>

Example: separate_scene_blend add modulate

This example would add colour components but multiply alpha components. The blend modes available are as in scene_blend. The more advanced form is also available:

Format2: separate_scene_blend <colour_src_factor> <colour_dest_factor> <alpha_src_factor> <alpha_dest_factor>

Example: separate_scene_blend one one_minus_dest_alpha one one

Again the options available in the second format are the same as those in the second format of scene_blend.

scene_blend_op

This directive changes the operation which is applied between the two components of the scene blending equation, which by default is ’add’ (sourceFactor * source + destFactor * dest). You may change this to ’add’, ’subtract’, ’reverse_subtract’, ’min’ or ’max’.

Format: scene_blend_op <add|subtract|reverse_subtract|min|max> Default: scene_blend_op add

separate_scene_blend_op

This directive is as scene_blend_op, except that you can set the operation for colour and alpha separately.

Format: separate_scene_blend_op <colourOp> <alphaOp> Default: separate_scene_blend_op add add

depth_check

Sets whether or not this pass renders with depth-buffer checking on or not.

Format: depth_check <on|off>

If depth-buffer checking is on, whenever a pixel is about to be written to the frame buffer the depth buffer is checked to see if the pixel is in front of all other pixels written at that point. If not, the pixel is not written. If depth checking is off, pixels are written no matter what has been rendered before. Also see depth_func for more advanced depth check configuration.

Default: depth_check on

depth_write

Sets whether or not this pass renders with depth-buffer writing on or not.

Format: depth_write <on|off>

If depth-buffer writing is on, whenever a pixel is written to the frame buffer the depth buffer is updated with the depth value of that new pixel, thus affecting future rendering operations if future pixels are behind this one. If depth writing is off, pixels are written without updating the depth buffer. Depth writing should normally be on but can be turned off when rendering static backgrounds or when rendering a collection of transparent objects at the end of a scene so that they overlap each other correctly.

Default: depth_write on

depth_func

Sets the function used to compare depth values when depth checking is on.

Format: depth_func <func>

If depth checking is enabled (see depth_check) a comparison occurs between the depth value of the pixel to be written and the current contents of the buffer. This comparison is normally less_equal, i.e. the pixel is written if it is closer (or at the same distance) than the current contents. The possible functions are:

always_fail

Never writes a pixel to the render target

always_pass

Always writes a pixel to the render target

less

Write if (new_Z < existing_Z)

less_equal

Write if (new_Z <= existing_Z)

equal

Write if (new_Z == existing_Z)

not_equal

Write if (new_Z != existing_Z)

greater_equal

Write if (new_Z >= existing_Z)

greater

Write if (new_Z >existing_Z)


Default: depth_func less_equal

depth_bias

Sets the bias applied to the depth value of this pass. Can be used to make coplanar polygons appear on top of others e.g. for decals.

Format: depth_bias <constant_bias> [<slopescale_bias>]

The final depth bias value is constant_bias * minObservableDepth + maxSlope * slopescale_bias. Slope scale biasing is relative to the angle of the polygon to the camera, which makes for a more appropriate bias value, but this is ignored on some older hardware. Constant biasing is expressed as a factor of the minimum depth value, so a value of 1 will nudge the depth by one ’notch’ if you will. Also see iteration_depth_bias

iteration_depth_bias

Sets an additional bias derived from the number of times a given pass has been iterated. Operates just like depth_bias except that it applies an additional bias factor to the base depth_bias value, multiplying the provided value by the number of times this pass has been iterated before, through one of the iteration variants. So the first time the pass will get the depth_bias value, the second time it will get depth_bias + iteration_depth_bias, the third time it will get depth_bias + iteration_depth_bias * 2, and so on. The default is zero.

Format: iteration_depth_bias <bias_per_iteration>

alpha_rejection

Sets the way the pass will have use alpha to totally reject pixels from the pipeline.

Format: alpha_rejection <function> <value>

Example: alpha_rejection greater_equal 128

The function parameter can be any of the options listed in the material depth_function attribute. The value parameter can theoretically be any value between 0 and 255, but is best limited to 0 or 128 for hardware compatibility.

Default: alpha_rejection always_pass

alpha_to_coverage

Sets whether this pass will use ’alpha to coverage’, a way to multisample alpha texture edges so they blend more seamlessly with the background. This facility is typically only available on cards from around 2006 onwards, but it is safe to enable it anyway - Ogre will just ignore it if the hardware does not support it. The common use for alpha to coverage is foliage rendering and chain-link fence style textures.

Format: alpha_to_coverage <on|off>

Default: alpha_to_coverage off

light_scissor

Sets whether when rendering this pass, rendering will be limited to a screen-space scissor rectangle representing the coverage of the light(s) being used in this pass, derived from their attenuation ranges.

Format: light_scissor <on|off> Default: light_scissor off

This option is usually only useful if this pass is an additive lighting pass, and is at least the second one in the technique. Ie areas which are not affected by the current light(s) will never need to be rendered. If there is more than one light being passed to the pass, then the scissor is defined to be the rectangle which covers all lights in screen-space. Directional lights are ignored since they are infinite.

This option does not need to be specified if you are using a standard additive shadow mode, i.e. SHADOWTYPE_STENCIL_ADDITIVE or SHADOWTYPE_TEXTURE_ADDITIVE, since it is the default behaviour to use a scissor for each additive shadow pass. However, if you’re not using shadows, or you’re using Integrated Texture Shadows where passes are specified in a custom manner, then this could be of use to you.

light_clip_planes

Sets whether when rendering this pass, triangle setup will be limited to clipping volume covered by the light. Directional lights are ignored, point lights clip to a cube the size of the attenuation range or the light, and spotlights clip to a pyramid bounding the spotlight angle and attenuation range.

Format: light_clip_planes <on|off> Default: light_clip_planes off

This option will only function if there is a single non-directional light being used in this pass. If there is more than one light, or only directional lights, then no clipping will occur. If there are no lights at all then the objects won’t be rendered at all.

When using a standard additive shadow mode, i.e. SHADOWTYPE_STENCIL_ADDITIVE or SHADOWTYPE_TEXTURE_ADDITIVE, you have the option of enabling clipping for all light passes by calling SceneManager::setShadowUseLightClipPlanes regardless of this pass setting, since rendering is done lightwise anyway. This is off by default since using clip planes is not always faster - it depends on how much of the scene the light volumes cover. Generally the smaller your lights are the more chance you’ll see a benefit rather than a penalty from clipping. If you’re not using shadows, or you’re using Integrated Texture Shadows where passes are specified in a custom manner, then specify the option per-pass using this attribute. A specific note about OpenGL: user clip planes are completely ignored when you use an ARB vertex program. This means light clip planes won’t help much if you use ARB vertex programs on GL, although OGRE will perform some optimisation of its own, in that if it sees that the clip volume is completely off-screen, it won’t perform a render at all. When using GLSL, user clipping can be used but you have to use gl_ClipVertex in your shader, see the GLSL documentation for more information. In Direct3D user clip planes are always respected.

illumination_stage

When using an additive lighting mode (SHADOWTYPE_STENCIL_ADDITIVE or SHADOWTYPE_TEXTURE_ADDITIVE), the scene is rendered in 3 discrete stages, ambient (or pre-lighting), per-light (once per light, with shadowing) and decal (or post-lighting). Usually OGRE figures out how to categorise your passes automatically, but there are some effects you cannot achieve without manually controlling the illumination. For example specular effects are muted by the typical sequence because all textures are saved until the ’decal’ stage which mutes the specular effect. Instead, you could do texturing within the per-light stage if it’s possible for your material and thus add the specular on after the decal texturing, and have no post-light rendering.

If you assign an illumination stage to a pass you have to assign it to all passes in the technique otherwise it will be ignored. Also note that whilst you can have more than one pass in each group, they cannot alternate, i.e. all ambient passes will be before all per-light passes, which will also be before all decal passes. Within their categories the passes will retain their ordering though.

Format: illumination_stage <ambient|per_light|decal> Default: none (autodetect)

normalise_normals

Sets whether or not this pass renders with all vertex normals being automatically re-normalised.

Format: normalise_normals <on|off>

Scaling objects causes normals to also change magnitude, which can throw off your lighting calculations. By default, the SceneManager detects this and will automatically re-normalise normals for any scaled object, but this has a cost. If you’d prefer to control this manually, call SceneManager::setNormaliseNormalsOnScale(false) and then use this option on materials which are sensitive to normals being resized.

Default: normalise_normals off

transparent_sorting

Sets if transparent textures should be sorted by depth or not.

Format: transparent_sorting <on|off|force>

By default all transparent materials are sorted such that renderables furthest away from the camera are rendered first. This is usually the desired behaviour but in certain cases this depth sorting may be unnecessary and undesirable. If for example it is necessary to ensure the rendering order does not change from one frame to the next. In this case you could set the value to ’off’ to prevent sorting.

You can also use the keyword ’force’ to force transparent sorting on, regardless of other circumstances. Usually sorting is only used when the pass is also transparent, and has a depth write or read which indicates it cannot reliably render without sorting. By using ’force’, you tell OGRE to sort this pass no matter what other circumstances are present.

Default: transparent_sorting on

cull_hardware

Sets the hardware culling mode for this pass.

Format: cull_hardware <clockwise|anticlockwise|none>

A typical way for the hardware rendering engine to cull triangles is based on the ’vertex winding’ of triangles. Vertex winding refers to the direction in which the vertices are passed or indexed to in the rendering operation as viewed from the camera, and will wither be clockwise or anticlockwise (that’s ’counterclockwise’ for you Americans out there ;). If the option ’cull_hardware clockwise’ is set, all triangles whose vertices are viewed in clockwise order from the camera will be culled by the hardware. ’anticlockwise’ is the reverse (obviously), and ’none’ turns off hardware culling so all triangles are rendered (useful for creating 2-sided passes).

Default: cull_hardware clockwise
NB this is the same as OpenGL’s default but the opposite of Direct3D’s default (because Ogre uses a right-handed coordinate system like OpenGL).

cull_software

Sets the software culling mode for this pass.

Format: cull_software <back|front|none>

In some situations the engine will also cull geometry in software before sending it to the hardware renderer. This setting only takes effect on SceneManager’s that use it (since it is best used on large groups of planar world geometry rather than on movable geometry since this would be expensive), but if used can cull geometry before it is sent to the hardware. In this case the culling is based on whether the ’back’ or ’front’ of the triangle is facing the camera - this definition is based on the face normal (a vector which sticks out of the front side of the polygon perpendicular to the face). Since Ogre expects face normals to be on anticlockwise side of the face, ’cull_software back’ is the software equivalent of ’cull_hardware clockwise’ setting, which is why they are both the default. The naming is different to reflect the way the culling is done though, since most of the time face normals are pre-calculated and they don’t have to be the way Ogre expects - you could set ’cull_hardware none’ and completely cull in software based on your own face normals, if you have the right SceneManager which uses them.

Default: cull_software back

lighting

Sets whether or not dynamic lighting is turned on for this pass or not. If lighting is turned off, all objects rendered using the pass will be fully lit. This attribute has no effect if a vertex program is used.

Format: lighting <on|off>

Turning dynamic lighting off makes any ambient, diffuse, specular, emissive and shading properties for this pass redundant. When lighting is turned on, objects are lit according to their vertex normals for diffuse and specular light, and globally for ambient and emissive.

Default: lighting on

shading

Sets the kind of shading which should be used for representing dynamic lighting for this pass.

Format: shading <flat|gouraud|phong>

When dynamic lighting is turned on, the effect is to generate colour values at each vertex. Whether these values are interpolated across the face (and how) depends on this setting.

flat

No interpolation takes place. Each face is shaded with a single colour determined from the first vertex in the face.

gouraud

Colour at each vertex is linearly interpolated across the face.

phong

Vertex normals are interpolated across the face, and these are used to determine colour at each pixel. Gives a more natural lighting effect but is more expensive and works better at high levels of tessellation. Not supported on all hardware.

Default: shading gouraud

polygon_mode

Sets how polygons should be rasterised, i.e. whether they should be filled in, or just drawn as lines or points.

Format: polygon_mode <solid|wireframe|points>

solid

The normal situation - polygons are filled in.

wireframe

Polygons are drawn in outline only.

points

Only the points of each polygon are rendered.

Default: polygon_mode solid

polygon_mode_overrideable

Sets whether or not the polygon_mode set on this pass can be downgraded by the camera, if the camera itself is set to a lower polygon mode. If set to false, this pass will always be rendered at its own chosen polygon mode no matter what the camera says. The default is true.

Format: polygon_mode_overrideable <true|false>

fog_override

Tells the pass whether it should override the scene fog settings, and enforce it’s own. Very useful for things that you don’t want to be affected by fog when the rest of the scene is fogged, or vice versa. Note that this only affects fixed-function fog - the original scene fog parameters are still sent to shaders which use the fog_params parameter binding (this allows you to turn off fixed function fog and calculate it in the shader instead; if you want to disable shader fog you can do that through shader parameters anyway).

Format: fog_override <override?> [<type> <colour> <density> <start> <end>]

Default: fog_override false

If you specify ’true’ for the first parameter and you supply the rest of the parameters, you are telling the pass to use these fog settings in preference to the scene settings, whatever they might be. If you specify ’true’ but provide no further parameters, you are telling this pass to never use fogging no matter what the scene says. Here is an explanation of the parameters:

type

none = No fog, equivalent of just using ’fog_override true’
linear = Linear fog from the <start> and <end> distances
exp = Fog increases exponentially from the camera (fog = 1/e^(distance * density)), use <density> param to control it
exp2 = Fog increases at the square of FOG_EXP, i.e. even quicker (fog = 1/e^(distance * density)^2), use <density> param to control it

colour

Sequence of 3 floating point values from 0 to 1 indicating the red, green and blue intensities

density

The density parameter used in the ’exp’ or ’exp2’ fog types. Not used in linear mode but param must still be there as a placeholder

start

The start distance from the camera of linear fog. Must still be present in other modes, even though it is not used.

end

The end distance from the camera of linear fog. Must still be present in other modes, even though it is not used.


Example: fog_override true exp 1 1 1 0.002 100 10000

colour_write

Sets whether or not this pass renders with colour writing on or not.

Format: colour_write <on|off>

If colour writing is off no visible pixels are written to the screen during this pass. You might think this is useless, but if you render with colour writing off, and with very minimal other settings, you can use this pass to initialise the depth buffer before subsequently rendering other passes which fill in the colour data. This can give you significant performance boosts on some newer cards, especially when using complex fragment programs, because if the depth check fails then the fragment program is never run.

Default: colour_write on

start_light

Sets the first light which will be considered for use with this pass. Format: start_light <number>

You can use this attribute to offset the starting point of the lights for this pass. In other words, if you set start_light to 2 then the first light to be processed in that pass will be the third actual light in the applicable list. You could use this option to use different passes to process the first couple of lights versus the second couple of lights for example, or use it in conjunction with the iteration option to start the iteration from a given point in the list (e.g. doing the first 2 lights in the first pass, and then iterating every 2 lights from then on perhaps).

Default: start_light 0

max_lights

Sets the maximum number of lights which will be considered for use with this pass. Format: max_lights <number>

The maximum number of lights which can be used when rendering fixed-function materials is set by the rendering system, and is typically set at 8. When you are using the programmable pipeline (See Using Vertex/Geometry/Fragment Programs in a Pass) this limit is dependent on the program you are running, or, if you use ’iteration once_per_light’ or a variant (See iteration), it effectively only bounded by the number of passes you are willing to use. If you are not using pass iteration, the light limit applies once for this pass. If you are using pass iteration, the light limit applies across all iterations of this pass - for example if you have 12 lights in range with an ’iteration once_per_light’ setup but your max_lights is set to 4 for that pass, the pass will only iterate 4 times.

Default: max_lights 8

iteration

Sets whether or not this pass is iterated, i.e. issued more than once.

Format 1: iteration <once | once_per_light> [lightType] Format 2: iteration <number> [<per_light> [lightType]] Format 3: iteration <number> [<per_n_lights> <num_lights> [lightType]] Examples:

iteration once

The pass is only executed once which is the default behaviour.

iteration once_per_light point

The pass is executed once for each point light.

iteration 5

The render state for the pass will be setup and then the draw call will execute 5 times.

iteration 5 per_light point

The render state for the pass will be setup and then the draw call will execute 5 times. This will be done for each point light.

iteration 1 per_n_lights 2 point

The render state for the pass will be setup and the draw call executed once for every 2 lights.


By default, passes are only issued once. However, if you use the programmable pipeline, or you wish to exceed the normal limits on the number of lights which are supported, you might want to use the once_per_light option. In this case, only light index 0 is ever used, and the pass is issued multiple times, each time with a different light in light index 0. Clearly this will make the pass more expensive, but it may be the only way to achieve certain effects such as per-pixel lighting effects which take into account 1..n lights.

Using a number instead of "once" instructs the pass to iterate more than once after the render state is setup. The render state is not changed after the initial setup so repeated draw calls are very fast and ideal for passes using programmable shaders that must iterate more than once with the same render state i.e. shaders that do fur, motion blur, special filtering.

If you use once_per_light, you should also add an ambient pass to the technique before this pass, otherwise when no lights are in range of this object it will not get rendered at all; this is important even when you have no ambient light in the scene, because you would still want the objects silhouette to appear.

The lightType parameter to the attribute only applies if you use once_per_light, per_light, or per_n_lights and restricts the pass to being run for lights of a single type (either ’point’, ’directional’ or ’spot’). In the example, the pass will be run once per point light. This can be useful because when you’re writing a vertex / fragment program it is a lot easier if you can assume the kind of lights you’ll be dealing with. However at least point and directional lights can be dealt with in one way. Default: iteration once

Example: Simple Fur shader material script that uses a second pass with 10 iterations to grow the fur:

// GLSL simple Fur
vertex_program GLSLDemo/FurVS glsl
{
source fur.vert
default_params
{
param_named_auto lightPosition light_position_object_space 0
param_named_auto eyePosition camera_position_object_space
param_named_auto passNumber pass_number
param_named_auto multiPassNumber pass_iteration_number
param_named furLength float 0.15
}
}
fragment_program GLSLDemo/FurFS glsl
{
source fur.frag
default_params
{
param_named Ka float 0.2
param_named Kd float 0.5
param_named Ks float 0.0
param_named furTU int 0
}
}
material Fur
{
technique GLSL
{
pass base_coat
{
ambient 0.7 0.7 0.7
diffuse 0.5 0.8 0.5
specular 1.0 1.0 1.0 1.5
vertex_program_ref GLSLDemo/FurVS
{
}
fragment_program_ref GLSLDemo/FurFS
{
}
texture_unit
{
texture Fur.tga
tex_coord_set 0
filtering trilinear
}
}
pass grow_fur
{
ambient 0.7 0.7 0.7
diffuse 0.8 1.0 0.8
specular 1.0 1.0 1.0 64
depth_write off
scene_blend src_alpha one
iteration 10
vertex_program_ref GLSLDemo/FurVS
{
}
fragment_program_ref GLSLDemo/FurFS
{
}
texture_unit
{
texture Fur.tga
tex_coord_set 0
filtering trilinear
}
}
}
}
Note
use gpu program auto parameters pass_number and pass_iteration_number to tell the vertex, geometry or fragment program the pass number and iteration number.

point_size

This setting allows you to change the size of points when rendering a point list, or a list of point sprites. The interpretation of this command depends on the point_size_attenuation option - if it is off (the default), the point size is in screen pixels, if it is on, it expressed as normalised screen coordinates (1.0 is the height of the screen) when the point is at the origin.

Note
Some drivers have an upper limit on the size of points they support - this can even vary between APIs on the same card! Don’t rely on point sizes that cause the points to get very large on screen, since they may get clamped on some cards. Upper sizes can range from 64 to 256 pixels.

Format: point_size <size> Default: point_size 1.0

point_sprites

This setting specifies whether or not hardware point sprite rendering is enabled for this pass. Enabling it means that a point list is rendered as a list of quads rather than a list of dots. It is very useful to use this option if you’re using a BillboardSet and only need to use point oriented billboards which are all of the same size. You can also use it for any other point list render.

Format: point_sprites <on|off> Default: point_sprites off

point_size_attenuation

Defines whether point size is attenuated with view space distance, and in what fashion. This option is especially useful when you’re using point sprites (See point_sprites) since it defines how they reduce in size as they get further away from the camera. You can also disable this option to make point sprites a constant screen size (like points), or enable it for points so they change size with distance.

You only have to provide the final 3 parameters if you turn attenuation on. The formula for attenuation is that the size of the point is multiplied by 1 / (constant + linear * dist + quadratic * d^2); therefore turning it off is equivalent to (constant = 1, linear = 0, quadratic = 0) and standard perspective attenuation is (constant = 0, linear = 1, quadratic = 0). The latter is assumed if you leave out the final 3 parameters when you specify ’on’.

Note that the resulting attenuated size is clamped to the minimum and maximum point size, see the next section.

Format: point_size_attenuation <on|off> [constant linear quadratic] Default: point_size_attenuation off

point_size_min

Sets the minimum point size after attenuation (point_size_attenuation). For details on the size metrics, See point_size.

Format: point_size_min <size> Default: point_size_min 0

point_size_max

Sets the maximum point size after attenuation (point_size_attenuation). For details on the size metrics, See point_size. A value of 0 means the maximum is set to the same as the max size reported by the current card.

Format: point_size_max <size> Default: point_size_max 0

Texture Units

Here are the attributes you can use in a ’texture_unit’ section of a .material script:

Available Texture Layer Attributes

You can also use a nested ’texture_source’ section in order to use a special add-in as a source of texture data, See External Texture Sources for details.

Attribute Descriptions

texture_alias

Sets the alias name for this texture unit.

Format: texture_alias <name>

Example: texture_alias NormalMap

Setting the texture alias name is useful if this material is to be inherited by other other materials and only the textures will be changed in the new material.(See Texture Aliases) Default: If a texture_unit has a name then the texture_alias defaults to the texture_unit name.

texture

Sets the name of the static texture image this layer will use.

Format: texture <texturename> [<type>] [unlimited | numMipMaps] [alpha] [<PixelFormat>] [gamma]

Example: texture funkywall.jpg

This setting is mutually exclusive with the anim_texture attribute. Note that the texture file cannot include spaces. Those of you Windows users who like spaces in filenames, please get over it and use underscores instead.

Parameters
typespecify a the type of texture to create - the default is ’2d’, but you can override this; here’s the full list:
1d

A 1-dimensional texture; that is, a texture which is only 1 pixel high. These kinds of textures can be useful when you need to encode a function in a texture and use it as a simple lookup, perhaps in a fragment program. It is important that you use this setting when you use a fragment program which uses 1-dimensional texture coordinates, since GL requires you to use a texture type that matches (D3D will let you get away with it, but you ought to plan for cross-compatibility). Your texture widths should still be a power of 2 for best compatibility and performance.

2d

The default type which is assumed if you omit it, your texture has a width and a height, both of which should preferably be powers of 2, and if you can, make them square because this will look best on the most hardware. These can be addressed with 2D texture coordinates.

3d

A 3 dimensional texture i.e. volume texture. Your texture has a width, a height, both of which should be powers of 2, and has depth. These can be addressed with 3d texture coordinates i.e. through a pixel shader.

cubic

This texture is made up of 6 2D textures which are pasted around the inside of a cube. Alternatively 1 cube texture can be used if supported by the texture format(DDS for example) and rendersystem. Can be addressed with 3D texture coordinates and are useful for cubic reflection maps and normal maps.

numMipMapsspecify the number of mipmaps to generate for this texture. The default is ’unlimited’ which means mips down to 1x1 size are generated. You can specify a fixed number (even 0) if you like instead. Note that if you use the same texture in many material scripts, the number of mipmaps generated will conform to the number specified in the first texture_unit used to load the texture - so be consistent with your usage.
alphaspecify that a single channel (luminance) texture should be loaded as alpha, rather than the default which is to load it into the red channel. This can be helpful if you want to use alpha-only textures in the fixed function pipeline. Default: none
PixelFormatspecify the desired pixel format of the texture to create, which may be different to the pixel format of the texture file being loaded. Bear in mind that the final pixel format will be constrained by hardware capabilities so you may not get exactly what you ask for. Names defined in Ogre::PixelFormat are valid values.
gammainforms the renderer that you want the graphics hardware to perform gamma correction on the texture values as they are sampled for rendering. This is only applicable for textures which have 8-bit colour channels (e.g.PF_R8G8B8). Often, 8-bit per channel textures will be stored in gamma space in order to increase the precision of the darker colours (http://en.wikipedia.org/wiki/Gamma_correction) but this can throw out blending and filtering calculations since they assume linear space colour values. For the best quality shading, you may want to enable gamma correction so that the hardware converts the texture values to linear space for you automatically when sampling the texture, then the calculations in the pipeline can be done in a reliable linear colour space. When rendering to a final 8-bit per channel display, you’ll also want to convert back to gamma space which can be done in your shader (by raising to the power 1/2.2) or you can enable gamma correction on the texture being rendered to or the render window. Note that the ’gamma’ option on textures is applied on loading the texture so must be specified consistently if you use this texture in multiple places.

anim_texture

Sets the images to be used in an animated texture layer. In this case an animated texture layer means one which has multiple frames, each of which is a separate image file. There are 2 formats, one for implicitly determined image names, one for explicitly named images.

Format1 (short): anim_texture <base_name> <num_frames> <duration>

Example: anim_texture flame.jpg 5 2.5

This sets up an animated texture layer made up of 5 frames named flame_0.jpg, flame_1.jpg, flame_2.jpg etc, with an animation length of 2.5 seconds (2fps). If duration is set to 0, then no automatic transition takes place and frames must be changed manually in code.

Format2 (long): anim_texture <frame1> <frame2> ... <duration>

Example: anim_texture flamestart.jpg flamemore.png flameagain.jpg moreflame.jpg lastflame.tga 2.5

This sets up the same duration animation but from 5 separately named image files. The first format is more concise, but the second is provided if you cannot make your images conform to the naming standard required for it.

Default: none

cubic_texture

Sets the images used in a cubic texture, i.e. one made up of 6 individual images making up the faces of a cube or 1 cube texture if supported by the texture format(DDS for example) and rendersystem.. These kinds of textures are used for reflection maps (if hardware supports cubic reflection maps) or skyboxes. There are 2 formats, a brief format expecting image names of a particular format and a more flexible but longer format for arbitrarily named textures.

Format1 (short): cubic_texture <base_name> <combinedUVW|separateUV>

The base_name in this format is something like ’skybox.jpg’, and the system will expect you to provide skybox_fr.jpg, skybox_bk.jpg, skybox_up.jpg, skybox_dn.jpg, skybox_lf.jpg, and skybox_rt.jpg for the individual faces.

Format2 (long): cubic_texture <front> <back> <left> <right> <up> <down> separateUV

In this case each face is specified explicitly, incase you don’t want to conform to the image naming standards above. You can only use this for the separateUV version since the combinedUVW version requires a single texture name to be assigned to the combined 3D texture (see below).

In both cases the final parameter means the following:

combinedUVW

The 6 textures are combined into a single ’cubic’ texture map which is then addressed using 3D texture coordinates with U, V and W components. Necessary for reflection maps since you never know which face of the box you are going to need. Note that not all cards support cubic environment mapping.

separateUV

The 6 textures are kept separate but are all referenced by this single texture layer. One texture at a time is active (they are actually stored as 6 frames), and they are addressed using standard 2D UV coordinates. This type is good for skyboxes since only one face is rendered at one time and this has more guaranteed hardware support on older cards.


Default: none

binding_type

Tells this texture unit to bind to either the fragment processing unit or the vertex processing unit (for Vertex Texture Fetch).

Format: binding_type <vertex|fragment> Default: binding_type fragment

content_type

Tells this texture unit where it should get its content from. The default is to get texture content from a named texture, as defined with the texture, cubic_texture, anim_texture attributes. However you can also pull texture information from other automated sources. The options are:

named

The default option, this derives texture content from a texture name, loaded by ordinary means from a file or having been manually created with a given name.

shadow

This option allows you to pull in a shadow texture, and is only valid when you use texture shadows and one of the ’custom sequence’ shadowing types (See Shadows). The shadow texture in question will be from the ’n’th closest light that casts shadows, unless you use light-based pass iteration or the light_start option which may start the light index higher. When you use this option in multiple texture units within the same pass, each one references the next shadow texture. The shadow texture index is reset in the next pass, in case you want to take into account the same shadow textures again in another pass (e.g. a separate specular / gloss pass). By using this option, the correct light frustum projection is set up for you for use in fixed-function, if you use shaders just reference the texture_viewproj_matrix auto parameter in your shader.

compositor

This option allows you to reference a texture from a compositor, and is only valid when the pass is rendered within a compositor sequence. This can be either in a render_scene directive inside a compositor script, or in a general pass in a viewport that has a compositor attached. Note that this is a reference only, meaning that it does not change the render order. You must make sure that the order is reasonable for what you are trying to achieve (for example, texture pooling might cause the referenced texture to be overwritten by something else by the time it is referenced). The extra parameters for the content_type are only required for this type: The first is the name of the compositor being referenced. (Required) The second is the name of the texture to reference in the compositor. (Required) The third is the index of the texture to take, in case of an MRT. (Optional)

Format: content_type <named|shadow|compositor> [<Referenced Compositor Name>] [<Referenced Texture Name>] [<Referenced MRT Index>] Default: content_type named Example: content_type compositor DepthCompositor OutputTexture

tex_coord_set

Sets which texture coordinate set is to be used for this texture layer. A mesh can define multiple sets of texture coordinates, this sets which one this material uses.

Note
Only has an effect with the fixed-function pipeline or the RTShaderSystem

Format: tex_coord_set <set_num>

Example: tex_coord_set 2

Default: tex_coord_set 0

tex_address_mode

Defines what happens when texture coordinates exceed 1.0 for this texture layer.You can use the simple format to specify the addressing mode for all 3 potential texture coordinates at once, or you can use the 2/3 parameter extended format to specify a different mode per texture coordinate.

Simple Format: tex_address_mode <uvw_mode>
Extended Format: tex_address_mode <u_mode> <v_mode> [<w_mode>]

wrap

Any value beyond 1.0 wraps back to 0.0. Texture is repeated.

clamp

Values beyond 1.0 are clamped to 1.0. Texture ’streaks’ beyond 1.0 since last line of pixels is used across the rest of the address space. Useful for textures which need exact coverage from 0.0 to 1.0 without the ’fuzzy edge’ wrap gives when combined with filtering.

mirror

Texture flips every boundary, meaning texture is mirrored every 1.0 u or v

border

Values outside the range [0.0, 1.0] are set to the border colour, you might also set the tex_border_colour attribute too.


Default: tex_address_mode wrap

tex_border_colour

Sets the border colour of border texture address mode (see tex_address_mode).

Format: tex_border_colour <red> <green> <blue> [<alpha>]
NB valid colour values are between 0.0 and 1.0.

Example: tex_border_colour 0.0 1.0 0.3

Default: tex_border_colour 0.0 0.0 0.0 1.0

filtering

Sets the type of texture filtering used when magnifying or minifying a texture. There are 2 formats to this attribute, the simple format where you simply specify the name of a predefined set of filtering options, and the complex format, where you individually set the minification, magnification, and mip filters yourself. Simple Format
Format: filtering <none|bilinear|trilinear|anisotropic>
Default: filtering bilinear With this format, you only need to provide a single parameter which is one of the following:

none

No filtering or mipmapping is used. This is equivalent to the complex format ’filtering point point none’.

bilinear

2x2 box filtering is performed when magnifying or reducing a texture, and a mipmap is picked from the list but no filtering is done between the levels of the mipmaps. This is equivalent to the complex format ’filtering linear linear point’.

trilinear

2x2 box filtering is performed when magnifying and reducing a texture, and the closest 2 mipmaps are filtered together. This is equivalent to the complex format ’filtering linear linear linear’.

anisotropic

This is the same as ’trilinear’, except the filtering algorithm takes account of the slope of the triangle in relation to the camera rather than simply doing a 2x2 pixel filter in all cases. This makes triangles at acute angles look less fuzzy. Equivalent to the complex format ’filtering anisotropic anisotropic linear’. Note that in order for this to make any difference, you must also set the max_anisotropy attribute too.

Complex Format
Format: filtering <minification> <magnification> <mip>
Default: filtering linear linear point This format gives you complete control over the minification, magnification, and mip filters. Each parameter can be one of the following:

none

Nothing - only a valid option for the ’mip’ filter , since this turns mipmapping off completely. The lowest setting for min and mag is ’point’.

point

Pick the closet pixel in min or mag modes. In mip mode, this picks the closet matching mipmap.

linear

Filter a 2x2 box of pixels around the closest one. In the ’mip’ filter this enables filtering between mipmap levels.

anisotropic

Only valid for min and mag modes, makes the filter compensate for camera-space slope of the triangles. Note that in order for this to make any difference, you must also set the max_anisotropy attribute too.

max_anisotropy

Sets the maximum degree of anisotropy that the renderer will try to compensate for when filtering textures. The degree of anisotropy is the ratio between the height of the texture segment visible in a screen space region versus the width - so for example a floor plane, which stretches on into the distance and thus the vertical texture coordinates change much faster than the horizontal ones, has a higher anisotropy than a wall which is facing you head on (which has an anisotropy of 1 if your line of sight is perfectly perpendicular to it). You should set the max_anisotropy value to something greater than 1 to begin compensating; higher values can compensate for more acute angles. The maximum value is determined by the hardware, but it is usually 8 or 16. In order for this to be used, you have to set the minification and/or the magnification filtering option on this texture to anisotropic.

Format: max_anisotropy <value>
Default: max_anisotropy 1

mipmap_bias

Sets the bias value applied to the mipmapping calculation, thus allowing you to alter the decision of which level of detail of the texture to use at any distance. The bias value is applied after the regular distance calculation, and adjusts the mipmap level by 1 level for each unit of bias. Negative bias values force larger mip levels to be used, positive bias values force smaller mip levels to be used. The bias is a floating point value so you can use values in between whole numbers for fine tuning. In order for this option to be used, your hardware has to support mipmap biasing (exposed through the render system capabilities), and your minification filtering has to be set to point or linear.

Format: mipmap_bias <value>
Default: mipmap_bias 0

colour_op

Determines how the colour of this texture layer is combined with the one below it (or the lighting effect on the geometry if this is the first layer).

Note
Only has an effect with the fixed-function pipeline or the RTShaderSystem

Format: colour_op <replace|add|modulate|alpha_blend>

This method is the simplest way to blend texture layers, because it requires only one parameter, gives you the most common blending types, and automatically sets up 2 blending methods: one for if single-pass multitexturing hardware is available, and another for if it is not and the blending must be achieved through multiple rendering passes. It is, however, quite limited and does not expose the more flexible multitexturing operations, simply because these can’t be automatically supported in multipass fallback mode. If want to use the fancier options, use colour_op_ex, but you’ll either have to be sure that enough multitexturing units will be available, or you should explicitly set a fallback using colour_op_multipass_fallback.

replace

Replace all colour with texture with no adjustment.

add

Add colour components together.

modulate

Multiply colour components together.

alpha_blend

Blend based on texture alpha.


Default: colour_op modulate

colour_op_ex

This is an extended version of the colour_op attribute which allows extremely detailed control over the blending applied between this and earlier layers. Multitexturing hardware can apply more complex blending operations that multipass blending, but you are limited to the number of texture units which are available in hardware.

Note
Only has an effect with the fixed-function pipeline or the RTShaderSystem

Format: colour_op_ex <operation> <source1> <source2> [<manual_factor>] [<manual_colour1>] [<manual_colour2>]

Example colour_op_ex add_signed src_manual src_current 0.5

See the IMPORTANT note below about the issues between multipass and multitexturing that using this method can create. Texture colour operations determine how the final colour of the surface appears when rendered. Texture units are used to combine colour values from various sources (e.g. the diffuse colour of the surface from lighting calculations, combined with the colour of the texture). This method allows you to specify the ’operation’ to be used, i.e. the calculation such as adds or multiplies, and which values to use as arguments, such as a fixed value or a value from a previous calculation.

Parameters
operation
source1

Use source1 without modification

source2

Use source2 without modification

modulate

Multiply source1 and source2 together.

modulate_x2

Multiply source1 and source2 together, then by 2 (brightening).

modulate_x4

Multiply source1 and source2 together, then by 4 (brightening).

add

Add source1 and source2 together.

add_signed

Add source1 and source2 then subtract 0.5.

add_smooth

Add source1 and source2, subtract the product

subtract

Subtract source2 from source1

blend_diffuse_alpha

Use interpolated alpha value from vertices to scale source1, then add source2 scaled by (1-alpha).

blend_texture_alpha

As blend_diffuse_alpha but use alpha from texture

blend_current_alpha

As blend_diffuse_alpha but use current alpha from previous stages (same as blend_diffuse_alpha for first layer)

blend_manual

As blend_diffuse_alpha but use a constant manual alpha value specified in <manual>

dotproduct

The dot product of source1 and source2

blend_diffuse_colour

Use interpolated colour value from vertices to scale source1, then add source2 scaled by (1-colour).

source1
source2
src_current

The colour as built up from previous stages.

src_texture

The colour derived from the texture assigned to this layer.

src_diffuse

The interpolated diffuse colour from the vertices (same as ’src_current’ for first layer).

src_specular

The interpolated specular colour from the vertices.

src_manual

The manual colour specified at the end of the command.


For example ’modulate’ takes the colour results of the previous layer, and multiplies them with the new texture being applied. Bear in mind that colours are RGB values from 0.0-1.0 so multiplying them together will result in values in the same range, ’tinted’ by the multiply. Note however that a straight multiply normally has the effect of darkening the textures - for this reason there are brightening operations like modulate_x2. Note that because of the limitations on some underlying APIs (Direct3D included) the ’texture’ argument can only be used as the first argument, not the second.

Note that the last parameter is only required if you decide to pass a value manually into the operation. Hence you only need to fill these in if you use the ’blend_manual’ operation.

IMPORTANT: Ogre tries to use multitexturing hardware to blend texture layers together. However, if it runs out of texturing units (e.g. 2 of a GeForce2, 4 on a GeForce3) it has to fall back on multipass rendering, i.e. rendering the same object multiple times with different textures. This is both less efficient and there is a smaller range of blending operations which can be performed. For this reason, if you use this method you really should set the colour_op_multipass_fallback attribute to specify which effect you want to fall back on if sufficient hardware is not available (the default is just ’modulate’ which is unlikely to be what you want if you’re doing swanky blending here). If you wish to avoid having to do this, use the simpler colour_op attribute which allows less flexible blending options but sets up the multipass fallback automatically, since it only allows operations which have direct multipass equivalents.

Default: none (colour_op modulate)

colour_op_multipass_fallback

Sets the multipass fallback operation for this layer, if you used colour_op_ex and not enough multitexturing hardware is available.

Format: colour_op_multipass_fallback <src_factor> <dest_factor>

Example: colour_op_multipass_fallback one one_minus_dest_alpha

Because some of the effects you can create using colour_op_ex are only supported under multitexturing hardware, if the hardware is lacking the system must fallback on multipass rendering, which unfortunately doesn’t support as many effects. This attribute is for you to specify the fallback operation which most suits you.

The parameters are the same as in the scene_blend attribute; this is because multipass rendering IS effectively scene blending, since each layer is rendered on top of the last using the same mechanism as making an object transparent, it’s just being rendered in the same place repeatedly to get the multitexture effect. If you use the simpler (and less flexible) colour_op attribute you don’t need to call this as the system sets up the fallback for you.

alpha_op_ex

Behaves in exactly the same away as colour_op_ex except that it determines how alpha values are combined between texture layers rather than colour values.The only difference is that the 2 manual colours at the end of colour_op_ex are just single floating-point values in alpha_op_ex.

Note
Only has an effect with the fixed-function pipeline or the RTShaderSystem

env_map

Turns on/off texture coordinate effect that makes this layer an environment map.

Note
Only has an effect with the fixed-function pipeline or the RTShaderSystem

Format: env_map <off|spherical|planar|cubic_reflection|cubic_normal>

Environment maps make an object look reflective by using automatic texture coordinate generation depending on the relationship between the objects vertices or normals and the eye.

spherical

A spherical environment map. Requires a single texture which is either a fish-eye lens view of the reflected scene, or some other texture which looks good as a spherical map (a texture of glossy highlights is popular especially in car sims). This effect is based on the relationship between the eye direction and the vertex normals of the object, so works best when there are a lot of gradually changing normals, i.e. curved objects.

planar

Similar to the spherical environment map, but the effect is based on the position of the vertices in the viewport rather than vertex normals. This effect is therefore useful for planar geometry (where a spherical env_map would not look good because the normals are all the same) or objects without normals.

cubic_reflection

A more advanced form of reflection mapping which uses a group of 6 textures making up the inside of a cube, each of which is a view if the scene down each axis. Works extremely well in all cases but has a higher technical requirement from the card than spherical mapping. Requires that you bind a cubic_texture to this texture unit and use the ’combinedUVW’ option.

cubic_normal

Generates 3D texture coordinates containing the camera space normal vector from the normal information held in the vertex data. Again, full use of this feature requires a cubic_texture with the ’combinedUVW’ option.


Default: env_map off

scroll

Sets a fixed scroll offset for the texture.

Note
Only applies to the fixed-function pipeline, if you’re using a vertex program this will have no effect unless you use the texture_matrix auto-param.

Format: scroll <x> <y>

This method offsets the texture in this layer by a fixed amount. Useful for small adjustments without altering texture coordinates in models. However if you wish to have an animated scroll effect, see the scroll_anim attribute.

scroll_anim

Sets up an animated scroll for the texture layer. Useful for creating fixed-speed scrolling effects on a texture layer (for varying scroll speeds, see wave_xform).

Note
Only applies to the fixed-function pipeline, if you’re using a vertex program this will have no effect unless you use the texture_matrix auto-param.

Format: scroll_anim <xspeed> <yspeed>

rotate

Rotates a texture to a fixed angle. This attribute changes the rotational orientation of a texture to a fixed angle, useful for fixed adjustments. If you wish to animate the rotation, see rotate_anim.

Note
Only applies to the fixed-function pipeline, if you’re using a vertex program this will have no effect unless you use the texture_matrix auto-param.

Format: rotate <angle>

The parameter is a anti-clockwise angle in degrees.

Note
Only applies to the fixed-function pipeline, if you’re using a vertex shader this will have no effect unless you use the texture_matrix auto-param.

rotate_anim

Sets up an animated rotation effect of this layer. Useful for creating fixed-speed rotation animations (for varying speeds, see wave_xform).

Note
Only applies to the fixed-function pipeline, if you’re using a vertex program this will have no effect unless you use the texture_matrix auto-param.

Format: rotate_anim <revs_per_second>

The parameter is a number of anti-clockwise revolutions per second.

scale

Adjusts the scaling factor applied to this texture layer. Useful for adjusting the size of textures without making changes to geometry. This is a fixed scaling factor, if you wish to animate this see wave_xform.

Note
Only applies to the fixed-function pipeline, if you’re using a vertex program this will have no effect unless you use the texture_matrix auto-param.

Format: scale <x_scale> <y_scale>

Valid scale values are greater than 0, with a scale factor of 2 making the texture twice as big in that dimension etc.

wave_xform

Sets up a transformation animation based on a wave function. Useful for more advanced texture layer transform effects. You can add multiple instances of this attribute to a single texture layer if you wish.

Note
Only applies to the fixed-function pipeline, if you’re using a vertex program this will have no effect unless you use the texture_matrix auto-param.

Format: wave_xform <xform_type> <wave_type> <base> <frequency> <phase> <amplitude>

Example: wave_xform scale_x sine 1.0 0.2 0.0 5.0

Parameters
xform_type
scroll_x

Animate the x scroll value

scroll_y

Animate the y scroll value

rotate

Animate the rotate value

scale_x

Animate the x scale value

scale_y

Animate the y scale value

wave_type
sine

A typical sine wave which smoothly loops between min and max values

triangle

An angled wave which increases & decreases at constant speed, changing instantly at the extremes

square

Max for half the wavelength, min for the rest with instant transition between

sawtooth

Gradual steady increase from min to max over the period with an instant return to min at the end.

inverse_sawtooth

Gradual steady decrease from max to min over the period, with an instant return to max at the end.

baseThe base value, the minimum if amplitude > 0, the maximum if amplitude < 0
frequencyThe number of wave iterations per second, i.e. speed
phaseOffset of the wave start
amplitudeThe size of the wave


The range of the output of the wave will be {base, base+amplitude}. So the example above scales the texture in the x direction between 1 (normal size) and 5 along a sine wave at one cycle every 5 second (0.2 waves per second).

transform

This attribute allows you to specify a static 4x4 transformation matrix for the texture unit, thus replacing the individual scroll, rotate and scale attributes mentioned above.

Note
Only applies to the fixed-function pipeline, if you’re using a vertex program this will have no effect unless you use the texture_matrix auto-param.

Format: transform m00 m01 m02 m03 m10 m11 m12 m13 m20 m21 m22 m23 m30 m31 m32 m33

The indexes of the 4x4 matrix value above are expressed as m<row><col>.

Declaring GPU Programs

In order to use a vertex, geometry or fragment program in your materials (See Using Vertex/Geometry/Fragment Programs in a Pass), you first have to define them. A single program definition can be used by any number of materials, the only prerequisite is that a program must be defined before being referenced in the pass section of a material.

The definition of a program can either be embedded in the .material script itself (in which case it must precede any references to it in the script), or if you wish to use the same program across multiple .material files, you can define it in an external .program script. You define the program in exactly the same way whether you use a .program script or a .material script, the only difference is that all .program scripts are guaranteed to have been parsed before all .material scripts, so you can guarantee that your program has been defined before any .material script that might use it. Just like .material scripts, .program scripts will be read from any location which is on your resource path, and you can define many programs in a single script.

Vertex, geometry and fragment programs can be low-level (i.e. assembler code written to the specification of a given low level syntax such as vs_1_1 or arbfp1) or high-level such as DirectX9 HLSL, Open GL Shader Language, or nVidia’s Cg language (See High-level Programs). High level languages give you a number of advantages, such as being able to write more intuitive code, and possibly being able to target multiple architectures in a single program (for example, the same Cg program might be able to be used in both D3D and GL, whilst the equivalent low-level programs would require separate techniques, each targeting a different API). High-level programs also allow you to use named parameters instead of simply indexed ones, although parameters are not defined here, they are used in the Pass.

Here is an example of a definition of a low-level vertex program:

vertex_program myVertexProgram asm
{
source myVertexProgram.asm
syntax vs_1_1
}

As you can see, that’s very simple, and defining a fragment or geometry program is exactly the same, just with vertex_program replaced with fragment_program or geometry_program, respectively. You give the program a name in the header, followed by the word ’asm’ to indicate that this is a low-level program. Inside the braces, you specify where the source is going to come from (and this is loaded from any of the resource locations as with other media), and also indicate the syntax being used. You might wonder why the syntax specification is required when many of the assembler syntaxes have a header identifying them anyway - well the reason is that the engine needs to know what syntax the program is in before reading it, because during compilation of the material, we want to skip programs which use an unsupportable syntax quickly, without loading the program first.

The current supported syntaxes are:

vs_1_1

This is one of the DirectX vertex shader assembler syntaxes.
Supported on cards from: ATI Radeon 8500, nVidia GeForce 3

vs_2_0

Another one of the DirectX vertex shader assembler syntaxes.
Supported on cards from: ATI Radeon 9600, nVidia GeForce FX 5 series

vs_2_x

Another one of the DirectX vertex shader assembler syntaxes.
Supported on cards from: ATI Radeon X series, nVidia GeForce FX 6 series

vs_3_0

Another one of the DirectX vertex shader assembler syntaxes.
Supported on cards from: ATI Radeon HD 2000+, nVidia GeForce FX 6 series

arbvp1

This is the OpenGL standard assembler format for vertex programs. It’s roughly equivalent to DirectX vs_1_1.

vp20

This is an nVidia-specific OpenGL vertex shader syntax which is a superset of vs 1.1. ATI Radeon HD 2000+ also supports it.

vp30

Another nVidia-specific OpenGL vertex shader syntax. It is a superset of vs 2.0, which is supported on nVidia GeForce FX 5 series and higher. ATI Radeon HD 2000+ also supports it.

vp40

Another nVidia-specific OpenGL vertex shader syntax. It is a superset of vs 3.0, which is supported on nVidia GeForce FX 6 series and higher.

ps_1_1, ps_1_2, ps_1_3

DirectX pixel shader (i.e. fragment program) assembler syntax.
Supported on cards from: ATI Radeon 8500, nVidia GeForce 3

Note
for ATI 8500, 9000, 9100, 9200 hardware, this profile can also be used in OpenGL. The ATI 8500 to 9200 do not support arbfp1 but do support atifs extension in OpenGL which is very similar in function to ps_1_4 in DirectX. Ogre has a built in ps_1_x to atifs compiler that is automatically invoked when ps_1_x is used in OpenGL on ATI hardware.
ps_1_4

DirectX pixel shader (i.e. fragment program) assembler syntax.
Supported on cards from: ATI Radeon 8500, nVidia GeForce FX 5 series

Note
for ATI 8500, 9000, 9100, 9200 hardware, this profile can also be used in OpenGL. The ATI 8500 to 9200 do not support arbfp1 but do support atifs extension in OpenGL which is very similar in function to ps_1_4 in DirectX. Ogre has a built in ps_1_x to atifs compiler that is automatically invoked when ps_1_x is used in OpenGL on ATI hardware.
ps_2_0

DirectX pixel shader (i.e. fragment program) assembler syntax.
Supported cards: ATI Radeon 9600, nVidia GeForce FX 5 series

ps_2_x

DirectX pixel shader (i.e. fragment program) assembler syntax. This is basically ps_2_0 with a higher number of instructions.
Supported cards: ATI Radeon X series, nVidia GeForce FX 6 series

ps_3_0

DirectX pixel shader (i.e. fragment program) assembler syntax.
Supported cards: ATI Radeon HD 2000+, nVidia GeForce FX6 series

ps_3_x

DirectX pixel shader (i.e. fragment program) assembler syntax.
Supported cards: nVidia GeForce FX7 series

arbfp1

This is the OpenGL standard assembler format for fragment programs. It’s roughly equivalent to ps_2_0, which means that not all cards that support basic pixel shaders under DirectX support arbfp1 (for example neither the GeForce3 or GeForce4 support arbfp1, but they do support ps_1_1).

fp20

This is an nVidia-specific OpenGL fragment syntax which is a superset of ps 1.3. It allows you to use the ’nvparse’ format for basic fragment programs. It actually uses NV_texture_shader and NV_register_combiners to provide functionality equivalent to DirectX’s ps_1_1 under GL, but only for nVidia cards. However, since ATI cards adopted arbfp1 a little earlier than nVidia, it is mainly nVidia cards like the GeForce3 and GeForce4 that this will be useful for. You can find more information about nvparse at http://developer.nvidia.com/object/nvparse.html.

fp30

Another nVidia-specific OpenGL fragment shader syntax. It is a superset of ps 2.0, which is supported on nVidia GeForce FX 5 series and higher. ATI Radeon HD 2000+ also supports it.

fp40

Another nVidia-specific OpenGL fragment shader syntax. It is a superset of ps 3.0, which is supported on nVidia GeForce FX 6 series and higher.

gpu_gp, gp4_gp

An nVidia-specific OpenGL geometry shader syntax.
Supported cards: nVidia GeForce FX8 series

glsles

OpenGL Shading Language for Embedded Systems. It is a variant of GLSL, streamlined for low power devices. Supported cards: PowerVR SGX series

You can get a definitive list of the syntaxes supported by the current card by calling GpuProgramManager::getSingleton().getSupportedSyntax().

Specifying Named Constants for Assembler Shaders

Assembler shaders don’t have named constants (also called uniform parameters) because the language does not support them - however if you for example decided to precompile your shaders from a high-level language down to assembler for performance or obscurity, you might still want to use the named parameters. Well, you actually can - GpuNamedConstants which contains the named parameter mappings has a ’save’ method which you can use to write this data to disk, where you can reference it later using the manual_named_constants directive inside your assembler program declaration, e.g.

vertex_program myVertexProgram asm
{
source myVertexProgram.asm
syntax vs_1_1
manual_named_constants myVertexProgram.constants
}

In this case myVertexProgram.constants has been created by calling highLevelGpuProgram->getNamedConstants().save("myVertexProgram.constants"); sometime earlier as preparation, from the original high-level program. Once you’ve used this directive, you can use named parameters here even though the assembler program itself has no knowledge of them.

Default Program Parameters

While defining a vertex, geometry or fragment program, you can also specify the default parameters to be used for materials which use it, unless they specifically override them. You do this by including a nested ’default_params’ section, like so:

vertex_program Ogre/CelShadingVP cg
{
source Example_CelShading.cg
entry_point main_vp
profiles vs_1_1 arbvp1
default_params
{
param_named_auto lightPosition light_position_object_space 0
param_named_auto eyePosition camera_position_object_space
param_named_auto worldViewProj worldviewproj_matrix
param_named shininess float 10
}
}

The syntax of the parameter definition is exactly the same as when you define parameters when using programs, See Program Parameter Specification. Defining default parameters allows you to avoid rebinding common parameters repeatedly (clearly in the above example, all but ’shininess’ are unlikely to change between uses of the program) which makes your material declarations shorter.

Declaring Shared Parameters

Often, not every parameter you want to pass to a shader is unique to that program, and perhaps you want to give the same value to a number of different programs, and a number of different materials using that program. Shared parameter sets allow you to define a ’holding area’ for shared parameters that can then be referenced when you need them in particular shaders, while keeping the definition of that value in one place. To define a set of shared parameters, you do this:

shared_params YourSharedParamsName
{
shared_param_named mySharedParam1 float4 0.1 0.2 0.3 0.4
...
}

As you can see, you need to use the keyword ’shared_params’ and follow it with the name that you will use to identify these shared parameters. Inside the curly braces, you can define one parameter per line, in a way which is very similar to the param_named syntax. The definition of these lines is: Format: shared_param_name <param_name> <param_type> [<[array_size]>] [<initial_values>]

The param_name must be unique within the set, and the param_type can be any one of float, float2, float3, float4, int, int2, int3, int4, matrix2x2, matrix2x3, matrix2x4, matrix3x2, matrix3x3, matrix3x4, matrix4x2, matrix4x3 and matrix4x4. The array_size option allows you to define arrays of param_type should you wish, and if present must be a number enclosed in square brackets (and note, must be separated from the param_type with whitespace). If you wish, you can also initialise the parameters by providing a list of values.

Once you have defined the shared parameters, you can reference them inside default_params and params blocks using shared_params_ref. You can also obtain a reference to them in your code via GpuProgramManager::getSharedParameters, and update the values for all instances using them.

Script Inheritance

When creating new script objects that are only slight variations of another object, it’s good to avoid copying and pasting between scripts. Script inheritance lets you do this; in this section we’ll use material scripts as an example, but this applies to all scripts parsed with the script compilers in Ogre 1.6 onwards.

For example, to make a new material that is based on one previously defined, add a colon **:** after the new material name followed by the name of the material that is to be copied.

Format: material <NewUniqueChildName> : <ReferenceParentMaterial>

The only caveat is that a parent material must have been defined/parsed prior to the child material script being parsed. The easiest way to achieve this is to either place parents at the beginning of the material script file, or to use the ’import’ directive (See Script Import Directive). Note that inheritance is actually a copy - after scripts are loaded into Ogre, objects no longer maintain their copy inheritance structure. If a parent material is modified through code at runtime, the changes have no effect on child materials that were copied from it in the script.

Material copying within the script alleviates some drudgery from copy/paste but having the ability to identify specific techniques, passes, and texture units to modify makes material copying easier. Techniques, passes, texture units can be identified directly in the child material without having to layout previous techniques, passes, texture units by associating a name with them, Techniques and passes can take a name and texture units can be numbered within the material script. You can also use variables, See Script Variables.

Names become very useful in materials that copy from other materials. In order to override values they must be in the correct technique, pass, texture unit etc. The script could be lain out using the sequence of techniques, passes, texture units in the child material but if only one parameter needs to change in say the 5th pass then the first four passes prior to the fifth would have to be placed in the script:

Here is an example:

material test2 : test1
{
technique
{
pass
{
}
pass
{
}
pass
{
}
pass
{
}
pass
{
ambient 0.5 0.7 0.3 1.0
}
}
}

This method is tedious for materials that only have slight variations to their parent. An easier way is to name the pass directly without listing the previous passes:

material test2 : test1
{
technique 0
{
pass 4
{
ambient 0.5 0.7 0.3 1.0
}
}
}

The parent pass name must be known and the pass must be in the correct technique in order for this to work correctly. Specifying the technique name and the pass name is the best method. If the parent technique/pass are not named then use their index values for their name as done in the example.

Adding new Techniques, Passes, to copied materials

If a new technique or pass needs to be added to a copied material then use a unique name for the technique or pass that does not exist in the parent material. Using an index for the name that is one greater than the last index in the parent will do the same thing. The new technique/pass will be added to the end of the techniques/passes copied from the parent material.

Note
if passes or techniques aren’t given a name, they will take on a default name based on their index. For example the first pass has index 0 so its name will be 0.

Identifying Texture Units to override values

A specific texture unit state (TUS) can be given a unique name within a pass of a material so that it can be identified later in cloned materials that need to override specified texture unit states in the pass without declaring previous texture units. Using a unique name for a Texture unit in a pass of a cloned material adds a new texture unit at the end of the texture unit list for the pass.

material BumpMap2 : BumpMap1
{
technique ati8500
{
pass 0
{
texture_unit NormalMap
{
texture BumpyMetalNM.png
}
}
}
}

Advanced Script Inheritance

Starting with Ogre 1.6, script objects can now inherit from each other more generally. The previous concept of inheritance, material copying, was restricted only to the top-level material objects. Now, any level of object can take advantage of inheritance (for instance, techniques, passes, and compositor targets).

material Test
{
technique
{
pass : ParentPass
{
}
}
}

Notice that the pass inherits from ParentPass. This allows for the creation of more fine-grained inheritance hierarchies.

Along with the more generalized inheritance system comes an important new keyword: "abstract." This keyword is used at a top-level object declaration (not inside any other object) to denote that it is not something that the compiler should actually attempt to compile, but rather that it is only for the purpose of inheritance. For example, a material declared with the abstract keyword will never be turned into an actual usable material in the material framework. Objects which cannot be at a top-level in the document (like a pass) but that you would like to declare as such for inheriting purpose must be declared with the abstract keyword.

abstract pass ParentPass
{
diffuse 1 0 0 1
}

That declares the ParentPass object which was inherited from in the above example. Notice the abstract keyword which informs the compiler that it should not attempt to actually turn this object into any sort of Ogre resource. If it did attempt to do so, then it would obviously fail, since a pass all on its own like that is not valid.

The final matching option is based on wildcards. Using the ’*’ character, you can make a powerful matching scheme and override multiple objects at once, even if you don’t know exact names or positions of those objects in the inherited object.

abstract technique Overrider
{
pass *colour*
{
diffuse 0 0 0 0
}
}

This technique, when included in a material, will override all passes matching the wildcard "\*color\*" (color has to appear in the name somewhere) and turn their diffuse properties black. It does not matter their position or exact name in the inherited technique, this will match them.

Texture Aliases

Texture aliases are useful for when only the textures used in texture units need to be specified for a cloned material. In the source material i.e. the original material to be cloned, each texture unit can be given a texture alias name. The cloned material in the script can then specify what textures should be used for each texture alias. Note that texture aliases are a more specific version of Script Variables which can be used to easily set other values.

Using texture aliases within texture units:
Format:
texture_alias <name>

Default: <name> will default to texture_unit <name> if set

texture_unit DiffuseTex
{
texture diffuse.jpg
}

texture_alias defaults to DiffuseTex.

Example: The base material to be cloned:

material TSNormalSpecMapping
{
technique GLSL
{
pass
{
ambient 0.1 0.1 0.1
diffuse 0.7 0.7 0.7
specular 0.7 0.7 0.7 128
vertex_program_ref GLSLDemo/OffsetMappingVS
{
param_named_auto lightPosition light_position_object_space 0
param_named_auto eyePosition camera_position_object_space
param_named textureScale float 1.0
}
fragment_program_ref GLSLDemo/TSNormalSpecMappingFS
{
param_named normalMap int 0
param_named diffuseMap int 1
param_named fxMap int 2
}
// Normal map
texture_unit NormalMap
{
texture defaultNM.png
tex_coord_set 0
filtering trilinear
}
// Base diffuse texture map
texture_unit DiffuseMap
{
texture defaultDiff.png
filtering trilinear
tex_coord_set 1
}
// spec map for shininess
texture_unit SpecMap
{
texture defaultSpec.png
filtering trilinear
tex_coord_set 2
}
}
}
technique HLSL_DX9
{
pass
{
vertex_program_ref FxMap_HLSL_VS
{
param_named_auto worldViewProj_matrix worldviewproj_matrix
param_named_auto lightPosition light_position_object_space 0
param_named_auto eyePosition camera_position_object_space
}
fragment_program_ref FxMap_HLSL_PS
{
param_named ambientColor float4 0.2 0.2 0.2 0.2
}
// Normal map
texture_unit
{
texture_alias NormalMap
texture defaultNM.png
tex_coord_set 0
filtering trilinear
}
// Base diffuse texture map
texture_unit
{
texture_alias DiffuseMap
texture defaultDiff.png
filtering trilinear
tex_coord_set 1
}
// spec map for shininess
texture_unit
{
texture_alias SpecMap
texture defaultSpec.png
filtering trilinear
tex_coord_set 2
}
}
}
}

Note that the GLSL and HLSL techniques use the same textures. For each texture usage type a texture alias is given that describes what the texture is used for. So the first texture unit in the GLSL technique has the same alias as the TUS in the HLSL technique since its the same texture used. Same goes for the second and third texture units.
For demonstration purposes, the GLSL technique makes use of texture_unit naming and therefore the texture_alias name does not have to be set since it defaults to the texture unit name. So why not use the default all the time since its less typing? For most situations you can. Its when you clone a material that and then want to change the alias that you must use the texture_alias command in the script. You cannot change the name of a texture_unit in a cloned material so texture_alias provides a facility to assign an alias name.

Now we want to clone the material but only want to change the textures used. We could copy and paste the whole material but if we decide to change the base material later then we also have to update the copied material in the script. With set_texture_alias, copying a material is very easy now. set_texture_alias is specified at the top of the material definition. All techniques using the specified texture alias will be effected by set_texture_alias.

Format:
set_texture_alias <alias name> <texture name>

material fxTest : TSNormalSpecMapping
{
set_texture_alias NormalMap fxTestNMap.png
set_texture_alias DiffuseMap fxTestDiff.png
set_texture_alias SpecMap fxTestMap.png
}

The textures in both techniques in the child material will automatically get replaced with the new ones we want to use.

The same process can be done in code as long you set up the texture alias names so then there is no need to traverse technique/pass/TUS to change a texture. You just call myMaterialPtr->applyTextureAliases(myAliasTextureNameList) which will update all textures in all texture units that match the alias names in the map container reference you passed as a parameter.

You don’t have to supply all the textures in the copied material.

material fxTest2 : fxTest
{
set_texture_alias DiffuseMap fxTest2Diff.png
set_texture_alias SpecMap fxTest2Map.png
}

Material fxTest2 only changes the diffuse and spec maps of material fxTest and uses the same normal map.

Another example:

material fxTest3 : TSNormalSpecMapping
{
set_texture_alias DiffuseMap fxTest2Diff.png
}

fxTest3 will end up with the default textures for the normal map and spec map setup in TSNormalSpecMapping material but will have a different diffuse map. So your base material can define the default textures to use and then the child materials can override specific textures.

Script Variables

A very powerful new feature in Ogre 1.6 is variables. Variables allow you to parameterize data in materials so that they can become more generalized. This enables greater reuse of scripts by targeting specific customization points. Using variables along with inheritance allows for huge amounts of overrides and easy object reuse.

abstract pass ParentPass
{
diffuse $diffuse_colour
}
material Test
{
technique
{
pass : ParentPass
{
set $diffuse_colour "1 0 0 1"
}
}
}

The ParentPass object declares a variable called "diffuse\_colour" which is then overridden in the Test material’s pass. The "set" keyword is used to set the value of that variable. The variable assignment follows lexical scoping rules, which means that the value of "1 0 0 1" is only valid inside that pass definition. Variable assignment in outer scopes carry over into inner scopes.

material Test
{
set $diffuse_colour "1 0 0 1"
technique
{
pass : ParentPass
{
}
}
}

The $diffuse_colour assignment carries down through the technique and into the pass.

Script Import Directive

Imports are a feature introduced to remove ambiguity from script dependencies. When using scripts that inherit from each other but which are defined in separate files sometimes errors occur because the scripts are loaded in incorrect order. Using imports removes this issue. The script which is inheriting another can explicitly import its parent’s definition which will ensure that no errors occur because the parent’s definition was not found.

import * from "parent.material"
material Child : Parent
{
}

The material "Parent" is defined in parent.material and the import ensures that those definitions are found properly. You can also import specific targets from within a file.

import Parent from "parent.material"

If there were other definitions in the parent.material file, they would not be imported.

Note, however that importing does not actually cause objects in the imported script to be fully parsed & created, it just makes the definitions available for inheritance. This has a specific ramification for vertex / fragment program definitions, which must be loaded before any parameters can be specified. You should continue to put common program definitions in .program files to ensure they are fully parsed before being referenced in multiple .material files. The ’import’ command just makes sure you can resolve dependencies between equivalent script definitions (e.g. material to material).