\input texinfo @c -*-texinfo-*- @c %**start of header @setfilename manual.info @settitle OGRE Manual v1.2.0 ('Dagon') @c %**end of header @titlepage @title OGRE Manual @author Steve Streeting @page @vskip 0pt plus 1filll Copyright @copyright{} The OGRE Team@*@* Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies.@*@* Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided that the entire resulting derived work is distributed under the terms of a permission notice identical to this one.@*@* @end titlepage @node Top @top OGRE Manual Copyright @copyright{} The OGRE Team@*@* This work is licenced under the Creative Commons Attribution-ShareAlike 2.5 License. To view a copy of this licence, visit @url{http://creativecommons.org/licenses/by-sa/2.5/} or send a letter to Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA.@*@* @ifinfo @menu * Introduction:: * The Core Objects:: * Scripts:: * Mesh Tools:: * Hardware Buffers:: * External Texture Sources:: * Shadows:: * Animation:: @detailmenu @end detailmenu @end menu @end ifinfo @c ------------------------------------------- @node Introduction @chapter Introduction This chapter is intended to give you an overview of the main components of OGRE and why they have been put together that way. @c ------------------------------------------- @node Object Orientation - more than just a buzzword @section Object Orientation - more than just a buzzword The name is a dead giveaway. It says Object-Oriented Graphics Rendering Engine, and that's exactly what it is. Ok, but why? Why did I choose to make such a big deal about this?@*@* Well, nowadays graphics engines are like any other large software system. They start small, but soon they balloon into monstrously complex beasts which just can't be all understood at once. It's pretty hard to manage systems of this size, and even harder to make changes to them reliably, and that's pretty important in a field where new techniques and approaches seem to appear every other week. Designing systems around huge files full of C function calls just doesn't cut it anymore - even if the whole thing is written by one person (not likely) they will find it hard to locate that elusive bit of code after a few months and even harder to work out how it all fits together.@*@* Object orientation is a very popular approach to addressing the complexity problem. It's a step up from decomposing your code into separate functions, it groups function and state data together in classes which are designed to represent real concepts. It allows you to hide complexity inside easily recognised packages with a conceptually simple interface so they are easy to recognise and have a feel of 'building blocks' which you can plug together again later. You can also organise these blocks so that some of them look the same on the outside, but have very different ways of achieving their objectives on the inside, again reducing the complexity for the developers because they only have to learn one interface.@*@* I'm not going to teach you OO here, that's a subject for many other books, but suffice to say I'd seen enough benefits of OO in business systems that I was surprised most graphics code seemed to be written in C function stylee. I was interested to see whether I could apply my design experience in other types of software to an area which has long held a place in my heart - 3D graphics engines. Some people I spoke to were of the opinion that using full C++ wouldn't be fast enough for a real-time graphics engine, but others (including me) were of the opinion that, with care, and object-oriented framework can be performant. We were right. In summary, here's the benefits an object-oriented approach brings to OGRE: @table @asis @item Abstraction Common interfaces hide the nuances between different implementations of 3D API and operating systems @item Encapsulation There is a lot of state management and context-specific actions to be done in a graphics engine - encapsulation allows me to put the code and data nearest to where it is used which makes the code cleaner and easier to understand, and more reliable because duplication is avoided @item Polymorphism The behaviour of methods changes depending on the type of object you are using, even if you only learn one interface, e.g. a class specialised for managing indoor levels behaves completely differently from the standard scene manager, but looks identical to other classes in the system and has the same methods called on it @end table @c ------------------------------------------- @node Multi-everything @section Multi-everything I wanted to do more than create a 3D engine that ran on one 3D API, on one platform, with one type of scene (indoor levels are most popular). I wanted OGRE to be able to extend to any kind of scene (but yet still implement scene-specific optimisations under the surface), any platform and any 3D API.@*@* Therefore all the 'visible' parts of OGRE are completely independent of platform, 3D API and scene type. There are no dependencies on Windows types, no assumptions about the type of scene you are creating, and the principles of the 3D aspects are based on core maths texts rather than one particular API implementation.@*@* Now of course somewhere OGRE has to get down to the nitty-gritty of the specifics of the platform, API and scene, but it does this in subclasses specially designed for the environment in question, but which still expose the same interface as the abstract versions.@*@* For example, there is a 'Win32Window' class which handles all the details about rendering windows on a Win32 platform - however the application designer only has to manipulate it via the superclass interface 'RenderWindow', which will be the same across all platforms. Similarly the 'SceneManager' class looks after the arrangement of objects in the scene and their rendering sequence. Applications only have to use this interface, but there is a 'BspSceneManager' class which optimises the scene management for indoor levels, meaning you get both performance and an easy to learn interface. All applications have to do is hint about the kind of scene they will be creating and let OGRE choose the most appropriate implementation - this is covered in a later tutorial.@*@* OGRE's object-oriented nature makes all this possible. Currently OGRE runs on both Windows and Linux, using plugins to drive the underlying rendering API (currently Direct3D or OpenGL). Applications use OGRE at the abstract level, thus ensuring that they automatically operate on all platforms and rendering subsystems that OGRE provides without any need for platform or API specific code.@*@* @node The Core Objects @chapter The Core Objects @heading Introduction This tutorial gives you a quick summary of the core objects that you will use in OGRE and what they are used for. @heading A Word About Namespaces OGRE uses a C++ feature called namespaces. This lets you put classes, enums, structures, anything really within a 'namespace' scope which is an easy way to prevent name clashes, i.e. situations where you have 2 things called the same thing. Since OGRE is designed to be used inside other applications, I wanted to be sure that name clashes would not be a problem. Some people prefix their classes/types with a short code because some compilers don't support namespaces, but I chose to use them because they are the 'right' way to do it. Sorry if you have a non-compliant compiler, but hey, the C++ standard has been defined for years, so compiler writers really have no excuse anymore. If your compiler doesn't support namespaces then it's probably because it's sh*t - get a better one. ;) This means every class, type etc should be prefixed with 'Ogre::', e.g. 'Ogre::Camera', 'Ogre::Vector3' etc which means if elsewhere in your application you have used a Vector3 type you won't get name clashes. To avoid lots of extra typing you can add a 'using namespace Ogre;' statement to your code which means you don't have to type the 'Ogre::' prefix unless there is ambiguity (in the situation where you have another definition with the same name). @heading UML Diagram Shown below is a UML diagram of the core objects and how they relate to each other. Even if you don't know UML I'm sure you can work out the gist... @image{images/uml-overview} More details on these objects can be found in the following sections. @node The Root Object @section The Root object The 'Root' object is the entry point to the OGRE system. This object MUST be the first one to be created, and the last one to be destroyed. In the example applications I chose to make an instance of Root a member of my application object which ensured that it was created as soon as my application object was, and deleted when the application object was deleted.@*@* The root object lets you configure the system, for example through the showConfigDialog() method which is an extremely handy method which performs all render system options detection and shows a dialog for the user to customise resolution, colour depth, full screen options etc. It also sets the options the user selects so that you can initialise the system directly afterwards.@*@* The root object is also your method for obtaining pointers to other objects in the system, such as the SceneManager, RenderSystem and various other resource managers. See below for details.@*@* Finally, if you run OGRE in continuous rendering mode, i.e. you want to always refresh all the rendering targets as fast as possible (the norm for games and demos, but not for windowed utilities), the root object has a method called startRendering, which when called will enter a continuous rendering loop which will only end when all rendering windows are closed, or any FrameListener objects indicate that they want to stop the cycle (see below for details of FrameListener objects).@*@* @node The RenderSystem object @section The RenderSystem object The RenderSystem object is actually an abstract class which defines the interface to the underlying 3D API. It is responsible for sending rendering operations to the API and setting all the various rendering options. This class is abstract because all the implementation is rendering API specific - there are API-specific subclasses for each rendering API (e.g. D3DRenderSystem for Direct3D). After the system has been initialised through Root::initialise, the RenderSystem object for the selected rendering API is available via the Root::getRenderSystem() method.@*@* However, a typical application should not normally need to manipulate the RenderSystem object directly - everything you need for rendering objects and customising settings should be available on the SceneManager, Material and other scene-oriented classes. It's only if you want to create multiple rendering windows (completely separate windows in this case, not multiple viewports like a split-screen effect which is done via the RenderWindow class) or access other advanced features that you need access to the RenderSystem object.@*@* For this reason I will not discuss the RenderSystem object further in these tutorials. You can assume the SceneManager handles the calls to the RenderSystem at the appropriate times.@*@* @node The SceneManager object @section The SceneManager object Apart from the Root object, this is probably the most critical part of the system from the application's point of view. Certainly it will be the object which is most used by the application. The SceneManager is in charge of the contents of the scene which is to be rendered by the engine. It is responsible for organising the contents using whatever technique it deems best, for creating and managing all the cameras, movable objects (entities), lights and materials (surface properties of objects), and for managing the 'world geometry' which is the sprawling static geometry usually used to represent the immovable parts of a scene.@*@* It is to the SceneManager that you go when you want to create a camera for the scene. It's also where you go to retrieve a material which is used by an object, or to remove a light from the scene. There is no need for your application to keep lists of objects, the SceneManager keeps a named set of all of the scene objects for you to access, should you need them. Look in the main documentation under the getCamera, getMaterial, getLight etc methods.@*@* The SceneManager also sends the scene to the RenderSystem object when it is time to render the scene. You never have to call the SceneManager::_renderScene method directly though - it is called automatically whenever a rendering target is asked to update.@*@* So most of your interaction with the SceneManager is during scene setup. You're likely to call a great number of methods (perhaps driven by some input file containing the scene data) in order to set up your scene. You can also modify the contents of the scene dynamically during the rendering cycle if you create your own FrameListener object (see later).@*@* Because different scene types require very different algorithmic approaches to deciding which objects get sent to the RenderSystem in order to attain good rendering performance, the SceneManager class is designed to be subclassed for different scene types. The default SceneManager object will render a scene, but it does little or no scene organisation and you should not expect the results to be high performance in the case of large scenes. The intention is that specialisations will be created for each type of scene such that under the surface the subclass will optimise the scene organisation for best performance given assumptions which can be made for that scene type. An example is the BspSceneManager which optimises rendering for large indoor levels based on a Binary Space Partition (BSP) tree.@*@* The application using OGRE does not have to know which subclasses are available. The application simply calls Root::getSceneManager(..) passing as a parameter one of a number of scene types (e.g. ST_GENERIC, ST_INTERIOR etc). OGRE will automatically use the best SceneManager subclass available for that scene type, or default to the basic SceneManager if a specialist one is not available. This allows the developers of OGRE to add new scene specialisations later and thus optimise previously unoptimised scene types without the user applications having to change any code.@*@* @node The ResourceManager Objects @section The ResourceManager Objects The ResourceManager class is actually just a base class for a number of other classes which are used to manage resources. In this context, resources are sets of data which must be loaded from somewhere to provide OGRE with the data it needs. Examples are textures, meshes and maps. There is a subclass of ResourceManager to manage each of the types of resources, e.g. TextureManager for loading textures, MeshManager for loading mesh objects.@*@* ResourceManager's ensure that resources are only loaded once and shared throughout the OGRE engine. They also manage the memory requirements of the resources they look after. They can also search in a number of locations for the resources they need, including multiple search paths and compressed archives (ZIP files).@*@* Most of the time you won't interact with resource managers directly. Resource managers will be called by other parts of the OGRE system as required, for example when you request for a texture to be added to a Material, the TextureManager will be called for you. If you like, you can call the appropriate resource manager directly to preload resources (if for example you want to prevent disk access later on) but most of the time it's ok to let OGRE decide when to do it.@*@* Probably the only time you will need to call a ResourceManager is when you want to tell it where to look for resources. You can do this by calling the addSearchPath and addArchive methods of the resource manager, which will cause it to also look in the folder/archive you specify next time it searches for files.@*@* The above methods only affect the particular resource manager you call (e.g. it will only affect texture loading if you call it on TextureManager). Alternatively you can also call the static method ResourceManager::addCommonSearchPath or ResourceManager::addCommonArchive if you want ALL resource managers to look in the folder/archive you specify.@*@* Because there is only ever 1 instance of each resource manager in the engine, if you do want to get a reference to a resource manager use the following syntax: @example TextureManager::getSingleton().someMethod() MeshManager::getSingleton().someMethod() @end example @*@* @node The Mesh Object @section The Mesh Object A Mesh object represents a discrete model, a set of geometry which is self-contained and is typically fairly small on a world scale. Mesh objects are assumed to represent movable objects and are not used for the sprawling level geometry typically used to create backgrounds.@*@* Mesh objects are a type of resource, and are managed by the MeshManager resource manager. They are typically loaded from OGRE's custom object format, the '.mesh' format. Mesh files are typically created by exporting from a modelling tool @xref{Exporters} and can be maipulated through various @ref{Mesh Tools}@*@* You can also create Mesh objects manually by calling the MeshManager::createManual method. This way you can define the geometry yourself, but this is outside the scope of this manual.@*@* Mesh objects are the basis for the individual movable objects in the world, which are called @ref{Entities}.@*@* Mesh objects can also be animated using @xref{Skeletal Animation}. @node Entities @section Entities An entity is an instance of a movable object in the scene. It could be a car, a person, a dog, a shuriken, whatever. The only assumption is that it does not necessarily have a fixed position in the world.@*@* Entities are based on discrete meshes, i.e. collections of geometry which are self-contained and typically fairly small on a world scale, which are represented by the Mesh object. Multiple entities can be based on the same mesh, since often you want to create multiple copies of the same type of object in a scene.@*@* You create an entity by calling the SceneManager::createEntity method, giving it a name and specifying the name of the mesh object which it will be based on (e.g. 'muscleboundhero.mesh'). The SceneManager will ensure that the mesh is loaded by calling the MeshManager resource manager for you. Only one copy of the Mesh will be loaded.@*@* Entities are not deemed to be a part of the scene until you attach them to a SceneNode (see the section below). By attaching entities to SceneNodes, you can create complex hierarchical relationships between the positions and orientations of entities. You then modify the positions of the nodes to indirectly affect the entity positions.@*@* When a Mesh is loaded, it automatically comes with a number of materials defined. It is possible to have more than one material attached to a mesh - different parts of the mesh may use different materials. Any entity created from the mesh will automatically use the default materials. However, you can change this on a per-entity basis if you like so you can create a number of entities based on the same mesh but with different textures etc.@*@* To understand how this works, you have to know that all Mesh objects are actually composed of SubMesh objects, each of which represents a part of the mesh using one Material. If a Mesh uses only one Material, it will only have one SubMesh.@*@* When an Entity is created based on this Mesh, it is composed of (possibly) multiple SubEntity objects, each matching 1 for 1 with the SubMesh objects from the original Mesh. You can access the SubEntity objects using the Entity::getSubEntity method. Once you have a reference to a SubEntity, you can change the material it uses by calling it's setMaterialName method. In this way you can make an Entity deviate from the default materials and thus create an individual looking version of it.@*@* @node Materials @section Materials The Material object controls how objects in the scene are rendered. It specifies what basic surface properties objects have such as reflectance of colours, shininess etc, how many texture layers are present, what images are on them and how they are blended together, what special effects are applied such as environment mapping, what culling mode is used, how the textures are filtered etc.@*@* Materials can either be set up programmatically, by calling SceneManager::createMaterial and tweaking the settings, or by specifying it in a 'script' which is loaded at runtime. @xref{Material Scripts} for more info.@*@* Basically everything about the appearance of an object apart from it's shape is controlled by the Material class.@*@* The SceneManager class manages the master list of materials available to the scene. The list can be added to by the application by calling SceneManager::createMaterial, or by loading a Mesh (which will in turn load material properties). Whenever materials are added to the SceneManager, they start off with a default set of properties; these are defined by OGRE as the following:@*@* @itemize @bullet @item ambient reflectance = ColourValue::White (full) @item diffuse reflectance = ColourValue::White (full) @item specular reflectance = ColourValue::Black (none) @item emmissive = ColourValue::Black (none) @item shininess = 0 (not shiny) @item No texture layers (& hence no textures) @item SourceBlendFactor = SBF_ONE, DestBlendFactor = SBF_ZERO (opaque) @item Depth buffer checking on @item Depth buffer writing on @item Depth buffer comparison function = CMPF_LESS_EQUAL @item Culling mode = CULL_CLOCKWISE @item Ambient lighting in scene = ColourValue(0.5, 0.5, 0.5) (mid-grey) @item Dynamic lighting enabled @item Gourad shading mode @item Solid polygon mode @item Bilinear texture filtering @end itemize You can alter these settings by calling SceneManager::getDefaultMaterialSettings() and making the required changes to the Material which is returned. Entities automatically have Material's associated with them if they use a Mesh object, since the Mesh object typically sets up it's required materials on loading. You can also customise the material used by an entity as described in @ref{Entities}. Just create a new Material, set it up how you like (you can copy an existing material into it if you like using a standard assignment statement) and point the SubEntity entries at it using SubEntity::setMaterialName(). @node Overlays @section Overlays Overlays allow you to render 2D and 3D elements on top of the normal scene contents to create effects like heads-up displays (HUDs), menu systems, status panels etc. The frame rate statistics panel which comes as standard with OGRE is an example of an overlay. Overlays can contain 2D or 3D elements. 2D elements are used for HUDs, and 3D elements can be used to create cockpits or any other 3D object which you wish to be rendered on top of the rest of the scene.@*@* You can create overlays either through the SceneManager::createOverlay method, or you can define them in an .overlay script. In reality the latter is likely to be the most practical because it is easier to tweak (without the need to recompile the code). Note that you can define as many overlays as you like: they all start off life hidden, and you display them by calling their 'show()' method. You can also show multiple overlays at once, and their Z order is determined by the Overlay::setZOrder() method.@*@* @heading Creating 2D Elements The OverlayElement class abstracts the details of 2D elements which are added to overlays. All items which can be added to overlays are derived from this class. It is possible (and encouraged) for users of OGRE to define their own custom subclasses of OverlayElement in order to provide their own user controls. The key common features of all OverlayElements are things like size, position, basic material name etc. Subclasses extend this behaviour to include more complex properties and behaviour.@*@* An important built-in subclass of OverlayElement is OverlayContainer. OverlayContainer is the same as a OverlayElement, except that it can contain other OverlayElements, grouping them together (allowing them to be moved together for example) and providing them with a local coordinate origin for easier lineup.@*@* The third important class is OverlayManager. Whenever an application wishes to create a 2D element to add to an overlay (or a container), it should call OverlayManager::createOverlayElement. The type of element you wish to create is identified by a string, the reason being that it allows plugins to register new types of OverlayElement for you to create without you having to link specifically to those libraries. For example, to create a panel (a plain rectangular area which can contain other OverlayElements) you would call OverlayManager::getSingleton().createOverlayElement("Panel", "myNewPanel");@*@* @heading Adding 2D Elements to the Overlay Only OverlayContainers can be added direct to an overlay. The reason is that each level of container establishes the Zorder of the elements contained within it, so if you nest several containers, inner containers have a higher zorder than outer ones to ensure they are displayed correctly. To add a container (such as a Panel) to the overlay, simply call Overlay::add2D.@*@* If you wish to add child elements to that container, call OverlayContainer::addChild. Child elements can be OverlayElements or OverlayContainer instances themselves. Remember that the position of a child element is relative to the top-left corner of it's parent.@*@* @heading A word about 2D coordinates OGRE allows you to place and size elements based on 2 coordinate systems: @strong{relative} and @strong{pixel} based. @table @asis @item Pixel Mode This mode is useful when you want to specify an exact size for your overlay items, and you don't mind if those items get smaller on the screen if you increase the screen resolution (in fact you might want this). In this mode the only way to put something in the middle or at the right or bottom of the screen reliably in any resolution is to use the aligning options, whilst in relative mode you can do it just by using the right relative coordinates. This mode is very simple, the top-left of the screen is (0,0) and the bottom-right of the screen depends on the resolution. As mentioned above, you can use the aligning options to make the horizontal and vertical coordinate origins the right, bottom or center of the screen if you want to place pixel items in these locations without knowing the resolution. @item Relative Mode This mode is useful when you want items in the overlay to be the same size on the screen no matter what the resolution. In relative mode, the top-left of the screen is (0,0) and the bottom-right is (1,1). So if you place an element at (0.5, 0.5), it's top-left corner is placed exactly in the center of the screen, no matter what resolution the application is running in. The same principle applies to sizes; if you set the width of an element to 0.5, it covers half the width of the screen. Note that because the aspect ratio of the screen is typically 1.3333 : 1 (width : height), an element with dimensions (0.25, 0.25) will not be square, but it will take up exactly 1/16th of the screen in area terms. If you want square-looking areas you will have to compensate using the typical aspect ratio eg use (0.1875, 0.25) instead. @end table @heading Transforming Overlays Another nice feature of overlays is being able to rotate, scroll and scale them as a whole. You can use this for zooming in / out menu systems, dropping them in from off screen and other nice effects. See the Overlay::scroll, Overlay::rotate and Overlay::scale methods for more information. @heading Scripting overlays Overlays can also be defined in scripts. @xref{Overlay Scripts} for details. @heading GUI systems Overlays are only really designed for non-interactive screen elements, although you can use them as a crude GUI. For a far more complete GUI solution, we recommend CEGui (@url{http://www.cegui.org.uk}), as demonstrated in the sample Demo_Gui. @node Scripts @chapter Scripts OGRE drives many of its features through scripts in order to make it easier to set up. The scripts are simply plain text files which can be edited in any standard text editor, and modiying them immediately takes effect on your OGRE-based applications, without any need to recompile. This makes prototyping a lot faster. Here are the items that OGRE lets you script: @itemize @bullet @item @ref{Material Scripts} @item @ref{Compositor Scripts} @item @ref{Particle Scripts} @item @ref{Overlay Scripts} @item @ref{Font Definition Scripts} @end itemize @node Material Scripts @section 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.@*@* @heading Loading scripts Material scripts are loaded when resource groups are initialised: OGRE looks in all resource locations associated with the group (see Root::addResourceLocation) for files with the '.material' extension and parses them. If you want to parse files manually, use 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 (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.@*@* @heading 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 or fragment programs, these are covered later):@*@* @example // 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 } } @end example Every material in the script must be given a name, which is the line 'material ' 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.@*@* @strong{ 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 copy from a previously defined material by using a @emph{colon} @strong{:} after the material name followed by the name of the reference material to copy. If the reference material can not be found then it is ignored. (@xref{Copying Materials})@*@* A material can be made up of many techniques (@xref{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 (@xref{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, @xref{Passes} for more details. @*@* Within each pass, there can be zero or many texture units in use (@xref{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 (@xref{Declaring Vertex and Fragment Programs}) and are used as described in @ref{Using Vertex and Fragment Programs in a Pass}. @subheading 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:@*@* @anchor{lod_distances} @subheading lod_distances This attribute controls the distances at which different Techniques can come into effect. @xref{Techniques} for a full discussion of this option. @*@* @anchor{receive_shadows} @subheading receive_shadows This attribute controls whether objects using this material can have shadows cast upon them.@*@* Format: receive_shadows @* Default: on@*@* Whether or not an object receives a shadow is the combination of a number of factors, @xref{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. @anchor{transparency_casts_shadows} @subheading transparency_casts_shadows This attribute controls whether transparent materials can cast certain kinds of shadow.@*@* Format: transparency_casts_shadows @* Default: off@*@* Whether or not an object casts a shadow is the combination of a number of factors, @xref{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. @anchor{set_texture_alias} @subheading set_texture_alias This attribute associates a texture alias with a texture name.@*@* Format: set_texture_alias @*@* This attribute is used to set the textures used in texture unit states that were copied from another material.(@xref{Copying Materials})@*@* @node Techniques @subsection 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: @itemize @bullet @item 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 (@xref{colour_op_multipass_fallback}). @item Whether vertex or fragment programs are used, and if so which syntax they use (e.g. vs_1_1, ps_2_x, arbfp1 etc) @item Other effects like cube mapping and dot3 blending @end itemize @* 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 unqiue 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 copying a material and modifying an existing technique: (@xref{Copying Materials})@*@* Format: technique name@*@* Techniques have only a small number of attributes of their own, the 'scheme'(@xref{scheme}) they belong to, and the LOD index within that scheme (@xref{lod_index}). We also mention an extra Material attribute called @ref{lod_distances} which isn't a Technique attribute but is directly related to the lod_index attribute, so it's listed here for convenience.@*@* @anchor{scheme} @subheading 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 @* Example: scheme hdr@* Default: scheme Default@*@* @anchor{lod_index} @subheading lod_index Sets the level-of-detail (LOD) index this Technique belongs to. @*@* Format: lod_index @* 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, ie 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, @xref{lod_distances} for details.@*@* Default: lod_index 0@*@* @anchor{lod_distances} @subheading lod_distances @strong{Note: this attribute must be specified in the outer material section (ie the parent of all the techniques), but it's specified here since it is most relevant to this section.}@*@* By setting this attribute, you indicate that you want this material to alter the Technique that it uses based on distance from the camera. You must give it a list of distances, in ascending order, each one indicating the distance at which the material will switch to the next LOD. Implicitly, all materials activate LOD index 0 for distances less than the smallest of these. You must ensure that there is at least one Technique with a @ref{lod_index} value for each distance in the list (so if you specify 3 distances, you must have techniques for indexes 1, 2 and 3). Note you must always have at least one Technique at lod_index 0.@*@* Format: lod_distances [ ... ]@* Example: lod_distances 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.@*@* Techniques also contain one or more passes (and there must be at least one), @xref{Passes}. @node Passes @subsection 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 unqiue 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 copying a material and modifying an existing pass: (@xref{Copying Materials})@*@* Passes have a set of global attributes (described below), zero or more nested texture_unit entries (@xref{Texture Units}), and optionally a reference to a vertex and / or a fragment program (@xref{Using Vertex and Fragment Programs in a Pass}). @*@* Here are the attributes you can use in a 'pass' section of a .material script: @itemize @bullet @item @ref{ambient} @item @ref{diffuse} @item @ref{specular} @item @ref{emissive} @item @ref{scene_blend} @item @ref{depth_check} @item @ref{depth_write} @item @ref{depth_func} @item @ref{depth_bias} @item @ref{alpha_rejection} @item @ref{cull_hardware} @item @ref{cull_software} @item @ref{lighting} @item @ref{shading} @item @ref{polygon_mode} @item @ref{fog_override} @item @ref{colour_write} @item @ref{max_lights} @item @ref{iteration} @item @ref{point_size} @item @ref{point_sprites} @item @ref{point_size_attenuation} @item @ref{point_size_min} @item @ref{point_size_max} @end itemize @heading Attribute Descriptions @anchor{ambient} @subheading ambient Sets the ambient colour reflectance properties of this pass. @strong{This attribute has no effect if a asm, CG, or HLSL shader program is used. With GLSL, the shader can read the OpenGL material state.} @*@* Format: ambient ( []| 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@*@* @anchor{diffuse} @subheading diffuse Sets the diffuse colour reflectance properties of this pass. @strong{This attribute has no effect if a asm, CG, or HLSL shader program is used. With GLSL, the shader can read the OpenGL material state.}@*@* Format: diffuse ( []| 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@*@* @anchor{specular} @subheading specular Sets the specular colour reflectance properties of this pass. @strong{This attribute has no effect if a asm, CG, or HLSL shader program is used. With GLSL, the shader can read the OpenGL material state.}@*@* Format: specular ( []| vertexcolour) @* 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 ie 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@*@* @anchor{emissive} @subheading emissive Sets the amount of self-illumination an object has. @strong{This attribute has no effect if a asm, CG, or HLSL shader program is used. With GLSL, the shader can read the OpenGL material state.}@*@* Format: emissive ( []| 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@*@* @anchor{scene_blend} @subheading scene_blend Sets the kind of blending this pass has with the existing contents of the scene. Wheras 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 @*@* Example: scene_blend add@*@* This is the simpler form, where the most commonly used blending modes are enumerated using a single parameter. Valid parameters are: @table @asis @item add The colour of the rendering output is added to the scene. Good for exposions, flares, lights, ghosts etc. Equivalent to 'scene_blend one one'. @item 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'. @item 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' @item alpha_blend The alpha value of the rendering output is used as a mask. Equivalent to 'scene_blend src_alpha one_minus_src_alpha' @end table @* Format2: scene_blend @*@* 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: @table @asis @item one Constant value of 1.0 @item zero Constant value of 0.0 @item dest_colour The existing pixel colour @item src_colour The texture pixel (texel) colour @item one_minus_dest_colour 1 - (dest_colour) @item one_minus_src_colour 1 - (src_colour) @item dest_alpha The existing pixel alpha value @item src_alpha The texel alpha value @item one_minus_dest_alpha 1 - (dest_alpha) @item one_minus_src_alpha 1 - (src_alpha) @end table @* Default: scene_blend one zero (opaque) @* @anchor{depth_check} @subheading depth_check Sets whether or not this pass renders with depth-buffer checking on or not.@*@* Format: depth_check @*@* 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@*@* @anchor{depth_write} @subheading depth_write Sets whether or not this pass renders with depth-buffer writing on or not.@* Format: depth_write @*@* 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@* @anchor{depth_func} @subheading depth_func Sets the function used to compare depth values when depth checking is on.@*@* Format: depth_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: @table @asis @item always_fail Never writes a pixel to the render target @item always_pass Always writes a pixel to the render target @item less Write if (new_Z < existing_Z) @item less_equal Write if (new_Z <= existing_Z) @item equal Write if (new_Z == existing_Z) @item not_equal Write if (new_Z != existing_Z) @item greater_equal Write if (new_Z >= existing_Z) @item greater Write if (new_Z >existing_Z) @end table @* Default: depth_func less_equal @anchor{depth_bias} @subheading 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 @*@* Where is between 0 and 16, the default being 0. The higher the value, the greater the offset (for if you want to do multiple overlapping decals).@*@* @anchor{alpha_rejection} @subheading alpha_rejection Sets the way the pass will have use alpha to totally reject pixels from the pipeline.@*@* Format: alpha_rejection @*@* 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@*@* @anchor{cull_hardware} @subheading cull_hardware Sets the hardware culling mode for this pass.@*@* Format: cull_hardware @*@* 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 triagles 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). @anchor{cull_software} @subheading cull_software Sets the software culling mode for this pass.@*@* Format: cull_software @*@* 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 traingle 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 precalculated 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@*@* @anchor{lighting} @subheading 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. @strong{This attribute has no effect if a vertex program is used.}@*@* Format: lighting @*@* 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@*@* @anchor{shading} @subheading shading Sets the kind of shading which should be used for representing dynamic lighting for this pass.@*@* Format: shading @*@* 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.@*@* @table @asis @item flat No interpolation takes place. Each face is shaded with a single colour determined from the first vertex in the face. @item gouraud Colour at each vertex is linearly interpolated across the face. @item 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 tesselation. Not supported on all hardware. @end table Default: shading gouraud@*@* @anchor{polygon_mode} @subheading polygon_mode Sets how polygons should be rasterised, ie whether they should be filled in, or just drawn as lines or points.@*@* Format: polygon_mode @*@* @table @asis @item solid The normal situation - polygons are filled in. @item wireframe Polygons are drawn in outline only. @item points Only the points of each polygon are rendered. @end table Default: polygon_mode solid@*@* @anchor{fog_override} @subheading 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.@*@* Format: fog_override [ ]@*@* 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:@* @table @asis @item type @strong{none} = No fog, equivalent of just using 'fog_override true'@* @strong{linear} = Linear fog from the and distances@* @strong{exp} = Fog increases exponentially from the camera (fog = 1/e^(distance * density)), use param to control it@* @strong{exp2} = Fog increases at the square of FOG_EXP, i.e. even quicker (fog = 1/e^(distance * density)^2), use param to control it @item colour Sequence of 3 floating point values from 0 to 1 indicating the red, green and blue intensities @item 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 @item start The start distance from the camera of linear fog. Must still be present in other modes, even though it is not used. @item end The end distance from the camera of linear fog. Must still be present in other modes, even though it is not used. @end table @* Example: fog_override true exp 1 1 1 0.002 100 10000 @anchor{colour_write} @subheading colour_write Sets whether or not this pass renders with colour writing on or not.@* Format: colour_write @*@* 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@* @anchor{max_lights} @subheading max_lights Sets the maximum number of lights which will be considered for use with this pass.@*@* Format: max_lights @*@* 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 (@xref{Using Vertex and Fragment Programs in a Pass}) this limit is dependent on the program you are running, or, if you use 'iteration once_per_light' (@xref{iteration}), it effectively only bounded by the number of passes you are willing to use. Whichever method you use, however, the max_lights limit applies.@*@* Default: max_lights 8@* @anchor{iteration} @subheading iteration Sets whether or not this pass is iterated, ie issued more than once.@*@* Basic Format: iteration [lightType]@*@* Advanced Format: iteration [ [lightType]]@*@* Examples: @table @asis @item iteration once The pass is only executed once which is the default behaviour. @item iteration once_per_light point The pass is executed once for each point light. @item iteration 5 The render state for the pass will be setup and then the draw call will execute 5 times. @item 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. @end table @* 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 ie. 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 sihouette to appear.@*@* The second parameter to the attribute only applies if you use once_per_light or per_light, 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 better if you can assume the kind of lights you'll be dealing with. @*@* Default: iteration once@*@* @anchor{fur_example} Example: Simple Fur shader material script that uses a second pass with 10 iterations to grow the fur: @example // 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 } } } } @end example Note: use gpu program auto parameters @ref{pass_number} and @ref{pass_iteration_number} to tell the vertex or fragment program the pass number and iteration number.@*@* @anchor{point_size} @subheading 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 @ref{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 @*@* Default: point_size 1.0@*@* @anchor{point_sprites} @subheading 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 @*@* Default: point_sprites off@*@* @anchor{point_size_attenuation} @subheading 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 (@xref{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 [constant linear quadratic] Default: point_size_attenuation off @anchor{point_size_min} @subheading point_size_min Sets the minimum point size after attenuation (@ref{point_size_attenuation}). For details on the size metrics, @xref{point_size}.@*@* Format: point_size_min Default: point_size_min 0 @anchor{point_size_max} @subheading point_size_max Sets the maximum point size after attenuation (@ref{point_size_attenuation}). For details on the size metrics, @xref{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 Default: point_size_max 0 @node Texture Units @subsection Texture Units Here are the attributes you can use in a 'texture_unit' section of a .material script: @heading Available Texture Layer Attributes @itemize @bullet @item @ref{texture_alias} @item @ref{texture} @item @ref{anim_texture} @item @ref{cubic_texture} @item @ref{tex_coord_set} @item @ref{tex_address_mode} @item @ref{tex_border_colour} @item @ref{filtering} @item @ref{max_anisotropy} @item @ref{colour_op} @item @ref{colour_op_ex} @item @ref{colour_op_multipass_fallback} @item @ref{alpha_op_ex} @item @ref{env_map} @item @ref{scroll} @item @ref{scroll_anim} @item @ref{rotate} @item @ref{rotate_anim} @item @ref{scale} @item @ref{wave_xform} @item @ref{transform} @end itemize You can also use a nested 'texture_source' section in order to use a special add-in as a source of texture data, @xref{External Texture Sources} for details. @heading Attribute Descriptions @anchor{texture_alias} @subheading texture_alias Sets the alias name for this texture unit.@*@* Format: texture_alias @*@* Example: texture_alias NormalMap@*@* Setting the texture alias name is usefull if this material is to be copied by other other materials and only the textures will be changed in the new material.(@xref{Copying Materials})@*@* Default: If a texture_unit has a name then the texture_alias defaults to the texture_unit name. @anchor{texture} @subheading texture Sets the name of the static texture image this layer will use.@*@* Format: texture [] [numMipMaps] [alpha]@*@* 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.@*@* The 'type' parameter allows you to specify a the type of texture to create - the default is '2d', but you can override this; here's the full list: @table @asis @item 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. @item 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. @item 3d A 3 dimensional texture ie 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 ie through a pixel shader. @item cubic This texture is made up of 6 2D textures which are pasted around the inside of a cube. Can be addressed with 3D texture coordinates and are useful for cubic reflection maps and normal maps. @end table The 'numMipMaps' option allows you to specify 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.@*@* Finally, the 'alpha' option allows you to specify that a single channel (luminence) 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@*@* @anchor{anim_texture} @subheading 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 @*@* 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 ... @*@* 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@*@* @anchor{cubic_texture} @subheading 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. 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 @*@* 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 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: @table @asis @item 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. @item 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. @end table @* Default: none @anchor{tex_coord_set} @subheading 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.@*@* Format: tex_coord_set @*@* Example: tex_coord_set 2@*@* Default: tex_coord_set 0@*@* @anchor{tex_address_mode} @subheading 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 @* Extended Format: tex_address_mode [] @table @asis @item wrap Any value beyond 1.0 wraps back to 0.0. Texture is repeated. @item 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. @item mirror Texture flips every boundary, meaning texture is mirrored every 1.0 u or v @item border Values outside the range [0.0, 1.0] are set to the border colour, you might also set the @ref{tex_border_colour} attribute too. @end table @* Default: tex_address_mode wrap@*@* @anchor{tex_border_colour} @subheading tex_border_colour Sets the border colour of border texture address mode (see @ref{tex_address_mode}). @*@* Format: tex_border_colour []@* 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@*@* @anchor{filtering} @subheading 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.@*@* @strong{Simple Format}@* Format: filtering @* Default: filtering bilinear@*@* With this format, you only need to provide a single parameter which is one of the following: @table @asis @item none No filtering or mipmapping is used. This is equivalent to the complex format 'filtering point point none'. @item 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'. @item 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'. @item 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 @ref{max_anisotropy} attribute too. @end table @*@* @strong{Complex Format}@* Format: filtering @* 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: @table @asis @item 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'. @item point Pick the closet pixel in min or mag modes. In mip mode, this picks the closet matching mipmap. @item linear Filter a 2x2 box of pixels around the closest one. In the 'mip' filter this enables filtering between mipmap levels. @item 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 @ref{max_anisotropy} attribute too. @end table @anchor{max_anisotropy} @subheading 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.@*@* In order for this to be used, you have to set the minification and/or the magnification @ref{filtering} option on this texture to anisotropic. Format: max_anisotropy @* Default: max_anisotropy 1 @anchor{colour_op} @subheading 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).@*@* Format: colour_op @*@* 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 @ref{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 @ref{colour_op_multipass_fallback}.@* @table @asis @item replace Replace all colour with texture with no adjustment. @item add Add colour components together. @item modulate Multiply colour components together. @item alpha_blend Blend based on texture alpha. @end table @* Default: colour_op modulate @anchor{colour_op_ex} @subheading colour_op_ex This is an extended version of the @ref{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 blendind, but you are limited to the number of texture units which are available in hardware.@*@* Format: colour_op_ex [] [] []@*@* Example colour_op_ex add_signed src_manual src_current 0.5@*@* See the IMPORTANT note below about the issues between mulitpass 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.@*@* @table @asis @item Operation options @table @asis @item source1 Use source1 without modification @item source2 Use source2 without modification @item modulate Multiply source1 and source2 together. @item modulate_x2 Multiply source1 and source2 together, then by 2 (brightening). @item modulate_x4 Multiply source1 and source2 together, then by 4 (brightening). @item add Add source1 and source2 together. @item add_signed Add source1 and source2 then subtract 0.5. @item add_smooth Add source1 and source2, subtract the product @item subtract Subtract source2 from source1 @item blend_diffuse_alpha Use interpolated alpha value from vertices to scale source1, then add source2 scaled by (1-alpha). @item blend_texture_alpha As blend_diffuse_alpha but use alpha from texture @item blend_current_alpha As blend_diffuse_alpha but use current alpha from previous stages (same as blend_diffuse_alpha for first layer) @item blend_manual As blend_diffuse_alpha but use a constant manual alpha value specified in @item dotproduct The dot product of source1 and source2 @item blend_diffuse_colour Use interpolated colour value from vertices to scale source1, then add source2 scaled by (1-colour). @end table @item Source1 and source2 options @table @asis @item src_current The colour as built up from previous stages. @item src_texture The colour derived from the texture assigned to this layer. @item src_diffuse The interpolated diffuse colour from the vertices (same as 'src_current' for first layer). @item src_specular The interpolated specular colour from the vertices. @item src_manual The manual colour specified at the end of the command. @end table @end table @* 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)@* @anchor{colour_op_multipass_fallback} @subheading 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 @*@* Example: colour_op_mulitpass_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.@*@* @anchor{alpha_op_ex} @subheading alpha_op_ex Behaves in exactly the same away as @ref{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. @anchor{env_map} @subheading env_map Turns on/off texture coordinate effect that makes this layer an environment map.@*@* Format: env_map @*@* 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.@*@* @table @asis @item 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. @item 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. @item 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 @ref{cubic_texture} to this texture unit and use the 'combinedUVW' option. @item 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 @ref{cubic_texture} with the 'combinedUVW' option. @end table @* Default: env_map off@* @anchor{scroll} @subheading scroll Sets a fixed scroll offset for the texture.@*@* Format: scroll @*@* 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 @ref{scroll_anim} attribute.@*@* @anchor{scroll_anim} @subheading 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 @ref{wave_xform}).@*@* Format: scroll_anim @* @anchor{rotate} @subheading 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 @ref{rotate_anim}.@*@* Format: rotate @*@* The parameter is a anticlockwise angle in degrees.@*@* @anchor{rotate_anim} @subheading rotate_anim Sets up an animated rotation effect of this layer. Useful for creating fixed-speed rotation animations (for varying speeds, see @ref{wave_xform}).@*@* Format: rotate_anim @*@* The parameter is a number of anticlockwise revolutions per second.@*@* @anchor{scale} @subheading 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 @ref{wave_xform}.@*@* Format: scale @*@* Valid scale values are greater than 0, with a scale factor of 2 making the texture twice as big in that dimension etc.@*@* @anchor{wave_xform} @subheading 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.@*@* Format: wave_xform @*@* Example: wave_xform scale_x sine 1.0 0.2 0.0 5.0@*@* @table @asis @item xform_type @table @asis @item scroll_x Animate the x scroll value @item scroll_y Animate the y scroll value @item rotate Animate the rotate value @item scale_x Animate the x scale value @item scale_y Animate the y scale value @end table @item wave_type @table @asis @item sine A typical sine wave which smoothly loops between min and max values @item triangle An angled wave which increases & decreases at constant speed, changing instantly at the extremes @item square Max for half the wavelength, min for the rest with instant transition between @item sawtooth Gradual steady increase from min to max over the period with an instant return to min at the end. @item inverse_sawtooth Gradual steady decrease from max to min over the period, with an instant return to max at the end. @end table @item base The base value, the minimum if amplitude > 0, the maximum if amplitdue < 0 @item frequency The number of wave iterations per second, i.e. speed @item phase Offset of the wave start @item amplitude The size of the wave @end table @* 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).@*@* @anchor{transform} @subheading 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. @*@* 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. @node Declaring Vertex and Fragment Programs @subsection Declaring Vertex and Fragment Programs In order to use a vertex or fragment program in your materials (@xref{Using Vertex and 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 @strong{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 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 nVidia's Cg language (@xref{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 targetting 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: @example vertex_program myVertexProgram asm { source myVertexProgram.asm syntax vs_1_1 } @end example As you can see, that's very simple, and defining a fragment program is exactly the same, just with vertex_program replaced with fragment_program. 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 progams which use an unsupportable syntax quickly, without loading the program first.@*@* The current supported syntaxes are: @table @asis @item vs_1_1 This is one of the DirectX vertex shader assembler syntaxes. @* Supported on cards from: ATI Radeon 8500, nVidia GeForce 3 @* @item vs_2_0 Another one of the DirectX vertex shader assembler syntaxes. @* Supported on cards from: ATI Radeon 9600, nVidia GeForce FX 5 series @* @item 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 @* @item vs_3_0 Another one of the DirectX vertex shader assembler syntaxes. @* Supported on cards from: nVidia GeForce FX 6 series @item arbvp1 This is the OpenGL standard assembler format for vertex programs. It's roughly equivalent to DirectX vs_1_1. @item vp20 This is an nVidia-specific OpenGL vertex shader syntax which is a superset of vs 1.1. @item 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. @item 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. @item ps_1_1, ps_1_2, ps_1_3 DirectX pixel shader (ie 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. @item ps_1_4 DirectX pixel shader (ie 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. @item ps_2_0 DirectX pixel shader (ie fragment program) assembler syntax. @* Supported cards: ATI Radeon 9600, nVidia GeForce FX 5 series@* @item ps_2_x DirectX pixel shader (ie 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@* @item ps_3_0 DirectX pixel shader (ie fragment program) assembler syntax. @* Supported cards: nVidia GeForce FX6 series@* @item ps_3_x DirectX pixel shader (ie fragment program) assembler syntax. @* Supported cards: nVidia GeForce FX7 series@* @item 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). @item 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. @item 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. @item 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. @end table You can get a definitive list of the syntaxes supported by the current card by calling GpuProgramManager::getSingleton().getSupportedSyntax().@*@* @anchor{Default Program Parameters} @subheading Default Program Parameters While defining a vertex 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: @example 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 } } @end example The syntax of the parameter definition is exactly the same as when you define parameters when using programs, @xref{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. @node High-level Programs @heading High-level Programs Support for high level vertex and fragment programs is provided through plugins; this is to make sure that an application using OGRE can use as little or as much of the high-level program functionality as they like. OGRE currently supports 3 high-level program types, Cg (an API- and card-independent, high-level language which lets you write programs for both OpenGL and DirectX for lots of cards), DirectX 9 High-Level Shader Language (HLSL), and OpenGL Shader Language (GLSL). HLSL is provided for people who only want to deploy in DirectX, or who don't want to include the Cg plugin for whatever reason. GLSL is only for the OpenGL API and can not be used with the DirectX api. To support both DirectX and OpenGL you could write your shaders in both HLSL and GLSL along with having seperate techniques in the material script. To be honest, Cg is a better bet because it lets you stay API independent - and don't be put off by the fact that it's made by nVidia, it will happily compile programs down to vendor-independent standards like DirectX and OpenGL's assembler formats, so you're not limited to nVidia cards.@*@* @subheading Cg programs In order to define Cg programs, you have to have to load Plugin_CgProgramManager.so/.dll at startup, either through plugins.cfg or through your own plugin loading code. They are very easy to define: @example fragment_program myCgFragmentProgram cg { source myCgFragmentProgram.cg entry_point main profiles ps_2_0 arbfp1 } @end example There are a few differences between this and the assembler program - to begin with, we declare that the fragment program is of type 'cg' rather than 'asm', which indicates that it's a high-level program using Cg. The 'source' parameter is the same, except this time it's referencing a Cg source file instead of a file of assembler. @*@* Here is where things start to change. Firstly, we need to define an 'entry_point', which is the name of a function in the Cg program which will be the first one called as part of the fragment program. Unlike assembler programs, which just run top-to-bottom, Cg programs can include multiple functions and as such you must specify the one which start the ball rolling.@*@* Next, instead of a fixed 'syntax' parameter, you specify one or more 'profiles'; profiles are how Cg compiles a program down to the low-level assembler. The profiles have the same names as the assembler syntax codes mentioned above; the main difference is that you can list more than one, thus allowing the program to be compiled down to more low-level syntaxes so you can write a single high-level program which runs on both D3D and GL. You are advised to just enter the simplest profiles under which your programs can be compiled in order to give it the maximum compatibility. The ordering also matters; if a card supports more than one syntax then the one listed first will be used. @subheading DirectX9 HLSL DirectX9 HLSL has a very similar language syntax to Cg but is tied to the DirectX API. The only benefit over Cg is that it only requires the DirectX 9 render system plugin, not any additional plugins. Declaring a DirectX9 HLSL program is very similar to Cg. Here's an example: @example vertex_program myHLSLVertexProgram hlsl { source myHLSLVertexProgram.txt entry_point main target vs_2_0 } @end example As you can see, the syntax is almost identical, except that instead of 'profiles' with a list of assembler formats, you have a 'target' parameter which allows a single assembler target to be specified - obviously this has to be a DirectX assembler format syntax code.@*@* @include glsl.inc @subheading Skeletal Animation in Vertex Programs You can implement skeletal animation in hardware by writing a vertex program which uses the per-vertex blending indices and blending weights, together with an array of world matrices (which will be provided for you by Ogre if you bind the automatic parameter 'world_matrix_array_3x4'). However, you need to communicate this support to Ogre so it does not perform skeletal animation in software for you. You do this by adding the following attribute to your vertex_program definition: @example includes_skeletal_animation true @end example When you do this, any skeletally animated entity which uses this material will forgo the usual animation blend and will expect the vertex program to do it, for both vertex positions and normals. Note that ALL submeshes must be assigned a material which implements this, and that if you combine skeletal animation with vertex animation (@xref{Animation}) then all techniques must be hardware accelerated for any to be. @subheading Morph Animation in Vertex Programs You can implement morph animation in hardware by writing a vertex program which linearly blends between the first and second position keyframes passed as positions and the first free texture coordinate set, and by binding the animation_parametric value to a parameter (which tells you how far to interpolate between the two). However, you need to communicate this support to Ogre so it does not perform morph animation in software for you. You do this by adding the following attribute to your vertex_program definition: @example includes_morph_animation true @end example When you do this, any skeletally animated entity which uses this material will forgo the usual software morph and will expect the vertex program to do it. Note that if your model includes both skeletal animation and morph animation, they must both be implemented in the vertex program if either is to be hardware acceleration. Note that ALL submeshes must be assigned a material which implements this, and that if you combine skeletal animation with vertex animation (@xref{Animation}) then all techniques must be hardware accelerated for any to be. @subheading Pose Animation in Vertex Programs You can implement pose animation (blending between multiple poses based on weight) in a vertex program by pulling in the original vertex data (bound to position), and as many pose offset buffers as you've defined in your 'includes_pose_animation' declaration, which will be in the first free texture unit upwards. You must also use the animation_parametric parameter to define the starting point of the constants which will contain the pose weights; they will start at the parameter you define and fill 'n' constants, where 'n' is the max number of poses this shader can blend, ie the parameter to includes_pose_animation. @example includes_pose_animation 4 @end example Note that ALL submeshes must be assigned a material which implements this, and that if you combine skeletal animation with vertex animation (@xref{Animation}) then all techniques must be hardware accelerated for any to be. @subheading Vertex Programs With Shadows When using shadows (@xref{Shadows}), the use of vertex programs can add some additional complexities, because Ogre can only automatically deal with everything when using the fixed-function pipeline. If you use vertex programs, and you are also using shadows, you may need to make some adjustments. @*@* If you use @strong{stencil shadows}, then any vertex programs which do vertex deformation can be a problem, because stencil shadows are calculated on the CPU, which does not have access to the modified vertices. If the vertex program is doing standard skeletal animation, this is ok (see section above) because Ogre knows how to replicate the effect in software, but any other vertex deformation cannot be replicated, and you will either have to accept that the shadow will not reflect this deformation, or you should turn off shadows for that object. @*@* If you use @strong{texture shadows}, then vertex deformation is acceptable; however, when rendering the object into a shadow texture (the shadow caster pass), the shadow has to be rendered in a solid colour (linked to the ambient colour for modulative shadows, black for additive shadows). You must therefore provide an alternative vertex program, so Ogre provides you with a way of specifying one to use when rendering the caster, @xref{Shadows and Vertex Programs}. @node Using Vertex and Fragment Programs in a Pass @subsection Using Vertex and Fragment Programs in a Pass Within a pass section of a material script, you can reference a vertex and / or a fragment program which is been defined in a .program script (@xref{Declaring Vertex and Fragment Programs}). The programs are defined separately from the usage of them in the pass, since the programs are very likely to be reused between many separate materials, probably across many different .material scripts, so this approach lets you define the program only once and use it many times.@*@* As well as naming the program in question, you can also provide parameters to it. Here's a simple example: @example vertex_program_ref myVertexProgram { param_indexed_auto 0 worldviewproj_matrix param_indexed 4 float4 10.0 0 0 0 } @end example In this example, we bind a vertex program called 'myVertexProgram' (which will be defined elsewhere) to the pass, and give it 2 parameters, one is an 'auto' parameter, meaning we do not have to supply a value as such, just a recognised code (in this case it's the world/view/projection matrix which is kept up to date automatically by Ogre). The second parameter is a manually specified parameter, a 4-element float. The indexes are described later.@*@* The syntax of the link to a vertex program and a fragment program are identical, the only difference is that 'fragment_program_ref' is used instead of 'vertex_program_ref'. @anchor{Program Parameter Specification} @subheading Parameter specification Parameters can be specified using one of 4 commands as shown below. The same syntax is used whether you are defining a parameter just for this particular use of the program, or when specifying the @ref{Default Program Parameters}. Parameters set in the specific use of the program override the defaults. @itemize @bullet @item @ref{param_indexed} @item @ref{param_indexed_auto} @item @ref{param_named} @item @ref{param_named_auto} @end itemize @anchor{param_indexed} @subheading param_indexed This command sets the value of an indexed parameter. @*@* format: param_indexed @*@* example: param_indexed 0 float4 10.0 0 0 0@*@* The 'index' is simply a number representing the position in the parameter list which the value should be written, and you should derive this from your program definition. The index is relative to the way constants are stored on the card, which is in 4-element blocks. For example if you defined a float4 parameter at index 0, the next index would be 1. If you defined a matrix4x4 at index 0, the next usable index would be 4, since a 4x4 matrix takes up 4 indexes.@*@* The value of 'type' can be float4, matrix4x4, float, int4, int. Note that 'int' parameters are only available on some more advanced program syntaxes, check the D3D or GL vertex / fragment program documentation for full details. Typically the most useful ones will be float4 and matrix4x4. Note that if you use a type which is not a multiple of 4, then the remaining values up to the multiple of 4 will be filled with zeroes for you (since GPUs always use banks of 4 floats per constant even if only one is used).@*@* 'value' is simply a space or tab-delimited list of values which can be converted into the type you have specified. @anchor{param_indexed_auto} @subheading param_indexed_auto This command tells Ogre to automatically update a given parameter with a derived value. This frees you from writing code to update program parameters every frame when they are always changing.@*@* format: param_indexed_auto @*@* example: param_indexed_auto 0 worldviewproj_matrix@*@* 'index' has the same meaning as @ref{param_indexed}; note this time you do not have to specify the size of the parameter because the engine knows this already. In the example, the world/view/projection matrix is being used so this is implicitly a matrix4x4.@*@* 'value_code' is one of a list of recognised values:@* @table @asis @item world_matrix The current world matrix. @item inverse_world_matrix The inverse of the current world matrix. @item transpose_world_matrix The transpose of the world matrix @item inverse_transpose_world_matrix The inverse transpose of the world matrix @item world_matrix_array_3x4 An array of world matrices, each represented as only a 3x4 matrix (3 rows of 4columns) usually for doing hardware skinning. You should make enough entries available in your vertex program for the number of bones in use, ie an array of numBones*3 float4's. @item view_matrix The current view matrix. @item inverse_view_matrix The inverse of the current view matrix. @item transpose_view_matrix The transpose of the view matrix @item inverse_transpose_view_matrix The inverse transpose of the view matrix @item projection_matrix The current projection matrix. @item inverse_projection_matrix The inverse of the projection matrix @item transpose_projection_matrix The transpose of the projection matrix @item inverse_transpose_projection_matrix The inverse transpose of the projection matrix @item worldview_matrix The current world and view matrices concatenated. @item inverse_worldview_matrix The inverse of the current concatenated world and view matrices. @item transpose_worldview_matrix The transpose of the world and view matrices @item inverse_transpose_worldview_matrix The inverse transpose of the current concatenated world and view matrices. @item viewproj_matrix The current view and projection matrices concatenated. @item inverse_viewproj_matrix The inverse of the view & projection matrices @item transpose_viewproj_matrix The transpose of the view & projection matrices @item inverse_transpose_viewproj_matrix The inverse transpose of the view & projection matrices @item worldviewproj_matrix The current world, view and projection matrices concatenated. @item inverse_worldviewproj_matrix The inverse of the world, view and projection matrices @item transpose_worldviewproj_matrix The transpose of the world, view and projection matrices @item inverse_transpose_worldviewproj_matrix The inverse transpose of the world, view and projection matrices @item render_target_flipping The value use to adjust transformed y position if bypassed projection matrix transform. It's -1 if the render target requires texture flipping, +1 otherwise. @item light_diffuse_colour The diffuse colour of a given light; this requires an index in the 'extra_params' field, and relates to the 'nth' closest light which could affect this object (ie 0 refers to the closest light - note that directional lights are always first in the list and always present). NB if there are no lights this close, then the parameter will be set to black. @item light_specular_colour The specular colour of a given light; this requires an index in the 'extra_params' field, and relates to the 'nth' closest light which could affect this object (ie 0 refers to the closest light). NB if there are no lights this close, then the parameter will be set to black. @item light_attenuation A float4 containing the 4 light attenuation variables for a given light. This requires an index in the 'extra_params' field, and relates to the 'nth' closest light which could affect this object (ie 0 refers to the closest light). NB if there are no lights this close, then the parameter will be set to all zeroes. The order of the parameters is range, constant attenuation, linear attenuation, quadric attenuation. @item light_position The position of a given light in world space. This requires an index in the 'extra_params' field, and relates to the 'nth' closest light which could affect this object (ie 0 refers to the closest light). NB if there are no lights this close, then the parameter will be set to all zeroes. Note that this property will work with all kinds of lights, even directional lights, since the parameter is set as a 4D vector. Point lights will be (pos.x, pos.y, pos.z, 1.0f) whilst directional lights will be (-dir.x, -dir.y, -dir.z, 0.0f). Operations like dot products will work consistently on both. @item light_direction The direction of a given light in world space. This requires an index in the 'extra_params' field, and relates to the 'nth' closest light which could affect this object (ie 0 refers to the closest light). NB if there are no lights this close, then the parameter will be set to all zeroes. DEPRECATED - this property only works on directional lights, and we recommend that you use light_position instead since that returns a generic 4D vector. @item light_position_object_space The position of a given light in object space (ie when the object is at (0,0,0)). This requires an index in the 'extra_params' field, and relates to the 'nth' closest light which could affect this object (ie 0 refers to the closest light). NB if there are no lights this close, then the parameter will be set to all zeroes. Note that this property will work with all kinds of lights, even directional lights, since the parameter is set as a 4D vector. Point lights will be (pos.x, pos.y, pos.z, 1.0f) whilst directional lights will be (-dir.x, -dir.y, -dir.z, 0.0f). Operations like dot products will work consistently on both. @item light_direction_object_space The direction of a given light in object space (ie when the object is at (0,0,0)). This requires an index in the 'extra_params' field, and relates to the 'nth' closest light which could affect this object (ie 0 refers to the closest light). NB if there are no lights this close, then the parameter will be set to all zeroes. DEPRECATED, except for spotlights - for directional lights we recommend that you use light_position_object_space instead since that returns a generic 4D vector. @item light_position_view_space The position of a given light in view space (ie when the camera is at (0,0,0)). This requires an index in the 'extra_params' field, and relates to the 'nth' closest light which could affect this object (ie 0 refers to the closest light). NB if there are no lights this close, then the parameter will be set to all zeroes. Note that this property will work with all kinds of lights, even directional lights, since the parameter is set as a 4D vector. Point lights will be (pos.x, pos.y, pos.z, 1.0f) whilst directional lights will be (-dir.x, -dir.y, -dir.z, 0.0f). Operations like dot products will work consistently on both. @item light_direction_view_space The direction of a given light in view space (ie when the camera is at (0,0,0)). This requires an index in the 'extra_params' field, and relates to the 'nth' closest light which could affect this object (ie 0 refers to the closest light). NB if there are no lights this close, then the parameter will be set to all zeroes. DEPRECATED, except for spotlights - for directional lights we recommend that you use light_position_view_space instead since that returns a generic 4D vector. @item light_power The 'power' scaling for a given light, useful in HDR rendering. This requires an index in the 'extra_params' field, and relates to the 'nth' closest light which could affect this object (ie 0 refers to the closest light). @item ambient_light_colour The colour of the ambient light currently set in the scene. @item fog_colour The colour of the fog currently set in the scene. @item fog_params The parameters of the fog currently set in the scene. Packed as (exp_density, linear_start, linear_end, 1.0 / (linear_end - linear_start)). @item camera_position The current cameras position in world space. @item camera_position_object_space The current cameras position in object space (ie when the object is at (0,0,0)). @item time The current time, factored by the optional parameter (or 1.0f if not supplied). @item time_0_x Single float time value, which repeats itself based on "cycle time" given as an 'extra_params' field @item costime_0_x Cosine of time_0_x @item sintime_0_x Sine of time_0_x @item tantime_0_x Tangent of time_0_x @item time_0_x_packed 4-element vector of time0_x, sintime0_x, costime0_x, tantime0_x @item time_0_1 As time0_x but scaled to [0..1] @item costime_0_1 As costime0_x but scaled to [0..1] @item sintime_0_1 As sintime0_x but scaled to [0..1] @item tantime_0_1 As tantime0_x but scaled to [0..1] @item time_0_1_packed As time0_x_packed but all values scaled to [0..1] @item time_0_2pi As time0_x but scaled to [0..2*Pi] @item costime_0_2pi As costime0_x but scaled to [0..2*Pi] @item sintime_0_2pi As sintime0_x but scaled to [0..2*Pi] @item tantime_0_2pi As tantime0_x but scaled to [0..2*Pi] @item time_0_2pi_packed As time0_x_packed but scaled to [0..2*Pi] @item frame_time The current frame time, factored by the optional parameter (or 1.0f if not supplied). @item fps The current frames per second @item viewport_width The current viewport width in pixels @item viewport_height The current viewport height in pixels @item inverse_viewport_width 1.0/the current viewport width in pixels @item inverse_viewport_height 1.0/the current viewport height in pixels @item viewport_size 4-element vector of viewport_width, viewport_height, inverse_viewport_width, inverse_viewport_height @item view_direction View direction vector in object space @item view_side_vector View local X axis @item view_up_vector View local Y axis @item fov Vertical field of view, in radians @item near_clip_distance Near clip distance, in world units @item far_clip_distance Far clip distance, in world units (may be 0 for infinite view projection) @item texture_viewproj_matrix Only applicable to vertex programs which have been specified as the 'shadow receiver' vertex program alternative; this provides details of the view/projection matrix for the current shadow projector. @anchor{pass_number} @item pass_number Sets the active pass index number in a gpu parameter. The first pass in a technique has an index of 0, the second an index of 1 and so on. This is usefull for multipass shaders (ie fur or blur shader) that need to know what pass it is. By setting up the auto parameter in a @ref{Default Program Parameters} list in a program definition, there is no requirement to set the pass number parameter in each pass and lose track. (@xref{fur_example}) @anchor{pass_iteration_number} @item pass_iteration_number Usefull for GPU programs that need to know what the current pass iteration number is. The first iteration of a pass is numbered 0. The last iteration number is one less than what is set for the pass iteration number. If a pass has its iteration attribute set to 5 then the last iteration number (5th execution of the pass) is 4.(@xref{iteration}) @anchor{animation_parametric} @item animation_parametric Useful for hardware vertex animation. For morph animation, sets the parametric value (0..1) representing the distance between the first position keyframe (bound to positions) and the second position keyframe (bound to the first free texture coordinate) so that the vertex program can interpolate between them. For pose animation, indicates a group of up to 4 parametric weight values applying to a sequence of up to 4 poses (each one bound to x, y, z and w of the constant), one for each pose. The original positions are held in the usual position buffer, and the offsets to take those positions to the pose where weight == 1.0 are in the first 'n' free texture coordinates; 'n' being determined by the value passed to includes_pose_animation. If more than 4 simultaneous poses are required, then you'll need more than 1 shader constant to hold the parametric values, in which case you should use this binding more than once, referencing a different constant entry; the second one will contain the parametrics for poses 5-8, the third for poses 9-12, and so on. @item custom This allows you to map a custom parameter on an individual Renderable (see Renderable::setCustomParameter) to a parameter on a GPU program. It requires that you complete the 'extra_params' field with the index that was used in the Renderable::setCustomParameter call, and this will ensure that whenever this Renderable is used, it will have it's custom parameter mapped in. It's very important that this parameter has been defined on all Renderables that are assigned the material that contains this automatic mapping, otherwise the process will fail. @end table @anchor{param_named} @subheading param_named This is the same as param_indexed, but uses a named parameter instead of an index. This can only be used with high-level programs which include parameter names; if you're using an assembler program then you have no choice but to use indexes. Note that you can use indexed parameters for high-level programs too, but it is less portable since if you reorder your parameters in the high-level program the indexes will change.@*@* format: param_named @*@* example: param_named shininess float4 10.0 0 0 0@*@* The type is required because the program is not compiled and loaded when the material script is parsed, so at this stage we have no idea what types the parameters are. Programs are only loaded and compiled when they are used, to save memory. @anchor{param_named_auto} @subheading param_named_auto This is the named equivalent of param_indexed_auto, for use with high-level programs.@*@* Format: param_named_auto @*@* Example: param_named_auto worldViewProj WORLDVIEWPROJ_MATRIX@*@* The allowed value codes and the meaning of extra_params are detailed in @ref{param_indexed_auto}. @anchor{Shadows and Vertex Programs} @subheading Shadows and Vertex Programs When using shadows (@xref{Shadows}), the use of vertex programs can add some additional complexities, because Ogre can only automatically deal with everything when using the fixed-function pipeline. If you use vertex programs, and you are also using shadows, you may need to make some adjustments. @*@* If you use @strong{stencil shadows}, then any vertex programs which do vertex deformation can be a problem, because stencil shadows are calculated on the CPU, which does not have access to the modified vertices. If the vertex program is doing standard skeletal animation, this is ok (see section above) because Ogre knows how to replicate the effect in software, but any other vertex deformation cannot be replicated, and you will either have to accept that the shadow will not reflect this deformation, or you should turn off shadows for that object. @*@* If you use @strong{texture shadows}, then vertex deformation is acceptable; however, when rendering the object into the shadow texture (the shadow caster pass), the shadow has to be rendered in a solid colour (linked to the ambient colour). You must therefore provide an alternative vertex program, so Ogre provides you with a way of specifying one to use when rendering the caster. Basically you link an alternative vertex program, using exactly the same syntax as the original vertex program link: @example shadow_caster_vertex_program_ref myShadowCasterVertexProgram { param_indexed_auto 0 worldviewproj_matrix param_indexed_auto 4 ambient_light_colour } @end example When rendering a shadow caster, Ogre will automatically use the alternate program. You can bind the same or different parameters to the program - the most important thing is that you bind @strong{ambiend_light_colour}, since this determines the colour of the shadow in modulative texture shadows. If you don't supply an alternate program, Ogre will fall back on a fixed-function material which will not reflect any vertex deformation you do in your vertex program. @*@* In addition, when rendering the shadow receivers with shadow textures, Ogre needs to project the shadow texture. It does this automatically in fixed function mode, but if the receivers use vertex programs, they need to have a shadow receiver program which does the usual vertex deformation, but also generates projective texture coordinates. The additional program linked into the pass like this: @example shadow_receiver_vertex_program_ref myShadowReceiverVertexProgram { param_indexed_auto 0 worldviewproj_matrix param_indexed_auto 4 texture_viewproj_matrix } @end example For the purposes of writing this alternate program, there is an automatic parameter binding of 'texture_viewproj_matrix' which provides the program with texture projection parameters. The vertex program should do it's normal vertex processing, and generate texture coordinates using this matrix and place them in texture coord sets 0 and 1, since some shadow techniques use 2 texture units. The colour of the vertices output by this vertex program must always be white, so as not to affect the final colour of the rendered shadow. @*@* When using additive texture shadows, the shadow pass render is actually the lighting render, so if you perform any fragmene program lighting you also need to pull in a custom fragment program. You use the shadow_receiver_fragment_program_ref for this: @example shadow_receiver_fragment_program_ref myShadowReceiverFragmentProgram { param_named_auto lightDiffuse light_diffuse_colour 0 } @end example You should pass the projected shadow coordinates from the custom vertex program. As for textures, texture unit 0 will always be the shadow texture. Any other textures which you bind in your pass will be carried across too, but will be moved up by 1 unit to make room for the shadow texture. Therefore your shadow receiver fragment program is likely to be the same as the bare lighting pass of your normal material, except that you insert an extra texture sampler at index 0, which you will use to adjust the result by (modulating diffuse and specular components). @include MaterialScriptCopy.inc @include CompositorScript.inc @node Particle Scripts @section Particle Scripts Particle scripts allow you to define particle systems to be instantiated in your code without having to hard-code the settings themselves in your source code, allowing a very quick turnaround on any changes you make. Particle systems which are defined in scripts are used as templates, and multiple actual systems can be created from them at runtime.@*@* @heading Loading scripts Particle system scripts are loaded at initialisation time by the system: by default it looks in all common resource locations (see Root::addResourceLocation) for files with the '.particle' extension and parses them. If you want to parse files with a different extension, use the ParticleSystemManager::getSingleton().parseAllSources method with your own extension, or if you want to parse an individual file, use ParticleSystemManager::getSingleton().parseScript.@*@* Once scripts have been parsed, your code is free to instantiate systems based on them using the ParticleSystemManager::getSingleton().createSystem() method which can take both a name for the new system, and the name of the template to base it on (this template name is in the script).@*@* @heading Format Several particle systems 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 a typical example: @example // A sparkly purple fountain Examples/PurpleFountain { material Examples/Flare2 particle_width 20 particle_height 20 cull_each false quota 10000 billboard_type oriented_self // Area emitter emitter Point { angle 15 emission_rate 75 time_to_live 3 direction 0 1 0 velocity_min 250 velocity_max 300 colour_range_start 1 0 0 colour_range_end 0 0 1 } // Gravity affector LinearForce { force_vector 0 -100 0 force_application add } // Fader affector ColourFader { red -0.25 green -0.25 blue -0.25 } } @end example @*@* Every particle system in the script must be given a name, which is the line before the first opening '{', in the example this is 'Examples/PurpleFountain'. This name must be globally unique. It can include path characters (as in the example) to logically divide up your particle systems, and also to avoid duplicate names, but the engine does not treat the name as hierarchical, just as a string.@*@* A system can have top-level attributes set using the scripting commands available, such as 'quota' to set the maximum number of particles allowed in the system. Emitters (which create particles) and affectors (which modify particles) are added as nested definitions within the script. The parameters available in the emitter and affector sections are entirely dependent on the type of emitter / affector.@*@* For a detailed description of the core particle system attributes, see the list below: @subheading Available Particle System Attributes @itemize @bullet @item @ref{quota} @item @ref{particle_material, material} @item @ref{particle_width} @item @ref{particle_height} @item @ref{cull_each} @item @ref{billboard_type} @item @ref{billboard_origin} @item @ref{billboard_rotation_type} @item @ref{common_direction} @item @ref{common_up_vector} @item @ref{particle_renderer, renderer} @item @ref{particle_sorted, sorted} @item @ref{particle_localspace, local_space} @item @ref{particle_point_rendering, point_rendering} @item @ref{particle_accurate_facing, accurate_facing} @item @ref{iteration_interval} @item @ref{nonvisible_update_timeout} @end itemize See also: @ref{Particle Emitters}, @ref{Particle Affectors} @node Particle System Attributes @subsection Particle System Attributes This section describes to attributes which you can set on every particle system using scripts. All atributes have default values so all settings are optional in your script.@*@* @anchor{quota} @subheading quota Sets the maximum number of particles this system is allowed to contain at one time. When this limit is exhausted, the emitters will not be allowed to emit any more particles until some destroyed (e.g. through their time_to_live running out). Note that you will almost always want to change this, since it defaults to a very low value (particle pools are only ever increased in size, never decreased).@*@* format: quota @* example: quota 10000@* default: 10@* @anchor{particle_material} @subheading material Sets the name of the material which all particles in this system will use. All paticles in a system use the same material, although each particle can tint this material through the use of it's colour property.@*@* format: material @* example: material Examples/Flare@* default: none (blank material)@* @anchor{particle_width} @subheading particle_width Sets the width of particles in world coordinates. Note that this property is absolute when billboard_type (see below) is set to 'point' or 'perpendicular_self', but is scaled by the length of the direction vector when billboard_type is 'oriented_common', 'oriented_self' or 'perpendicular_common'.@* format: particle_width @* example: particle_width 20@* default: 100@* @anchor{particle_height} @subheading particle_height Sets the height of particles in world coordinates. Note that this property is absolute when billboard_type (see below) is set to 'point' or 'perpendicular_self', but is scaled by the length of the direction vector when billboard_type is 'oriented_common', 'oriented_self' or 'perpendicular_common'.@* format: particle_height @* example: particle_height 20@* default: 100@* @anchor{cull_each} @subheading cull_each All particle systems are culled by the bounding box which contains all the particles in the system. This is normally sufficient for fairly locally constrained particle systems where most particles are either visible or not visible together. However, for those that spread particles over a wider area (e.g. a rain system), you may want to actually cull each particle individually to save on time, since it is far more likely that only a subset of the particles will be visible. You do this by setting the cull_each parameter to true.@*@* format: cull_each @* example: cull_each true@* default: false@* @anchor{particle_renderer} @subheading renderer Particle systems do not render themselves, they do it through ParticleRenderer classes. Those classes are registered with a manager in order to provide particle systems with a particular 'look'. OGRE comes configured with a default billboard-based renderer, but more can be added through plugins. Particle renders are registered with a unique name, and you can use that name in this attribute to determine the renderer to use. The default is 'billboard'.@*@* Particle renderers can have attributes, which can be passed by setting them on the root particle system.@*@* format: renderer @* default: billboard@* @anchor{particle_sorted} @subheading sorted By default, particles are not sorted. By setting this attribute to 'true', theparticles will be sorted with respect to the camera, furthest first. This can make certain rendering effects look better at a small sorting expense.@*@* format: sorted @* default: false@* @anchor{particle_localspace} @subheading local_space By default, particles are emitted into world space, such that if you transform the node to which the system is attached, it will not affect the particles (only the emitters). This tends to give the normal expected behaviour, which is to model how real world particles travel independently from the objects they are emitted from. However, to create some effects you may want the particles to remain attached to the local space the emitter is in and to follow them directly. This option allows you to do that.@*@* format: local_space @* default: false@* @anchor{billboard_type} @subheading billboard_type This is actually an attribute of the 'billboard' particle renderer (the default), and is an example of passing attributes to a particle renderer by declaring them directly within the system declaration. Particles using the default renderer are rendered using billboards, which are rectangles formed by 2 triangles which rotate to face the given direction. However, there is more than 1 way to orient a billboard. The classic approach is for the billboard to directly face the camera: this is the default behaviour. However this arrangement only looks good for particles which are representing something vaguely spherical like a light flare. For more linear effectd like laser fire, you actually want the particle to have an orientation of it's own.@*@* format: billboard_type @* example: billboard_type oriented_self@* default: point@* The options for this parameter are: @table @asis @item point The default arrangement, this approximates spherical particles and the billboards always fully face the camera. @item oriented_common Particles are oriented around a common, typically fixed direction vector (see @ref{common_direction}), which acts as their local Y axis. The billboard rotates only around this axis, giving the particle some sense of direction. Good for rainstorms, starfields etc where the particles will travelling in one direction - this is slightly faster than oriented_self (see below). @item oriented_self Particles are oriented around their own direction vector, which acts as their local Y axis. As the particle changes direction, so the billboard reorients itself to face this way. Good for laser fire, fireworks and other 'streaky' particles that should look like they are travelling in their own direction. @item perpendicular_common Particles are perpendicular to a common, typically fixed direction vector (see @ref{common_direction}), which acts as their local Z axis, and their local Y axis coplanar with common direction and the common up vector (see @ref{common_up_vector}). The billboard never rotates to face the camera, you might use double-side material to ensure particles never culled by back-facing. Good for aureolas, rings etc where the particles will perpendicular to the ground - this is slightly faster than perpendicular_self (see below). @item perpendicular_self Particles are perpendicular to their own direction vector, which acts as their local Z axis, and their local Y axis coplanar with their own direction vector and the common up vector (see @ref{common_up_vector}). The billboard never rotates to face the camera, you might use double-side material to ensure particles never culled by back-facing. Good for rings stack etc where the particles will perpendicular to their travelling direction. @end table @anchor{billboard_origin} @subheading billboard_origin Specifying the point which acts as the origin point for all billboard particles, controls the fine tuning of where a billboard particle appears in relation to it's position.@*@* format: billboard_origin @* example: billboard_origin top_right@* default: center@* The options for this parameter are: @table @asis @item top_left The billboard origin is the top-left corner. @item top_center The billboard origin is the center of top edge. @item top_right The billboard origin is the top-right corner. @item center_left The billboard origin is the center of left edge. @item center The billboard origin is the center. @item center_right The billboard origin is the center of right edge. @item bottom_left The billboard origin is the bottom-left corner. @item bottom_center The billboard origin is the center of bottom edge. @item bottom_right The billboard origin is the bottom-right corner. @end table @anchor{billboard_rotation_type} @subheading billboard_rotation_type By default, billboard particles will rotate the texture coordinates to according with particle rotation. But rotate texture coordinates has some disadvantage, e.g. the corners of the texture will lost after rotate, and the corners of the billboard will fill with unwant texture area when using wrap address mode or sub-texture sampling. This settings allow you specifying other rotation type.@*@* format: billboard_rotation_type @* example: billboard_rotation_type vertex@* default: texcoord@* The options for this parameter are: @table @asis @item vertex Billboard particles will rotate the vertices around their facing direction to according with particle rotation. Rotate vertices guarantee texture corners exactly match billboard corners, thus has advantage mentioned above, but should take more time to generate the vertices. @item texcoord Billboard particles will rotate the texture coordinates to according with particle rotation. Rotate texture coordinates is faster than rotate vertices, but has some disadvantage mentioned above. @end table @anchor{common_direction} @subheading common_direction Only required if @ref{billboard_type} is set to oriented_common or perpendicular_common, this vector is the common direction vector used to orient all particles in the system.@*@* format: common_direction @* example: common_direction 0 -1 0@* default: 0 0 1@* @*@* See also: @ref{Particle Emitters}, @ref{Particle Affectors} @anchor{common_up_vector} @subheading common_up_vector Only required if @ref{billboard_type} is set to perpendicular_self or perpendicular_common, this vector is the common up vector used to orient all particles in the system.@*@* format: common_up_vector @* example: common_up_vector 0 1 0@* default: 0 1 0@* @*@* See also: @ref{Particle Emitters}, @ref{Particle Affectors} @anchor{particle_point_rendering} @subheading point_rendering This is actually an attribute of the 'billboard' particle renderer (the default), and sets whether or not the billboardset will use point rendering rather than manually generated quads.@*@* By default a billboardset is rendered by generating geometry for a textured quad in memory, taking into account the size and orientation settings, and uploading it to the video card. The alternative is to use hardware point rendering, which means that only one position needs to be sent per billboard rather than 4 and the hardware sorts out how this is rendered based on the render state.@*@* Using point rendering is faster than generating quads manually, but is more restrictive. The following restrictions apply: @itemize @bullet @item Only the 'point' orientation type is supported @item Size and appearance of each particle is controlled by the material pass (@ref{point_size}, @ref{point_size_attenuation}, @ref{point_sprites}) @item Per-particle size is not supported (stems from the above) @item Per-particle rotation is not supported, and this can only be controlled through texture unit rotation in the material definition @item Only 'center' origin is supported @item 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 point sprites to get very large on screen, since they may get clamped on some cards. Upper sizes can range from 64 to 256 pixels. @end itemize You will almost certainly want to enable in your material pass both point attenuation and point sprites if you use this option. @*@* @anchor{particle_accurate_facing} @subheading accurate_facing This is actually an attribute of the 'billboard' particle renderer (the default), and sets whether or not the billboardset will use a slower but more accurate calculation for facing the billboard to the camera. Bt default it uses the camera direction, which is faster but means the billboards don't stay in the same orientation as you rotate the camera. The 'accurate_facing true' option makes the calculation based on a vector from each billboard to the camera, which means the orientation is constant even whilst the camera rotates. @*@* format: accurate_facing on|off@* default: accurate_facing off 0@* @*@* @anchor{iteration_interval} @subheading iteration_interval Usually particle systems are updated based on the frame rate; however this can give variable results with more extreme frame rate ranges, particularly at lower frame rates. You can use this option to make the update frequency a fixed interval, whereby at lower frame rates, the particle update will be repeated at the fixed interval until the frame time is used up. A value of 0 means the default frame time iteration. @*@* format: iteration_interval @* example: iteration_interval 0.01@* default: iteration_interval 0@* @*@* @anchor{nonvisible_update_timeout} @subheading nonvisible_update_timeout Sets when the particle system should stop updating after it hasn't been visible for a while. By default, visible particle systems update all the time, even when not in view. This means that they are guaranteed to be consistent when they do enter view. However, this comes at a cost, updating particle systems can be expensive, especially if they are perpetual. @*@* This option lets you set a 'timeout' on the particle system, so that if it isn't visible for this amount of time, it will stop updating until it is next visible. A value of 0 disables the timeout and always updates.@*@* format: nonvisible_update_timeout @* example: nonvisible_update_timeout 10@* default: nonvisible_update_timeout 0@* @*@* @node Particle Emitters @subsection Particle Emitters Particle emitters are classified by 'type' e.g. 'Point' emitters emit from a single point whilst 'Box' emitters emit randomly from an area. New emitters can be added to Ogre by creating plugins. You add an emitter to a system by nesting another section within it, headed with the keyword 'emitter' followed by the name of the type of emitter (case sensitive). Ogre currently supports 'Point', 'Box', 'Cylinder', 'Ellipsoid', 'HollowEllipsoid' and 'Ring' emitters. @subheading Particle Emitter Universal Attributes @itemize @bullet @item @ref{angle} @item @ref{colour} @item @ref{colour_range_start} @item @ref{colour_range_end} @item @ref{direction} @item @ref{emission_rate} @item @ref{position} @item @ref{velocity} @item @ref{velocity_min} @item @ref{velocity_max} @item @ref{time_to_live} @item @ref{time_to_live_min} @item @ref{time_to_live_max} @item @ref{duration} @item @ref{duration_min} @item @ref{duration_max} @item @ref{repeat_delay} @item @ref{repeat_delay_min} @item @ref{repeat_delay_max} @end itemize @*@* See also: @ref{Particle Scripts}, @ref{Particle Affectors} @node Particle Emitter Attributes @subsection Particle Emitter Attributes This section describes the common attributes of all particle emitters. Specific emitter types may also support their own extra attributes.@*@* @anchor{angle} @subheading angle Sets the maximum angle (in degrees) which emitted particles may deviate from the direction of the emitter (see direction). Setting this to 10 allows particles to deviate up to 10 degrees in any direction away from the emitter's direction. A value of 180 means emit in any direction, whilst 0 means emit always exactly in the direction of the emitter.@*@* format: angle @* example: angle 30@* default: 0@* @anchor{colour} @subheading colour Sets a static colour for all particle emitted. Also see the colour_range_start and colour_range_end attributes for setting a range of colours. The format of the colour parameter is "r g b a", where each component is a value from 0 to 1, and the alpha value is optional (assumes 1 if not specified).@*@* format: colour []@* example: colour 1 0 0 1@* default: 1 1 1 1@* @anchor{colour_range_start} @anchor{colour_range_end} @subheading colour_range_start & colour_range_end As the 'colour' attribute, except these 2 attributes must be specified together, and indicate the range of colours available to emitted particles. The actual colour will be randomly chosen between these 2 values.@*@* format: as colour@* example (generates random colours between red and blue):@* @ @ @ @ colour_range_start 1 0 0@* @ @ @ @ colour_range_end 0 0 1@* default: both 1 1 1 1@* @anchor{direction} @subheading direction Sets the direction of the emitter. This is relative to the SceneNode which the particle system is attached to, meaning that as with other movable objects changing the orientation of the node will also move the emitter.@*@* format: direction @* example: direction 0 1 0@* default: 1 0 0@* @anchor{emission_rate} @subheading emission_rate Sets how many particles per second should be emitted. The specific emitter does not have to emit these in a continuous burst - this is a relative parameter and the emitter may choose to emit all of the second's worth of particles every half-second for example, the behaviour depends on the emitter. The emission rate will also be limited by the particle system's 'quota' setting.@*@* format: emission_rate @* example: emission_rate 50@* default: 10@* @anchor{position} @subheading position Sets the position of the emitter relative to the SceneNode the particle system is attached to.@*@* format: position @* example: position 10 0 40@* default: 0 0 0@* @anchor{velocity} @subheading velocity Sets a constant velocity for all particles at emission time. See also the velocity_min and velocity_max attributes which allow you to set a range of velocities instead of a fixed one.@*@* format: velocity @* example: velocity 100@* default: 1@* @anchor{velocity_min} @anchor{velocity_max} @subheading velocity_min & velocity_max As 'velocity' except these attributes set a velocity range and each particle is emitted with a random velocity within this range.@*@* format: as velocity@* example:@* @ @ @ @ velocity_min 50@* @ @ @ @ velocity_max 100@* default: both 1@* @anchor{time_to_live} @subheading time_to_live Sets the number of seconds each particle will 'live' for before being destroyed. NB it is possible for particle affectors to alter this in flight, but this is the value given to particles on emission. See also the time_to_live_min and time_to_live_max attributes which let you set a lifetime range instead of a fixed one.@*@* format: time_to_live @* example: time_to_live 10@* default: 5@* @anchor{time_to_live_min} @anchor{time_to_live_max} @subheading time_to_live_min & time_to_live_max As time_to_live, except this sets a range of lifetimes and each particle gets a random value inbetween on emission.@*@* format: as time_to_live@* example:@* @ @ @ @ time_to_live_min 2@* @ @ @ @ time_to_live_max 5@* default: both 5@* @* @anchor{duration} @subheading duration Sets the number of seconds the emitter is active. The emitter can be started again, see @ref{repeat_delay}. A value of 0 means infinite duration. See also the duration_min and duration_max attributes which let you set a duration range instead of a fixed one.@*@* format: duration @* example:@* @ @ @ @ duration 2.5@* default: 0@* @* @anchor{duration_min} @anchor{duration_max} @subheading duration_min & duration_max As duration, except these attributes set a variable time range between the min and max values each time the emitter is started.@*@* format: as duration@* example:@* @ @ @ @ duration_min 2@* @ @ @ @ duration_max 5@* default: both 0@* @* @anchor{repeat_delay} @subheading repeat_delay Sets the number of seconds to wait before the emission is repeated when stopped by a limited @ref{duration}. See also the repeat_delay_min and repeat_delay_max attributes which allow you to set a range of repeat_delays instead of a fixed one.@*@* format: repeat_delay @* example:@* @ @ @ @ repeat_delay 2.5@* default: 0@* @* @anchor{repeat_delay_min} @anchor{repeat_delay_max} @subheading repeat_delay_min & repeat_delay_max As repeat_delay, except this sets a range of repeat delays and each time the emitter is started it gets a random value inbetween.@*@* format: as repeat_delay@* example:@* @ @ @ @ repeat_delay 2@* @ @ @ @ repeat_delay 5@* default: both 0@* @* See also: @ref{Standard Particle Emitters}, @ref{Particle Scripts}, @ref{Particle Affectors} @node Standard Particle Emitters @subsection Standard Particle Emitters Ogre comes preconfigured with a few particle emitters. New ones can be added by creating plugins: see the Plugin_ParticleFX project as an example of how you would do this (this is where these emitters are implemented). @itemize @bullet @item @ref{Point Emitter} @item @ref{Box Emitter} @item @ref{Cylinder Emitter} @item @ref{Ellipsoid Emitter} @item @ref{Hollow Ellipsoid Emitter} @item @ref{Ring Emitter} @end itemize @*@* @anchor{Point Emitter} @subheading Point Emitter This emitter emits particles from a single point, which is it's position. This emitter has no additional attributes over an above the standard emitter attributes.@*@* To create a point emitter, include a section like this within your particle system script: @example emitter Point { // Settings go here } @end example @* Please note that the name of the emitter ('Point') is case-sensitive. @anchor{Box Emitter} @subheading Box Emitter This emitter emits particles from a random location within a 3-dimensional box. It's extra attributes are:@*@* @table @asis @item width Sets the width of the box (this is the size of the box along it's local X axis, which is dependent on the 'direction' attribute which forms the box's local Z).@* format: width @* example: width 250@* default: 100@* @item height Sets the height of the box (this is the size of the box along it's local Y axis, which is dependent on the 'direction' attribute which forms the box's local Z).@* format: height @* example: height 250@* default: 100@* @item depth Sets the depth of the box (this is the size of the box along it's local Z axis, which is the same as the 'direction' attribute).@* format: depth @* example: depth 250@* default: 100@* @end table @* To create a box emitter, include a section like this within your particle system script: @example emitter Box { // Settings go here } @end example @anchor{Cylinder Emitter} @subheading Cylinder Emitter This emitter emits particles in a random direction from within a cylinder area, where the cylinder is oriented along the Z-axis. This emitter has exactly the same parameters as the @ref{Box Emitter} so there are no additional parameters to consider here - the width and height determine the shape of the cylinder along it's axis (if they are different it is an ellipsoid cylinder), the depth determines the length of the cylinder. @anchor{Ellipsoid Emitter} @subheading Ellipsoid Emitter This emitter emits particles from within an ellipsoid shaped area, ie a sphere or squashed-sphere area. The parameters are again identical to the @ref{Box Emitter}, except that the dimensions describe the widest points along each of the axes. @anchor{Hollow Ellipsoid Emitter} @subheading Hollow Ellipsoid Emitter This emitter is just like @ref{Ellipsoid Emitter} except that there is a hollow area in the centre of the ellipsoid from which no particles are emitted. Therefore it has 3 extra parameters in order to define this area: @table @asis @item inner_width The width of the inner area which does not emit any particles. @item inner_height The height of the inner area which does not emit any particles. @item inner_depth The depth of the inner area which does not emit any particles. @end table @anchor{Ring Emitter} @subheading Ring Emitter This emitter emits particles from a ring-shaped area, ie a little like @ref{Hollow Ellipsoid Emitter} except only in 2 dimensions. @table @asis @item inner_width The width of the inner area which does not emit any particles. @item inner_height The height of the inner area which does not emit any particles. @end table @*@* See also: @ref{Particle Scripts}, @ref{Particle Emitters} @node Particle Affectors @subsection Particle Affectors Particle affectors modify particles over their lifetime. They are classified by 'type' e.g. 'LinearForce' affectors apply a force to all particles, whilst 'ColourFader' affectors alter the colour of particles in flight. New affectors can be added to Ogre by creating plugins. You add an affector to a system by nesting another section within it, headed with the keyword 'affector' followed by the name of the type of affector (case sensitive). Ogre currently supports 'LinearForce' and 'ColourFader' affectors.@*@* Particle affectors actually have no universal attributes; they are all specific to the type of affector.@*@* See also: @ref{Standard Particle Affectors}, @ref{Particle Scripts}, @ref{Particle Emitters} @node Standard Particle Affectors @subsection Standard Particle Affectors Ogre comes preconfigured with a few particle affectors. New ones can be added by creating plugins: see the Plugin_ParticleFX project as an example of how you would do this (this is where these affectors are implemented). @itemize @bullet @item @ref{Linear Force Affector} @item @ref{ColourFader Affector} @item @ref{ColourFader2 Affector} @item @ref{Scaler Affector} @item @ref{Rotator Affector} @item @ref{ColourInterpolator Affector} @item @ref{ColourImage Affector} @end itemize @anchor{Linear Force Affector} @subheading Linear Force Affector This affector applies a force vector to all particles to modify their trajectory. Can be used for gravity, wind, or any other linear force. It's extra attributes are:@*@* @table @asis @item force_vector Sets the vector for the force to be applied to every particle. The magnitude of this vector determines how strong the force is.@* @ @ @ @ format: force_vector @* @ @ @ @ example: force_vector 50 0 -50@* @ @ @ @ default: 0 -100 0 (a fair gravity effect)@* @item force_application Sets the way in which the force vector is applied to particle momentum.@* @ @ @ @ format: force_application @* @ @ @ @ example: force_application average@* @ @ @ @ default: add@* The options are: @table @asis @item average The resulting momentum is the average of the force vector and the particle's current motion. Is self-stabilising but the speed at which the particle changes direction is non-linear. @item add The resulting momentum is the particle's current motion plus the force vector. This is traditional force acceleration but can potentially result in unlimited velocity. @end table @end table @* To create a linear force affector, include a section like this within your particle system script: @example affector LinearForce { // Settings go here } @end example Please note that the name of the affector type ('LinearForce') is case-sensitive. @anchor{ColourFader Affector} @subheading ColourFader Affector This affector modifies the colour of particles in flight. It's extra attributes are: @table @asis @item red Sets the adjustment to be made to the red component of the particle colour per second.@* @ @ @ @ format: red @* @ @ @ @ example: red -0.1@* @ @ @ @ default: 0@* @item green Sets the adjustment to be made to the green component of the particle colour per second.@* @ @ @ @ format: green @* @ @ @ @ example: green -0.1@* @ @ @ @ default: 0@* @item blue Sets the adjustment to be made to the blue component of the particle colour per second.@* @ @ @ @ format: blue @* @ @ @ @ example: blue -0.1@* @ @ @ @ default: 0@* @item alpha Sets the adjustment to be made to the alpha component of the particle colour per second.@* @ @ @ @ format: alpha @* example: alpha -0.1@* default: 0@* @end table To create a colour fader affector, include a section like this within your particle system script: @example affector ColourFader { // Settings go here } @end example @anchor{ColourFader2 Affector} @subheading ColourFader2 Affector This affector is similar to the @ref{ColourFader Affector}, except it introduces two states of colour changes as opposed to just one. The second colour change state is activated once a specified amount of time remains in the particles life. @table @asis @item red1 Sets the adjustment to be made to the red component of the particle colour per second for the first state.@* @ @ @ @ format: red @* @ @ @ @ example: red -0.1@* @ @ @ @ default: 0@* @item green1 Sets the adjustment to be made to the green component of the particle colour per second for the first state.@* @ @ @ @ format: green @* @ @ @ @ example: green -0.1@* @ @ @ @ default: 0@* @item blue1 Sets the adjustment to be made to the blue component of the particle colour per second for the first state.@* @ @ @ @ format: blue @* @ @ @ @ example: blue -0.1@* @ @ @ @ default: 0@* @item alpha1 Sets the adjustment to be made to the alpha component of the particle colour per second for the first state.@* @ @ @ @ format: alpha @* example: alpha -0.1@* default: 0@* @item red2 Sets the adjustment to be made to the red component of the particle colour per second for the second state.@* @ @ @ @ format: red @* @ @ @ @ example: red -0.1@* @ @ @ @ default: 0@* @item green2 Sets the adjustment to be made to the green component of the particle colour per second for the second state.@* @ @ @ @ format: green @* @ @ @ @ example: green -0.1@* @ @ @ @ default: 0@* @item blue2 Sets the adjustment to be made to the blue component of the particle colour per second for the second state.@* @ @ @ @ format: blue @* @ @ @ @ example: blue -0.1@* @ @ @ @ default: 0@* @item alpha2 Sets the adjustment to be made to the alpha component of the particle colour per second for the second state.@* @ @ @ @ format: alpha @* example: alpha -0.1@* default: 0@* @item state_change When a particle has this much time left to live, it will switch to state 2.@* @ @ @ @ format: state_change @* example: state_change 2@* default: 1@* @end table To create a ColourFader2 affector, include a section like this within your particle system script: @example affector ColourFader2 { // Settings go here } @end example @anchor{Scaler Affector} @subheading Scaler Affector This affector scales particles in flight. It's extra attributes are: @table @asis @item rate The amount by which to scale the particles in both the x and y direction per second. @end table To create a scale affector, include a section like this within your particle system script: @example affector Scaler { // Settings go here } @end example @anchor{Rotator Affector} @subheading Rotator Affector This affector rotates particles in flight. This is done by rotating the texture. It's extra attributes are: @table @asis @item rotation_speed_range_start The start of a range of rotation speeds to be assigned to emitted particles.@* @ @ @ @ format: rotation_speed_range_start @* example: rotation_speed_range_start 90@* default: 0@* @item rotation_speed_range_end The end of a range of rotation speeds to be assigned to emitted particles.@* @ @ @ @ format: rotation_speed_range_end @* example: rotation_speed_range_end 180@* default: 0@* @item rotation_range_start The start of a range of rotation angles to be assigned to emitted particles.@* @ @ @ @ format: rotation_range_start @* example: rotation_range_start 0@* default: 0@* @item rotation_range_end The end of a range of rotation angles to be assigned to emitted particles.@* @ @ @ @ format: rotation_range_end @* example: rotation_range_end 360@* default: 0@* @end table To create a rotate affector, include a section like this within your particle system script: @example affector Rotator { // Settings go here } @end example @anchor{ColourInterpolator Affector} @subheading ColourInterpolator Affector Similar to the ColourFader and ColourFader2 Affector?s, this affector modifies the colour of particles in flight, except it has a variable number of defined stages. It swaps the particle colour for several stages in the life of a particle and interpolates between them. It's extra attributes are: @table @asis @item time0 The point in time of stage 0.@* @ @ @ @ format: time0 <0-1 based on lifetime>@* example: time0 0@* default: 1@* @item colour0 The colour at stage 0.@* @ @ @ @ format: colour0 []@* example: colour0 1 0 0 1@* default: 0.5 0.5 0.5 0.0@* @item time1 The point in time of stage 1.@* @ @ @ @ format: time1 <0-1 based on lifetime>@* example: time1 0.5@* default: 1@* @item colour1 The colour at stage 1.@* @ @ @ @ format: colour1 []@* example: colour1 0 1 0 1@* default: 0.5 0.5 0.5 0.0@* @item time2 The point in time of stage 2.@* @ @ @ @ format: time2 <0-1 based on lifetime>@* example: time2 1@* default: 1@* @item colour2 The colour at stage 2.@* @ @ @ @ format: colour2 []@* example: colour2 0 0 1 1@* default: 0.5 0.5 0.5 0.0@* @item [...] @end table The number of stages is variable. The maximal number of stages is 6; where time5 and colour5 are the last possible parameters. To create a colour interpolation affector, include a section like this within your particle system script: @example affector ColourInterpolator { // Settings go here } @end example @anchor{ColourImage Affector} @subheading ColourImage Affector This is another affector that modifies the colour of particles in flight, but instead of programmatically defining colours, the colours are taken from a specified image file. The range of colour values begins from the left side of the image and move to the right over the lifetime of the particle, therefore only the horizontal dimension of the image is used. Its extra attributes are: @table @asis @item image The start of a range of rotation speed to be assigned to emitted particles.@* @ @ @ @ format: image @* example: image rainbow.png@* default: none@* @end table To create a ColourImage affector, include a section like this within your particle system script: @example affector ColourImage { // Settings go here } @end example @node Overlay Scripts @section Overlay Scripts Overlay scripts offer you the ability to define overlays in a script which can be reused easily. Whilst you could set up all overlays for a scene in code using the methods of the SceneManager, Overlay and OverlayElement classes, in practice it's a bit unwieldy. Instead you can store overlay definitions in text files which can then be loaded whenever required.@*@* @heading Loading scripts Overlay scripts are loaded at initialisation time by the system: by default it looks in all common resource locations (see Root::addResourceLocation) for files with the '.overlay' extension and parses them. If you want to parse files with a different extension, use the OverlayManager::getSingleton().parseAllSources method with your own extension, or if you want to parse an individual file, use OverlayManager::getSingleton().parseScript.@*@* @heading Format Several overlays may be defined in a single script. The script format is pseudo-C++, with sections delimited by curly braces ({}), comments indicated by starting a line with '//' (note, no nested form comments allowed), and inheritance through the use of templates. The general format is shown below in a typical example: @example // The name of the overlay comes first MyOverlays/ANewOverlay { zorder 200 container Panel(MyOverlayElements/TestPanel) { // Center it horzontally, put it at the top left 0.25 top 0 width 0.5 height 0.1 material MyMaterials/APanelMaterial // Another panel nested in this one container Panel(MyOverlayElements/AnotherPanel) { left 0 top 0 width 0.1 height 0.1 material MyMaterials/NestedPanel } } } @end example The above example defines a single overlay called 'MyOverlays/ANewOverlay', with 2 panels in it, one nested under the other. It uses relative metrics (the default if no metrics_mode option is found).@*@* Every overlay in the script must be given a name, which is the line before the first opening '{'. This name must be globally unique. It can include path characters (as in the example) to logically divide up your overlays, and also to avoid duplicate names, but the engine does not treat the name a hierarchical, just as a string. Within the braces are the properties of the overlay, and any nested elements. The overlay itself only has a single property 'zorder' which determines how'high' it is in the stack of overlays if more than one is displayed at the same time. Overlays with higher zorder values are displayed on top.@*@* @heading Adding elements to the overlay Within an overlay, you can include any number of 2D or 3D elements. You do this by defining a nested block headed by: @table @asis @item 'element' if you want to define a 2D element which cannot have children of it's own @item 'container' if you want to define a 2D container object (which may itself have nested containers or elements) @end table @* The element and container blocks are pretty identical apart from their ability to store nested blocks. @heading 'container' / 'element' blocks These are delimited by curly braces. The format for the header preceding the first brace is:@*@* [container | element] ( ) [: ]@* { ...@*@* @table @asis @item type_name Must resolve to the name of a OverlayElement type which has been registered with the OverlayManager. Plugins register with the OverlayManager to advertise their ability to create elements, and at this time advertise the name of the type. OGRE comes preconfigured with types 'Panel', 'BorderPanel' and 'TextArea'. @item instance_name Must be a name unique among all other elements / containers by which to identify the element. Note that you can obtain a pointer to any named element by calling OverlayManager::getSingleton().getOverlayElement(name). @item template_name Optional template on which to base this item. See templates. @end table The properties which can be included within the braces depend on the custom type. However the following are always valid: @itemize @bullet @item @ref{metrics_mode} @item @ref{horz_align} @item @ref{vert_align} @item @ref{left} @item @ref{top} @item @ref{width} @item @ref{height} @item @ref{overlay_material, material} @item @ref{caption} @end itemize @heading Templates You can use templates to create numerous elements with the same properties. A template is an abstract element and it is not added to an overlay. It acts as a base class that elements can inherit and get its default properties. To create a template, the keyword 'template' must be the first word in the element definition (before container or element). The template element is created in the topmost scope - it is NOT specified in an Overlay. It is recommended that you define templates in a separate overlay though this is not essential. Having templates defined in a separate file will allow different look & feels to be easily substituted.@*@* Elements can inherit a template in a similar way to C++ inheritance - by using the : operator on the element definition. The : operator is placed after the closing bracket of the name (separated by a space). The name of the template to inherit is then placed after the : operator (also separated by a space).@*@* A template can contain template children which are created when the template is subclassed and instantiated. Using the template keyword for the children of a template is optional but recommended for clarity, as the children of a template are always going to be templates themselves.@*@* @example template container BorderPanel(MyTemplates/BasicBorderPanel) { left 0 top 0 width 1 height 1 // setup the texture UVs for a borderpanel // do this in a template so it doesn't need to be redone everywhere material Core/StatsBlockCenter border_size 0.05 0.05 0.06665 0.06665 border_material Core/StatsBlockBorder border_topleft_uv 0.0000 1.0000 0.1914 0.7969 border_top_uv 0.1914 1.0000 0.8086 0.7969 border_topright_uv 0.8086 1.0000 1.0000 0.7969 border_left_uv 0.0000 0.7969 0.1914 0.2148 border_right_uv 0.8086 0.7969 1.0000 0.2148 border_bottomleft_uv 0.0000 0.2148 0.1914 0.0000 border_bottom_uv 0.1914 0.2148 0.8086 0.0000 border_bottomright_uv 0.8086 0.2148 1.0000 0.0000 } template container Button(MyTemplates/BasicButton) : MyTemplates/BasicBorderPanel { left 0.82 top 0.45 width 0.16 height 0.13 material Core/StatsBlockCenter border_up_material Core/StatsBlockBorder/Up border_down_material Core/StatsBlockBorder/Down } template element TextArea(MyTemplates/BasicText) { font_name Ogre char_height 0.08 colour_top 1 1 0 colour_bottom 1 0.2 0.2 left 0.03 top 0.02 width 0.12 height 0.09 } MyOverlays/AnotherOverlay { zorder 490 container BorderPanel(MyElements/BackPanel) : MyTemplates/BasicBorderPanel { left 0 top 0 width 1 height 1 container Button(MyElements/HostButton) : MyTemplates/BasicButton { left 0.82 top 0.45 caption MyTemplates/BasicText HOST } container Button(MyElements/JoinButton) : MyTemplates/BasicButton { left 0.82 top 0.60 caption MyTemplates/BasicText JOIN } } } @end example The above example uses templates to define a button. Note that the button template inherits from the borderPanel template. This reduces the number of attributes needed to instantiate a button.@*@* Also note that the instantiate of a Button needs a template name for the caption attribute. So templates can also be used by elements that need dynamic creation of children elements (the button creates a TextAreaElement in this case for its caption).@*@* @xref{OverlayElement Attributes}, @ref{Standard OverlayElements} @node OverlayElement Attributes @subsection OverlayElement Attributes These attributes are valid within the braces of a 'container' or 'element' block in an overlay script. They must each be on their own line. Ordering is unimportant.@*@* @anchor{metrics_mode} @subheading metrics_mode Sets the units which will be used to size and position this element.@*@* Format: metrics_mode @* Example: metrics_mode pixels@* This can be used to change the way that all measurement attributes in the rest of this element are interpreted. In relative mode, they are interpreted as being a parametric value from 0 to 1, as a proportion of the width / height of the screen. In pixels mode, they are simply pixel offsets.@*@* Default: metrics_mode relative@* @anchor{horz_align} @subheading horz_align Sets the horizontal alignment of this element, in terms of where the horizontal origin is.@*@* Format: horz_align @* Example: horz_align center@*@* This can be used to change where the origin is deemed to be for the purposes of any horizontal positioning attributes of this element. By default the origin is deemed to be the left edge of the screen, but if you change this you can center or right-align your elements. Note that setting the alignment to center or right does not automatically force your elements to appear in the center or the right edge, you just have to treat that point as the origin and adjust your coordinates appropriately. This is more flexible because you can choose to position your element anywhere relative to that origin. For example, if your element was 10 pixels wide, you would use a 'left' property of -10 to align it exactly to the right edge, or -20 to leave a gap but still make it stick to the right edge.@*@* Note that you can use this property in both relative and pixel modes, but it is most useful in pixel mode.@*@* Default: horz_align left@* @anchor{vert_align} @subheading vert_align Sets the vertical alignment of this element, in terms of where the vertical origin is.@*@* Format: vert_align @* Example: vert_align center@*@* This can be used to change where the origin is deemed to be for the purposes of any vertical positioning attributes of this element. By default the origin is deemed to be the top edge of the screen, but if you change this you can center or bottom-align your elements. Note that setting the alignment to center or bottom does not automatically force your elements to appear in the center or the bottom edge, you just have to treat that point as the origin and adjust your coordinates appropriately. This is more flexible because you can choose to position your element anywhere relative to that origin. For example, if your element was 50 pixels high, you would use a 'top' property of -50 to align it exactly to the bottom edge, or -70 to leave a gap but still make it stick to the bottom edge.@*@* Note that you can use this property in both relative and pixel modes, but it is most useful in pixel mode.@*@* Default: vert_align top@* @anchor{left} @subheading left Sets the horizontal position of the element relative to it's parent.@*@* Format: left @* Example: left 0.5@*@* Positions are relative to the parent (the top-left of the screen if the parent is an overlay, the top-left of the parent otherwise) and are expressed in terms of a proportion of screen size. Therefore 0.5 is half-way across the screen.@*@* Default: left 0@* @anchor{top} @subheading top Sets the vertical position of the element relative to it's parent.@*@* Format: top @* Example: top 0.5@*@* Positions are relative to the parent (the top-left of the screen if the parent is an overlay, the top-left of the parent otherwise) and are expressed in terms of a proportion of screen size. Therefore 0.5 is half-way down the screen.@*@* Default: top 0@* @anchor{width} @subheading width Sets the width of the element as a proportion of the size of the screen.@*@* Format: width @* Example: width 0.25@*@* Sizes are relative to the size of the screen, so 0.25 is a quarter of the screen. Sizes are not relative to the parent; this is common in windowing systems where the top and left are relative but the size is absolute.@*@* Default: width 1@* @anchor{height} @subheading height Sets the height of the element as a proportion of the size of the screen.@*@* Format: height @* Example: height 0.25@*@* Sizes are relative to the size of the screen, so 0.25 is a quarter of the screen. Sizes are not relative to the parent; this is common in windowing systems where the top and left are relative but the size is absolute.@*@* Default: height 1@* @anchor{overlay_material} @subheading material Sets the name of the material to use for this element.@*@* Format: material @* Example: material Examples/TestMaterial@*@* This sets the base material which this element will use. Each type of element may interpret this differently; for example the OGRE element 'Panel' treats this as the background of the panel, whilst 'BorderPanel' interprets this as the material for the center area only. Materials should be defined in .material scripts.@*@* Note that using a material in an overlay element automatically disables lighting and depth checking on this material. Therefore you should not use the same material as is used for real 3D objects for an overlay.@*@* Default: none@* @anchor{caption} @subheading caption Sets a text caption for the element.@*@* Format: caption @* Example: caption This is a caption@*@* Not all elements support captions, so each element is free to disregard this if it wants. However, a general text caption is so common to many elements that it is included in the generic interface to make it simpler to use. This is a common feature in GUI systems.@*@* Default: blank@* @anchor{rotation} @subheading rotation Sets the rotation of the element.@*@* Format: rotation Example: rotation 30 0 0 1 Default: none @node Standard OverlayElements @subsection Standard OverlayElements Although OGRE's OverlayElement and OverlayContainer classes are designed to be extended by applications developers, there are a few elements which come as standard with Ogre. These include: @itemize @bullet @item @ref{Panel} @item @ref{BorderPanel} @item @ref{TextArea} @item @ref{TextBox} @end itemize @* This section describes how you define their custom attributes in an .overlay script, but you can also change these custom properties in code if you wish. You do this by calling setParameter(paramname, value). You may wish to use the StringConverter class to convert your types to and from strings. @anchor{Panel} @subheading Panel (container) This is the most bog-standard container you can use. It is a rectangular area which can contain other elements (or containers) and may or may not have a background, which can be tiled however you like. The background material is determined by the material attribute, but is only displayed if transparency is off.@*@* Attributes: @table @asis @item transparent If set to 'true' the panel is transparent and is not rendered itself, it is just used as a grouping level for it's children. @item tiling Sets the number of times the texture(s) of the material are tiled across the panel in the x and y direction. is the texture layer, from 0 to the number of texture layers in the material minus one. By setting tiling per layer you can create some nice multitextured backdrops for your panels, this works especially well when you animate one of the layers. @item uv_coords Sets the texture coordinates to use for this panel. @end table @anchor{BorderPanel} @subheading BorderPanel (container) This is a slightly more advanced version of Panel, where instead of just a single flat panel, the panel has a separate border which resizes with the panel. It does this by taking an approach very similar to the use of HTML tables for bordered content: the panel is rendered as 9 square areas, with the center area being rendered with the main material (as with Panel) and the outer 8 areas (the 4 corners and the 4 edges) rendered with a separate border material. The advantage of rendering the corners separately from the edges is that the edge textures can be designed so that they can be stretched without distorting them, meaning the single texture can serve any size panel.@*@* Attributes: @table @asis @item border_size The size of the border at each edge, as a proportion of the size of the screen. This lets you have different size borders at each edge if you like, or you can use the same value 4 times to create a constant size border. @item border_material The name of the material to use for the border. This is normally a different material to the one used for the center area, because the center area is often tiled which means you can't put border areas in there. You must put all the images you need for all the corners and the sides into a single texture. @item border_topleft_uv [also border_topright_uv, border_bottomleft_uv, border_bottomright_uv]; The texture coordinates to be used for the corner areas of the border. 4 coordinates are required, 2 for the top-left corner of the square, 2 for the bottom-right of the square. @item border_left_uv [also border_right_uv, border_top_uv, border_bottom_uv]; The texture coordinates to be used for the edge areas of the border. 4 coordinates are required, 2 for the top-left corner, 2 for the bottom-right. Note that you should design the texture so that the left & right edges can be stretched / squashed vertically and the top and bottom edges can be stretched / squashed horizontally without detrimental effects. @end table @anchor{TextArea} @subheading TextArea (element) This is a generic element that you can use to render text. It uses fonts which can be defined in code using the FontManager and Font classes, or which have been predefined in .fontdef files. See the font definitions section for more information.@*@* Attributes: @table @asis @item font_name The name of the font to use. This font must be defined in a .fontdef file to ensure it is available at scripting time. @item char_height The height of the letters as a proportion of the screen height. Character widths may vary because OGRE supports proportional fonts, but will be based on this constant height. @item colour A solid colour to render the text in. Often fonts are defined in monochrome, so this allows you to colour them in nicely and use the same texture for multiple different coloured text areas. The colour elements should all be expressed as values between 0 and 1. If you use predrawn fonts which are already full colour then you don't need this. @item colour_bottom / colour_top As an alternative to a solid colour, you can colour the text differently at the top and bottom to create a gradient colour effect which can be very effective. @end table @anchor{TextBox} @subheading TextBox (element) This element is a box that allows text input. It is composed of 2 elements, a TextArea, which defines the size, colour etc of the text to be used when typed, and a back panel which is the box-element on which the text is written.@*@* Attributes: @table @asis @item text_area