OGRE中文帮助手册

编辑：夜魔鱼先生


文档:手册:1-4-0:1. 介绍 - OGRE 3D 中文

文档:手册:1-4-0:1. 介绍

From OGRE 3D 中文

这个章节将要给你一个OGRE组成的概观，并且谈谈为什么采用这样的方式。


文档:手册:1-4-0:1.1 面向对象-不是说说而已 - OGRE 3D 中文

文档:手册:1-4-0:1.1 面向对象-不是说说而已

OGRE这个名字很直白，就是 Object-Oriented Graphics Rendering Engine(面对对象的图形渲染引擎)。那么，我干嘛还要费这么多口舌来说呢？

嗯，现在的图形引擎就像任何庞大的软件系统。在一开始很苗条，但很快变成惊人复杂的怪兽，让人难以理解它。这样大的系统难于管理，任何对系统的修改都可能影响其可靠性。而在这样一个不断出现新技术和手段的领域，修改又是必不可少。大量的使用c函数调用也无法对这一情况有任何改善 —— 即使所有的函数都是同一个人写的。通常会发现，几个月以后，一小段代码也会变得复杂难懂；该如何组织这些函数也会变成一个难题。

面对对象是解决复杂性问题的一个常用手段。它逐步的把代码分解到函数中，把函数和表示状态的数据用类组织起来，以表示现实中的各种概念。它能让你把复杂性隐藏在容易确定的代码包当中，只暴露出简单易用的接口。这样你就有了可以搭建在一起的“建筑材料”。你也可以通过组织这些材料使它们有一致的外部接口，而在内部，实现这些接口的方法却各不相同。这同样减少了复杂性，因为开发者只需要学习一种接口。

我没打算在这儿教你面对对象的思想。有很多其它的书是关于这一话题的。我在商业系统编程中已经看到很多面对对象的好处，而让我惊讶的是，多数的图形程序是以C函数风格写成的。我对能否把自己设计方面的经验用于其它领域很有兴趣。这个领域正是我十分关注的3维图形引擎。有的人认为对于实时图形引擎，完全采用C++不够快，但也有人(包括我)认为，花点力气，面对对象的框架也足以胜任完成实时图象引擎。现在看来，我们是对的。面对对象带给OGRE的好处概括的说有以下几点：

  • 抽象性
一致的接口，隐藏了不同3D应用程序接口和操作系统的实现差异
  • 封装性
在图形引擎中，有大量的状态管理和上下文相关操作的代码。封装能把这些代码放在和相关状态和上下文数据最近的地方，这样以来代码就更容易理解。而且由于封装避免了复制代码方式的重用，也使得程序变得更可靠。
  • 多态性
当一接口用于不同类型对象时，自动选择的不同方法的行为。例如，虽然一个为室内场景设计的类，其行为和标准场景管理完全不同，但调用它的方法和这一系统中的其它类是完全一致的。


文档:手册:1-4-0:1.2 出色的扩展性 - OGRE 3D 中文

文档:手册:1-4-0:1.2 出色的扩展性

我不希望自己的引擎只能使用一套3D应用程序接口，或是只能在一个平台上的运行，或是只能有一种类型的场景(最流行的室内场景)。我想要OGRE能够扩展出任何类型的场景(并且能够在顶层实现针对每个类型场景的优化)，可以运行于任何平台和任何3D程序接口。

因此，ORGE中所有能够“看见”的部分都是完全独立于平台、3D接口和场景类型的。OGRE中没有对窗体类型的依赖，没有预先假定你将于创建的场景的类型。所有3D方面的概念都是基于核心的数学描述而不是某种特殊的应用程序接口。

当然有的地方OGRE必须处理底层的平台特性，接口和场景，但这都是针对这些环境设计的子类来完成。在抽象层次暴露的接口仍然是一致的。

例如，“Win32Window”类处理所有的在Win32平台上的渲染窗口的细节问题 —— 而程序的设计者只需要通过它的超类“Render”来使用它，这个超类在所有平台上都是相同的。类似的，虽然这里有像“BspSceneManager”这样的类针对室内场景进行优化，程序只需要向“SceneManager”类提供场景中对象的参数和渲染顺序就可以了。这意味着你在不必费力气学习各种接口的同时，结果也是优化了的。应用程序需要做的就是提一下它要创建什么样的场景，让OGRE选择适当的实现 —— 在后面的章节还会具体的介绍这些。

OGRE的面对对象的特性使得一切成为可能。通过插件使用不同的接口(目前包括Direct3D和OpenGL)，现在OGRE已经可以同时运行在Windows，Linux和Mac OSX上。在抽象层次上运用OGRE的程序，可以工作在所有OGRE提供了渲染子系统的环境中，不需要关心任何平台特性和特殊的程序接口。


文档:手册:1-4-0:2. 核心对象 - OGRE 3D 中文

文档:手册:1-4-0:2. 核心对象

介绍

该教程帮助你快速了解你在OGRE中用到的核心对象。

命名空间（Namespaces）

OGRE使用了C++中命名空间（Namespaces）的特性，你可以将类（Classes），枚举（Enums），结构（Structures）放在同一个命名空间（Namespaces）下，这样，可以防止命名混淆（就是将不同的类起了相同的名称的情况）。由于OGRE是在应用程序内部进行调用的，所以，在OGRE设计的时候，必须防止命名混淆（Name Clashes）情况的出现。在一些人看来，命名混淆不是一个大问题，他们不习惯使用命名空间（Namespaces），并且，有的编译器甚至不支持命名空间（Namespaces）这种特性。但是，我认为使用命名空间（Namespaces）是种更加正确的编程方式。所以，如果你使用的编译器不支持命名空间（Namespaces）这种特性的话，你最好选择一种支持它的编译器，毕竟，C++早已将命名空间（Namespaces）特性作为其标准的一部分了，编译器制作者们没有理由不在自己的编译器中实现该特性。使用了命名空间（Namespaces）意味着你在使用OGRE中定义的类、数据类型时，必须加上“Ogre::”的前缀，比如：“Ogre::Camera”，“Ogre::Vector3”等等，这样，可以避免命名混淆（Name Clashes）。如果你不想在每次调用它们之前先写前缀的话，你可以在程序开头加上“using namespace Ogre;”。如果你在程序开头已经加好了“using namespace Ogre;”，而你的程序中仍有与Ogre中定义重名的类或类别，那么，你必须在使用该类时加上“Ogre::”的前缀。

概览

下面的这张UML图表展现了OGRE中的核心对象以及它们之间是如何互相联系的，这张图表并没有描述所有的类，它只把几个关键的类彼此间是如何关联的作了一个大概的描述。

在这张图表的最顶部是根（Root）对象。这是你进入OGRE系统的“入口”，根（Root）对象用来创建OGRE系统中的所有的基础元素，比如：场景管理器（Scene Managers），绘制系统（Rendering Systems），绘制窗口（Render Windows）和插件加载器（Loading Plugins）。根（Root）对象是OGRE系统中一切的开始，它会提供给你实现具体功能的核心对象，根（Root）对象更像是OGRE系统中的一个组织者。OGRE的其余的类大致分为下列三种角色：

场景管理

场景管理描述了你的场景中有哪些内容，以及它们是如何组织在一起的。场景管理提供了与现实情况贴近的极其自然的接口供你调用，也就是说，你在调用这些接口时不会使用到“设置这几个对象的绘制状态，然后画三个多边形”这样的语言，而是“我想要把这几个事物放在这几个地方，它们的材质是这样的，我可以从这个场景中看到它们”这种贴近现实情况的语言。

资源管理

不管地形、纹理还是字体等一切对象，绘制它们都需要不同的资源。如何加载、重用、卸载这些资源是非常重要的，因此，有专门的一批类来完成这些事情。

渲染

最后，屏幕上的所有一切是如何被渲染出来的，这涉及到渲染管线、指定的渲染系统、被传送到管道的所有的缓存、渲染状态等API对象等底层对象。场景管理器子系统中的类将这所有的一切组织起来，提供了更加简单的高级别的接口以供调用。

你也许已经注意到了在图表的边缘上还有一些插件（Plugins）。OGRE在设计时就考虑了其扩展性，而使用插件则是一种最为常见的扩展方式。许多OGRE中的类能被继承及不断扩展，你可以自定义一个改变了场景的组织方式，添加了新的绘制系统应用（绘制系统应用指的是Direct3D、OpenGL）的场景管理器（SceneManager）的插件，或者提供加载资源的其它方式（比如从网络加载或从数据库加载）的插件。虽然插件只完成OGRE系统中某个方面的工作，但插件这种方式可以覆盖到系统的方方面面。从这个意义上来说，OGRE决不仅仅只是一个针对某类问题而提供的封闭型的解决方案，它在许多方面都可以方便地进行扩展，以满足你的需要。


文档:手册:1-4-0:2.1 Root 对象 - OGRE 3D 中文

文档:手册:1-4-0:2.1 Root 对象

根（Root）对象是OGRE系统的入口，该对象在程序一开始时创建，最后结束时销毁。在例子中，我将会证实这一点。

根（Root）对象帮助你配置系统，比如，通过showConfigDialog方法，OGRE会对绘制系统（Render System）的所有选项进行检测，并且提供一个对话框，供用户对这些选项（比如色彩深度（Colour Depth）、是否全屏显示）进行修改。系统会根据用户选项进行初始化。

根（Root）对象还可以帮助你获得系统中其它对象的指针，比如：场景管理器（SceneManager），绘制系统（RenderSystem），还有其它的资源管理器（Resource Managers）等等。

最后，如果你在连续绘制模式（Continuous Rendering Mode）下使用OGRE时，也就是说，你想尽可能地不断刷新所有需要绘制的对象时（这个场景常常运用于游戏（Games）或演示（Demos）中，而不是一般的窗口工具（Windowed Utilities）），根（Root）对象有一个方法叫做“startRendering”，调用该方法后，程序将不断地重绘直到所有的绘制窗口关闭为止，或者，你可以通过帧监听器（FrameListener）对象来告诉绘制窗口停止重绘（后面的章节会介绍帧监听器（FrameListener）对象）。


文档:手册:1-4-0:2.2 RenderSystem 对象 - OGRE 3D 中文

文档:手册:1-4-0:2.2 RenderSystem 对象

渲染系统（RenderSystem）对象事实上是一个抽象类，它定义了3D API的接口。它负责设置所有的渲染参数并且传送渲染指令给底层的API，该类是抽象类，因为其实现依赖于某个具体的渲染系统的API接口（比如Direct3D的D3DRenderSystem）。当系统经过Root::initialise初始化后，通过调用Root::getRenderSystem()方法，渲染系统（RenderSystem）对象产生了。

然而，一个通常意义上的应用程序不会直接操作渲染系统（RenderSystem）对象，你需要渲染的所有对象和场景设定都可以由场景管理器（SceneManager）、材质（Material）或其它面向场景的类（Scene-oriented Classes）来完成。只有当你想要创建多个渲染窗口（这里的多个渲染窗口，并非指的是借助类RenderWindow在同一个窗口下创建多个视口（Viewports），而是指的完全独立的多个窗口）或者想要访问其它高级特性时，你才需要直接访问渲染系统（RenderSystem）对象。

由于这个原因，我不会在后面的教程中讨论渲染系统（RenderSystem）对象，你可以认为场景管理器（SceneManager）会在适当的时候调用渲染系统（RenderSystem）对象。


文档:手册:1-4-0:2.3 SceneManager 对象 - OGRE 3D 中文

文档:手册:1-4-0:2.3 SceneManager 对象

除了根（Root）对象，从应用程序的视角来看，场景管理器（SceneManager）对象应该是OGRE系统中最重要的部分了，当然，它也是应用程序中最经常用到的对象。场景管理器（SceneManager）控制着由OGRE引擎绘制的场景中的所有内容，它还负责组织创建管理所有的摄像机（Cameras）、可移动的实体（Entities）、光线（Lights）和材质（Materials：对象的表面属性），并且管理场景中静态的部分，比如：整个场景地形。

当你想要为场景创建一个摄像机（Camera）或是在场景中添加或者删除一个光源（Light）时，你必须通过场景管理器（SceneManager）来实现。你没有必要在你的应用程序中维护这些对象的列表（Lists），场景管理器（SceneManager）管理着场景中所有的对象，你只需要通过这些对象的名称就可以在场景管理器（SceneManager）中获取该对象，你可以在主文档（Main Documetation）中找到getCamera，getLight，getEntity等方法。

当需要绘制场景时，场景管理器（SceneManager）会将场景送到绘制系统（RenderSystem）对象中去。你不必直接调用SceneManager::_renderScene方法，当一个绘制对象需要被重绘时，该方法会被自动调用。所以，你与场景管理器（SceneManager）的交互通常发生在场景设置（Scene Setup）时。你可能调用大量的方法（这些方法通常将存有场景数据的文件加载到你的应用程序中）设置你的场景。如果你创建了自己的帧监听器（FrameListener）对象，你还可以在程序运行的过程中动态修改场景中的内容。

因为不同的场景类型需要通过不同的算法决定哪些对象应该传到绘制系统（RenderSystem）对象中去，以获得最好的绘制效果，所以，场景管理器（SceneManager）根据不同的场景类型派生出多个子类，默认的场景管理器（SceneManager）对象可以绘制一个场景，但如果绘制的是较大的场景，默认的场景管理器（SceneManager）不能对该场景进行效率上的优化。不同场景需要应用相应的场景管理器（SceneManager）对其进行组织及优化。举个例子，BspSceneManager可以对大型的基二叉树空间分割(BSP：Binary Space Partition)树的室内级别（Indoor Levels）的场景进行优化。

使用OGRE的应用程序无需知道场景管理器有哪些具体的子类，应用程序只需要简单地调用Root::createSceneManager(..)方法，通过传入该方法中的参数（该参数表明了场景的类型，比如：ST_GENERIC,ST_INTERIOR等），OGRE会自动地选择对应于该场景类型的最好的场景管理器（SceneManager）的子类，如果没有找到能适用于该场景类型的子类， OGRE的开发者们可以在使用最基本的场景管理器（SceneManager）的基础上，添加新的场景优化算法以优化那些原本无法被优化的场景类型，与其同时，场景管理器（SceneManager）的上层应用无需更改任何代码。


文档:手册:1-4-0:2.4 ResourceGroupManager 对象 - OGRE 3D 中文

文档:手册:1-4-0:2.4 ResourceGroupManager 对象

资源组管理器（ResourceGroupManager）实际上是提供加载纹理（Textures）、网格（Meshes）等可重用资源的“集线器（Hub）”。使用它，你可以将你用到的资源进行分组，并且，这些资源可以根据你的需要加载或删除。资源组管理器（ResourceGroupManager）中包括了大量的资源管理器（ResourceManagers），每个资源管理器（ResourceManagers）分管某类资源，比如纹理管理器（TextureManager）、网格管理器（MeshManager）。这儿所谓的资源是指OGRE运行时需要加载的数据。

资源管理器（ResourceManager）能保证某类资源只被加载一次，它能较好地管理这些资源占用的内存，还可以在不同的位置搜寻需要的资源，搜寻的位置不仅包括文件路径（Paths），还包括压缩文件（ZIP文件）。

多数情况下，你不需要直接与资源管理器（Resource Managers）打交道，资源管理器（Resource Managers）能在OGRE系统需要其资源的情况下自动调用，比如，当你需要将某种纹理（Texture）加到某种材质（Material）上时，纹理管理器（TextureManager）会被自动调用。如果你愿意，你也可以自己调用相应的资源管理器（Resource Manager）预先加载你需要的资源（这样做可以防止发生磁盘读取延迟）。当然，在多数情况下，OGRE会在合适的时候自动加载这些资源。

你需要做的唯一的一件事就是告诉资源管理器（Resource Managers）到哪儿去找你想要加载的资源，你可以通过调用Root::getSingleton().addResourceLocation这个方法来实现这个功能，该方法能将位置信息传递给资源组管理器（ResourceGroupManager）。

由于在引擎中每类资源管理器（Resource Managers）只有一个实例，你可以通过下面的方法来获取这些资源管理器（Resource Managers）：

TextureManager::getSingleton().someMethod()
MeshManager::getSingleton().someMethod()


文档:手册:1-4-0:2.5 Mesh 对象 - OGRE 3D 中文

文档:手册:1-4-0:2.5 Mesh 对象

网格（Mesh）对象表示的是具体的模型，它自身包括了一整套用来描述自身模型的数据，在广域范围（World Scale）内，网格（Mesh）对象相对比较小，网格（Mesh）对象通常用来表示可以移动的对象，而非那些静态的诸如背景之类的对象。

网格（Mesh）对象也是一种资源，它由“MeshManager”这种资源管理器（Resource Manager）管理。网格（Mesh）对象的数据结构是OGRE自己定义的一种数据结构，这些结构通常被存放在后缀名为“.mesh”的文件中，网格（Mesh）文件通常由一种建模工具（Modelling Tool）导出生成（见4.1导出器（Exporters）），该文件可以被网格工具（见4.网格工具（Mesh Tools））编辑。

你可以通过调用MeshManager::createManual方法手动创建网格（Mesh）对象，通过这种方式，你可以定义自己需要的网格（Mesh）对象的数据结构，不过，这种创建方式已经超出了本用户手册的说明范围。

网格（Mesh）对象是可移动对象的基础，它被实体（2.6实体（Entities））所调用。

网格（Mesh）对象也可以运动（Animated），请参见8.1骨骼动画（Skeletal Animation）。


文档:手册:1-4-0:2.6 实体 - OGRE 3D 中文

文档:手册:1-4-0:2.6 实体

实体（Entity）是场景中可移动对象的实例，它可以是一辆车、一个人、一条狗等等，实体（Entity）在世界（World）场景中不一定非要一个固定的坐标位置。

实体（Entities）是以网格（Meshes）作为自身基础的，网格（Mesh）对象包括了一整套用来描述自身模型的数据，在广域范围（World Scale）内，网格（Mesh）对象相对比较小。多个实体（Entities）可以共用一种网格，比如，你常常会在一个场景下创建同一种对象的多个拷贝。

你可以通过调用SceneManager::createEntity方法创建一个实体（Entity），然后，给该实体（Entity）命名，并且将与其相关的网格（Mesh）对象关联起来（比如：“muscleboundhero.mesh”）。场景管理器（SceneManager）会通过“MeshManager”这种资源管理器（Resource Manager）为你加载该网格（Mesh），每类网格（Mesh）只会被加载一次。

只有当你将实体（Entities）与一个场景结点（SceneNode）关联起来后，该实体（Entities）才真正成为了场景中的一部分。通过关联不同的实体（Entities）到不同的场景结点（SceneNodes），你可以在实体（Entities）之间创建出复杂的位置及方向的继承关系。你可以通过修改场景结点（SceneNodes）的位置来改变与之关联的实体（Entity）的位置。

当网格（Mesh）被加载后，与该网格（Mesh）相关的材质（Materials）数据也会随之加载。一类网格（Mesh）可以包含多种材质（Material）数据，因为一个网格的不同部分可能采用了不同种的材质（Materials）。任何在网格（Mesh）基础上创建的实体，会自动采用该网格（Mesh）上所采用的默认的材质（Materials）。当然，你也可以为这些相同的实体分配不同的纹理（Textures）。

想要理解如何分配不同的纹理（Textures），你必须首先理解所有的网格（Mesh）对象实际上是由子网格对象（SubMesh）构成的，每个子网格对象（SubMesh）代表了网格（Mesh）对象的一部分，该部分只能使用一种材质（Meterial）。如果一个网格（Mesh）只采用了一种材质（Material），那么，它可能只包含了一个子网格（SubMesh）。

当基于网格（Mesh）创建出一个实体（Entity）时，该实体（Entity）可能由多个子实体（SubEntity）构建而成，子实体（SubEntity）与网格（Mesh）中的子网格（SubMesh）一一对应。你可以通过调用Entity::getSubEntity方法获得子实体（SubEntity）。一旦你得到子实体（SubEntity）的指针，你可以通过调用setMaterialName方法改变其材质（Material）。通过这种方法，你可以改变你所创建的实体（Entity）的默认材质（Materials），从而使你创建出来的实体（Entity）与众不同。


文档:手册:1-4-0:2.7 材质 - OGRE 3D 中文

文档:手册:1-4-0:2.7 材质

材质（Materials）是从来描述场景中的对象是如何被绘制出来的。它被用来指定对象的表面属性（比如：物体的反射光颜色、物体自身的光的颜色等等），不同的纹理层（Texture Layers）叠加在一起，可以表现出不同的应用效果,比如：应用拣选模式（Culling Mode）过滤材质（Textures）形成环境映射（Environment Mapping）等。

材质（Materials）也可以通过编程来进行设置，通过调用SceneManager::createMaterial可以创建出新的材质（Materials）。你也可以在程序运行时，通过脚本（Script）来加载材质（Materials）。你可以在章节3.1“材质脚本（Material Scripts）”中了解更多关于这方面的信息。

基本上来说，每一个在场景中可以看到的对象都会与材质（Material）类产生关联。

场景管理器（SceneManager）类管理着出现在场景中的所有材质（Materials）的链表（Master List）。如果应用程序调用SceneManager::createMaterial方法或者加载了新的网格（Mesh）对象，该链表（List）则立即加入新的材质（Materials）信息（加载网格（Mesh）时，其默认材质信息会被加入到该链表(List)中）。无论这些材质（Materials）何时被加入到场景管理器（SceneManager）中，这些材质（Materials）的属性会被OGRE自动设为默认值：

  • ambient reflectance = ColourValue::White (full)
  • diffuse reflectance = ColourValue::White (full)
  • specular reflectance = ColourValue::Black (none)
  • emmissive = ColourValue::Black (none)
  • shininess = 0 (not shiny)
  • No texture layers (& hence no textures)
  • SourceBlendFactor = SBF_ONE, DestBlendFactor = SBF_ZERO (opaque)
  • Depth buffer checking on
  • Depth buffer writing on
  • Depth buffer comparison function = CMPF_LESS_EQUAL
  • Culling mode = CULL_CLOCKWISE
  • Ambient lighting in scene = ColourValue(0.5, 0.5, 0.5) (mid-grey)
  • Dynamic lighting enabled
  • Gourad shading mode
  • Solid polygon mode
  • Bilinear texture filtering

你能通过调用SceneManager::getDefaultMaterialSettings方法改变这些默认设置。由于网格（Mesh）对象通常在加载时设置它的默认材质（Materials），如果某个实体（Entities）与该网格（Mesh）对象相关联，那么它同时也会自动与网格（Mesh）对象上的材质（Materials）关联在一起。你也可以通过参照章节2.6（实体（Entities））的相关内容来定制这些材质（Materials），只要创建一种你所需要的材质（Materials）（你也可以通过程序加载现有的材质（Materials）数据到你的应用程序中），通过子实体（SubEntity）的SubEntity::setMaterialName方法加载它就可以实现定制材质（Materials）的功能了。


文档:手册:1-4-0:2.8 层（Overlays） - OGRE 3D 中文

文档:手册:1-4-0:2.8 层（Overlays）

From OGRE 3D 中文

层（Overlays）允许你在一般的场景内容上绘制2D或3D元素，例如：提示信息（heads-up displays（HUDs））、菜单系统、状态栏等。OGRE系统中的帧状态栏（Frame Rate Statistics Panel）就是层（Overlays）的一个例子。层（Overlays）可以是2D元素或者3D元素。2D元素通常在提示信息（HUDs）中使用，3D元素则用在类似于驾驶员座舱，作为场景顶部元素（On Top Of The Rest Of The Scene）的3D对象上。

你可以通过调用SceneManager::createOverlay方法创建层（Overlays），或者你也可以通过创建一段“.overlay”脚本来定义层（Overlays）。事实上，后面一种方式比较常用（因为修改脚本后无需重新编译代码）。注意：你可以按你的需要定义尽可能多的层（Overlays），它们一开始都是不显示的，除非你调用了“show()”方法。你还可以同时显示多个层（Overlays），它们之间的遮挡关系可以通过调用Overlay::setZOrder()方法调整它们的Z的大小来实现。

创建2D元素

OverlayElement类是添加到层（Overlays）的2D元素的抽象。所以通过该类继承得到的类的对象都可以添加到层（Overlays）中去。OGRE系统鼓励用户通过定义OverlayElement类的子类来提供他们自己的界面控件。层元素（OverlayElements）的关键属性包括尺寸、位置、材质（Material）名称等属性。OverlayElement类的子类则扩展了更多复杂的属性和行为。

OverlayElement类的一个非常重要的子类是OverlayContainer类。OverlayContainer类除了能够包含其它的层元素（OverlayElements）之外，其它的特性都和OverlayElement类一样。OverlayContainer类还为它所包含的层元素（OverlayElements）提供了本地坐标（Local Coordinate），以方便它们能很容易地摆放在一起。

还有一个很重要的类是OverlayManager类，不管应用程序什么时候想创建一个加在层上（或者容器内）的2D元素，都可以通过调用OverlayManager::createOverlayElement方法来实现。你想创建的元素的类型是由一个字符串来进行标识的，原因是你可以在OverlayManager中注册你自定义的层元素（OverlayElement）类型。举例来说，如果你想要创建一个面板（一个可以容纳其它层元素（OverlayElements）的四边形），你可以调用OverlayManager::getSingleton().createOverlayElement(“Panel”, “myNewPanel”)。

在层（Overlays）中加入2D元素

在层（Overlays）中可以直接添加的元素只有层容器（OverlayContainers）。原因是每个级别的容器都为自己容器中的元素建立了Zorder，所以，如果你将几个容器放在同一个层中时，容器中元素可以先根据其Zorder，再根据容器的摆放关系正常显示。想在一个层（Overlays）中添加一个容器（比如面板），调用Overlay::add2D方法即可。

如果你想在容器中添加子元素，调用OverlayContainer::addChild方法即可。子元素可以是层元素（OverlayElements），也可以是层容器（OverlayContainer）。记住，子元素的坐标位置是根据他们的父容器的左上角来进行定位的。

关于2D坐标

OGRE系统允许你通过绝对坐标（pixel）或者相对坐标(relative)的方式来对元素进行定位。

绝对坐标方式（Pixel Mode）

当你想给你的层元素指定精确的尺寸大小时，这种方式非常有用。不管屏幕上的其它元素大小如何变化，通过这种方式指定尺寸的层元素的大小永远不发生改变。在这种方式下，你想把某个元素放在屏幕的右边或者底部都要通过像素计算得出，而如果采用相对坐标方式（Relative Mode）则简单得多。不过，这种方式相对比较简单，屏幕左上角的坐标为(0,0)，右下角的坐标则由你的屏幕设置（640*480,800*600,1024*768等等）所决定。再提醒一次，如果你要将一个元素定位到屏幕的中间或者底部时，最好采用相对坐标方式（Relative Mode）。

相对坐标方式（Relative Mode）

如果你想要你所创建的元素与你的屏幕设置尺寸保持固定比例的话，你应该使用这种方式。在相对坐标方式（Relative Mode）中，屏幕左上角的坐标为（0,0），右下角坐标为(1,1)。所以，如果你将一个元素放在(0.5,0.5)，则它正好放在屏幕的正中央。这个规则对设置尺寸也同样有效。如果你将一个元素的宽度设为0.5，则它的宽度正好是屏幕的一半。请注意，由于屏幕的长宽比一般为1.3333:1，所以一个元素如果被设为(0.25,0.25)，则该元素不可能是正方形的。但它的大小正好是整个屏幕大小的1/16。如果你想将一个元素的形状设为正方形，你可以将其尺寸设为（0.1875,0.25）。

层（Overlays）的转换

层（Overlays）的另一个特性是可以旋转，滚动（Scroll），按比例缩放。你可以将这些特性用于菜单系统，可以实现菜单系统的缩放、拖拽或是其它效果。请参见Overlay::scroll,Overlay::rotate和Overlay::scale方法。

层（Overlays）的脚本编写

层（Overlays）也可以由脚本来定义，请参见3.4层脚本（Overlay Scripts）。

GUI系统

层（Overlays）只用于不发生交互的屏幕用户，如果你需要更加复杂的GUI解决方案，我们推荐CEGui（http://www.cegui.org.hk/ ）。你可以在Demo_Gui例子中看到关于它的演示。


文档:手册:1-4-0:3. 脚本 - OGRE 3D 中文

文档:手册:1-4-0:3. 脚本

3. 脚本

为了使创建更加容易，OGRE令他的许多特性都通过脚本驱动。脚本都是简单的文本文件，他们可以用任何标准文本编辑器编辑，修改他们可以立即作用于你的程序，而不需重新编译。这会使原型开发速度快很多。下面是几项OGRE提供的脚本：

  • 3.1 材质脚本
  • 3.2 合成器（Compositor）脚本
  • 3.3 粒子脚本
  • 3.4 表层（Overlay）脚本
  • 3.5 字体定义脚本


文档:手册:1-4-0:3.1 材质脚本 - OGRE 3D 中文

文档:手册:1-4-0:3.1 材质脚本

3.1 材质脚本

材质脚本提供了一种在脚本中定义复杂材质的能力，且这些材质可以轻松地重复使用。其实，你原本可以在你的代码里利用材质类和纹理层类的相关方法为一个场景创建所有材质，然而，事实上，这样处理起来是有点儿困难的。因此，将材质的定义存储在文本文件里按需装载是比较好的替代方法。

装载脚本
当资源组初始化完毕时，材质脚本才被装载：OGRE在所有与组相关的资源位置查找带有'.material'扩展名的文件，并且对他们进行语法解析。如果你想手工解析，那么使用MaterialSerializer::parseScript。
重点是要知道分析过程并没有完全装载全部材质：只是定义部分被装载，纹理和其他资源没有装载。这是由于拥有一个庞大的材质库是很正常的事，然而在任何一个场景内用到的仅仅是其中相对较小的一个子集。要是每一个脚本都如数装载全体材质，就会造成不必要的内存浪费。你可以通过标准方法访问一个延期装载的材质（MaterialManager::getSingleton（）.getByName（）），但是在你尝试使用它之前，你必须先调用'load'方法。当你使用实体等的标准材质赋值方法时，OGRE自动为你完成了这些工作。
另一个重要的问题是，材质名在系统装载的所有脚本中必须是唯一的，因为OGRE总是通过材质的名字来识别各个材质的。
格式
若干个材质可以定义在一个材质脚本里。脚本的格式有些类似C++，以花括号（'{'，'}'）分隔各个部分，注释由双斜线'//'放在一行的开始表示（注意，注释不可以嵌套）。一般格式如下例所示（注意，我们只考虑不使用顶点和片断编程的有确定功能的材质，这些在后面会涉及）：
// 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
   }
}
脚本里的每一个材质都要给一个名字，就是左花括号'{'前面的'material 什么什么'的那行。这个名字在整个系统中应该是唯一的。它可以包含路径名（就像例子里写得那样）以便逻辑上区分你的材质，但是也还要尽量避免命名重复，因为OGRE引擎并不把它认作是结构，而是只把它当作一个字符串对待。
注意：'：'是表示脚本里材质复制的分隔符，所以不能用作材质名的一部分。
一个材质可以通过在它的材质名后面使用冒号：后跟要复制的所涉及的材质名，从而复制以前定义过的材质。如果被复制的材质没有找到，那么它会被忽略。（详见3.1.11 材质拷贝部分）
一个材质可以由多个技术组成（详见3.1.1 技术（Techniques）部分）——一个技术就是一种达成你所要的效果的方法。你可以提供不止一种技术，以便在显示卡无法渲染前面的技术时，还有补救措施；或者在物体在较远距离时为了保存渲染能力你希望定义较低的细节层次时，有相应的技术可供使用。
每个技术可由多个渲染通路组成（详见3.1.2 渲染通路（Pass）部分），那是一个物体的一次完整渲染，从而能够以不同的设定、多次使用、来制造各种混合效果。如果你定义的渲染通路使用了多于当前运行的显示卡所能提供的纹理单元，OGRE也可以在运行时将你定义的渲染通路分割成多个渲染通路（注意，这只有在你未使用片断编程时有效）。每个渲染通路有许多的顶层属性，诸如'ambient'是设置材质反射的环境光的数量和颜色的。如果你使用了顶点编程，那么某些选项则不能应用，详细情形请参阅3.1.2 渲染通路（Pass）部分。
在每个渲染通路内部，可能没有使用纹理单元，也可能使用多个（详见3.1.3 纹理单元部分）。这些定义了要被使用的纹理，且可选一些混合操作（使用多重纹理）和纹理效果。
你也可以在渲染通路中使用所给的一系列参数引用顶点和片断程序（如果要用术语的话，或者应该叫做顶点和像素渲染）。这些程序单独在.program脚本中声明（详见3.1.4 顶点程序与片断程序的声明），使用如3.1.9 在渲染通路中使用顶点程序和片断程序所述。
顶层材质属性
虽然，一个材质定义的最外层并没有多少它自己的属性，大多数可配置的参数都在内部，但是，确实还是有几个属性需要我们知道，它们是：
lod_distances
这个属性控制着在不同距离上由哪个技术参与形成效果的距离。3.1.1 技术（Techniques）部分有对于这个选项的全面讨论。
receive_shadows
这个属性控制着使用这种材质的物体上是否可以有阴影。
格式: receive_shadows <on|off>
默认: on
一个物体是否可以接收到阴影是由多种因素复合决定的，细节详见7. 阴影。注意透明物体从来不接收阴影，所以这个选项支队不透明的固体实心物体有效。
transparency_casts_shadows
这个属性控制着透明物体是否可以生成特定种类的阴影。
格式: transparency_casts_shadows <on|off>
默认: off
一个物体是否能够产生阴影，也是有多种因素复合决定的，细节详见7. 阴影。例如，当使用纹理阴影时，透明材质一般是不渲染阴影的，因为它们不阻挡光线。而使用这个标记就重载了这一属性。
set_texture_alias
这个属性将一个纹理别名关联到一个纹理名上。
格式: set_texture_alias <纹理别名> <纹理名>
这个属性设置从其他材质复制过来的，在纹理单元状态里使用的纹理。（详见3.1.11 材质拷贝部分）


文档:手册:1-4-0:3.1.1 技术（Techniques） - OGRE 3D 中文

文档:手册:1-4-0:3.1.1 技术（Techniques）

From OGRE 3D 中文

3.1.1 技术

在你的材质脚本中，一个“技术”就是一个单独的渲染物体的方法。最简单的材质定义只包含一个技术，然而由于计算机的处理能力千差万别，除非你确定运行你的程序的所有显示卡都能运行你的这个技术，否则最好不要只写一个技术。此外，如果你想使用材质细节层次技术渲染材质，例如距离越远的物体使用越简单越低表现效果的技术，这可能是比较简单的定义方法。

当一个材质首次被使用时，它就被“编译”了。这包括扫描其中包含的技术定义，并且标记出其中哪些技术是当前渲染API和显示卡所支持的。如果所有技术都不支持，那么你的这些材质会被当作空白渲染。编译证明了如下几件事：

  • 每个渲染通路中的纹理单元入口数
需要注意的是，如果脚本中的纹理单元入口数超过当前显示卡的纹理单元数，只要没有使用片断程序，技术仍可被支持。在这种情况下，OGRE会将含有过多纹理单元入口的哪一个渲染通路分割成多个较小些的渲染通路，使得分割后的渲染通路中的纹理单元入口数不超过当前显示卡的纹理单元数，同时，多重纹理混合也相应地变成多重渲染通路混合（详见colour_op_multipass_fallback部分）
  • 无论是顶点程序还是片断程序，只要使用就要指明其语法规则（例如：vs_1_1, ps_2_x, arbfp1 等等）
  • 其他诸如立方体映射贴图以及dot3混合等效果。

在一个材质脚本中，技术的排列要有一定的先后顺序，例如，排在前面的技术比排在后面的技术有更高的优先级。一般来说，你要把最高级最需要的技术放在脚本的前面，然后将其他的备用的技术按照顺序依次放在后面。

为了帮助我们清晰的辨识每一个使用到的技术，你选择可以给技术取个名字，当然你也可以选择不取名。但是，脚本中没有名字的技术会以该技术的索引号为名。例如：材质中第一个技术的索引号为0，如果它没有名字的话，那么它的名字就是“0”。技术名在脚本中应当是唯一的，否则最终的技术会得到所有同名技术融合后的结果。如果发生这种情况，一条警告消息会发给Ogre.log。当复制材料和修改已存在的技术时，如果给技术取了名字，会很有帮助：（详见3.1.11 材质拷贝）

格式：Format: technique 技术名

技术只有为数不多的几个属于它们自己的属性：它们所属的“方案”（详见下面 scheme 部分），该方案的细节层次索引（详见下面 lod_index 部分）。另外还有一个材质属性，叫做 lod_distances，它不是技术属性，然而却与 lod_index 有直接关系，所以为方便起见也把它列在这里。

scheme

设置技术所属的“方案”。材质方案被用来控制从一套技术到另一套技术的顶层转换。例如，你也许会使用这个属性定义材质的“高”、“中”、“低”复杂度水平，使得用户在权衡过后，可以挑选出显示效果与显示质量的适当比率。另一个可能的情况是，你可以针对顶级机器采用高动态范围全开的管线，而对于其他机器选用较简单的管线；这种问题就能够用“方案”来实现。活动方案被控制在视口层，且默认的活动方案是“Default”。

格式: scheme <方案名>
示例: scheme hdr
默认: scheme Default

lod_index

设置该技术所属的细节层次索引。

格式: lod_index <数字>
数字的合法数值范围是 0（最高细节层次）到 65535，尽管这是不可能的。在技术之间的细节层次索引中不能留空当。也就是说，细节层次索引要按顺序排列，例如：0，1，2，3，……；而不能出现：0，10，20，30，……，这样的情况。
示例: lod_index 1

每个技术都必须对应属于一个细节层次索引，默认它们都属于索引0，即最高等级的细节层次。增加索引的数值意味着降低细节层次。你可以给不止一个技术赋值相同的细节层次索引，这就是说OGRE会自动从中挑选最好的技术。为了方便阅读，建议你先按照细节层次顺序，然后再按照优先级顺序，排列你的技术，尽管按照优先级排列是唯一必要条件（OGRE按照排列的前后顺序决定哪一个是“最好的”）。你必须在lod_index 0层上至少有一个技术。

在一个细节层次水平上所应用的距离是靠包含在材质里的lod_distances属性决定的。细节详见下面lod_distances部分。

默认: lod_index 0

lod_distances

注意：这一属性必须在材质部分之外指定（例如，所有技术的父层次），而在这里进行介绍是因为它与这部分关系最密切。

在设置这个属性前，你先要指定你想要这个材质基于距离镜头的远近距离决定它使用的技术。你必须给定一个升序的距离表，其中每一项指定了材质将要转换到下一个细节层次的距离。暗含的意思就是，如果小于距离表中最小值，则所有材质在细节层次0上都会显示。你必须保证每个细节层次上至少有一个技术（所以，如果你指定了三个距离，你就必须有技术1、技术2和技术3）。注意你必须总是保证在lod_index 0上至少有一个技术。

格式: lod_distances <distance_1> [<distance_2> ... <distance_n>]
示例: lod_distances 300.0 600.5 1200

距离在300单位以下时，上例会令材质选用lod_index 0中最好的技术；距离在300到600之间时，会选用lod_index 1中最好的技术；距离在600到1200之间时，选用lod_index 2中最好的技术；距离在1200以上时，选用lod_index 3中最好的技术。

技术也包括一个或一个以上渲染通路（且必须至少有一个），详见3.1.2 渲染通路（Pass）部分。


文档:手册:1-4-0:3.1.2 渲染通路（Pass） - OGRE 3D 中文

文档:手册:1-4-0:3.1.2 渲染通路（Pass）

From OGRE 3D 中文

3.1.2 渲染通路（Pass）

一个渲染通路就是几何问题里的一次渲染；一个带有一整套渲染属性的渲染API的一次调用。一个技术可以包含有1到16个渲染通路，当然，渲染通路用得越多，技术在渲染的时候开销越大。

为了清楚识别使用的到底是哪个渲染通路，渲染通路常常被起个名字，当然，也可以不起，名字并不是必需的。脚本中没有名字的渲染通路将会以渲染通路索引号为名。例如：在一个技术里，第一个渲染通路索引号是index 0，所以，如果脚本中没有对它命名，那么它的名字就是“0”。一个技术中的渲染通路的名字必须是唯一的，否则，最后一个渲染通路的结果就会是所有相同名字的渲染通路的效果的融合。如果发生这种事，一个警告消息就会发到Ogre.log中。而且，命名渲染通路还有助于复制材质和修改已经存在的渲染通路：（详见3.1.11 材质拷贝部分）

渲染通路有一套全局属性（如下所述），0或多个纹理单元入口，：（详见3.1.3 纹理单元部分），以及可选的对于顶点程序或片断程序的引用（详见3.1.9 在渲染通路中使用顶点程序和片断程序部分）。

下面介绍在.material脚本中“渲染通路”部分能够使用的一些属性：

  • ambient
  • diffuse
  • specular
  • emissive
  • scene_blend
  • depth_check
  • depth_write
  • depth_func
  • depth_bias
  • alpha_rejection
  • cull_hardware
  • cull_software
  • lighting
  • shading
  • polygon_mode
  • fog_override
  • colour_write
  • max_lights
  • start_light
  • iteration
  • point_size
  • point_sprites
  • point_size_attenuation
  • point_size_min
  • point_size_max

属性详解

ambient

设置此渲染通路中周围环境的反射系数。当asm，CG，HLSL（High Level Shader Language高级渲染语言）使用时，该属性无效。与GLSL（）一起使用时，渲染器可以读OpenGL材质状态。

格式: ambient (<red> <green> <blue> [<alpha>]| vertexcolour)
数值的取值范围在0.0到1.0之间。
示例: ambient 0.0 0.8 0.0

渲染通路的基本颜色取决于各顶点红色，绿色和蓝色光的反射量。此属性决定了反射多少环境光（无目标的全局光）。也可以如在网格中定义的一样，通过使用关键字vertexcolour而不是使用颜色值，使环境反射系数跟踪顶点颜色。默认值是全白的，意思就是物体整个完全被照亮。如果你想要看见散射和镜面反射的效果，就要减少这个属性的相关数值，或者改变颜色的混合，使物体有一个不是白色的基础色。如果使用了'lighting off'属性将动态光照被关闭了或者任何纹理层有'colour_op replace'属性，那么“ambient”这个属性无效。

默认: ambient 1.0 1.0 1.0 1.0

diffuse

设置此渲染通路中漫反射系数。当asm，CG，HLSL（High Level Shader Language，高级渲染语言）使用时，该属性无效。与GLSL（OpenGL's Shader Language，OpenGL的渲染语言）一起使用时，渲染器可以读OpenGL材质状态。

格式: diffuse (<red> <green> <blue> [<alpha>]| vertexcolour)
数值的取值范围在0.0到1.0之间。
示例: diffuse 1.0 0.5 0.5

渲染通路的基本颜色取决于各顶点红色，绿色和蓝色光的反射量。此属性决定了反射多少四散光（来自场景中光照类实例的光）。也可以像在网格里一样定义，用vertexcolour关键字而不是用颜色值，令四散反射系数追踪顶点颜色。默认值是全白，意思就是物体反射所能接收到的所有白光。如果使用了'lighting off'属性将动态光照被关闭了或者任何纹理层有'colour_op replace'属性，那么“ambient”这个属性无效。

Default: diffuse 1.0 1.0 1.0 1.0

specular

设置此渲染通路中镜面反射颜色的反射系数。当asm，CG，HLSL（High Level Shader Language，高级渲染语言）使用时，该属性无效。与GLSL（OpenGL's Shader Language，OpenGL的渲染语言）一起使用时，渲染器可以读OpenGL材质状态。

格式: specular (<red> <green> <blue> [<alpha>]| vertexcolour) <shininess>
数值的取值范围在0.0到1.0之间。闪耀值（shininess）可以是任意比0大的值。
示例: specular 1.0 1.0 1.0 12.5

渲染通路的基本颜色取决于各顶点红色，绿色和蓝色光的反射量。此属性决定了反射多少镜面光（来自场景中光照类实例的高光）。也可以像在网格里一样定义，用vertexcolour关键字而不是用颜色值，令镜面反射系数追踪顶点颜色。默认值没有镜面反光。镜面反射的这种高光取决于颜色参数，闪耀值的设置大小。闪耀值设置得越高，高光就越耀眼。闪耀值在0.0到1.0之间时，使用要小心，因为这会引起高光颜色会被应用到有使用这种高光属性材质的整个平面。这样的话，当对该平面的视角发生改变的时候，会发生特别恶心的闪烁。闪耀值在1到128之间时，在DirectX和OpenGL渲染器上都表现良好。如果使用了'lighting off'属性将动态光照被关闭了或者任何纹理层有'colour_op replace'属性，那么“ambient”这个属性无效。

默认: specular 0.0 0.0 0.0 0.0 0.0

emissive

设置一个物体自发光的量。当asm，CG，HLSL（High Level Shader Language，高级渲染语言）使用时，该属性无效。与GLSL（OpenGL's Shader Language，OpenGL的渲染语言）一起使用时，渲染器可以读OpenGL材质状态。

格式: emissive (<red> <green> <blue> [<alpha>]| vertexcolour)
数值的取值范围在0.0到1.0之间。
示例: emissive 1.0 0.0 0.0

如果一个物体是自发光的，那么它就不需要外界的光去照亮它，无论是环境光还是其它的光，就好像有自己的环境光一样。然而，其实这个属性并不像名字所暗示的那样，这个物体对场景中的其他物体来说并不是一个光源（如果你想让它成为一个光源，你需要创建一个光源然后将光源放在这个物体的中心上）。也可以像在网格里一样定义，用vertexcolour关键字而不是用颜色值，令这样放射出来的颜色追踪顶点颜色。如果使用了'lighting off'属性将动态光照被关闭了或者任何纹理层有'colour_op replace'属性，那么“ambient”这个属性无效。

默认: emissive 0.0 0.0 0.0 0.0

scene_blend

设置此渲染通路与场景中现有的内容混合的方式。纹理单元入口所见的那个纹理混合操作被看作是纹理层之间的混合，而这个混合是将此渲染通路的输出结果与当前渲染目标的内容相结合。所以，这种混合就允许物体透明和其他特殊效果。有两种形式可供选择使用：一是使用预定义混合形式；二是使用自定义的办法，源因数和目标因数都有你自己DIY。

格式1: scene_blend <add|modulate|alpha_blend|colour_blend>
示例: scene_blend add

这是一个比较简单的形式，常用的混合形式由一个参数枚举出来，可用的混合形式参数如下：

  • add
渲染输出的颜色被叠加到场景中，用在爆炸、闪光、闪电、鬼魂等地方效果很好。相当于“scene_blend one one”
  • modulate
另一种将渲染输出加到场景内容中，一般用于给场景着色和加深场景颜色。对于浓烟弥漫的玻璃，半透明的物体等，有很好的使用效果。相当于“scene_blend dest_colour zero”。
  • colour_blend
基于输入文件的亮度给场景着色，但是并不加深颜色。相当于“scene_blend src_colour one_minus_src_colour”。
  • alpha_blend
渲染输出的alpha值被用作遮罩。相当于“scene_blend src_alpha one_minus_src_alpha”
格式2: scene_blend <src_factor> <dest_factor>
示例: scene_blend one one_minus_dest_alpha

这种格式允许你通过设置源和目标因数，从而完全控制混合操作。最终被写入渲染目标的颜色结果是(texture * sourceFactor) + (scene_pixel * destFactor)。两个参数的可选值如下：

one
常数值1.0
zero
常数值0.0
dest_colour
已存在的像素颜色
src_colour
纹理像素颜色
one_minus_dest_colour
1 -（dest_colour）
one_minus_src_colour
1 -（src_colour）
dest_alpha
已存在的像素alpha值
src_alpha
纹理像素alpha值
one_minus_dest_alpha
1 -（dest_alpha）
one_minus_src_alpha
1 -（src_alpha）
默认: scene_blend one zero （这句意为不透明的）

depth_check

设置此渲染通路的深度缓冲检测的状态是打开状态还是关闭状态。

格式: depth_check <on|off>

如果深度缓冲检测处于打开状态，则无论何时一个像素要想写入画面缓冲，深度缓冲检测就检查这个像素是否比在那一点的其它像素都要靠前。如果不是，那么这个像素就不写入。如果深度缓冲检测关闭了，则无论之前渲染的结果，一律写入这个像素。更高级的配置还可参看depth_func

默认: depth_check on

depth_write

设置此渲染通路的深度缓冲写入的状态是打开状态还是关闭状态。

格式: depth_write <on|off>

如果深度缓冲写入处于打开状态，无论何时一个像素想要写入画面缓冲，深度缓冲都会更新那个像素的深度值，因此，如果将来的像素在这个像素的后面，就会影响将来的渲染操作。如果这一属性被关闭了，那么像素就不会更新深度缓冲。一般来说，这一属性是打开的，但是，当你渲染静态背景或者位于场景后部的一系列透明物体以便它们能够彼此正确地重叠时，也可以关闭。

默认: depth_write on

depth_func

当深度检测打开时，设置用于比较深度值的函数。

格式: depth_func <func>

如果深度检测处于打开状态（参看depth_check），那么将要写入的像素的深度值与缓冲区中现有内容的深度值会发生比较。一般来说，这种比较是小于等于，例如：将要写入的像素比现有内容距离我们更近（或相等）。可能的函数如下：

always_fail
永远不向渲染目标写入像素
always_pass
总是将像素写入渲染目标
less
如果将要写入的像素的深度小于现在缓冲区内容的深度，则写入
less_equal
如果将要写入的像素的深度小于等于现在缓冲区内容的深度，则写入
equal
如果将要写入的像素的深度等于现在缓冲区内容的深度，则写入
not_equal
如果将要写入的像素的深度不等于现在缓冲区内容的深度，则写入
greater_equal
如果将要写入的像素的深度大于等于现在缓冲区内容的深度，则写入
greater
如果将要写入的像素的深度大于现在缓冲区内容的深度，则写入
默认: depth_func less_equal

depth_bias

设置此渲染通路的深度值的偏向。可用于使共面的多边形中的一个位于其它之上。例如：印制花纹图案。

格式: depth_bias <constant_bias> [<slopescale_bias>]

深度偏向值最终由偏向常数（constant_bias）*最小可观察的深度（minObservableDepth）+最大坡度（maxSlope）*坡度偏向（slopescale_bias）共同决定。坡度偏向与多边形到镜头的角度有关，形成相应的偏向值，但是在一些时间比较早的硬件上，这被忽略了。偏向常数是形成最小深度值的一个因素，所以1的价值就在于一点一点地缓慢地推进深度。

alpha_rejection

设置此项，可以使用alpha作为一个阀值，令渲染通路拒绝来自管线的像素。

格式: alpha_rejection <function> <value>
示例: alpha_rejection greater_equal 128

如上例所示，拒绝所有来自管线的alpha值大于等于128的像素。 function参数可以选择在depth_function属性的参数列表中所列的参数。value参数理论上可以是0到255之间的任意数，但是考虑到硬件兼容性，最好限制在0到128之间。

默认: alpha_rejection always_pass

cull_hardware

设置此渲染通路的硬件裁剪模式。

格式: cull_hardware <clockwise|anticlockwise|none>

硬件渲染引擎裁剪三角形的典型方法是基于三角形顶点的环绕顺序。顶点环绕顺序又与渲染操作中顶点传送和编号的方向有关，从镜头中看到的有可能是顺时针的也可能是逆时针的。如果选择了'cull_hardware clockwise'设置，则所有从镜头看顺时针顺序的三角形被硬件剪裁掉。显然，'anticlockwise'设置裁剪掉逆时针顺序的三角形。'none'设置关闭硬件裁剪，即所有三角形都渲染（用于渲染双侧道路）。

默认: cull_hardware clockwise

默认值与OpenGL的默认值相同，与Direct3D的默认值相反（因为OGRE与OpenGL一样使用右手坐标系）。

cull_software

设置此渲染通路的软件裁剪模式。

格式: cull_software <back|front|none>

在某些情形下，引擎也会在将几何体送往硬件渲染前进行软件裁剪。此设置仅在场景管理器使用它时起效（因为最好用在大量平面的世界几何体，而不是移动的几何体，因为用于移动的物体上代价会很大），但是如果在送入硬件之前可以有效裁剪的话还是可以使用的。在这种情况下，裁剪就要基于面向镜头的是三角形的背面还是正面——这个定义是基于面法向的（即：垂直于多边形平面且标示出正面方向的向量）。因为OGRE期望平面的逆时针方向为正向，所以软件裁剪'cull_software back'相当于硬件裁剪'cull_hardware clockwise'设置，也是为什么这两个作为默认设置的原因。虽然反映裁剪方式的命名是不同的，但是由于多数时候面法向都是预先计算好的且不一定是OGRE期望的方式，因此如果你有使用你自定义的面法向的场景管理器，也可以设置'cull_hardware none'然后完全基于你的面法向进行软件裁剪。

默认: cull_software back

lighting

设置动态光照是处于打开状态还是关闭状态。如果光照被关闭，那么所有使用此渲染通路的物体将被完全照亮。如果使用了顶点程序，则此属性无效。

格式: lighting <on|off>

关闭动态光照会使得任何环境光、漫反射光、镜面反射光、放射光和阴影属性都成为了多余的。当打开光照时，物体按照顶点的法向被照亮。

默认: lighting on

shading

设置此渲染通路中为表现动态光照而使用的各种阴影形式。

格式: shading <flat|gouraud|phong>

当动态光照打开时，效果就在每个顶点处生成颜色值。这些值是否全平面插入（如何插入）就依赖于这个属性设置。

flat
无插值参与。每个平面的阴影由平面上第一个顶点的颜色决定。
gouraud
平面上每个顶点的颜色采用线性插入。
phong
在全平面上插入顶点法线向量，被用于决定每个像素的颜色。能够得到更加自然的光照效果，但是代价也相应更高，在高级应用中表现更好。并不是所有硬件都支持此属性。
默认: shading gouraud

polygon_mode

设置多边形应该如何被栅格化。例如：它们应该是被填充后画出来，还是作为点（只有顶点）、线（只有外边框）画出来。

格式: polygon_mode <solid|wireframe|points>
solid
一般情况——填充多边形
wireframe
多边形只画外边框
points
只画每个多边形的点
默认: polygon_mode solid

fog_override

这个属性告诉渲染通路是否撤销场景的雾设置，而强制执行此渲染通路它自己的设置。当场景中其他的物体被雾遮挡，而你不想让雾影响某些物体时非常有用。当然反之亦然。注意这只影响固定功能雾——原来的场景雾参数仍然被送入渲染器，使用fog_params参数绑定（这就允许你关闭固定功能雾，转而在渲染器中计算；如果你想关闭阴影雾，你可以通过阴影参数关闭它。）

格式: fog_override <override?> [<type> <colour> <density> <start> <end>]
默认: fog_override false

如果你指定第一个参数为真，并给出了其余参数，就表明你要告诉渲染通路如果在使用这些雾设置和使用场景设置之间选择的话，优先选择使用这些雾设置。如果你指定第一个参数为真，但没给出其余参数，就表明你要告诉渲染通路不使用任何雾设置，无论场景如何设置。以下是参数的解释：

type
none = 没有雾，相当于使用'fog_override true'。
linear = 线性雾，从 <start> 开始到 <end> 结束的这一段距离有雾。
exp = 雾以几何方式增加（fog = 1/e^（distance * density））, 使用浓度 <density> 参数控制。
exp2 = 雾以几何的二次方增加，更加快速（fog = 1/e^（distance * density）^2），使用浓度 <density> 参数控制。
colour
3个0到1之间的符点数组成的序列，表示红色、绿色、蓝色的亮度。
density
用于'exp'或者'exp2'雾类型的浓度参数。虽不用于线性模式，但是也必须写上，作为占位符。
start
线性雾距离镜头的开始距离。在其它模式下，尽管不用这个参数，也必须写上，作为占位符。
end
线性雾距离镜头的结束距离。在其它模式下，尽管不用这个参数，也必须写上，作为占位符。
示例: fog_override true exp 1 1 1 0.002 100 10000

colour_write

设置此渲染通路的颜色写入是打开还是关闭的。

格式: colour_write <on|off>

如果颜色写入被关闭，那么此渲染通路中没有可见像素写入屏幕。你也许认为这没什么用，但是如果你关闭颜色写入并且合理利用其他一些小的渲染设置，你可以使用这个渲染通路在执行后续的填充颜色数据的渲染通路之前初始化深度缓冲区。这样可以极大地提升效果，尤其是当你使用复杂的片断程序的时候，因为如果深度检测失败了，片断程序根本就不会运行。

默认: colour_write on

start_light

设置此渲染通路使用的首个光源。

格式: start_light <number>

你可以使用这个属性设置此渲染通路的光源的开始位置。换句话说，如果你设置start_light为2，那么被处理的第一个光源就是实际列表中的第三个光源。例如，你可以利用这个选项，使用不同的渲染通路处理第一组的几个光源对第二组的几个光源，或者使用它与iteration选项协作，从列表的给定点开始迭代（例如，在第一个渲染通路里处理头两个光源，然后从此开始每次两个光源重复进行）

默认: start_light 0

max_lights

设置此渲染通路使用的光源的最大数量。

格式: max_lights <number>

光源的最大数量由渲染系统设定，通常为8，常用于渲染固定功能材质。当你要使用可编程管线（详见3.1.9 在渲染通路中使用顶点程序和片断程序部分），这个限制依赖于你要运行的程序。如果你使用'iteration once_per_light'（详见下面 iteration），则它的有效性仅限于你想使用的渲染通路的数量。但是，无论你使用哪种方法，都要应用max_lights限制。

默认: max_lights 8

iteration

设置此渲染通路是否被迭代，多次重复执行。

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

示例：

iteration once
渲染通路只执行一次，默认设置。
iteration once_per_light point
渲染通路每个光源点执行一次。
iteration 5
此渲染通路的渲染状态将被建立，并且绘图调用将执行5次。
iteration 5 per_light point
此渲染通路的渲染状态将被建立，并且绘图调用将每个光源点各执行5次。
iteration 1 per_n_lights 2 point
此渲染通路的渲染状态将被建立，并且绘图调用将每2个光源点执行5次。

依照默认设置，渲染通路只执行一次。但是，如果你使用可编程管线，或者你希望超出支持的光源数量限制，你或许想要使用once_per_light选项。在这种情况下，只有光源0被使用，每次使用不同的光源作为光源0，渲染通路执行多次。显然，这会使渲染通路的代价很高，但是，考虑1到n个光源的每像素光照效果，这可能是唯一达到这种效果的办法。

使用数字代替“once”表示建立渲染状态后渲染通路的一次以上的迭代执行。渲染状态在初始化建立后就不再改变，所以对于使用需要迭代多次相同渲染状态的可编程渲染，重复的绘图调用是非常快速和理想的。例如，皮毛、动作模糊、特殊滤镜等渲染。

如果你使用了once_per_light，你也应该在此渲染通路之前的技术里增加一个环境渲染通路，否则，当这个物体附近没有光源时，它就不会被渲染；即使你的场景里没有环境光时，这也是很重要的，因为原本你仍然是想要显示物体的轮廓的。

此属性的光源类型参数仅在你使用once_per_light、per_light或者per_n_light时应用，且还限制运行单一类型光源（'点光源'、'方向光源'或'斑光源'）的渲染通路。如下面的例子所示，这个渲染通路将会每个电光源执行一次。如果你能估计到将要处理的光源类型，这会是有用的，因为当你要写一个顶点/片断程序时，它会很容易。至少点光源和方向光源可以用一种方法处理。

默认: iteration once

示例：使用了一个在第二次渲染通路中包含10次迭代操作用以生成皮毛的简单的皮毛渲染材质脚本

// 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
      }
    }
  }
}

注意：使用GPU程序自动参数pass_number和pass_iteration_number告诉顶点或片断程序渲染通路数量和迭代数。

point_size

此设置允许你在渲染一个点列或者一个point sprites列时改变点的大小。这个命令的插值依赖于point_size_attenuation选项——如果是关闭的（默认情况），点的大小是屏幕像素的大小；如果是打开的，表现为标准化屏幕坐标（屏幕高为1.0）。

注意：某些设备有其所支持的点的大小的上限——相同的显卡不同的应用程序接口可能不同！不要相信点的大小，因为那些屏幕上很大的点可能仅限于某些显卡。最高像素的范围从64像素到256像素。

格式: point_size <size>
默认: point_size 1.0

point_sprites

这个设置指定此渲染通路的硬件point sprites渲染是否打开。如果打开了，意味着一个点列被作为一个四元组列渲染而不是作为一列点渲染。如果你使用了公告板集并且只需要使用基于公告板的大小相同的点，使用这个选项是非常有用的。你也可以在任何其它点列渲染中使用这个属性。

格式: point_sprites <on|off>
默认: point_sprites off

point_size_attenuation

定义点的大小是否根据视觉空间距离增加而衰减，以及以何种方式衰减。当你使用point sprites时，这个选项特别有用，因为它定义了当远离镜头时，应如何减小尺寸。你也可以关闭这个选项，使point sprites成为一个常数的屏幕尺寸（像点一样），或者打开这个选项，使之随距离而改变。

如果你打开了这个选项，你只要提供最后3个参数。衰减方程为点的大小乘以1 / （constant + linear * dist + quadratic * d^2）；因此关闭这个选项就相当于（constant = 1, linear = 0, quadratic = 0）且标准透视缩减是（constant = 0, linear = 1, quadratic = 0）。后者假设你指定打开这个选项但未给出后3个参数。

注意衰减的结果应限于点尺寸的最小和最大值之间（详见下面介绍）。

格式: point_size_attenuation <on|off> [constant linear quadratic]
默认: point_size_attenuation off

point_size_min

设置点衰减（详见上面point_size_attenuation）的最小值。细节详见上面point_size。

格式: point_size_min <size>
默认: point_size_min 0

point_size_max

设置点衰减（详见上面point_size_attenuation）的最大值。细节详见上面point_size。 0值意味着将最大值设置为当前显卡所支持的最大值。

格式: point_size_max <size>
默认: point_size_max 0


文档:手册:1-4-0:3.1.3 纹理单元 - OGRE 3D 中文

文档:手册:1-4-0:3.1.3 纹理单元

3.1.3 纹理单元

以下是你可以在.material脚本的'texture_unit'部分使用的属性：

可用的纹理层属性

  • texture_alias
  • texture
  • anim_texture
  • cubic_texture
  • tex_coord_set
  • tex_address_mode
  • tex_border_colour
  • filtering
  • max_anisotropy
  • mipmap_bias
  • colour_op
  • colour_op_ex
  • colour_op_multipass_fallback
  • alpha_op_ex
  • env_map
  • scroll
  • scroll_anim
  • rotate
  • rotate_anim
  • scale
  • wave_xform
  • transform
  • binding_type
  • content_type

为了使用作为纹理数据源的特殊扩展，你也可以使用嵌套的'texture_source'部分，详见6. 外部纹理源部分。

属性描述

纹理别名texture_alias

设置此纹理单元的别名。

格式: texture_alias <纹理别名>
示例: texture_alias NormalMap

如果此材质被其他材质复制且在新材质中只有纹理会被改变，这种情况下，设置别名是很有用处的。

默认：如果一个纹理单元有名字，那么此纹理单元的别名默认就是这个名字。
纹理texture

设置这一层要使用的静态纹理图像的名字。

格式: texture <texturename> [<type>] [unlimited | numMipMaps] [alpha] [<PixelFormat>]
示例: texture funkywall.jpg

这个设置与anim_texture属性是互斥的。注意纹理文件不能包含空格。喜欢在文件名里用空格的Windows用户们，请不要使用空格，而使用下划线替代。

参数type允许你指定创建的纹理类型——默认值是'2d'，但是你可以改变；下面给出了全部列表：

1d
1维纹理；即仅有1像素高的纹理。这种纹理可以用于在纹理内（也可能在片断程序内）编码一个功能和使用它来进行简单查找。当你用一维纹理坐标的片断程序时这个设置是很重要的，因为GL要求你使用相匹配的纹理类型。（虽然D3D会让你通过，但是为了跨平台考虑，还是要注意这一点。）为了有最好的兼容性和显示效果，纹理宽度仍然需要是2的整数次幂，并且有深度。
2d
如果你省略type参数，则假设2d为默认值。纹理的宽度和高度都最好是2的整数次幂，使之成为一个正方形，因为这样的设置在大多数硬件上表现最好。可以由2D纹理坐标指向。
3d
三维纹理，例如volume纹理。这类纹理有2的整数次幂的宽和高，且有深度。可由3D纹理坐标指向，例如通过像素渲染器（pixel shader）。
cubic
这类纹理由贴在立方体内侧的6个2D纹理组成。可由3D纹理坐标指向，并且对于立方体反射映射（cubic reflection maps）和标准映射（normal maps）很有用。

'numMipMaps'选项允许你指定这个纹理的mipmap数量。默认值无限（'unlimited'）意味着mips的大小生成下限到1x1。你可以随意指定一个固定的数（甚至是0）。注意，如果你在多个材质脚本中使用相同的纹理，生成的mipmap数量将与装载纹理的第一个纹理单元中指定的数量一致——所以务必保持你的使用一致。

'alpha'选项允许你指定一个单独的通道（透明的）纹理作为alpha装载，而不是默认的载入红色通道。这有助于在固定功能的管线中使用只有alpha的纹理。默认值：none

<PixelFormat>选项允许你指定想要创建的像素格式，可能不同于装载的纹理文件的像素格式。应当牢记于心的是最终的像素格式会受到硬件能力的限制，所以你可能得不到完全符合你的要求的格式。可用选项如下：

PF_L8
8位像素格式，所有位表示luminace。
PF_L16
16位像素格式，所有位表示luminace。
PF_A8
8位像素格式，所有位表示alpha。
PF_A4L4
8位像素格式，4位alpha，4位luminace。
PF_BYTE_LA
2字节像素格式，1字节luminace，1字节alpha。
PF_R5G6B5
16位像素格式，5位红，6位绿，5位蓝。
PF_B5G6R5
16位像素格式，5位蓝，6位绿，5位红。
PF_R3G3B2
8位像素格式，3位红，3位绿，2位蓝。
PF_A4R4G4B4
16位像素格式，alpha、红、绿、蓝各4位。
PF_A1R5G5B5
16位像素格式，1位alpha，红、绿、蓝各5位。
PF_R8G8B8
24位像素格式，红、绿、蓝各8位。
PF_B8G8R8
24位像素格式，蓝、绿、红各8位。
PF_A8R8G8B8
32位像素格式，alpha、红、绿、蓝各8位。
PF_A8B8G8R8
32位像素格式，alpha、蓝、绿、红各8位。
PF_B8G8R8A8
32位像素格式，蓝、绿、红、alpha各8位。
PF_R8G8B8A8
32位像素格式，红、绿、蓝、alpha各8位。
PF_X8R8G8B8
32位像素格式，8位红，8位绿，8位蓝，与PF_A8R8G8B8一样，不过去掉了alpha。
PF_X8B8G8R8
32位像素格式，8位蓝，8位绿，8位红，与PF_A8B8G8R8一样，不过去掉了alpha。
PF_A2R10G10B10
32位像素格式，2位alpha，红、绿、蓝各10位。
PF_A2B10G10R10
32位像素格式，2位alpha，蓝、绿、红各10位。
PF_FLOAT16_R
16位像素格式，16位符点数红
PF_FLOAT16_RGB
48位像素格式，16位符点数红，16位符点数绿，16位符点数蓝。
PF_FLOAT16_RGBA
64位像素格式，16位符点数红，16位符点数绿，16位符点数蓝，16位符点数alpha。
PF_FLOAT32_R
32位像素格式，32位符点数红。
PF_FLOAT32_RGB
96位像素格式，32位符点数红，32位符点数绿，32位符点数蓝。
PF_FLOAT32_RGBA
128位像素格式，32位符点数红，32位符点数绿，32位符点数蓝，32位符点数alpha。
PF_SHORT_RGBA
64位像素格式，16位红、绿、蓝、alpha。
活动纹理anim_texture

设置用于活动纹理层的图像。这种情况下的活动纹理指的是有多幅画面，而每一幅画面都是单独的一个图像文件。有两种格式，一种是隐式的决定图像名，一种是显式的命名。

格式1 (短格式): anim_texture <base_name> <num_frames> <duration>
示例: anim_texture flame.jpg 5 2.5

上面格式1的例子建立了一个有5幅画面组成的活动纹理层，分别被命名为flame_0.jpg，flame_1.jpg，flame_2.jpg等等，长度2.5秒（2fps）。如果延时（duration）设置为0，那么不发生自动转换，需要在代码中手动改变。

格式2 (长格式): anim_texture <frame1> <frame2> ... <duration>
示例: anim_texture flamestart.jpg flamemore.png flameagain.jpg moreflame.jpg lastflame.tga 2.5

上面格式2的例子也建立了与格式1的例子一样延时的动画，只不过这次是由5个单独命名的图像文件组成的。第一种格式更简单，之所以给出第二种格式是为了解决图像不能统一命名的情况。

默认: 无
立方体纹理cubic_texture

设置在立方体纹理内使用的图像。由6个独立的图像组成一个立方体的6个面。如果硬件支持的话，这类纹理常被用在反射映射（reflection maps）或者天空盒（skyboxes）中。共有两种格式，一种是简短格式，图像名按一定特殊格式命名；另一种格式虽然更灵活，可以任意取名，但是长度也相应更长。

格式1 (短格式): cubic_texture <base_name> <combinedUVW|separateUV>

格式1这种格式的基础名如'skybox.jpg'，系统会希望你提供的各面图像名为skybox_fr.jpg，skybox_bk.jpg，skybox_up.jpg，skybox_dn.jpg，skybox_lf.jpg，and skybox_rt.jpg。

格式2 (长格式): cubic_texture <front> <back> <left> <right> <up> <down> separateUV

格式2这种格式，每一面都显式地指定，以防如果没办法按一致的标准命名。你可以使用带separateUV参数的格式2，因为combinedUVW需要一个单独的纹理名赋值给复合3D纹理（见下面）。

两种格式中，最后一个参数的意思如下：

combinedUVW
6个纹理被合在一个立方体纹理映射中，使用带U，V，W元素的3D纹理坐标。对于反射映射是必要的，因为你永远不知道你将要需要的是哪一个面。需要注意的是，不是所有的显卡都支持立方体环境映射。
separateUV
6个纹理被分开来保存，但是被一个纹理层引用。在任一时刻只有一个纹理处于活动状态（实际上，它们被作为6幅画面保存起来），所以使用2D UV坐标。这种类型适用于天空盒（skyboxes）因为每次只有一面被渲染，而且在更老的显卡上也有硬件支持。
默认: 无
绑定类型binding_type

告诉这个纹理单元是绑定到片断处理单元还是绑定到顶点处理单元（3.1.10 顶点纹理拾取（Vertex Texture Fetch））。

格式: binding_type <vertex|fragment>
默认: binding_type fragment
内容类型content_type

告诉这个纹理单元从哪里取得它的内容，默认是从用texture，cubic_texture，anim_texture属性定义的一个命名纹理中取得内容。但是，你也可以从其他自动化的来源获取。选项如下：

named
默认选项，内容来自一个有名字的纹理，以平常的方式从一个文件或者根据给定的名字手动创建装载。
shadow
这个选项允许你拉入一个阴影纹理，并且只有在你使用纹理阴影和'custom sequence'阴影类型（详见[[文档:手册:1-4-0:7. 阴影|7. 阴影）时才可用。除非你使用基于光源的渲染通路循环或者在同一渲染通路的多个纹理单元中使用light_start选项使得光源从更高的序号开始，否则，讨论中的阴影纹理将会从第n个最近光源产生阴影。当你在同一个渲染通路的多个纹理单元中使用这个选项时，每一个引用下一个阴影纹理。万一你想要在另一个渲染通路里再次使用同一个阴影纹理，阴影纹理序号在下一个渲染通路内被重置（例如：单独的specular/gloss渲染通路）。依靠使用这个选项，正确的光源可视区域投影就被使用固定的方式建立起来了。如果你使用渲染器，只需在渲染器中引用texture_viewproj_matrix auto 参数即可。
格式: content_type <named|shadow>
默认: content_type named
纹理坐标集tex_coord_set
设置这个纹理层要使用的纹理坐标集。一个网格可以定义多个纹理坐标集，此属性设置这个材质使用哪一个坐标集。
格式: tex_coord_set <set_num>
示例: tex_coord_set 2
默认: tex_coord_set 0
纹理寻址模式tex_address_mode
定义在这个纹理层的纹理坐标超过1.0时发生的事情。你可以选择简单格式，一次对全部3个纹理坐标指定寻址模式，或者扩展的格式，使用三分之二的参数每个纹理坐标指定不同的模式。
简单格式: tex_address_mode <uvw_mode>
扩展格式: tex_address_mode <u_mode> <v_mode> [<w_mode>]
wrap
任何超过1.0的值都被置为0.0。纹理被重复一次。
clamp
超过1.0的值被固定为1.0。超过1.0的其它地方的纹理，沿用最后像素的纹理。用于当叠加过滤时，需要从0.0到1.0精确覆盖且没有模糊边界的纹理。
mirror
每到边界处纹理翻转，意思就是每个1.0 u或者v处纹理被镜像翻转。
border
超出[0.0, 1.0]范围的值都被置为边界色，也可以设置tex_border_colour属性。
默认: tex_address_mode wrap
纹理边界色tex_border_colour
设置边界色。（参考tex_address_mode）。
格式: tex_border_colour <red> <green> <blue> [<alpha>]
颜色的数值取值范围在0.0到1.0。
示例: tex_border_colour 0.0 1.0 0.3
默认: tex_border_colour 0.0 0.0 0.0 1.0
过滤filtering
设置当放大或缩小纹理时，使用的纹理过滤形式。这个属性有两种格式，简单格式就是指定预先定义好的过滤选项集的名字；复杂格式，就要你自己分别设定缩小，放大，mip过滤。
简单格式
格式: filtering <none|bilinear|trilinear|anisotropic>
默认: filtering bilinear

这种格式，你只需要提供如下的一个参数：

none
不使用过滤或mipmapping缩放。这相当于复杂格式的'filtering point point none'。
bilinear
当放大或缩小一个纹理时，使用2x2 box过滤，从列表中挑出一个mipmap但是在mipmaps的各级之间不使用过滤。这相当于复杂格式的'filtering linear linear point'。
trilinear
当放大或缩小一个纹理时，使用2x2 box过滤，最近的2个mipmaps被一起过滤。这相当于复杂格式的'filtering linear linear linear'。
anisotropic
除了过滤算法考虑了与镜头相关的三角形坡面而不是一味地简单做一个2x2像素过滤之外，这个属性与'trilinear'相同。这使得三角形的锐角看起来较少失真。相当于复杂格式的'filtering anisotropic anisotropic linear'。注意，要想这个属性有所不同，你还必须设置max_anisotropy属性。
复杂格式
Format: filtering <minification> <magnification> <mip>
Default: filtering linear linear point
这个格式给你对于缩小，放大，和mip过滤完全的控制权。参数如下：
none
无——唯一的一个'mip'过滤可用的参数，此参数完全关闭了mipmapping。对于缩小和放大的最低设置是'point'。
point
挑选缩小和放大模式最近的像素。在mip模式中，此选项挑选出最符合mipmap要求的。
linear
围绕最近像素点过滤出一个2x2大小的像素块。在'mip'过滤中，这可以在mipmap各层级之间衔接。
anisotropic
仅针对缩小和放大模式可用，对于三角形的摄像机空间斜坡过滤补偿。注意，要想这个属性有所不同，还必须设置max_anisotropy属性。
最大各向异性max_anisotropy
当过滤纹理时，设置渲染器将要补偿的各项异性的程度。这个度就是纹理在屏幕可见部分的高和宽的比值，就如伸向远方且竖直方向的纹理坐标比水平方向的纹理坐标变化的更快的地平面有比面对着你的墙更高的各向异性（如果你的目光与墙面垂直，则各向异性为1）。为了进行补偿，你需要把max_anisotropy属性设置为比1大的值。最大值由硬件决定，而通常来说设为8或者16。
为了使用这个属性，你必须设置这个纹理的缩小和/或放大过滤。
格式: max_anisotropy <value>
默认: max_anisotropy 1
mipmap_bias

设置用于mipmap计算的偏向值，因此允许你决定哪一级的纹理细节用于哪个距离。在规定的距离计算之后应用偏向值，对每一个偏向单元做出1级mipmap级别调整。负的偏向值强制增大使用的mip级别，正的偏向值减小使用的mip级别。偏向是符点数，所以你可以使用所有的数值进行调整。

为了使用这个属性，你的硬件必须支持mipmap偏向（通过渲染系统能力暴露出来），而且你的缩小过滤必须被设置成point或linear。

格式: mipmap_bias <value>
默认: mipmap_bias 0
colour_op

决定这个纹理层的颜色如何与它下面的一层叠加复合起来（或者如果它是第一层的话，如何将它与光照效果复合起来）。

格式: colour_op <replace|add|modulate|alpha_blend>

这个方法是混合纹理层最简单的方法，因为它只需要一个参数，给你最普通的混合类型，并且自动建立两种混合方法：一种是针对单渲染通路多纹理硬件可用时的混合；另一种是针对单渲染通路多纹理硬件不可用时通过多渲染通路完成混合。然而，这是相当受限的，并且无法使用更加灵活的多纹理操作，简单地因为这些在多渲染通路回撤模式下不能被自动地支持，或者你需要使用colour_op_multipass_fallback显式地设置一个回撤点。

replace
不加调整，用纹理颜色替换所有颜色。
add
加颜色成分。
modulate
乘颜色成分。
alpha_blend
基于纹理alpha混合。
默认: colour_op modulate
colour_op_ex

这是colour_op属性的扩展版，对于在这个纹理层与前面一个纹理层之间应用的混合允许极详细的控制。多纹理硬件可以应用更加复杂的混合操作，但受限于硬件所能用的纹理单元数。

格式: colour_op_ex <operation> <source1> <source2> [<manual_factor>] [<manual_colour1>] [<manual_colour2>]
示例: colour_op_ex add_signed src_manual src_current 0.5

看下面有关使用这个方法在多渲染通路和多纹理之间可能出现的问题。纹理颜色操作决定了渲染后最终平面出现的颜色。纹理单元被用来从各种不同的源中混合颜色值（例如，将通过光源计算的表面四散光与纹理的颜色叠加复合到一起）。这种方法允许你指定使用的“操作”，例如用“加”还是“乘”计算，以及用什么值作参数，是固定值还是以前算好的值。

Operation options
source1
不加任何改变地使用source1。
source2
不加任何改变地使用source2。
modulate
source1乘source2。
modulate_x2
source1乘source2，再乘2 (加亮).
modulate_x4
source1乘source2，再乘4 (加亮).
add
source1加source2。
add_signed
source1加source2，再减0.5.
add_smooth
source1加source2, 再减它们的乘积。
subtract
source1减source2
blend_diffuse_alpha
使用向顶点插入alpha值的方法调整source1，用（1-alpha）调节source2，再把两次调节后的结果相加。
blend_texture_alpha
同blend_diffuse_alpha，但是对纹理使用alpha。
blend_current_alpha
同blend_diffuse_alpha，但是对之前的stages使用当前alpha（对于第一层来说，与blend_diffuse_alpha相同）
blend_manual
同blend_diffuse_alpha，但是使用一个恒量alpha值，这个值在<manual>中指定。
dotproduct
source1点积source2
blend_diffuse_colour
使用向顶点中插入的颜色值调节source1，然后加上用（1-colour）调节过的source2。
Source1 and source2 options
src_current
建立于前面stages的颜色
src_texture
来自被赋值给这一层的纹理的颜色
src_diffuse
来自顶点的插入的四散光颜色（对于第一层来说，与src_current相同）。
src_specular
来自顶点的插入的镜面反射光颜色。
src_manual
在命令尾部手动指定的颜色。

例如'modulate'取用前面纹理层的颜色结果，并且把新的纹理乘到这个结果上。牢记颜色是0.0-1.0的RGB值，所以把它们乘在一起通过做乘法使之着色会得到相同范围的结果。但是要注意连续的乘法一般有加深变暗纹理的效果，因此有像modulate_x2一样的增亮操作。由于某些APIs（包括Direct3D）的限制，'texture'参数只能被用作第一个参数，而不能是第二个参数。

还应注意的是，最后一个参数只有在你决定手动给操作传递数值时，才是必要的。因此，在你使用'blend_manual'操作时，才需要你填充这些参数。

重点: OGRE试图使用多纹理硬件混合纹理层。但是，如果纹理单元数不足（GeForce2是2个，GeForce3是4个），它就不得不退而使用多路渲染，例如用不同纹理多次渲染同一物体。这不仅是低效的而且可供使用的混合操作的范围也小。因此，如果你使用这个方法，你就需要设置colour_op_multipass_fallback属性用来指定在硬件不足时使用哪种效果（默认是'modulate'，如果你在此运用了华丽的混合操作，结果肯定不如预期来得好）。如果你希望避免这种情况，使用更简单的colour_op属性，虽没有太多的灵活混合操作，但是可以自动建立多路渲染，因为它只允许有直接多路等价渲染的操作。

默认: none (colour_op modulate)
colour_op_multipass_fallback

在如果使用了colour_op_ex属性且没有足够的多纹理硬件支持时，设置这个纹理层的多路后撤操作。

格式: colour_op_multipass_fallback <src_factor> <dest_factor>
示例: colour_op_mulitpass_fallback one one_minus_dest_alpha

因为你使用colour_op_ex属性创建的一些效果仅在多纹理硬件下支持，如果硬件缺乏，系统不得不后撤为多路渲染，不幸的是有许多效果并不被支持。这个属性就可以让你指定最适合你的后撤操作。

参数与scene_blend属性相同；这是因为多路渲染是有效地场景混合渲染，每一层都在采用了一种令物体透明的技术的前一层之上被渲染，它重复地在同一地方渲染就得到了多纹理效果。如果你使用了更简单的（同时也低灵活性的）colour_op属性，你不需要调用属性，因为系统为你创建了后撤操作。

alpha_op_ex

行为方式与colour_op_ex如出一辙，只不过它是决定alpha值如何在纹理层之间复合，而不是colour值。唯一的区别是colour_op_ex最后是两个颜色值，而alpha_op_ex是一个浮点值。

env_map

打开/关闭纹理坐标效果，以决定这一层能否环境映射。

格式: env_map <off|spherical|planar|cubic_reflection|cubic_normal>

环境映射依靠使用基于物体的顶点或法线与观察着眼睛之间的关系自动生成的纹理坐标使得物体看起来是有反射效果的。

spherical
球面环境映射。需要一个单独的纹理，这个纹理或者是被反射场景的凸透镜视图，或者是其它球面映射的纹理（平滑高亮的纹理是比较好的）。这一效果基于视线和物体顶点法线之间的关系，所以当有大量渐变法线时效果最好，例如：弯曲的物体。
planar
与球面环境映射相似，但是效果基于视口内的顶点位置而不是顶点法线。这一效果也因此用于平面物体（由于法线全都一样，球面env_map表现不好）或者没有法线的物体。
cubic_reflection
一种更高级的反射映射形式，使用一组6个纹理组成一个立方体的内表面，如果沿着场景的坐标轴看其中每一个纹理都是一个视图。在所有情况下工作得都极好，可是比球面映射需要更高规格的显卡。而且需要你绑定cubic_texture到这个纹理单元并且使用'combinedUVW'选项。
cubic_normal
生成三维纹理坐标，其中包括含有顶点数据的法线信息中的摄像机空间法向量。此外，这个特性的完全使用也需要设置'combinedUVW'选项的cubic_texture。
默认: env_map off
scroll

给纹理设置一个固定的滚动偏移量。

格式: scroll <x> <y>

此方法给纹理的偏移在这一层设定了一个固定的量。对于不改变纹理坐标模式的小调整很有用。但是如果你想要一个动态的滚动效果，详见scroll_anim属性。

scroll_anim

给纹理层设置一个动态的滚动。对于在纹理层上创建固定速度的滚动效果很有用（对于不同的滚动速度，详见wave_xform属性）。

格式: scroll_anim <xspeed> <yspeed>
rotate

将一个纹理旋转一个固定的角度。

这个属性只将纹理方向旋转一个固定的角度，对于固定的调整比较有用。如果你想要动态调整，详见rotate_anim。

格式: rotate <angle>

参数<angle>是逆时针旋转的角的度数。

rotate_anim

为这一层创建动态旋转效果。对于创建固定速度的旋转动作比较有用（对于变速的情况，详见wave_xform）。

格式: rotate_anim <revs_per_second>

参数<revs_per_second>是每秒逆时针旋转的次数。

scale

调整这个纹理层应用的比例系数。用于调整纹理的大小，不改变几何体。这是一个固定的比例系数，如果你想要动态的比例系数，详见wave_xform。

格式: scale <x_scale> <y_scale>

比例的有效值要大于0，比例系数如果为2，就表示在那一维上的纹理有2倍那么大。

wave_xform

建立一个基于波功能的动态改变形式。用于更高级的纹理层改变效果。你可以在一个纹理层中随意添加多个此属性的实例。

格式: wave_xform <xform_type> <wave_type> <base> <frequency> <phase> <amplitude>
示例: wave_xform scale_x sine 1.0 0.2 0.0 5.0
xform_type
scroll_x
变动x滚动值
scroll_y
变动y滚动值
rotate
变动旋转值
scale_x
变动x比例值
scale_y
变动y比例值
wave_type
sine
典型的正弦波，在最小值和最大值之间平稳地循环。
triangle
以恒定的速度增加减少的有角度的波，在极值时立即改变。
square
最大是波长的一半，最小是瞬时转换之间的停止时间。
sawtooth
经过一段时间，从最小逐渐持续增加到最大，最后立即回到最小。
inverse_sawtooth
经过一段时间，从最大逐渐持续减少到最小，最后又立即返回最大。::base
基值，如果amplitude > 0就是指最小值，amplitdue < 0就是指最大值。
frequency
波每秒重复的次数，即速度。
phase
波开始的偏移量。
amplitude
波的大小。

波的输出范围在{base, base+amplitude}。所以，以在x方向调整纹理为例，沿正弦波方向从1（标准值）调整到5，即表示每5秒一个周期（每秒0.2个波）。

transform

这个属性允许你为纹理单元指定一个4x4变换矩阵，因而取代上述的滚动、旋转、比例属性。

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

上面4x4矩阵中的数值序号为m<row><col>，前面一个为行号，后面一个为列号。


文档:手册:1-4-0:3.1.4 顶点程序与片断程序的声明 - OGRE 3D 中文

文档:手册:1-4-0:3.1.4 顶点程序与片断程序的声明

3.1.4 顶点程序与片断程序的声明

为了在你的材质中使用顶点或者片断程序（参看：3.1.9 在渲染通路中使用顶点程序和片断程序），首先你必须定义它们。一个程序定义可以被多个材质使用，唯一的前提条件是必须在引用它之前在材质的渲染通路部分中定义。

程序定义可以被嵌套在.material脚本内（在这种情况下，它必须位于任何对它的引用之前，即必须先定义后引用）或者如果你希望跨多个.material脚本使用同一个程序，你可以在一个外部的.program脚本中定义。程序定义的方式与在.program或者.material脚本中一样，唯一的区别是所有.program脚本都肯定会在.material脚本之前被处理，因此确保你的程序肯定在任何.material脚本之前被定义。正像.material脚本一样，.program脚本可以从你指定的资源路径上的任意位置读取，并且你可以在一个脚本中定义多个程序。

顶点和片断程序既可以是低级渲染语言（例如按照给定的诸如vs_1_1或者arbfp1的低级语法规格写成的汇编代码）也可以是高级渲染语言，例如DirectX9 HLSL，Open GL Shader Language，或者nVidia's Cg language（参看：高级程序部分）。高级语言给你许多优势，例如能够写出更加直观的代码，能够在一个程序中针对多种架构（例如，一段Cg程序既可用在D3D上，也可用在GL上，与此同时，低级的程序也许会需要单独的技术，各自针对不同的API）。高级程序也让你使用命名的参数替代简单的编号参数，尽管参数并不在这里定义，它们用在渲染通路里。

一个低级顶点程序示例如下：

vertex_program myVertexProgram asm
{
    source myVertexProgram.asm
    syntax vs_1_1
}

如你所见，很简单。定义一个片断程序，与此相同，只是将vertex_program换成fragment_program。在头部给出程序的名字，后跟'asm'指示这是一个低级程序。在大括号内部，你要指定资源来自何处（从指定的资源位置查找，进行装载），还要指出要使用的语法规格。你可能会奇怪为什么要指定语法规格，头部不是已经指定了汇编器的语法了吗，其实原因在于，引擎需要在读取程序之前知道语法规格，因为在材质编译期间，我们想迅速退出使用不支持语法的程序，一开始就不装载这个程序。

当前支持的语法有：

vs_1_1
这是一种DirectX顶点渲染器汇编语法。
支持显卡有：ATI Radeon 8500，nVidia GeForce 3。
vs_2_0
另一种DirectX顶点渲染器汇编语法。
支持显卡有：ATI Radeon 9600，nVidia GeForce FX 5系列。
vs_2_x
另一种DirectX顶点渲染器汇编语法。
支持显卡有：ATI Radeon X系列，nVidia GeForce FX 6系列。
vs_3_0
另一种DirectX顶点渲染器汇编语法。
支持显卡有：nVidia GeForce FX 6系列。
arbvp1
这是OpenGL标准顶点程序汇编格式。大体上相当于DirectX vs_1_1。
vp20
这是一种nVidia特有的OpenGL顶点渲染器语法，是vs 1.1的一个超集。
vp30
另一种nVidia特有的OpenGL顶点渲染器语法。它是vs 2.0的一个超集，被nVidia GeForce FX 5系及以上系列支持。
vp40
另一种nVidia特有的OpenGL顶点渲染器语法。它是vs 3.0的一个超集，被nVidia GeForce FX 6系及以上系列支持。
ps_1_1, ps_1_2, ps_1_3
DirectX像素渲染器（例如片断程序）汇编语法。
支持显卡：ATI Radeon 8500，nVidia GeForce 3。
注解：对于ATI 8500，9000，9100，9200硬件，也可用于OpenGL。ATI 8500到9200不支持arbfp1但是确实支持OpenGL的atifs扩展，非常类似DirectX的ps_1_4。OGRE有针对atifs编译器的ps_1_x模块，当在ATI硬件上使用ps_1_x时，它会自动执行。
ps_1_4
DirectX像素渲染器（片断程序）汇编语法。
支持显卡有：ATI Radeon 8500，nVidia GeForce FX 5系列。
注解：对于ATI 8500，9000，9100，9200硬件，此项也可用于OpenGL。ATI 8500到9200不支持arbfp1但是支持OpenGL的atifs扩展，功能上非常类似于DirectX中的ps_1_4。OGRE有针对atifs编译器的ps_1_x模块，当在ATI硬件上使用ps_1_x时，它会自动执行。
ps_2_0
DirectX像素渲染器（片断程序）汇编语法。
支持显卡有：ATI Radeon 9600，nVidia GeForce FX 5系列。
ps_2_x
DirectX像素渲染器（片断程序）汇编语法。基本上是带有更多指令的ps_2_0。
支持显卡有：ATI Radeon X系列，nVidia GeForce FX 6系列。
ps_3_0
DirectX像素渲染器（片断程序）汇编语法。
支持显卡有：nVidia GeForce FX 6系列。
ps_3_x
DirectX像素渲染器（片断程序）汇编语法。
支持显卡有：nVidia GeForce FX 7系列。
arbfp1
这是OpenGL标准片断程序汇编格式。大体上相当于ps_2_0，意味着不是所有支持DirectX下的基本像素渲染器都支持arbfp1（例如GeForce3和GeForce4就都不支持arbfp1，但是它们都支持ps_1_1）。
fp20
这是一个nVidia特有的OpenGL片断程序语法，是ps 1.3的一个超集。它允许你为基本片断程序使用'nvparse'格式。实际上，它使用NV_texture_shader和NV_register_combiners在GL下提供相当于DirectX's ps_1_1的功能，但是仅限于nVidia显卡。然而，因为ATI显卡比nVidia早一步采用arbfp1，所以它主要用于像GeForce3和GeForce4系列的nVidia显卡。你可以在http://developer.nvidia.com/object/nvparse.html找到更多有关nvparse的信息。
fp30
另一种nVidia特有的OpenGL片断渲染语法。它是ps 2.0的一个超集，被nVidia GeForce FX 5系列或更高级的显卡支持。
fp40
另一种nVidia特有的OpenGL片断渲染语法。它是ps 3.0的一个超集，被nVidia GeForce FX 6系列或更高级的显卡支持。

你可以通过调用GpuProgramManager::getSingleton（）.getSupportedSyntax（）得到当前显卡支持的语法列表。

默认的程序参数

当定义一个顶点或片断程序时，除非特殊情况下参数被重载了，否则你也可以指定默认参数用于材质中。要使用默认参数，需要你嵌套一个'default_params'块，如下所示：

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
    }
      //默认参数块结束
}

参数定义的语法与使用程序定义参数是完全一样的，参看：程序参数规格。定义默认参数可以使你避免重复绑定公用的参数（如上面例子清楚地显示：除'shininess'外，其他所有参数在程序的使用中间都不会发生改变），同时也可以使你的材质声明更短些。 高级程序 通过插件提供对于高级的顶点和片断程序的支持；这是为了确保使用OGRE的应用程序可以随意少用或多用高级程序功能。OGRE现在支持3种高级程序，Cg（3.1.5 Cg程序）（一种API独立且显卡独立的高级程序语言，可以让你对于许多显卡在OpenGL和DirectX上编写程序），DirectX9高级渲染语言（3.1.6 DirectX9 HLSL），OpenGL 图形库渲染语言（3.1.7 OpenGL GLSL）。HLSL只能与DirectX渲染系统共同使用，而GLSL只能与GL渲染系统一起使用。Cg两种都可使用。根据使用经验显示，再针对特定渲染系统的渲染语言中，程序越高级，特别是在有大量纹理获取的片断程序中，能够产生出的代码越好。

要既支持HLSL又支持GLSL，一种方法是在材质脚本中分别包括各自的技术，各自引用各自的技术。但是，如果程序基本一样，参数相同，同时技术又十分复杂，只就会使你的材质脚本在快速复制中变得臃肿不堪。替代这种方法的是，如果唯一的不同就是顶点和片断程序的语言，你可以使用OGRE的3.1.8 统一高级程序自动地挑选一个最适合你渲染系统的程序，这样你只需要使用一个技术就可以了。

顶点程序中的骨骼动画
你可以通过写一个顶点程序，在这段程序中利用一组世界矩阵（如果你绑定了自动参数'world_matrix_array_3x4'，那么这个矩阵会由OGRE提供）使用每顶点混合索引和混合权重的方法在硬件中实现骨骼动画。由于需要你与OGRE交流这个支持，所以不能实现软件骨骼动画。要想实现骨骼动画，需要在你的vertex_program定义中增加如下属性：
includes_skeletal_animation true
当你做了如上设置，任何使用这个材质的骨骼动画实体都将放弃原定的混合渲染，而是期望顶点程序完成渲染，不仅是顶点还有法线。注意，所有子网格必须被指定一个这里使用的材质，并且如果你将骨骼动画与顶点动画组合在一起（参看8. 动画部分），那么所有技术应当被硬件加速。
顶点程序中的变形动画
你可以通过编写一个顶点程序硬件实现变形动画，即在第一个位置关键帧和第二个位置关键帧之间线性混合，传递的关键帧包括位置和第一个的空纹理坐标集，并且将animation_parametric值绑定到一个参数上（就是告诉你在二者之间多远的地方插值）。但是，由于你需要和OGRE交流这一支持，所以不能软件实现变形动画。要想实现变形动画，需要在vertex_program定义中增加如下属性：
includes_morph_animation true
当你做了如上设置，任何使用这个材质的骨骼动画实体都将放弃原定的形状，转而期望顶点程序完成它。注意如果你的模型既包括骨骼动画又包括变形动画，其中一个使用硬件加速，那么他们必须在顶点程序中都被实现。注意，所有子网格必须被指定一个这里使用的材质，并且如果你将骨骼动画与顶点动画组合在一起（参看8. 动画部分），那么所有技术应当被硬件加速。
顶点程序中的姿势动画
你可以依靠拉动原始的顶点数据（某一位置）在一个顶点程序中实现姿势动画（根据权重在多个姿势之间混合），'includes_pose_animation'声明中定义的那些姿势偏移量缓冲区将在从第一个空的纹理单元开始的那些纹理单元中。你必须也使用animation_parametric参数，定义要包含姿势权重的常量的开始点；它们从你定义的参数开始，填入'n'个常量，其中'n'是这个渲染器所能混合的姿势的最大数，即includes_pose_animation参数。
includes_pose_animation 4
注意，所有子网格必须被指定一个这里使用的材质，并且如果你将骨骼动画与顶点动画组合在一起（参看8. 动画部分），那么所有技术应当被硬件加速。
顶点程序中的顶点纹理拾取
如果你的顶点程序使用了3.1.10 顶点纹理拾取（Vertex Texture Fetch），你需要用'uses_vertex_texture_fetch'指令声明。这足以告诉OGRE，你的程序使用了这一特性，且硬件对这一特性的支持应该被检查。
uses_vertex_texture_fetch true
带有阴影的顶点程序
当你使用阴影时（参见7. 阴影部分），运用顶点程序可能会增加额外的复杂度，因为当使用固定功能管线时，OGRE只能自动处理所有的事。如果你使用了顶点程序，同时也使用了阴影，你可能需要做出一些调整。
如果你使用了模板阴影，那么任何执行顶点改变的顶点程序可能会有问题，因为模板阴影在CPU上计算，但是CPU并没有访问过这些被修改过的顶点。如果正在执行标准的骨骼动画，那么一切还好，因为OGRE知道如何软件复制效果，但是任何其它的顶点改变都不能被复制，并且你将或者不得不接受阴影没有反映到这次改变上的事实，或者干脆关闭这个物体的阴影。
如果你使用了纹理阴影，那么顶点改变是可接受的。但是，当渲染一个物体的阴影纹理时（阴影施放者渲染通路），阴影不得不渲染成实心的颜色（链接到调制阴影的环境色，对于额外的阴影渲染为黑色）。因此你必须提供一个供选择的顶点程序，所以OGRE为你提供了一个方法，指定一个解决方案当渲染阴影施放者时使用，详情请参看：阴影和顶点程序。

上一章节：3.1.3 纹理单元
下一章节：3.1.5 Cg程序


文档:手册:1-4-0:3.1.5 Cg程序 - OGRE 3D 中文

文档:手册:1-4-0:3.1.5 Cg程序

3.1.5 Cg程序

为了定义Cg程序，你需要在开始时装载Plugin_CgProgramManager.so/.dll，方式可以通过plugins.cfg也可以通过自己的插件装载代码。它们非常容易定义：

fragment_program myCgFragmentProgram cg
{
    source myCgFragmentProgram.cg
    entry_point main
    profiles ps_2_0 arbfp1
}

Cg程序与汇编程序有少许不同，在开始部分，我们声明片断程序的类型为'cg'而不是'asm'，即指明这段程序使用的是Cg高级程序。'source'参数是一样的，只不过这次引用的是Cg源文件，而不是汇编文件。

接下来就是开始有变化的地方了。首先，我们要定义一个'entry_point'，这是Cg程序中的一个函数名，也是第一个被调用的片断程序部分。与汇编程序从头到尾运行不同，Cg程序可以包含多个函数，所以你要指定从哪里开始。

接下来，不是固定的'syntax'参数，而是你要指定一个或多个'profiles'；即Cg如何将程序编译为低级的汇编程序。它们有与上面提到的汇编语法代码一样的名字；唯一的不同就是你可以列出不止一种汇编语言，因此你可以将程序编译成多种低级汇编程序，所以你写的一个高级程序既可以运行在D3D下也可以运行在GL下。建议你在编译程序时只写入最简单的profile以便获得最大的兼容性。此外，顺序也很关键。如果显卡支持多种语法，那么会使用列在第一个的那一种。

最后，还有一个可选项叫做'compile_arguments'，你可以像在cgc命令行编译器上面一样指定你想要使用的参数。


文档:手册:1-4-0:3.1.6 DirectX9 HLSL - OGRE 3D 中文

文档:手册:1-4-0:3.1.6 DirectX9 HLSL

3.1.6 DirectX9 HLSL

DirectX9 HLSL有一个与Cg非常近似的语法，但是被绑定在DirectX API上。唯一超过Cg的优势就是它只需要DirectX渲染系统插件，不需要其他插件。声明一个DirectX9 HLSL程序非常类似于Cg。举例如下：

vertex_program myHLSLVertexProgram hlsl
{
    source myHLSLVertexProgram.txt
    entry_point main
    target vs_2_0
}

如你所见，除了用一个汇编格式列表代替了'profiles'，几乎主要的语法都是见过的。你有一个'target'参数，用以指定一个针对性的汇编语法——显然必须是DirectX汇编形式语法代码。

重要注释——矩阵的顺序：有一件事需要牢记，HLSL允许你使用2种不同方式处理矩阵和向量相乘——mul（v，m）或者mul（m，v）。二者之间唯一的区别就是矩阵被有效地变换。在OGRE中传递矩阵你应该使用mul（m，v）——因为这与渲染器从像RenderMonkey一样的工具中生成的结果保持一致，并且也和Cg一致，但是与使用mul（v，m）的Dx9 SDK和FX合成器不一致——在使用那些渲染器时，你不得不转换mul（）的参数。

注意，如果你在渲染器中使用了float3x4 / matrix3x4类型，且绑定了OGRE自动定义（例如骨骼矩阵），那么你在程序定义时或许需要使用column_major_matrices = false选项（下面讨论）。这是因为OGRE会将float3x4视为行主的，节省一定的空间（3个float4的空间而不是4个float4的空间只占用了前3个），并且也告诉OGRE像这样传递所有矩阵，这样可以使你对于所有计算一致地使用mul（m，v）。OGRE也将告诉渲染器按行主形式编译（你不必设置/Zpr编译选项或者#pragma pack（行主）选项，因为OGRE为你做了这些）。注意OGRE不支持以float4x3形式传递骨骼，但是没关系，你根本也不需要这样传递。

高级选项

preprocessor_defines <defines>
这个选项允许你定义可以在HLSL渲染代码内部使用的符号用以改变行为（通过使用#ifdef或者#if语句）。定义用';'或者','隔开，并且可选择'='操作符指定定义值，没有'='的那些隐含地被定义为1。
column_major_matrices <true|false>
这个选项的默认值为'true'，因此OGRE传递的矩阵自动绑定为适合mul（m，v）使用的形式。设置这个选项为false，起到2个作用：它自动转换成4x4矩阵并且在渲染编译中设置好/Zpr（行主）选项。这意味着你仍然可以使用mul（m，v），但是矩阵的排布已经替换成了行主的。这只在你需要使用骨骼矩阵（float3x4）时有用，因为它为包含的每一个骨骼都节省了一个float4常量的空间。


文档:手册:1-4-0:3.1.7 OpenGL GLSL - OGRE 3D 中文

文档:手册:1-4-0:3.1.7 OpenGL GLSL

3.1.7 OpenGL GLSL

OpenGL GLSL有着与HLSL相似的语法，但是与OpenGL API绑定。比Cg好在只需要OpenGL渲染系统插件，不需其他额外的插件。声明也与Cg类似，但更简单。举例如下：

vertex_program myGLSLVertexProgram glsl
{
    source myGLSLVertexProgram.txt
}

在GLSL中，不需要定义进入点（entry point），因为它总是从'main()'开始，而且也没有目标定义（target definition），因为GLSL源都编译到本地图形处理单元中了，不用再进行中间编译。

GLSL支持使用模块化的渲染。这就意味着你可以写GLSL外部功能，供多渲染器使用。

vertex_program myExteranalGLSLFunction1 glsl
{
    source myExternalGLSLfunction1.txt
}
vertex_program myExteranalGLSLFunction2 glsl
{
    source myExternalGLSLfunction2.txt
}
vertex_program myGLSLVertexProgram1 glsl
{
    source myGLSLfunction.txt
    attach myExteranalGLSLFunction1 myExteranalGLSLFunction2
}
vertex_program myGLSLVertexProgram2 glsl
{
    source myGLSLfunction.txt
    attach myExteranalGLSLFunction1
}

外部GLSL功能可以附加到使用它们的程序上，使用'attach'，然后是所有需要的外部程序名，这些程序名写在同一行上，其间用空格隔开。这在顶点程序和片断程序内都可以使用。

GLSL纹理取样器

在GLSL中，为了从材质脚本向纹理取样器传递纹理单元索引值，要使用'int'类型命名参数。如下例所示：摘自GLSL example.frag资源

varying vec2 UV;
uniform sampler2D diffuseMap;
void main(void)
{
    gl_FragColor = texture2D(diffuseMap, UV);
}

在材质脚本中：

fragment_program myFragmentShader glsl
{
  source example.frag
}
material exampleGLSLTexturing
{
  technique
  {
    pass
    {
      fragment_program_ref myFragmentShader
      {
        param_named diffuseMap int 0
      }
      texture_unit
      {
        texture myTexture.jpg 2d
       }
    }
  }
}

索引值0表示渲染通路的第一个渲染单元，索引值1表示第二个，以此类推。

矩阵参数

下面是按GLSL mat2，mat3，mat4格式传递矩阵的例子：

material exampleGLSLmatixUniforms
{
  technique matrix_passing
  {
    pass examples
    {
      vertex_program_ref myVertexShader
      {
        // mat4 uniform
        param_named OcclusionMatrix matrix4x4 1 0 0 0  0 1 0 0  0 0 1 0  0 0 0 0
        // or
        param_named ViewMatrix float16 0 1 0 0  0 0 1 0  0 0 0 1  0 0 0 0
       // mat3
        param_named TextRotMatrix float9 1 0 0  0 1 0  0 0 1
      }
      fragment_program_ref myFragmentShader
      {
        // mat2 uniform
        param_named skewMatrix float4 0.5 0 -0.5 1.0
      }
    }
  }
}

在GLSL中访问OpenGL状态

GLSL可以直接访问大多数GL状态，所以你无须通过材质脚本中的param_named_auto传递这些状态。这些状态包括光源、材质状态，以及所有在OpenGL中使用的矩阵的状态，如：模型视图矩阵，世界视图投影矩阵等。

绑定顶点属性
GLSL原生支持自动绑定大多数普通的每顶点输入属性（例如：gl_Vertex，gl_Normal，gl_MultiTexCoord0等）。但是，也有一些不是自动绑定的。必须在渲染中使用'attribute <type> <name>'语法声明，然后OGRE才将顶点数据绑定到它上面。
关于内建的属性的详细介绍，请参见GLSL手册的7.3节，OGRE支持如下的自动绑定属性：
tangent
如果你在你的GLSL顶点程序的开头部分声明了一个如'attribute vec3 tangent;'一样的属性，OGRE会自动地将VES_TANGENT类型的顶点元素绑定到这个属性上。注意为了最大限度地兼容渲染器版本，默认情况下，切线被放在一个多余的纹理坐标内，而不是一个切线元素内，但是你可以使用OgreXmlConverter / OgreMeshUpgrader或者通过你的导出器控制这一切。
binormal
如果你在你的GLSL顶点程序的开头部分声明了一个如'attribute vec3 binormal;'一样的属性，OGRE会VES_BINORMAL类型的顶点元素绑定到这个属性上。注意没有OGRE工具生成双法线，因为它们可以通过顶点程序中的法线和切线被轻易地计算出来。
blendIndices
如果你在你的GLSL顶点程序的开头部分声明了一个如'attribute vec4 blendIndices;'一样的属性，OGRE会自动地将VES_BLEND_INDICES类型的顶点元素绑定到这个属性上。
blendWeights
如果你在你的GLSL顶点程序的开头部分声明了一个如'attribute vec4 blendWeights;'一样的属性，OGRE会自动地将VES_BLEND_WEIGHTS类型的顶点元素绑定到这个属性上。
预处理器定义
GLSL支持你在代码中使用预处理器——一些靠实现定义，但是你也可以定义你自己的，即对于同一技术的几种不同变体使用使用相同的源代码。为了使用这个特性，在你的GLSL代码中包含进预处理器条件，诸如#ifdef SYMBOL，#if SYMBOL==2之类的等等。然后，在你的程序定义中，使用'preprocessor_defines'选项，后跟一个字符串。定义用';'或者','隔开，其中还可以选择使用'='操作符指定定义值。没有'='的那些被隐含地定义为1。例如：
// in your GLSL
#ifdef CLEVERTECHNIQUE
    // some clever stuff here
#else
    // normal technique
#endif
#if NUM_THINGS==2
    // Some specific code
#else
    // something else
#endif
// in  your program definition
preprocessor_defines CLEVERTECHNIQUE,NUMTHINGS=2
这种方法你可以使用相同的源代码又可以包括少许变化，每一个都定义为不同的OGRE程序名，但是基于相同的源代码。


文档:手册:1-4-0:3.1.8 统一高级程序 - OGRE 3D 中文

文档:手册:1-4-0:3.1.8 统一高级程序

3.1.8 统一高级程序

如前文所述，同时编写HLSL和GLSL程序以便针对各自的平台经常是十分有用的，但是如果通过多纹理技术做这个工作，当仅是编程语言不同时，可能会引起材质定义臃肿的问题。好在，还有另一种选择。你可以在一个“统一的”程序定义中“包含”多个程序，那样就能依赖于渲染系统和硬件支持自动地选择一个“代理”程序。

vertex_program myVertexProgram unified
{
    delegate realProgram1
    delegate realProgram2
    ... etc
}

这对顶点和片断程序都有效，并且你想列出多少个代理程序你就可以列出多少个——第一个被当前渲染系统和硬件支持的程序将会被用于真正的程序中。这近乎于一个微技术系统，但是是为了一个单独的程序而且带有特定的目的。你只能把这用在程序带有全部相同的输入、特定的纹理及其他渲染通路/取样状态这些地方。程序之间唯一的不同之处是语言（或者用HLSL的话来说可能就是目标——你可以在单独一个统一程序中包含带有不同目标的多个HLSL程序，或者任意数量的其他高级语言程序），这可能成为一个非常重要的特性。例如，没有这项特性，你就必须如下所示定义一个同时支持HLSL和GLSL的可编程材质：

vertex_program myVertexProgramHLSL hlsl
{
    source prog.hlsl
    entry_point main_vp
    target vs_2_0
}
fragment_program myFragmentProgramHLSL hlsl
{
    source prog.hlsl
    entry_point main_fp
    target ps_2_0
}
vertex_program myVertexProgramGLSL glsl
{
    source prog.vert
}
fragment_program myFragmentProgramGLSL glsl
{
    source prog.frag
    default_params
    {
        param_named tex int 0
    }
}
material SupportHLSLandGLSLwithoutUnified
{
    // HLSL technique
    technique
    {
        pass
        {
            vertex_program_ref myVertexProgramHLSL
            {
                param_named_auto worldViewProj world_view_proj_matrix
                param_named_auto lightColour light_diffuse_colour 0
                param_named_auto lightSpecular light_specular_colour 0
                param_named_auto lightAtten light_attenuation 0
            }
            fragment_program_ref myFragmentProgramHLSL
            {
            }
        }
    }
    // GLSL technique
    technique
    {
        pass
        {
            vertex_program_ref myVertexProgramGLSL
            {
                param_named_auto worldViewProj world_view_proj_matrix
                param_named_auto lightColour light_diffuse_colour 0
                param_named_auto lightSpecular light_specular_colour 0
                param_named_auto lightAtten light_attenuation 0
            }
            fragment_program_ref myFragmentProgramGLSL
            {
            }
        }
    }
}

这真是一个小例子。你向HLSL中添加的所有东西，不得不也复制一遍到GLSL中。因此，替代这种做法，你可以使用统一程序定义，如下所示：

vertex_program myVertexProgramHLSL hlsl
{
    source prog.hlsl
    entry_point main_vp
    target vs_2_0
}
fragment_program myFragmentProgramHLSL hlsl
{
    source prog.hlsl
    entry_point main_fp
    target ps_2_0
}
vertex_program myVertexProgramGLSL glsl
{
    source prog.vert
}
fragment_program myFragmentProgramGLSL glsl
{
    source prog.frag
    default_params
    {
        param_named tex int 0
    }
}
// Unified definition
vertex_program myVertexProgram unified
{
    delegate myVertexProgramGLSL
    delegate myVertexProgramHLSL
}
fragment_program myFragmentProgram unified
{
    delegate myFragmentProgramGLSL
    delegate myFragmentProgramHLSL
}
material SupportHLSLandGLSLwithUnified
{
    // HLSL and GLSL technique
    technique
    {
        pass
        {
            vertex_program_ref myVertexProgram
            {
                param_named_auto worldViewProj world_view_proj_matrix
                param_named_auto lightColour light_diffuse_colour 0
                param_named_auto lightSpecular light_specular_colour 0
                param_named_auto lightAtten light_attenuation 0
            }
            fragment_program_ref myFragmentProgram
            {
            }
        }
    }
}

在运行时中使用到myVertexProgram或者myFragmentProgram时，OGRE基于当前硬件/渲染系统的支持自动挑选一个对应代理的真实程序。如果没有代理可被支持，那么引用统一程序的整个技术被标记为不支持，然后像平常一样检查材质中的下一个技术，看看是否支持当前的渲染系统和硬件。随着你的材质变得越来越大，你就会发现你需要特别的支持HLSL和GLSL（或者需要为了其他什么原因编写多个版本的接口兼容的程序），而统一程序确实可以帮助减少重复。


文档:手册:1-4-0:3.1.9 在渲染通路中使用顶点程序和片断程序 - OGRE 3D 中文

文档:手册:1-4-0:3.1.9 在渲染通路中使用顶点程序和片断程序

3.1.9 在渲染通路中使用顶点程序和片断程序

在材质脚本的pass段中，你可以引用.program脚本中定义的顶点程序和/或片断程序（详见3.1.4 顶点程序与片断程序的声明）。这些程序与使用他们的渲染通路分开定义，是因为他们很可能在多个分开的材质间被重复使用，更可能跨越多个不同的.material材质脚本，所以这种方法可以让你只定义一次而多次使用。

如前文所述命名程序一样，你也可以向它提供参数。下面是一个简单的例子：

vertex_program_ref myVertexProgram
{
    param_indexed_auto 0 worldviewproj_matrix
    param_indexed      4 float4  10.0 0 0 0
}

在这个例子中，我们给渲染通路绑定了一个叫做'myVertexProgram'的顶点程序（它可能被定义在其他地方），并且给它2个参数，一个是'auto'参数，意为我们不必提供数值，只要一个识别码就够了（在这个例子中它是由Ogre自动更新的世界/视点/投影矩阵）。第二个参数是人工指定的参数，一个浮点四元组。其索引于后文描述。

连接到顶点程序和片断程序的语法是一致的，唯一的区别是用'fragment_program_ref'代替了'vertex_program_ref'。

多数情况下顶点程序和片断程序在渲染通路中是彼此联合的，但这不是一成不变的。你可以有一个可以被多个不同片断程序使用的顶点程序。出现的另一种情况是你可以将固定功能管线和可编程管线（shaders）混合在一起使用。你可以使用非可编程顶点固定功能管线，然后在渲染通路中提供一个fragment_program_ref，即渲染通路中会没有vertex_program_ref段。渲染通路中引用的片断程序必须符合以相关API定义的要求，以便从顶点固定管线的输出中读取内容。你也可能只有顶点程序，其输出内容给片断固定功能管线。

渲染API（DirectX和OpenGL）之间的从固定功能管线中读取或者向固定功能管线中写入的要求是相似的，但是每种渲染器（顶点或者片断）实际如何做还要依赖于渲染语言。对于HLSL（DirectX API）和相关的asm，请参考MSDN，链接是http://msdn.microsoft.com/library/。对于GLSL（OpenGL），请参考GLSL规范1.1的7.6节，可在http://developer.3dlabs.com/documents/index.htm获得。GLSL提供的多种变量的编译版本允许你的程序读写各种不同的固定功能管线。对于Cg，请参考CgUsersManual.pdf中的语言概述部分，连同Cg工具包一并可在http://developer.nvidia.com/object/cg_toolkit.html获得。对于HLSL和Cg它的各种绑定允许你的渲染程序读写各种固定功能管线。

参数详解

参数可以被指定为如下四种之一。无论你要定义一个参数只为这个程序特别使用，还是指定默认的程序参数，语法都是一样的。程序特殊使用的参数设置会重载默认值。

  • param_indexed
  • param_indexed_auto
  • param_named
  • param_named_auto
param_indexed
此命令设置索引参数的数值。
格式：param_indexed <index> <type> <value>
示例：param_indexed 0 float4 10.0 0 0 0
'index'简单地是表示应当被写进参数表的位置的数值，应当从你的程序定义派生。索引是与常量在显卡上的存储方式相关的，即四元组方式。例如，如果你在索引0位置定义了一个float4参数，那么下一个索引就会是1。如果你在索引0位置定义了一个matrix4x4，那么下一个可用索引就会是4，因为一个4x4矩阵占据4个索引位置。
'type'的值可以是float4，matrix4x4，float<n>，int4，int<n>。注意'int'参数只可用于某些更为高级的程序语法中，细节请检查D3D或者GL顶点/片断程序有关文档。一般最有用的是float4和matrix4x4。注意如果你使用了一个不是4的倍数的类型，那么剩余的值会被填充为0（因为GPU总是使用4个浮点数一组表示常量，尽管只用了其中的一个）。
'value'简单地是由空格或者tab制表符分割的数值列表，这些数值可以被转换成你指定过的类型。
param_indexed_auto
此命令告诉Ogre用源数值自动更新给定的参数。这就将你从编写代码的繁重劳动中解放出来，当参数总是在改变的时候，不用逐桢去更新。
格式：param_indexed_auto <index> <value_code> <extra_params>
示例：param_indexed_auto 0 worldviewproj_matrix
'index'意思与param_indexed中所述相同；注意，这次你不必指定参数的大小，因为引擎已经知道了。在示例中，使用了世界/视点/投影矩阵暗含地就是说这是matrix4x4。
'value_code'是如下列表中的一个值：
world_matrix
当前世界矩阵。
inverse_world_matrix
当前世界矩阵的反转矩阵。
transpose_world_matrix
当前世界矩阵的转置矩阵
inverse_transpose_world_matrix
当前世界矩阵的反转转置矩阵。
world_matrix_array_3x4
一组世界矩阵，每一个由3x4矩阵表示（3行4列）通常用于doing hardware skinning。你应当令你的顶点程序入口数量足够多以便应付实际使用中的骨骼数量，即要有一组numBones*3个float4。
view_matrix
当前视点矩阵。
inverse_view_matrix
当前视点矩阵的反转矩阵。
transpose_view_matrix
当前视点矩阵的转置矩阵。
inverse_transpose_view_matrix
当前视点矩阵的反转转置矩阵。
projection_matrix
当前投影矩阵。
inverse_projection_matrix
当前投影矩阵的反转矩阵。
transpose_projection_matrix
当前投影矩阵的转置矩阵。
inverse_transpose_projection_matrix
当前投影矩阵的反转转置矩阵。
worldview_matrix
当前世界视点联合矩阵。
inverse_worldview_matrix
当前世界视点联合矩阵的反转矩阵。
transpose_worldview_matrix
当前世界视点联合矩阵的转置矩阵。
inverse_transpose_worldview_matrix
当前世界视点联合矩阵的反转转置矩阵。
viewproj_matrix
当前视点投影联合矩阵。
inverse_viewproj_matrix
当前视点投影联合矩阵的反转矩阵。
transpose_viewproj_matrix
当前视点投影联合矩阵的转置矩阵。
inverse_transpose_viewproj_matrix
当前视点投影联合矩阵的反转转置矩阵。
worldviewproj_matrix
当前世界视点投影联合矩阵。
inverse_worldviewproj_matrix
当前世界视点投影联合矩阵的反转矩阵。
transpose_worldviewproj_matrix
当前世界视点投影联合矩阵的转置矩阵。
inverse_transpose_worldviewproj_matrix
当前世界视点投影联合矩阵的反转转置矩阵。
render_target_flipping
如果绕过投影矩阵变换，此值用来调节改变y坐标。如果渲染目标需要纹理翻转，此值为-1，反之，为+1。
light_diffuse_colour
给定光源的漫反射颜色；这需要'extra_params'中的一个索引，并且关联到能够影响到这个物体的'第n个'最近光源（0代表最近的光源——注意直射光总在列表的首位且总是存在的）。如果附近没有光源，那么参数将被置为黑。
light_specular_colour
给定光源的镜面反射颜色；这需要'extra_params'中的一个索引，并且关联到能够影响到这个物体的'第n个'最近光源（0代表最近的光源——注意直射光总在列表的首位且总是存在的）。如果附近没有光源，那么参数将被置为黑。
light_attenuation
一个float4包含给定光源的4个光源衰减变量。这需要'extra_params'中的一个索引，并且关联到能够影响到这个物体的'第n个'最近光源（0代表最近的光源——注意直射光总在列表的首位且总是存在的）。如果附近没有光源，那么参数将全被置为0。参数的顺序是范围，常量衰减，线性衰减，二次衰减。
spotlight_params
一个float4包含3个点光源参数和一个控制值。参数的顺序是cos（内角/2），cos（外角/2），falloff，且最后的w值为1.0f。对于非点光源，此值为float4(1,0,0,1)。这需要'extra_params'中的一个索引，并且关联到能够影响到这个物体的第'n个'最近光源（0代表最近的光源——注意直射光总在列表的首位且总是存在的）。如果光源比这个还少，那么细节就不像点光源了。
light_position
给定光源在世界空间中的位置。这需要'extra_params'中的一个索引，并且关联到能够影响到这个物体的'第n个'最近光源（0代表最近的光源——注意直射光总在列表的首位且总是存在的）。如果附近没有光源，那么参数将全被置为0。注意，这个属性可用于所有光源，甚至直射光，因为参数被设置为4D向量。点光源会是（pos.x，pos.y，pos.z，1.0f），与此同时，直射光会是（-dir.x，-dir.y，-dir.z，0.0f）。像点积之类的操作在这两种情况下都可以使用。
light_direction
给定光源在世界空间内的方向。这需要'extra_params'中的一个索引，并且关联到能够影响到这个物体的'第n个'最近光源（0代表最近的光源——注意直射光总在列表的首位且总是存在的）。如果附近没有光源，那么参数将全被置为0。 不建议使用——这个属性只用于直射光，而我们建议你使用light_position替代，因为它返回的是一个一般的4D向量。
light_position_object_space
给定光源在物体空间中的位置（即物体在（0，0，0）时）。这需要'extra_params'中的一个索引，并且关联到能够影响到这个物体的'第n个'最近光源（0代表最近的光源——注意直射光总在列表的首位且总是存在的）。如果附近没有光源，那么参数将全被置为0。注意，这个属性可用于所有光源，甚至直射光，因为参数被设置为4D向量。点光源会是（pos.x，pos.y，pos.z，1.0f），与此同时，直射光会是（-dir.x，-dir.y，-dir.z，0.0f）。像点积之类的操作在这两种情况下都可以使用。
light_direction_object_space
给定光源在物体空间内的方向（即物体在（0，0，0）时）。这需要'extra_params'中的一个索引，并且关联到能够影响到这个物体的'第n个'最近光源（0代表最近的光源——注意直射光总在列表的首位且总是存在的）。如果附近没有光源，那么参数将全被置为0。 不建议使用，点光源除外，对于直射光我们建议你使用light_position_object_space替代，因为它返回的是一个一般的4D向量。
light_distance_object_space
给定光源距物体中心的距离——这对于相对小的物体的每个顶点距离计算是有用的估计。这需要'extra_params'中的一个索引，并且关联到能够影响到这个物体的第'n个'最近光源（0代表最近的光源——注意直射光总在列表的首位且总是存在的）。如果附近没有光源，那么参数将全被置为0。
light_position_view_space
给定光源在视点空间中的位置（即物体在（0，0，0）时）。这需要'extra_params'中的一个索引，并且关联到能够影响到这个物体的'第n个'最近光源（0代表最近的光源——注意直射光总在列表的首位且总是存在的）。如果附近没有光源，那么参数将全被置为0。注意，这个属性可用于所有光源，甚至直射光，因为参数被设置为4D向量。点光源会是（pos.x，pos.y，pos.z，1.0f），与此同时，直射光会是（-dir.x，-dir.y，-dir.z，0.0f）。像点积之类的操作在这两种情况下都可以使用。
light_direction_view_space
给定光源在视点空间内的方向（即物体在（0，0，0）时）。这需要'extra_params'中的一个索引，并且关联到能够影响到这个物体的'第n个'最近光源（0代表最近的光源——注意直射光总在列表的首位且总是存在的）。如果附近没有光源，那么参数将全被置为0。 不建议使用，点光源除外，对于直射光我们建议你使用light_position_object_space替代，因为它返回的是一个一般的4D向量。
light_power
给定光源的'能量'调节，HDR渲染中有用。这需要'extra_params'中的一个索引，并且关联到能够影响到这个物体的'第n个'最近光源（0代表最近的光源——注意直射光总在列表的首位且总是存在的）。
light_diffuse_colour_array
同light_diffuse_colour，只不过这是一组参数多个光源，且'extra_params'表示要被处理的'第n个最近'光源的数量。这个参数与基于光源的渲染通路循环选项不兼容但是可以被单渲染通路光照使用。
light_specular_colour_array
同light_specular_colour，只不过这是一组参数多个光源，且'extra_params'表示要被处理的'第n个最近'光源的数量。这个参数与基于光源的渲染通路循环选项不兼容但是可以被单渲染通路光照使用。
light_attenuation_array
同light_attenuation，只不过这是一组参数多个光源，且'extra_params'表示要被处理的'第n个最近'光源的数量。这个参数与基于光源的渲染通路循环选项不兼容但是可以被单渲染通路光照使用。
spotlight_params_array
同spotlight_params，只不过这是一组参数多个光源，且'extra_params'表示要被处理的'第n个最近'光源的数量。这个参数与基于光源的渲染通路循环选项不兼容但是可以被单渲染通路光照使用。
light_position_array
同light_position，只不过这是一组参数多个光源，且'extra_params'表示要被处理的'第n个最近'光源的数量。这个参数与基于光源的渲染通路循环选项不兼容但是可以被单渲染通路光照使用。
light_direction_array
同light_direction，只不过这是一组参数多个光源，且'extra_params'表示要被处理的'第n个最近'光源的数量。这个参数与基于光源的渲染通路循环选项不兼容但是可以被单渲染通路光照使用。
light_position_object_space_array
同light_position_object_space，只不过这是一组参数多个光源，且'extra_params'表示要被处理的'第n个最近'光源的数量。这个参数与基于光源的渲染通路循环选项不兼容但是可以被单渲染通路光照使用。
light_direction_object_space_array
同light_direction_object_space，只不过这是一组参数多个光源，且'extra_params'表示要被处理的'第n个最近'光源的数量。这个参数与基于光源的渲染通路循环选项不兼容但是可以被单渲染通路光照使用。
light_distance_object_space_array
同light_distance_object_space，只不过这是一组参数多个光源，且'extra_params'表示要被处理的'第n个最近'光源的数量。这个参数与基于光源的渲染通路循环选项不兼容但是可以被单渲染通路光照使用。
light_position_view_space_array
同light_position_view_space，只不过这是一组参数多个光源，且'extra_params'表示要被处理的'第n个最近'光源的数量。这个参数与基于光源的渲染通路循环选项不兼容但是可以被单渲染通路光照使用。
light_direction_view_space_array
同light_direction_view_space，只不过这是一组参数多个光源，且'extra_params'表示要被处理的'第n个最近'光源的数量。这个参数与基于光源的渲染通路循环选项不兼容但是可以被单渲染通路光照使用。
light_power_array
同light_power，只不过这是一组参数多个光源，且'extra_params'表示要被处理的'第n个最近'光源的数量。这个参数与基于光源的渲染通路循环选项不兼容但是可以被单渲染通路光照使用。
ambient_light_colour
场景中当前设置的环境光颜色。
surface_ambient_colour
渲染通路的环境反射颜色属性（详见ambient部分）。这样允许你手动访问固定功能管线属性。
surface_diffuse_colour
渲染通路的漫反射颜色属性（详见diffuse部分）。这样允许你手动访问固定功能管线属性。
surface_specular_colour
渲染通路的镜面反射颜色属性（详见specular部分）。这样允许你手动访问固定功能管线属性。
surface_emissive_colour
渲染通路的自发光的量（详见emissive部分）。这样允许你手动访问固定功能管线属性。
surface_shininess
渲染通路的闪光，影响镜面高光的大小（详见specular部分）。这样允许你手动绑定固定功能管线属性。
derived_ambient_light_colour
源环境光颜色，其'r'、'g'、'b'分量由surface_ambient_colour与ambient_light_colour相乘之积分别填充，'a'分量由平面环境alpha分量填充。
derived_scene_colour
源场景色，其'r'、'g'、'b'分量由derived_ambient_light_colour与surface_emissive_colour相加之和分别填充，'a'分量由平面漫反射alpha分量填充。
derived_light_diffuse_colour
源漫反射光颜色，其'r'、'g'、'b'分量由surface_diffuse_colour与light_diffuse_colour相乘之积分别填充，'a'分量由平面漫反射alpha分量填充。这需要'extra_params'中的一个索引，并且关联到能够影响到这个物体的'第n个'最近光源（0代表最近的光源）。
derived_light_specular_colour
源镜面反射光颜色，其'r'、'g'、'b'分量由surface_specular_colour与light_specular_colour相乘之积分别填充，'a'分量由平面镜面反射alpha分量填充。这需要'extra_params'中的一个索引，并且关联到能够影响到这个物体的'第n个'最近光源（0代表最近的光源）。
derived_light_diffuse_colour_array
同derived_light_diffuse_colour，只不过这是一组参数多个光源，且'extra_params'表示要被处理的'第n个最近'光源的数量。这个参数与基于光源的渲染通路循环选项不兼容但是可以被单渲染通路光照使用。
derived_light_specular_colour_array
同derived_light_specular_colour，只不过这是一组参数多个光源，且'extra_params'表示要被处理的'第n个最近'光源的数量。这个参数与基于光源的渲染通路循环选项不兼容但是可以被单渲染通路光照使用。
fog_colour
场景中当前设置的雾的颜色。
fog_params
场景中当前设置的雾的参数。（（exp_density，linear_start，linear_end，1.0 /（linear_end - linear_start））。
camera_position
世界空间中当前摄像机的位置。
camera_position_object_space
物体空间中当前摄像机的位置（当物体在（0，0，0）时）。
time
当前时间，可选参数（或者为1.0f，如果没有提供的话）。
time_0_x
单浮点时间值，基于作为'extra_params'给出的“周期时间”重复。
costime_0_x
time_0_x的余弦。
sintime_0_x
time_0_x的正弦。
tantime_0_x
time_0_x的正切。
time_0_x_packed
time0_x，sintime0_x，costime0_x，tantime0_x四元向量。
time_0_1
同time0_x但是取值范围限制在[0..1]。
costime_0_1
同costime0_x但是取值范围限制在[0..1]。
sintime_0_1
同sintime0_x但是取值范围限制在[0..1]。
tantime_0_1
同tantime0_x但是取值范围限制在[0..1]。
time_0_1_packed
同time0_x_packed但是所有值的取值范围限制在[0..1]。
time_0_2pi
同time0_x但是取值范围限制在[0..2*Pi]。
costime_0_2pi
同costime0_x但是取值范围限制在[0..2*Pi]。
sintime_0_2pi
同sintime0_x但是取值范围限制在[0..2*Pi]。
tantime_0_2pi
同tantime0_x但是取值范围限制在[0..2*Pi]。
time_0_2pi_packed
同time0_x_packed但是取值范围限制在[0..2*Pi]。
frame_time
当前桢时间，可选参数（或者为1.0f，如果没有提供的话）。
fps
当前每秒桢数。
viewport_width
当前视口像素宽度。
viewport_height
当前视口像素高度。
inverse_viewport_width
当前视口像素宽度倒数（1.0/当前视口像素宽度）。
inverse_viewport_height
当前视口像素高度倒数（1.0/当前视口像素高度）。
viewport_size
视口大小，四元向量viewport_width、viewport_height、inverse_viewport_width、inverse_viewport_height。
texel_offsets
提供对纹理元素到像素映射的渲染系统特定纹理坐标偏移量细节。float4（horizontalOffset，verticalOffset，horizontalOffset / viewport_width，verticalOffset / viewport_height）。
view_direction
物体空间中视点方向向量。
view_side_vector
视点本地X坐标。
view_up_vector
视点本地Y坐标。
fov
垂直弧线可视区域。
near_clip_distance
近裁剪距离，世界单位。
far_clip_distance
远裁剪距离，世界单位（对于无限视点投影来说可能是0）。
texture_viewproj_matrix
应用于被指定作为“阴影接受者”的顶点程序或者是纹理单元被标记为content_type shadow；这为当前阴影投影机提供了视点/投影矩阵的细节。可选的'extra_params'入口指定了投影机表示哪个光源（对于content_type shadow的例子，在一个渲染通路里可能出现不止一个阴影纹理），其中0是默认的并且表示该渲染通路引用的第一个光源。
scene_depth_range
提供有关从当前被用来渲染的摄像机观察到的深度范围信息。float4（minDepth，maxDepth，depthRange，1 / depthRange）。
shadow_scene_depth_range
提供有关从与选定的光源相关的阴影摄像机观察到的深度范围信息。需要一个光源索引参数。float4（minDepth，maxDepth，depthRange，1 / depthRange）。
texture_size
提供选定纹理单元的纹理大小。需要一个纹理单元索引参数。float4（width，height，depth，1）。对于2D纹理，深度设置为1，对于1D纹理，高度和深度设置为1。
inverse_texture_size
提供选定纹理单元的纹理大小的倒数。需要一个纹理单元索引参数。float4（1 / width，1 / height，1 / depth，1）。对于2D纹理，深度设置为1，对于1D纹理，高度和深度设置为1。
packed_texture_size
提供选定纹理单元的打包纹理大小。需要一个纹理单元索引参数。float4（width，height，1 / width，1 / height）。对于3D纹理，深度被忽略掉，对于1D纹理，高度被设置为1。
pass_number
设置gpu参数中活动渲染通路索引号。技术中第一个渲染通路编号为0，第二个编号为1，以此类推。这对于需要知道各是什么渲染通路的多通路渲染（如皮毛或者模糊渲染）是有用的。依靠在程序定义中的默认的程序参数列表里设置自动参数，没有必要在每个渲染通路中设置渲染通路号参数。（详见fur_example）
pass_iteration_number
用于需要知道当前渲染通路循环数是多少的GPU程序。渲染通路的第一次循环编号为0。最后一次循环号是渲染通路循环数-1。如果一个渲染通路它的循环属性被置为5，那么最后一次的循环号（第5次执行这个渲染通路）是4。（详见iteration）
animation_parametric
用于硬件顶点动画。对于变形动画来说，设置参数值（0..1）表示第一个位置关键桢（绑定到位置）与第二个位置关键桢（绑定到第一个空的纹理坐标）之间的距离，以便顶点程序可以在它们之间插值。对于姿势动画，说明一组最多有4个参数权值，它们应用于一组姿势，每组姿势最多4个，(每一个绑定到常量的x、y、z、w上），一个姿势一个。原始位置被放在一般的位置缓冲器中，且权重为1.0的姿势所在的位置的偏移量是前n个空纹理坐标；'n'由传递给includes_pose_animation的值决定。如果需要的同步姿势比4个多，那么你会需要不止一个渲染器常量存放这些参数值，在这种情况下，你需要使用这个进行多次绑定，引用不同的常量入口；第二个会包含姿势5到8的参数，第三个包含姿势9到12的参数，以此类推。
custom
这允许你映射一个自定义参数到GPU程序参数上（详见Renderable::setCustomParameter）。它需要你添上'extra_params'中索引，该索引在Renderable::setCustomParameter调用时会被用到，且这会保证无论何时使用这个Renderable，它都会有其自定义的参数映射。重要的是这个参数已经在所有Renderables上定义了，且包含这个自动映射的材质赋值给Renderables，否则过程会失败。
param_named
这同param_indexed是一样的，但是使用一个命名的参数替代索引号。这只能与包括参数名的高级程序一起使用；如果你要使用一个编译程序，那么你除了索引别无选择。注意，你也可以在高级程序中使用索引参数，但是这样它就不便移动了，因为如果你用高级程序渲染参数，索引号会发生改变。
格式: param_named <name> <type> <value>
示例：param_named shininess float4 10.0 0 0 0
这里的type是必需的，因为当材质脚本被分析时，程序并不被编译和装载，所以在这时，我们不知道参数是什么类型。程序只有被使用过后才装载和编译，为的是节约内存。
param_named_auto
功能同param_indexed_auto，只不过这个是有名字的，用于高级程序。
格式：param_named_auto <name> <value_code> <extra_params>
示例：param_named_auto worldViewProj WORLDVIEWPROJ_MATRIX
extra_params允许的数值代码和意思详见param_indexed_auto。

阴影和顶点程序

当使用阴影时（详见7. 阴影），顶点程序的使用可以增加一些额外的复杂度，因为Ogre只在使用固定功能管线时才能自动处理所有事情。如果你使用顶点程序，并且也正要使用阴影，你可能需要做出一些调整。

如果你使用模版阴影，那么任何执行顶点变形操作的顶点程序可能会有问题，因为模版阴影在CPU上计算，并不访问被修改过的顶点。如果顶点程序要完成标准骨骼动画，这是可以的（参看上述部分），因为Ogre知道如何用软件方法复制效果，但是任何其他顶点变形都不能被复制，且你将或者不得不接受阴影无法反映改变的结果或者干脆关闭那个物体的阴影。

如果你使用纹理阴影，那么顶点变形是可以接受的；但是，当渲染物体到阴影纹理中时（阴影施放者通路），阴影不得不被渲染为固体颜色（参看环境光颜色）。因此你必须提供一个备选顶点程序，Ogre提供给你一种方法，指定一个程序渲染阴影施放者时使用。基本上，你可以使用与原始顶点程序完全相同的语法连接备选顶点程序：

shadow_caster_vertex_program_ref myShadowCasterVertexProgram
{
    param_indexed_auto 0 worldviewproj_matrix
    param_indexed_auto 4 ambient_light_colour
}

当渲染阴影施放者时，Ogre会自动地使用备选程序。你可以向程序上绑定相同或不同的参数——最重要的事情是绑定ambiend_light_colour，因为这决定着经过调节后的阴影的颜色。如果你不提供备选程序，Ogre会回退到固定功能材质上，但是任何你在顶点程序中所作出的顶点改变在这里都不会反映出来。

此外，当用阴影纹理渲染阴影接收者时，Ogre需要投影阴影纹理。在固定功能模式下这是自动完成的，但是如果接收者使用了顶点程序，它们需要有一个阴影接收者程序完成通常的顶点改变，但是也生成了投影纹理坐标。连接到渲染通路里的额外的程序如下所示：

shadow_receiver_vertex_program_ref myShadowReceiverVertexProgram
{
    param_indexed_auto 0 worldviewproj_matrix
    param_indexed_auto 4 texture_viewproj_matrix
}

就写这个备选程序来说，有一个'texture_viewproj_matrix'绑定的自动参数，给程序提供纹理投影参数。顶点程序应该完成它的一般顶点处理，而使用这个矩阵生成纹理坐标且将他们放置在纹理坐标集0和1中，因为一些阴影技术使用2个纹理单元。这种顶点程序的顶点输出颜色必须总是白的，以便不影响最终渲染完成的阴影颜色。

当使用附加的纹理阴影时，阴影渲染通路实际上是光照渲染，所以如果你运行了任何片断程序进行光照渲染，你也许要拉入一个自定义的片断程序。shadow_receiver_fragment_program_ref的使用方法如下：

shadow_receiver_fragment_program_ref myShadowReceiverFragmentProgram
{
    param_named_auto lightDiffuse light_diffuse_colour 0
}

你应当放过来自自定义顶点程序的投影阴影坐标。至于纹理，纹理单元0将会总是阴影纹理。任何其他渲染通路里绑定的纹理也会被处理，但是会被向后移动一个单位以便为阴影纹理留出空间。因此你的阴影接收者片断程序很可能与你的一般材质的光照渲染通路是一样的，除了你额外在索引0处插入了一个纹理采样器，使用它调整结果（调节漫反射和镜面反射分量）。


文档:手册:1-4-0:3.1.10 顶点纹理拾取（Vertex Texture Fetch） - OGRE 3D 中文

文档:手册:1-4-0:3.1.10 顶点纹理拾取（Vertex Texture Fetch）

From OGRE 3D 中文

3.1.10 顶点纹理拾取（Vertex Texture Fetch）

介绍

近几代显卡允许你从顶点程序中的纹理读取内容，而不是像以前一样仅仅从片断程序中读取。例如：这就允许你读取纹理内容并且显示基于所包含颜色深度的顶点。

声明顶点纹理拾取的使用

因为对于顶点纹理拾取的硬件支持还不是十分普遍，所以当声明要使用顶点纹理的顶点程序时，你需要使用uses_vertex_texture_fetch指示标志，以便如果硬件不支持时，技术可以回退，采用别的技术。针对DirectX的渲染器并不是严格必需使用这个标志，因为顶点纹理拾取仅仅在vs_3_0中支持，作为必要的语法写入你的渲染器定义中，但是对于OpenGL（GLSL），都是支持GLSL的显卡而不支持顶点纹理，所以你必须显式地指明你需要顶点纹理拾取支持。

渲染系统纹理绑定的区别

不幸地是，绑定纹理以便他们可为顶点程序所用的方法并不是十分标准化的。在此文档编写时，就顶点纹理来说，在DirectX9下的Shader Model 3.0（SM3.0）硬件就包括4种不同的取样器绑定。另一方面，OpenGL可以通过GLSL访问顶点纹理（并且在编译器里还可以通过NV_vertex_program_3，尽管并不常用），而且纹理是与片断管线共享的。我希望随着DirectX10的问世，DirectX也转向GL这种模式，因为统一渲染架构意味着在两个舞台之间共享纹理资源。像现在这样，我们被不一致的情形缠住了。

为了应对这种情况，你需要在一个纹理单元内使用binding_type属性指明你的纹理针对哪一个纹理单元——‘片断’（默认）还是‘顶点’。对于没有分开单独绑定的渲染系统，事实上这什么也没做。但是对于那些确实要分开绑定的渲染系统，它会保证你的纹理被绑定在正确的处理单元上。注意，DirectX9对于顶点和片断管线是分开绑定的，一个纹理绑定到顶点处理单元仍然会占用一个‘槽位’，那么这个槽位就不能供片断管线使用了。我不试图去找哪里记载了这个，但是nVidia例子确定地避免将一个纹理绑定到顶点和片断单元的同一个槽位，并且在我试图这么做时，片断单元中纹理不能正确显示，而我将它移动到下一个单元时，它就可以正确显示了。

纹理格式限制

在撰写本文档时，你能够在顶点程序中使用的纹理类型被限制为1个分量或4个分量的全精度浮点格式。代码上相当于PF_FLOAT32_R或者PF_FLOAT32_RGBA。其他格式都不支持。另外，纹理必须是规则的2D纹理（不能是cube或者volumn映射），并且它是不支持mipmap技术和过滤技术的，虽然如此，但是如果你想要在你的顶点程序中实现过滤，你还是可以通过多次取样实现它。

硬件限制

在撰写本文档时（2006年3季度初），ATI当前的显卡产品（Radeon X1n00）不支持纹理拾取技术。nVidia的6n00和7n00系列显卡都支持纹理拾取技术。ATI支持一种可供选择的方法，叫做“对顶点缓冲器的渲染”，但是现在还没有被标准化并且在实现上还有很大的不同，所以还不能认为它是可以随便替代的方法。尽管Radeon X1n00显卡声称支持vs_3_0（需要顶点纹理拾取），这仍是一个问题。


文档:手册:1-4-0:3.1.11 材质拷贝 - OGRE 3D 中文

文档:手册:1-4-0:3.1.11 材质拷贝

3.1.11 材质拷贝

当新创建的材质脚本与另一个材质脚本仅有微小差别时，脚本编写者需要在脚本内拷贝粘贴。对于简单脚本来说，拷贝/粘贴方式是可以接受的。但是当需要多种变化时，编辑顶点和像素渲染器中使用的多路渲染的复杂材质就变成一项冗长乏味的工作。为了减少创建与以前定义过的材质只有微小差别的新材质的冗余，新材质可以拷贝之前定义的材质，仅改变或增加特定的技术、渲染通路、纹理单元。

要创建一个基于之前定义好的材质的新材质需要在新材质名后面增加一个冒号后面紧跟着是被拷贝的材质名。格式: material <NewUniqueChildName> : <ReferanceParentMaterial> 唯一要注意的是，父材质必须于子材质被解析之前先行有所定义或解析。最简单的方法是将父材质放在材质脚本的前面位置。材质脚本被装入Ogre后，材质就不再维护它的拷贝继承关系。如果父材质在运行时通过代码有所改变，那么这些变化不会作用于它的子材质。

脚本中的材质拷贝减轻了拷贝/粘贴的繁复劳动，而有能力识别改变的特定技术、渲染通路、纹理单元，使得材质拷贝变得更容易。子材质中的技术、渲染通路、纹理单元可以被直接识别，免去了必须依靠名字关联他们，布置这些技术、渲染通路、纹理单元。技术和渲染通路可以有名字，纹理单元可以在材质脚本内编号。

注意：使用名字是一个可选项，所以较早以前的脚本仍然可以很好的工作，而且你仍然可以从他们那里继承。

在从其他材质拷贝过来的材质中名字变得非常有用。为了重载数值，它们必须在正确的技术、渲染通路、纹理单元中。在子材质中，脚本可以用技术、渲染通路、纹理单元的顺序排列布局，但是假如只有一个参数需要改变比如第5个渲染通路，那么这第5个渲染通路前面的四个渲染通路就必须占4个位置。举例如下：

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

这种方法对于只有微小改变的材质还是有些繁冗。一个更为简单的方法就是直接命名渲染通路，而不列出前面的几个渲染通路。看下面的例子：

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

必须知道父渲染通路名，为了让它正常工作，它还必须在正确的技术里。指明技术名和渲染通路名是最好的方法。如果父技术或父渲染通路没有被命名，那么就如上面的例子一样，使用它们的索引值作为它们的名字。

向拷贝材质中增加新的技术、渲染通路

如果要向拷贝材质中增加一个新的技术或渲染通路，就要给这个技术或渲染通路起一个独一无二的名字，这个名字不能出现在父材质中。也可以用父材质中最后一个索引加1作为索引名。新增加的技术、渲染通路将被添加到从父材质拷贝来的那些技术或渲染通路的后面。

注意：如果渲染通路或技术无法给定名称，那么它们会根据各自的索引被赋予默认的名字。例如，第一个渲染通路索引是0，那么它的名字也就是0。

处理程序引用和渲染器参数

对于一个只需要改变渲染通路中某些渲染器参数的子材质来说，可按下述方法进行：

material furtest2 : furtest1
{
  technique ati8500
  {
    pass fur3
    {
      fragment_program_ref
      {
        param_named furlength float 0.5
      }
    }
  }
}

没有要求必须给片断程序引用一个名字，因为父材质已经命名了；这同样也适用于顶点程序，但是仅限于在从父材质拷贝来的渲染通路里定义过的程序引用名。如果父材质中没有程序引用，则会生成一个例外，因为材质分析器没有关于脚本想要实现什么东西的任何提示。

程序引用可以被增加到没有程序引用的拷贝渲染通路里。整个程序引用将必须在渲染通路里被定义出来。

如果一个不同的程序引用要被用在拷贝渲染通路里，那么只要加入这个不同的顶点/片断程序引用名就可以了。这在你想要从父材质继承同时要为其中一个渲染通路使用一个不同的渲染程序的时候是很有用的。

识别纹理单元重载数值

在一个材质的渲染通路内可以给特殊的纹理单元状态（TUS）一个唯一的名字，以便以后当需要重载未事先声明纹理单元的渲染通路中的指定纹理单元状态时它可以在克隆材质中被识别。让克隆材质的渲染通路里的纹理单元使用唯一的名字为渲染通路纹理单元列表后面增加了一个新纹理单元。

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

纹理别名

当仅需要为了克隆材质指定纹理单元中使用的纹理时，纹理别名是有用的。在原材质中，即要被克隆的原始材质，每一个纹理单元都可以被给予一个纹理别名。然后脚本中的克隆材质就可以指定每一个纹理别名分别使用什么纹理。

纹理单元中的纹理别名用法如下：格式:texture_alias <name> 默认:此<name>默认与texture_unit的<name>相同，如果设置如下：

texture_unit DiffuseTex
{
  texture diffuse.jpg
}

texture_alias默认为DiffuseTex。示例：要被克隆的基础材质：

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

注意，GLSL和HLSL技术使用了相同的纹理。每一个纹理使用类型都被给了一个纹理别名来描述纹理被用来做什么。所以，GLSL里的第一个纹理单元有与HLSL里的纹理单元状态一样的别名，因为使用的是相同的纹理。第二、第三个纹理单元也是如此。

就演示来说，GLSL技术使用了texture_unit命名，因而texture_alias名字就不必设置，因为它默认就是texture_unit名字。那么既然减少打字，为什么不都用默认值？就大多数情况来说，是可以的。当你克隆了一个材质，然后想改变别名时，你必须在脚本中使用texture_alias命令。你不能改变克隆材质中的texture_unit名字，而texture_alias提供了一个赋值别名的工具。

现在我们想要克隆材质但只改变使用的纹理。我们可以拷贝粘贴全部材质，但是如果我们以后决定改变基础材质，那么我们也必须在脚本中更新拷贝材质。利用set_texture_alias，拷贝一个材质现在是非常容易的。在材质定义的首部指定set_texture_alias。使用指定纹理别名的所有技术将被set_texture_alias影响。

格式: set_texture_alias <alias name> <texture name>

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

在子材质中的两种技术里的纹理将被自动替换成我们想使用的新的纹理。

只要你建立了纹理别名，同样的过程也可以用代码完成，所以那时就没有必要在技术/渲染通路/纹理单元状态之间来回移动改变纹理。你只要调用myMaterialPtr->applyTextureAliases（myAliasTextureNameList）就会更新所有符合你作为参数传递的映射容器引用中的别名的纹理单元中的所有纹理。

你不必提供拷贝材质中的所有纹理。

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

材质fxTest2只改变材质fxTest的漫反射映射和镜面反射映射，而使用相同的普通映射。

另一个例子：

material fxTest3 : TSNormalSpecMapping
{
  set_texture_alias DiffuseMap fxTest2Diff.png
}

fxTest3的普通映射和镜面映射使用TSNormalSpecMapping材质中的默认设置，但是将有不同的漫反射映射。所以你的基础材质可以定义为默认材质去使用，然后子材质可以重载特定的纹理。


文档:手册:1-4-0:3.2 合成器（Compositor）脚本 - OGRE 3D 中文

文档:手册:1-4-0:3.2 合成器（Compositor）脚本

3.2 合成器（Compositor）脚本

合成器架构是OGRE API的一部分，它允许你轻松定义全屏的后加工处理效果。合成器脚本给你提供了在脚本里定义合成器效果的能力，并且它们可以重复使用而且容易更改，而不必使用API去定义它们。虽然你仍然要使用代码实例化一个针对可视视口的合成器，但是比起实际上定义合成器本身这已经是相当简单的过程了。

合成器基本原理

进行后处理效果通常包括最开始的用纹理渲染场景，其中有些是添加到主窗口的有些是替代主窗口的。一旦场景中有了纹理，你就可以将场景图像送入一个片断程序，并在片断程序中通过全屏范围渲染它。这一后处理渲染的目标可以是主结果，又或者是另一种渲染纹理，以至于在画面上形成多级回旋。你甚至可以在两个渲染纹理之间反复进行渲染，以达到需要多次循环的回旋效果，而不是每层使用一个单独的纹理。最终，你将得到一个全屏窗口的最终渲染输出结果。这将代替整个窗口（因此，主窗口不必渲染场景本身），或者是一个联合效果。

因此，我们可以讨论一下，如何有效地实现这些技术，需要如下一些定义：

合成器
一个可以被应用于用户视口的全屏效果定义。当你写合成器脚本时，这就是你在这部分要详细定义的东西。
合成器实例
一个被应用于单一视口的合成器实例。根据合成器定义创建这些实例。参看3.2.4 合成器应用。
合成器链
在一个视口上同时打开不止一个合成器实例是可能的，即一个合成器将其前面一个合成器的结果作为自己的输入。这就是合成器链。每一个至少有一个合成器的视口都有一个合成器链。参看3.2.4 合成器应用。
目标
就是渲染目标，一系列渲染操作的结果被送到此处。一个目标可能就是一个最后的输出结果（并且这是隐含的，即不必声明它），或者是脚本中用texture行声明的中间渲染纹理。不是输出目标的其他目标都有确定的大小和你可以控制的像素格式。
输出目标
也是目标，但是它是所有操作的唯一最终结果。此目标的大小和像素格式不能由合成器控制，因为它是由使用它的应用环境决定的，因此你不能在你的脚本里声明它。但是，你确实可以为它声明一个目标通路。详见下面介绍。
目标通路
一个目标在一个合成效果过程中可以被多次渲染。个别情况下，如果在两个纹理之间反复回旋，每个目标你都会得到不只一个目标通路。目标通路在脚本中用target行或者target_output行声明，后者是只能有一个的最终输出目标通路。
通路
在一个目标通路里，有一个或多个单独的渲染通路，分别进行各自的渲染动作，例如渲染初始场景（或者从合成器链中的上一个合成器取结果），渲染全屏图像，或者清空一个或多个缓冲器。典型地，在一个单独的目标通路里，你将使用'render scene'通路或者'render quad'通路，二者选其一，不能同时用。清空两种类型都可以使用。

装载脚本

合成器脚本是在资源组被初始化时被装载的：OGRE在所有与组相关的资源位置（详见Root::addResourceLocation）搜索'.compositor'后缀的文件，并解析它。如果你想人工解析，使用CompositorSerializer::parseScript。

格式

多个合成器可能被定义在单独的一个脚本里。脚本格式是借用C++的，以大括号（'{'，'}'）为段分隔符，以'//'作为一行的开始表示注释这一行（注意，不允许嵌套注释）。一般格式见如下例子所示：

// This is a comment
// Black and white effect
compositor B&W
{
    technique
    {
        // Temporary textures
        texture rt0 target_width target_height PF_A8R8G8B8

        target rt0
        {
            // Render output from previous compositor (or original scene)
            input previous
        }

        target_output
        {
            // Start with clear output
            input none
            // Draw a fullscreen quad with the black and white image
            pass render_quad
            {
                // Renders a fullscreen quad with a material
                material Ogre/Compositor/BlackAndWhite
                input 0 rt0
            }
        }
    }
}

脚本中每个合成器都必须给定一个名字，即最开始的大括号（'{'）前面的'compositor <name>'行。这个名字必须是全局唯一的。它可以包括路径字符（如上例所示）以便逻辑上区分你的合成器，也为了避免重名，但是引擎并不将这个名字分级对待，而仅作为字符串处理。名字里也可以包含空格，但是如果这样的话，就必须用双引号括起来，如compositor "My Name"。

合成器的主要部件是技术，目标通路和合成器通路，详细情况后续章节会有所介绍。


文档:手册:1-4-0:3.2.1 技术（Techniques） - OGRE 3D 中文

文档:手册:1-4-0:3.2.1 技术（Techniques）

From OGRE 3D 中文

3.2.1 技术（Techniques）

合成器技术在描述所要达到效果的方法方面与材质技术极为相似。假如要为硬件不支持你要使用的技术而提供回撤机制，那么在一个合成器定义中可以有不止一个技术。从硬件支持方面来说，基于以下两点评估技术：

材质支持
渲染全屏的所有合成器通路使用一个材质。对于要被支持的技术，所有被引用的材质必须至少已经材质技术。如果不支持，合成器技术被标记为不支持，且不会被使用。
纹理格式支持
这个稍微更复杂一些。当你在技术中请求一个纹理时，你请求的是一个像素格式。不是所有格式都被硬件支持，特别是浮点格式。但是，这种情况下硬件一般会将请求的纹理格式降级到硬件支持的格式——因为合成器效果的原因，如果遇到这种情况，你也许想使用不同的方法。因此，当评估技术时，合成器会首先寻找当前硬件本身支持的最准确的你请求的像素格式，并且如果不支持，会跳到下一个技术，因此允许你使用采取不同方法的更简单的像素格式定义其它技术。如果发现当前硬件不支持任何一个技术，它会再次尝试，这次允许硬件降级纹理格式，因此找到某个对你所请求纹理格式的支持。

与材质技术一样，按脚本中定义的顺序评估合成器技术。声明在前的技术，其优先级高于后面的。示例：technique { } 技术可以有如下嵌套元素：

  • texture
  • target
  • target_output
texture
这声明了为了在target passes中使用的一个渲染纹理。
格式: texture <Name> <Width> <Height> <Pixel Format>
这里介绍一下上面用到的参数：
Name
给渲染纹理的这个名字在这个合成器中必须是唯一的。当纹理被用作对渲染全屏的材质的输入时，这个名字被用来指示被渲染到target passes和passes中的纹理。
Width, Height
渲染材质的宽和高。你既可以指定固定的宽和高，也可以要求纹理匹配合成器所在视口的物理维度大小（指定target_width和target_height代替数值维度）。
Pixel Format
渲染材质的像素格式。这影响内存占用，能使用什么颜色通道，在这些通道里会有什么样的精度。可用的选项有PF_A8R8G8B8，PF_R8G8B8A8，PF_R8G8B8，PF_FLOAT16_RGBA，PF_FLOAT16_RGB，PF_FLOAT16_R，PF_FLOAT32_RGBA，PF_FLOAT32_RGB以及PF_FLOAT32_R。
示例: texture rt0 512 512 PF_R8G8B8A8
示例: texture rt1 target_width target_height PF_FLOAT32_RGB


文档:手册:1-4-0:3.2.2 目标通路（Target Passes） - OGRE 3D 中文

文档:手册:1-4-0:3.2.2 目标通路（Target Passes）

From OGRE 3D 中文

目标通路是向一个给定的目标进行渲染的行动，这个给定的目标或者是渲染纹理或者是最终的输出。你可以通过增加多个目标通路到你的合成器脚本里的方法多次更新相同的渲染纹理——这对两个渲染纹理之间要实现不能由单一渲染完成的复杂混合‘反复’渲染十分有用，例如模糊。

共有两类目标通路，其中更新渲染纹理的是：

格式: target <Name> { }

... 另一种定义最终输出渲染的是：

格式: target_output { }

二者的内容是相似的，唯一的真正区别是你只有一个单独的target_output入口，而target入口可以有很多。下面的是你可以在合成器脚本的'target'或'target_output'段中使用的属性：

  • input
  • only_initial
  • visibility_mask
  • lod_bias
  • material_scheme
  • pass

Attribute Descriptions

input

设置目标的输入模式，告诉目标通路在它的任何通路被渲染以前输入什么。

格式: input (none | previous)

默认: input none

none
目标将没有东西作为输入，目标的所有内容必须使用它自己的通路生成。注意，这并不意味着目标会是空的，只不过是没有数据填入。若要让这个目标真的为空，你需要一个'clear'通路。
previous
目标会装入视口的上一个内容。如果这是链表中的第一个合成器，那么这或许是初始场景；如果视口有多重合成器可用，那么它或许会是来自链表中前一合成器的输出。

only_initial

如果设置为打开，那么这个目标通路只会在效果已经打开后初始化地执行一次。这可能对只执行一次的渲染是有用的，此后的静态内容可以被剩余的合成器使用。

格式: only_initial (on | off)

默认: only_initial off

visibility_mask

为这个目标通路中的任意render_scene设置可视掩码。这是一个位掩码（尽管它必须被指定为十进制数，而不是十六进制数）并映射到SceneManager::setVisibilityMask。

格式: visibility_mask <mask>

默认: visibility_mask 4294967295

lod_bias

为这个目标通路中的任意render_scene设置场景LOD偏向。默认是1.0，所有比1.0低的值意味着更低的质量，越高意味着质量越高。

格式: lod_bias <lodbias>

默认: lod_bias 1.0

material_scheme

为这个目标通路中的任意render_scene设置材质方案。材质方案允许你为场景里所有物体选择渲染路径。

格式: material_scheme <Name>

默认: material_scheme Default


文档:手册:1-4-0:3.2.3 合成器通路（Compositor Passes） - OGRE 3D 中文

文档:手册:1-4-0:3.2.3 合成器通路（Compositor Passes）

From OGRE 3D 中文

3.2.3 合成器通路

一个通路就是目标通路中表现的一个单独的渲染动作。

格式: 'pass' (render_quad | clear | stencil | render_scene) { }

总共有四类：

clear
这类通路将目标内一个或多个缓冲器的内容设置为固定的值。这样就能清空颜色缓冲器为固定的颜色，设置深度缓冲器为特定的一类内容，将一个值填到模板缓冲器中，或者是上述三者的任意组合。
stencil
这类通路为子通路配置模板操作。它可以为你设置模板函数，操作和引用值来表现你所要的模板效果。
render_scene
这类通路用于表现常规场景渲染。它会用到来自父目标通路的visibility_mask，lod_bias，和material_scheme。
render_quad
这类通路使用一个给定的材质渲染一片覆盖整个渲染目标的区域。毫无疑问，你会想要将其它目标通路的结果输入进这个操作里，以表现全屏效果。

可在.compositor脚本的'pass'段使用的属性如下：

可用的通路属性

  • 材质material
  • 输入input
  • 标识符identifier
  • 首渲染队列first_render_queue
  • 末渲染队列last_render_queue
  • 清空clear
  • 模板stencil
material
对于类型'render_quad'的通路来说，设置用于渲染方块区域的材质。你会想要在这个材质上使用shaders以表现全屏效果，并使用input属性将其它纹理目标映射到这个材质需要的纹理绑定上。
格式: material <Name>

input
对于类型'render_quad'的通路来说，就是你如何将一个或多个局部渲染纹理（见compositor_texture）映射到你要用来全屏区域的材质。要绑定超过一个纹理，则用不同的取样器索引号，重复这个属性。
格式: input <sampler> <Name>

sampler
要设置的纹理取样器，必须是一个数，取值范围[0, OGRE_MAX_TEXTURE_LAYERS-1]。
Name
要绑定的局部渲染纹理名，在compositor_texture中声明并在一个或多个目标通路里渲染
示例: input 0 rt0

identifier
与通路相关联的一个数字标识符。用于给合成器注册一个监听者（CompositorInstance::addListener），并且能够在你收到有关事件时，标识哪个通路是要被进行处理。0到2的32次方之间的数都是可以的。
格式: identifier <number>
示例: identifier 99945
默认: identifier 0

first_render_queue
对于类型'render_quad'的通路来说，这个属性设置渲染中包含的第一个渲染队列id。默认是RENDER_QUEUE_SKIES_EARLY的值。
格式: first_render_queue <id>
默认: first_render_queue 5

last_render_queue
对于类型'render_quad'的通路来说，这个属性设置渲染中包含的最后一个渲染队列id。默认是RENDER_QUEUE_SKIES_LATE的值。
格式: last_render_queue <id>
默认: last_render_queue 95

Clear Section

对于类型'clear'的通路来说，这一段定义缓冲区清空参数。

格式: clear { }

可在.compositor脚本的'clear'段使用的属性如下：

  • 缓冲区buffers
  • 颜色值colour_value
  • 深度值depth_value
  • 模板值stencil_value
buffers
设置被这个通路清空的缓冲区。
格式: buffers [colour] [depth] [stencil]
默认: buffers colour depth

colour_value
如果颜色缓冲区要被清空的话，设置此通路用来填充颜色缓冲区的颜色。
格式: colour_value <red> <green> <blue> <alpha>
默认: colour_value 0 0 0 0

depth_value
如果深度缓冲区要被清空的话，设置此通路用来填充深度缓冲区的深度值。
格式: depth_value <depth>
默认: depth_value 1.0

stencil_value
如果模板缓冲区要被清空的话，设置此通路用来填充模板缓冲区的模板值。
格式: stencil_value <value>
默认: stencil_value 0.0

Stencil Section 对于类型'stencil'的通路，这一段定义模板操作参数。

格式: stencil { }

可在.compositor脚本的'stencil'段使用的属性如下：

  • 模板检测check
  • 比较函数comp_func
  • 引用值ref_value
  • 掩码mask
  • 失败操作fail_op
  • depth_fail_op
  • pass_op
  • two_sided
check
允许或禁止模板检测，因而控制此部分其余特性的使用。如果模板检测是off，那么这部分的其余选项没有任何作用。
格式: check (on | off)

comp_func
设置比较函数，所使用的比较方法如下进行：
(ref_value & mask) comp_func (Stencil Buffer Value & mask)
比较结果将会是模板缓冲器上的3个动作之一，或测试失败，或模板测试成功但深度缓冲检测失败，或模板测试成功且深度缓冲检测也成功。依据上述不同结果，分别在fail_op，depth_fail_op和pass_op里设置相应动作。如果模板检测失败，那么没有颜色或深度会被写入帧缓冲区。
格式: comp_func (always_fail | always_pass | less | less_equal | not_equal | greater_equal | greater)
默认: comp_func always_pass

ref_value
设置comp_func中所描述的用于和模板缓冲区比较的引用值。
格式: ref_value <value>
默认: ref_value 0.0

mask
设置comp_func中所描述的用于和模板缓冲区比较的掩码。
格式: mask <value>
默认: mask 4294967295

fail_op
如果模板比较（comp_func）和深度比较都失败了，设置对模板缓冲区里的值的处理方法。
格式: fail_op (keep | zero | replace | increment | decrement | increment_wrap | decrement_wrap | invert)
默认: depth_fail_op keep
这些动作意思是：
keep
保持模板缓冲区不变。
zero
设置模板值为0。
replace
设置模板值为引用值。
increment
模板值加1，直到最大值。
decrement
模板值减1，直到0。
increment_wrap
模板值加1，到最大值时，折返回0。
decrement_wrap
模板值减1，低于0时，折返回最大值。
invert
将模板值取倒数。

depth_fail_op
如果模板比较（comp_func）通过了，但深度比较失败，设置对模板缓冲器里的值的处理方法。
格式: depth_fail_op (keep | zero | replace | increment | decrement | increment_wrap | decrement_wrap | invert)
默认: depth_fail_op keep

pass_op
如果模板比较（comp_func）和深度比较都通过了，设置对模板缓冲区里的值的处理方法。
格式: pass_op (keep | zero | replace | increment | decrement | increment_wrap | decrement_wrap | invert)
默认: pass_op keep

two_sided
允许或禁止双侧模板操作，意即反转的操作应用于背面的多边形。
格式: two_sided (on | off)
默认: two_sided off


文档:手册:1-4-0:3.2.4 合成器应用 - OGRE 3D 中文

文档:手册:1-4-0:3.2.4 合成器应用

3.2.4 合成器应用

向视口增加一个合成器实例是非常简单的。你所要做的是：

CompositorManager::getSingleton（）.addCompositor（viewport, compositorName）;

上面例子中viewport是指向你的视口的指针，而compositorName是要创建实例的那个合成器的名字。这样，一个新的合成器实例就会被加到那个视口的新合成器链表中。你可以多次调用这个方法，向这个视口上的合成器链表中增加更多的合成器。就默认来说，每个被加入的合成器都是不可用的，但是你可以修改这个状态，通过调用：

CompositorManager::getSingleton（）.setCompositorEnabled（viewport, compositorName, enabledOrDisabled）;

更多的有关定义和使用合成器的信息，请看示例区的Demo_Compositor，以及媒体区的Examples.compositor脚本。


文档:手册:1-4-0:3.3 粒子脚本 - OGRE 3D 中文

文档:手册:1-4-0:3.3 粒子脚本

3.3 粒子脚本

粒子脚本允许你实例化地在你的脚本代码中定义粒子系统，而不必在源代码中进行设置，使得你做任何修改都能得到快速回应。脚本里定义的粒子系统被用作模板，并且多个实际的系统可以在运行时从这里被创建。

装载脚本

粒子系统脚本在系统初始化时被装载：默认它在普通资源所在位置搜寻'.particle'后缀的文件并分析它。如果你想分析不同扩展名的文件，请使用你的扩展名调用ParticleSystemManager::getSingleton（）.parseAllSources方法，或者你想分析单个文件，请使用ParticleSystemManager::getSingleton（）.parseScript。

一旦脚本被分析完，你就可以基于这些代码使用SceneManager::createParticleSystem（）方法实例化系统，此方法不但可以带新系统的名字也可以带模板名（脚本中的模板）。

格式

几个粒子系统可以被定义在单个脚本中。脚本格式是伪C++的，用大括号（｛｝）作为段分隔符，用'//'开始一行表示注释（注意，不允许嵌套注释）。一般格式如下面典型例子所示：

// 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
    }
}

脚本中每个粒子必须被给一个名字，第一个大括号之前的那行，上面例子中是'Examples/PurpleFountain'。这个名字必须是全局唯一的。可以包含路径字符（就像上面例子那样），从逻辑上区分开你的粒子系统，并且可以避免重名，但是引擎并不把它视作是一种层次结构，而是把它当作是一个字符串。

系统可以有使用脚本命令获得的顶层属性集，例如'quota'是设置系统允许的最多粒子数量。Emitter（创建粒子）和affector（改变粒子）作为嵌套定义被加入脚本中。Emitter和affector段中可用的参数完全依赖于emitter/affector的类型。

要想了解核心粒子系统的详细介绍，请看下面列表：

可用的粒子系统属性

  • quota
  • material
  • particle_width
  • particle_height
  • cull_each
  • billboard_type
  • billboard_origin
  • billboard_rotation_type
  • common_direction
  • common_up_vector
  • renderer
  • sorted
  • local_space
  • point_rendering
  • accurate_facing
  • iteration_interval
  • nonvisible_update_timeout

也可参看：粒子发射器 粒子影响器


文档:手册:1-4-0:3.3.1 粒子系统属性 - OGRE 3D 中文

文档:手册:1-4-0:3.3.1 粒子系统属性

3.3.1 粒子系统属性

这部分描述了可以在任何一个使用脚本的粒子系统上设置的属性。所有属性都有默认值，所有设置在脚本中都是可选的。

quota

设置这个系统在某一时刻所允许包含的最多粒子数。当达到这个限制时，粒子发射器将不允许再发射粒子，直到某些粒子被消灭（例如，它们的time_to_live存续时间用尽）。值得注意的是，你几乎是肯定要改变这个设置的，因为默认值太短了（粒子池只能增加，而不能减少）。

格式: quota <max_particles>

示例: quota 10000

默认: 10

material

设置这个系统中的全体粒子将要使用的材质的名字。此系统中的全部粒子使用相同的材质，尽管每一个粒子可以通过使用它自己的颜色属性为材质附加颜色。

格式: material <material_name>

示例: material Examples/Flare

默认: none （空材质）

particle_width

在世界坐标中，设置粒子的宽度。注意，当billboard_type（）被设置为'point'或者'perpendicular_self'时，这个属性是绝对值；而当billboard_type是'oriented_common'，'oriented_self'或者'perpendicular_common'时，它是依方向向量的长度而定的。

格式: particle_width <width>

示例: particle_width 20

默认: 100

particle_height

在世界坐标中，设置粒子的高度。注意，当billboard_type（）被设置为'point'或者'perpendicular_self'时，这个属性是绝对值；而当billboard_type是'oriented_common'，'oriented_self'或者'perpendicular_common'时，它是依方向向量的长度而定的。

格式: particle_height <height>

示例: particle_height 20

默认: 100

cull_each

所有的粒子系统都被包括在一个包含这个系统所有粒子的边界盒内。这对一般的局部的有限的粒子系统，如大部分粒子是同时可见的或是同时不可见的，是足够的。但是，对于那些在更大面积上扩散的粒子（例如，一个雨水系统），实际上你也许想要单独的处理每一个粒子以便节约时间，因为很可能只有一小部分的粒子是可见的。你可以通过设置cull_each的参数为真，做到这一点。

格式: cull_each <true|false>

示例: cull_each true

默认: false

renderer

粒子系统并不渲染它本身，它们通过ParticleRenderer类完成这一点。那些类被带着一个管理器注册，为的是给粒子系统提供一个特殊的外观。OGRE默认配置了一个基于公告板的渲染器（billboard-based renderer），但是更多的可以通过插件增加。粒子渲染器要用一个唯一的名字注册，你可以利用这个名字决定使用哪个渲染器。默认的是'billboard'。

粒子渲染器可以有属性，并且可以通过在根粒子系统中设定属性进行传递。

格式: renderer <renderer_name>

默认: billboard

sorted

默认情况下，粒子是不排序的。若设定这个属性为'真'，粒子将会根据摄影机的位置关系被排序，最远的优先。通过花费一小点儿排序的代价，就可以制作出特定的渲染效果。

格式: sorted <true|false>

默认: false

local_space

默认情况下，粒子是被发射到世界空间的，例如，如果你改变了粒子系统所在的节点，它不会影响到粒子本身（只是粒子发射器）。这就意味着给出了一般期望的行为，即建立了真实世界的粒子离开发射它们的物体后独立运动的模型。但是，要建立一些效果，你可能想让粒子保持附加在粒子发射器所在的局部空间内并直接跟随它们。这个选项就可以让你实现这一点。

格式: local_space <true|false>

默认: false

billboard_type

这实际上是'公告板'粒子渲染器（默认）的一个属性，同时也是通过在系统声明中直接声明的方法给粒子渲染器传递属性的一个示例。使用默认渲染器的粒子被用公告板进行渲染，即由2个旋转到面向指定方向的三角形组成的矩形构成的平面。但是，定向一个公告板有不止一种方法。传统方法是公告板直接面对摄像机：这也是默认的方法。但是，这种安排只是对于表现像光晕一样的模糊的球状物看上去还算可以。对于更多的诸如激光射线这样的线性效果，事实上你想要粒子有其自己的方向。

格式: billboard_type <point|oriented_common|oriented_self|perpendicular_common|perpendicular_self>

示例: billboard_type oriented_self

默认: point

此参数有如下选项：

point
默认排列，它估计球状粒子和公告板总是完全面对摄像机。
oriented_common
粒子面向一个共同的固定的方向向量（参看common_direction），即它们的局部Y轴。公告板只围绕这个轴旋转，给粒子一些方向感。利于暴风雨，流星等粒子按一个方向移动的效果——较oriented_self（见下面）略快。
oriented_self
粒子面向它们自己的方向向量，即它们的局部Y轴。隨着粒子改变方向，公告板也重定向它自己面向这个方向。利于激光射线，焰火，以及其它的按其自己的方向行进的粒子。
perpendicular_common
粒子垂直于一个共同的固定的方向向量（参看common_direction），即它们的局部Z轴和它们的局部Y轴共同确定的平面，有共同的方向和向上的向量（参看common_up_vector）。公告板从未旋转至面向摄像机，你可能使用双面材质以便确保粒子不会被背面包含。利于光环，圆环等粒子将垂直于地面的效果——较perpendicular_self（见下面）略快。
perpendicular_self
粒子垂直于它们自己的方向向量，即它们的Z轴和Y轴共同确定的平面，有它们自己的方向向量和共同的向上向量（参见common_up_vector）。公告板从未旋转至面向摄像机，你可能使用双面材质以便确保粒子不会被背面包含。利于圆环堆等粒子将垂直于它们的行进方向的效果。

billboard_origin

指定所有公告板粒子的起始点，控制公告板粒子的出现位置。

格式: billboard_origin <top_left|top_center|top_right|center_left|center|center_right|bottom_left|bottom_center|bottom_right>

示例: billboard_origin top_right

默认: center

此参数有如下选项：

top_left
公告板起始点在左上角。
top_center
公告板起始点在顶边中央。
top_right
公告板起始点在右上角。
center_left
公告板起始点在左边中央。
center
公告板起始点在中央。
center_right
公告板起始点在右边中央。
bottom_left
公告板起始点在左下角。
bottom_center
公告板起始点在底边中央。
bottom_right
公告板起始点在右下角。

billboard_rotation_type

默认情况下，公告板粒子会根据粒子旋转去旋转纹理坐标。但是旋转纹理坐标有一些缺点，例如，纹理的四角会在旋转后丢失，而当使用折叠地址模式或者子纹理采样时，公告板的四角会被不想要的纹理区域填充。这个设置允许你指定其它的旋转类型。

格式: billboard_rotation_type <vertex|texcoord>

示例: billboard_rotation_type vertex

默认: texcoord

此参数有如下选项：

vertex
公告板粒子将依据粒子旋转规则绕它们面向的方向旋转它们的顶点。旋转顶点满足纹理角完全匹配公告板角，因此有上面提及的优点，但是需要花费较多的时间以生成顶点。
texcoord
公告板粒子将依据粒子旋转规则旋转纹理坐标。旋转纹理坐标比旋转顶点更快，但是有上面提及的一些缺点。

common_direction

如果billboard_type被设置为oriented_common或者perpendicular_common才需要，这个向量是用于定位系统中所有粒子的共用向量。

格式: common_direction <x> <y> <z>

示例: common_direction 0 -1 0

默认: 0 0 1

还可参看：3.3.2 粒子发射器，3.3.5 粒子影响器

common_up_vector

如果billboard_type被设置为perpendicular_self或者perpendicular_common才需要，这个向量是用于定位系统中所有粒子的共用向上向量。

格式: common_up_vector <x> <y> <z>

示例: common_up_vector 0 1 0

默认: 0 1 0

还可参看：3.3.2 粒子发射器，3.3.5 粒子影响器

point_rendering

事实上，这是‘公告板’粒子渲染器（默认设置）的一个属性，设置与否关系到公告板将使用点渲染而不是手动生成渲染画面。

默认情况下，公告板区域依靠内存中的一块纹理矩形生成的几何体渲染的，要考虑到大小和方向设置，以及将它装载入显卡的问题。可选择的方式是使用硬件指针渲染，即意味着每个公告板只有一个位置需要被传送而不是4个，并且硬件依据渲染状态排序如何渲染。

虽然使用点渲染较手动生成渲染区域更快，但是多了许多限制。限制如下：

仅支持'point'定向类型
每个粒子的大小和外观由材质通路控制（point_size， point_size_attenuation，point_sprites）
不支持每个粒子大小（源自上文）
不支持每个粒子旋转，且这只能通过材质定义中的纹理单元旋转控制
仅支持'center'起始点
一些驱动程序对于支持的点的大小有上限限制——甚至相同卡的不同API之间也可能区别！不要依靠点的大小让屏幕上的东西变得很大，因为它们可能会受限于某些卡。大小的上限可能在64到256像素之间。

如果你使用这个选项，你将几乎是肯定要打开材质通路中的point attenuation和point sprites。

accurate_facing

事实上，这是‘公告板’粒子渲染器（默认设置）的一个属性，且设置与否关系到公告板区域将使用一个有些慢但更精确的计算使公告板面向摄像机。默认使用摄像机方向，这样更快，但同时意味着，当你旋转摄像机时，公告板不会保持相同的方向。'accurate_facing true'选项基于从每一个公告板到摄像机的向量进行计算，即意味着即使摄像机旋转方向也是一致的。

格式: accurate_facing on|off

默认: accurate_facing off 0

iteration_interval

通常粒子系统是基于帧率被更新的；但是随着更极端的帧率范围，这可以给出不同的结果，特别是低帧率。你可以使用这个选项设定升级频率为固定的间隔，在低帧率时，粒子更新会按固定的间隔重复，直到帧率恢复正常。0值意为默认帧时间循环。

格式: iteration_interval <secs>

示例: iteration_interval 0.01

默认: iteration_interval 0

nonvisible_update_timeout

当粒子系统在其已经无法可见需要停止更新时设置。默认情况下，可见粒子系统一直更新，即使不在视口内。这意味着当它们进入视口时可以保证一致性。但是，更新粒子系统所花费的代价可能是很昂贵的。

这个选项让你在粒子系统上设置一个'timeout'时限，以便如果它这么长时间不可见，即停止更新，直到它下次可见。值0表示关闭timeout，总是更新。

格式: nonvisible_update_timeout <secs>

示例: nonvisible_update_timeout 10

默认: nonvisible_update_timeout 0


文档:手册:1-4-0:3.3.2 粒子发射器 - OGRE 3D 中文

文档:手册:1-4-0:3.3.2 粒子发射器

3.3.2 粒子发射器

粒子发射器按类型划分为几类，例如：Point发射器从单独一点发射，而Box发射器则是从一块儿区域随机发射。新的发射器可以通过插件加入到Ogre中去。向系统中增加一个发射器需要将发射器嵌入到其它块中，以关键字“emitter”后跟发射器类型名（大小写敏感）开头。Ogre现在支持'Point'，'Box'，'Cylinder'，'Ellipsoid'，'HollowEllipsoid'以及'Ring'发射器。

粒子发射器通用属性

  • angle
  • colour
  • colour_range_start
  • colour_range_end
  • direction
  • emission_rate
  • position
  • velocity
  • velocity_min
  • velocity_max
  • time_to_live
  • time_to_live_min
  • time_to_live_max
  • duration
  • duration_min
  • duration_max
  • repeat_delay
  • repeat_delay_min
  • repeat_delay_max

也可参见：3.3 粒子脚本，3.3.5 粒子影响器


文档:手册:1-4-0:3.3.3 粒子发射器属性 - OGRE 3D 中文

文档:手册:1-4-0:3.3.3 粒子发射器属性

3.3.3 粒子发射器属性

这部分描述的是所有小辫子发射器的通用属性。特殊的发射器类型可能也支持它们自己的额外的属性。

angle

设置发射的粒子可以偏离发射方向的最大角（按角度计算，参看 direction）。此值设置为10允许粒子在任一方向上最多偏离发射方向10度。值180意味着可以朝任意方向发射，而0意味着总是精确地沿发射器方向发射。

格式: angle <degrees>

示例: angle 30

默认: 0

colour

为所有发射的粒子设置一个静态颜色。也可参看colour_range_start和colour_range_end属性，设置一组颜色。颜色参数的格式是"r g b a"，每个分量的取值范围是从0到1之间，alpha值是可选项（如果未指定，则假定alpha为1）。

格式: colour <r g b> [<a>]

示例: colour 1 0 0 1

默认: 1 1 1 1

colour_range_start和colour_range_end

除了这两个属性必须一起制定外，其它的都和'colour'属性一样，并且制定了被发射出去的粒子的可用颜色范围。实际的颜色将会在这两个值之间随机选择。

格式: 同 colour

示例（随机生成红蓝之间的颜色）: colour_range_start 1 0 0 colour_range_end 0 0 1

默认: 都是 1 1 1 1

direction

设置发射器的方向。这与粒子系统所在的SceneNode有关，意思就是随着其它可移动物体改变节点方向，发射器也会随着移动。

格式: direction <x> <y> <z>

示例: direction 0 1 0

默认: 1 0 0

emission_rate

设置每秒要发射多少粒子。在连续发射过程中，个别发射器不是必须发射这些的——这是一个相对参数，发射器可能选择每半秒就发射完所有的粒子，这主要取决于发射器。此属性也会受到粒子系统的'quota'设置的限制。

格式: emission_rate <particles_per_second>

示例: emission_rate 50

默认: 10

position

设置发射器相对于粒子系统所在的场景节点所处的位置。

格式: position <x> <y> <z>

示例: position 10 0 40

默认: 0 0 0

velocity

给所有粒子设置发射时的速率。也可参看velocity_min和velocity_max两个属性，它们允许你设置一个速率范围，而不是一个固定不变的值。

格式: velocity <world_units_per_second>

示例: velocity 100

默认: 1

velocity_min & velocity_max

这两个属性除了是设置一个速率范围外，其它的与'velocity'一样。而且每一个粒子都是以在这个范围内的随机速率被发射出去的。

格式: 同 velocity

示例: velocity_min 50 velocity_max 100

默认: 都是 1

time_to_live

设置每个粒子在被销毁之前存活的秒数。粒子影响器是可以改变这个数值的，但是这个值是发射时才传给粒子的。参看time_to_live_min和time_to_live_max属性，这连个可以让你设置一个生命时间范围，而不是一个固定的数值。

格式: time_to_live <seconds>

示例: time_to_live 10

默认: 5

time_to_live_min & time_to_live_max

这两个属性除了是设置一个生命时间范围以外，其它的与time_to_live一样，并且每个粒子在发射时得到这一范围内的一个随机的数值，作为其存在时间。

格式: 同 time_to_live

示例: time_to_live_min 2 time_to_live_max 5

默认: 都是 5

duration

设置发射器处于活动状态的秒数。发射器可以被再次打开，查看repeat_delay。数值0意味着无限时。参看duration_min和duration_max属性，这两个属性可以让你设置一个时间范围，而不是一个固定值。

格式: duration <seconds>

示例: duration 2.5

默认: 0

duration_min & duration_max

除了这两个属性是设置一个可变的时间范围外，其它的与duration一样。

格式: 同 duration

示例: duration_min 2 duration_max 5

默认: 都是 0

repeat_delay

设置重新开始发射需要等待的秒数。参看repeat_delay_min和repeat_delay_max属性，这两个属性允许你设置一个repeat_delays时间范围，而不是设置一个固定的值。

格式: repeat_delay <seconds>

示例: repeat_delay 2.5

默认: 0

repeat_delay_min & repeat_delay_max

这两个属性除了是设置重新开始需要等待的时间范围外，其它的与repeat_delay一样，并且每次发射器被启动，它都会在这个范围内得到一个随机数值，作为重新开始发射需要的等待时间。

格式: 同 repeat_delay

示例: repeat_delay 2 repeat_delay 5

默认: 都是 0

还可以参看：3.3.4 标准粒子发射器，3.3 粒子脚本，3.3.5 粒子影响器


文档:手册:1-4-0:3.3.4 标准粒子发射器 - OGRE 3D 中文

文档:手册:1-4-0:3.3.4 标准粒子发射器

3.3.4 标准粒子发射器

Ogre预先定义了几种粒子发射器。新的粒子发射器可以通过创建插件增加：可以查看Plugin_ParticleFX项目，它是教你如何创建新的粒子发射器的好例子（那里实现了这些发射器）。

  • Point Emitter
  • Box Emitter
  • Cylinder Emitter
  • Ellipsoid Emitter
  • Hollow Ellipsoid Emitter
  • Ring Emitter

Point Emitter

这个发射器从一个定点，即它所在的位置，发射粒子。除了标准发射器属性，这个发射器没有其它属性。

要创建一个点发射器，需要在你的粒子系统脚本中包含类似下面的部分：

emmiter Point
{
    // Settings go here
}

请注意，发生器的名字（'Point'）是大小写敏感的。

Box Emitter

这个发射器从一个3维盒子里的随机位置发射粒子。它有额外的属性：

width
设置盒子的宽度（这是盒子沿着它自己的X轴的长度，依赖于形成盒子Z坐标的'direction'属性）。
格式：width <units>
示例：width 250
默认：100
height
设置盒子的高度（这是盒子沿着它自己的Y轴的长度，依赖于形成盒子Z坐标的'direction'属性）。
格式：height <units>
示例：height 250
默认：100
depth
设置盒子的深度（这是盒子沿着它自己的Z轴的长度，与'direction'属性相同）
格式：depth <units>
示例：depth 250
默认：100

要创建一个盒发射器，需要在你的粒子系统脚本中包含类似下面的部分：

emitter Box
{
    // Settings go here
}

Cylinder Emitter

这个发射器从一个沿Z轴摆放的圆柱体区域内的随机方向发射粒子。这个发射器有着与Box Emitter完全一致的参数，所以在此不多赘言——宽度和高度决定圆柱体沿坐标轴的形状（如果宽度和高度不同，那么得到的结果是椭圆柱体），深度决定了圆柱体的长度。

Ellipsoid Emitter

这个发射器是从一个椭圆体形状的区域里发射粒子的，例如一个球体或者压扁了的球体区域。参数再一次与Box Emitter相似，除了维度描述为每个坐标轴上的范围最广的点。

Hollow Ellipsoid Emitter

这个发射器很像Ellipsoid Emitter，除了椭圆体中心有一个空洞区域不发射粒子。因此，它有3个额外的参数定义这个空洞区域：

inner_width
不发射任何粒子的内部区域的宽度。
inner_height
不发射任何粒子的内部区域的高度。
inner_depth
不发射任何粒子的内部区域的深度。

Ring Emitter

这个发射器从一个环状区域发射粒子。除了只有2个维度外，有点像Hollow Ellipsoid Emitter。

inner_width
不发射任何粒子的内部区域的宽度。
inner_height
不发射任何粒子的内部区域的高度。

还可参看：3.3 粒子脚本，3.3.2 粒子发射器

Emitting Emitters

在粒子逾期时产生新的发射器是可能的，例如产生火焰类型的效果。这是通过以下指令控制的：

emit_emitter_quota
这个参数是一个系统级参数，就是告诉系统任意一次可能使用多少个发射器。也就是允许进行空间分配处理。
name
这个参数是一个发射器级参数，即给发射器确定一个名字。这样，当粒子消亡时，其它粒子发生器可以引用这个名字作为生成的新发射器。
emit_emitter
这个参数是一个发射器级参数，如果指定，则意为当这个发射器发射的粒子消亡时，生成一个新的发射器。


文档:手册:1-4-0:3.3.5 粒子影响器 - OGRE 3D 中文

文档:手册:1-4-0:3.3.5 粒子影响器

3.3.5 粒子影响器

粒子影响器可以在粒子存续期间对粒子进行修改。它们按“类型”分为：LinearForce影响器，对所有粒子应用一个力；ColourFader影响器改变飞行中的粒子的颜色。新的影响器可以通过创建插件的形式增加到Ogre中来。你可以通过将影响器嵌套在另一个别的程序块里的办法，向系统中增加一个影响器，以关键字affector开头，后跟影响器的类型名（注意：大小写敏感）。Ogre当前支持LinearForce和ColourFader两种影响器。

粒子影响器事实上没有统一的属性；属性都是每种影响器特有的。

也可参看：3.3.6 标准粒子影响器，3.3 粒子脚本，3.3.2 粒子发射器


文档:手册:1-4-0:3.3.6 标准粒子影响器 - OGRE 3D 中文

文档:手册:1-4-0:3.3.6 标准粒子影响器

3.3.6 标准粒子影响器

Ogre预定义了几种粒子影响器。新的影响器还可以通过插件的形式增加：如何通过插件创建新的影响器，您可以参看Plugin_ParticleFX项目作为一个例子。（那里有这些粒子影响器的实现方式）

  • Linear Force Affector
  • ColourFader Affector
  • ColourFader2 Affector
  • Scaler Affector
  • Rotator Affector
  • ColourInterpolator Affector
  • ColourImage Affector
  • DeflectorPlane Affector
  • DirectionRandomiser Affector

Linear Force Affector

这个影响器对所有粒子施加一个力，改变粒子的运动轨迹。可以用于重力，风力，或者其它线性力。其额外属性有：

force_vector
为应用到每一个粒子的那个力设置向量。这个向量的模决定了力的大小。
格式：force_vector <x> <y> <z>
示例：force_vector 50 0 -50
默认：0 -100 0（一个重力效果）
force_application
设置这个力向量作用于粒子动量的方法。
格式：force_application <add|average>
示例：force_application average
默认：add
可选参数有：
average
最终动量是这个力与粒子当前运动的平均值。这样也就使得其本身虽然是稳定的，但是在粒子改变方向时的速度是非线性的。
add
最终动量是粒子的当前运动与这个力之和。这是传统的力的叠加，但是潜在地可能导致无限速率。

要创建一个线性力影响器，需要你的粒子系统脚本中包含一段如下代码：

affector LinearForce
{
    // 设置写在这里
}

请注意：影响器类型的名字（LinearForce）是大小写敏感的。

ColourFader Affector

此影响器修改飞行中的粒子的颜色。额外的属性有：

red
设置每秒时间内粒子颜色中的红色分量的调整量。
格式：red <delta_value>
示例：red -0.1
默认：0
green
设置每秒时间内粒子颜色中的绿色分量的调整量。
格式：green <delta_value>
示例：green -0.1
默认：0
blue
设置每秒时间内粒子颜色中的蓝色分量的调整量。
格式：blue <delta_value>
示例：blue -0.1
默认：0
alpha
设置每秒时间内粒子颜色中的alpha分量的调整量。
格式：alpha <delta_value>
示例：alpha -0.1
默认：0
要创建一个颜色减弱影响器，需要在你的粒子系统脚本中包含如下一段代码：
affector ColourFader
{
    // 设置写在这里
}

ColourFader2 Affector

此影响器类似ColourFader Affector，只不过这个影响器有两个颜色改变状态。在粒子存续期内，指定还剩一段时间时，激活第二个颜色改变状态。

red1
设置在第一个状态期间每秒时间内粒子颜色的红色分量的调整量。
格式：red <delta_value>
示例：red -0.1
默认：0
green1
设置在第一个状态期间每秒时间内粒子颜色的绿色分量的调整量。
格式：green <delta_value>
示例：green -0.1
默认：0
blue1
设置在第一个状态期间每秒时间内粒子颜色的蓝色分量的调整量。
格式：blue <delta_value>
示例：blue -0.1
默认：0
alpha1
设置在第一个状态期间每秒时间内粒子颜色的alpha分量的调整量。
格式：alpha <delta_value>
示例：alpha -0.1
默认：0
red2
设置在第二个状态期间每秒时间内粒子颜色的红色分量的调整量。
格式：red <delta_value>
示例：red -0.1
默认：0
green2
设置在第二个状态期间每秒时间内粒子颜色的绿色分量的调整量。
格式：green <delta_value>
示例：green -0.1
默认：0
blue2
设置在第二个状态期间每秒时间内粒子颜色的蓝色分量的调整量。
格式：blue <delta_value>
示例：blue -0.1
默认：0
alpha2
设置在第二个状态期间每秒时间内粒子颜色的alpha分量的调整量。
格式：alpha <delta_value>
示例：alpha -0.1
默认：0
state_change
当一个粒子还有这么多存续时间时，它将转入状态二。
格式：state_change <seconds>
示例：state_change 2
默认：1

要创建一个颜色减弱2影响器，需要在你的粒子系统脚本中包含如下一段代码：

affector ColourFader2
{
    // 设置写在这里
}

Scaler Affector

此影响器调节飞行中的粒子的大小。额外的属性有：

rate
每秒时间内在x和y方向上对粒子的调节量。

要创建一个伸缩影响器，需要在你的粒子系统脚本中包含如下一段代码：

affector Scaler
{
    // 设置写在这里
}

Rotator Affector

此影响器依靠旋转粒子的贴图纹理来旋转飞行中的粒子。额外的属性有：

rotation_speed_range_start
赋值给发射出去的粒子的旋转速度范围的初始值。
格式：rotation_speed_range_start <degrees_per_second>
示例：rotation_speed_range_start 90
默认：0
rotation_speed_range_end
赋值给发射出去的粒子的旋转速度范围的结束值。
格式：rotation_speed_range_end <degrees_per_second>
示例：rotation_speed_range_end 180
默认：0
rotation_range_start
赋值给发射出去的粒子的旋转角度的初始值。
格式：rotation_range_start <degrees>
示例：rotation_range_start 0
默认：0
rotation_range_end
赋值给发射出去的粒子的旋转角度的结束值。
格式：rotation_range_end <degrees>
示例：rotation_range_end 360
默认：0

要创建一个旋转影响器，需要在你的粒子系统脚本中包含如下一段代码：

affector Rotator
{
    // 设置写在这里
}

ColourInterpolator Affector

类似于ColourFader和ColourFader2，此影响器也是修改飞行中的粒子的颜色。只不过这个影响器有一组不定个数的已经定义好的状态。它在粒子存续期内在几种状态间插值变换粒子的颜色。额外的属性有：

time0
状态0的时间点。
格式：time0 <0到1，基于粒子的存续时间>
示例：time0 0
默认：1
colour0
状态0时的颜色。
格式：colour0 <r g b> [<a>]
示例：colour0 1 0 0 1
默认：0.5 0.5 0.5 0.0
time1
状态1的时间点。
格式：time1 <0到1，基于粒子的存续时间>
示例：time1 0.5
默认：1
colour1
状态1时的颜色。
格式：colour1 <r g b> [<a>]
示例：colour1 0 1 0 1
默认：0.5 0.5 0.5 0.0
time2
状态2的时间点。
格式：time2 <0到1，基于粒子的存续时间>
示例：time2 1
默认：1
colour2
状态2时的颜色。
格式：colour2 <r g b> [<a>]
示例：colour2 0 0 1 1
默认：0.5 0.5 0.5 0.0
[...]

状态数是可变的。最多6个。即time5和colour5是最后的参数。要想创建一个颜色插值影响器，需要在你的粒子系统脚本中包含如下一段代码：

affector ColourInterpolator
{
    // 设置写在这里
}

ColourImage Affector

这是另一个改变飞行粒子的颜色的影响器，但替代编程定义颜色的是，从一个指定的图像文件中取得颜色。在粒子的存续时间内，颜色的取值范围是从图像的左侧开始向右移动，因此，只使用了水平方向的图像。额外属性有：

image
赋值给发射出去的粒子的旋转速度范围的初始值。
格式：image <image_name>
示例：image rainbow.png
默认：无

要创建一个图像颜色影响器，需要在你的粒子系统脚本中包含如下一段代码：

affector ColourImage
{
    // 设置写在这里
}

DeflectorPlane Affector

此影响器定义一个平面，这个平面反弹碰到它的粒子。额外的属性有：

plane_point
反弹平面上一点。与plane_normal一起使用。
默认：plane_point 0 0 0
plane_normal
反弹平面的法线向量。与plane_point一起使用。
默认：plane_normal 0 1 0
bounce
当一个粒子被反弹时的弹力大小。0表示没有反弹，1表示100%反弹。
默认：bounce 1.0

DirectionRandomiser Affector

此影响器随机选定粒子运动的方向。额外属性有：

randomness
每一轴向上随机性的大小。
示例：randomness 5
默认：randomness 1
scope
每一轮受影响的粒子的百分比。
示例：scope 0.5
默认：scope 1.0
keep_velocity
决定是否不改变粒子的速率。
示例：keep_velocity true //不改变粒子速率
默认：keep_velocity false //即改变粒子速率


文档:手册:1-4-0:3.4 表层（Overlay）脚本 - OGRE 3D 中文

文档:手册:1-4-0:3.4 表层（Overlay）脚本

3.4 表层（Overlay）脚本

表层脚本提供给你用脚本定义图层以方便重复使用的能力。与此同时，你可以使用SceneManager，Overlay以及OverlayElement类的方法在代码中为一个场景建立所有图层，虽然在使用中，有点儿不太好用。相反你可以以文本文件的方式储存层定义，而在需要的时候调用。

装载脚本

表层脚本在初始化时由系统装入：默认，它搜索所有普通资源位置（参看Root::addResourceLocation）查找有'.overlay'扩展名的文件，并分析它。如果你想要分析别的扩展名的文件，则对你的那个扩展名使用OverlayManager::getSingleton().parseAllSources方法，或者如果你想要分析一个单独文件，则使用OverlayManager::getSingleton().parseScript。

格式

多个层可以被定义在单独一个脚本中。脚本格式是伪C++的，用打括号（{}）分割各个部分，以'//'开始的一行表示注释（注意，不允许嵌套注释），且通过使用模板继承。典型例子的一般格式如下所示：

// 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
        }
    }

}

上例定义了一个叫'MyOverlays/ANewOverlay'的层，其中有2个面板，且其中一个嵌套在另一个上。它使用关联矩阵（如果未发现metrics_mode选项）。

脚本中每一层都必须被起一个名字，即在第一个大括号'{'前。此名字必须是全局独一无二的。可以包含路径字符（如上例所示）从逻辑上区分你的层，还要避免复制层名，引擎不会认为这里有什么结构关系，而只是把它当作一条字符串。层的属性和嵌套元素都在括号内部。层本身仅有一个属性'zorder'，在同时显示不止一个层时，决定这一层放在这一堆的层里面多‘高’的位置上。层的'zorder'值越高，显示得就越靠近表面。

向层中添加元素

在层中，你可以包含任意个2D或3D元素。要做到这一点，依靠定义一个如下开始的嵌套的代码块：

element
如果你想定义一个无孩子的2D元素
container
如果你想定义一个2D容器对象（即可以有嵌套在自己内部的容器或元素）

除了储存嵌套块的能力有所不同，元素和容器块是极其相似的。

容器/元素块

这两种都是按大括号分割的。第一个大括号前的头部格式是：

[container | element] <type_name> ( <instance_name>) [: <template_name>]
{ ...
type_name
必须给出已在OverlayManager注册过的OverlayElement类型名。插件在OverlayManager注册，以声明其创建元素的能力，同时声明类型名。OGRE已经预定义了Panel，BorderPanel，TextArea三种类型。
instance_name
必须是一个在所有其他elements/containers中独一无二的名字以便能够识别出这个元素。注意，你可以通过调用OverlayManager::getSingleton().getOverlayElement(name)而取得一个指向任意已命名的元素的指针。
template_name
基于此项的可选模板。详见下面介绍的模板。

可包含在括号中的属性依赖于用户定义的类型。但是下面的这几个属性总是可用的：

  • metrics_mode
  • horz_align
  • vert_align
  • left
  • top
  • width
  • height
  • material
  • caption

模板

你可以使用模板创建各种有相同属性的元素。一个模板就是一个抽象元素，而且它并不增加到某一层中。它扮演的就是一个基类，元素可以继承并取得默认属性。要创建一个模板，关键字template必须是元素定义的第一个词（在container或element之前）。模板元素被创建在最外层——它并不在某一层里指定。建议你在一个单独的层中定义模板，尽管这么做并不是必要的。在单独文件中定义模板，允许有不同的外观，方便替代。

元素可以通过类似于C++继承的方式继承一个模板——通过在元素定义上使用：操作符。：操作符被放置在名字的右括号之后（以空格分隔）。要继承的模板名放在：操作符之后（也以空格分隔）。

一个模板中可以包含子模板，子模板在模板被实例化时被创建。虽然使用template关键字对于子模板来说是可选的，但是为了清楚起见还是建议使用，因为子模板本身也是要做模板的。

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
        }
    }
}

上面的例子使用了模板定义一个按钮。注意，按钮模板继承自borderPanel模板。这样减少了初始化一个按钮所需要的属性数量。

还要注意的是，实例化一个按钮需要一个模板名作为标题属性。所以模板也可以被需要动态创建子元素的元素使用（在此例中，按钮创建了一个TextAreaElement作为它的标题）。

参看：3.4.1 表层元素（OverlayElement）属性，3.4.2 标准表层元素


文档:手册:1-4-0:3.4.1 表层元素（OverlayElement）属性 - OGRE 3D 中文

文档:手册:1-4-0:3.4.1 表层元素（OverlayElement）属性

3.4.1 表层元素（OverlayElement）属性

这些属性可以用在表层脚本中的container或element代码块中。必须各自分别占用一行。顺序并不重要。

metrics_mode

用来设置元素的大小和位置的单位。

格式: metrics_mode <pixels|relative> 示例: metrics_mode pixels

这可以用来改变此元素中剩余的所有尺寸属性的解释方式。相对模式中，它们被解释为0到1之间的参数值，即屏幕的宽/高的比率。像素模式中，它们简单地就是像素偏移量。

默认: metrics_mode relative

horz_align

设置此元素的水平对齐，即水平起点的位置。

格式: horz_align <left|center|right> 示例: horz_align center

这个属性可以用来改变任何水平方向的元素属性的起点位置。默认这个起点位置是在屏幕的左边，但是如果你改变这个属性，你可以将元素居中或居右放置。注意，设置了居中或居右对齐并不是自动强制你的元素出现在中间或右边，你还必须以此为起点适当调整坐标。这样灵活是为了你可以选择将你的元素放置在相对于这个起点的任意位置。例如，如果你的元素是10像素宽，你如果使用-10的left属性，那么它会准确地对齐右边；或者-20，那么会留下一个空位但仍然靠右对齐。

注意，虽然你既可以使用这个属性的相对模式，也可以使用像素模式，但是最有用的还是像素模式。

默认: horz_align left

vert_align

设置此元素的垂直对齐，即垂直起点的位置。

格式: vert_align <top|center|bottom> 示例: vert_align center

这个属性可以用来改变任何垂直方向的元素属性的起点位置。默认这个起点位置是在屏幕的顶边，但是如果你改变这个属性，你可以将元素居中或居下放置。注意，设置了居中或居下对齐并不是自动强行使你的元素出现在中间或底边，你还必须以此为起点适当调整坐标。这样灵活是为了你可以选择将你的元素放置在相对于这个起点的任意位置。例如，如果你的元素是50像素高，你如果使用-50的top属性，那么它会准确地对齐底边；或者-70，那么会留下一个空位但仍然靠下对齐。

注意，虽然你既可以使用这个属性的相对模式，也可以使用像素模式，但是最有用的还是像素模式。

默认: vert_align top

left

设置元素相对于它上一层的水平位置。

格式: left <value> 示例: left 0.5

位置是相对上一层的位置而言的（如果上一层是一个表层，则是屏幕的左上角；否则，是上一层内容的左上角）且表示为屏幕大小的比例。因此，0.5表示屏幕宽度的一半位置。

默认: left 0

top

设置元素相对于它上一层的垂直位置。

格式: top <value> 示例: top 0.5

位置是相对上一层的位置而言的（如果上一层是一个表层，则是屏幕的左上角；否则，是上一层内容的左上角）且表示为屏幕大小的比例。因此，0.5表示屏幕高度的一半位置。

默认: left 0

width

以屏幕宽度的某一比率设置元素的宽度。

格式: width <value> 示例: width 0.25

大小是相对于屏幕大小而言的，所以0.25就是屏幕的四分之一。大小不是相对于父元素的大小；在窗口系统中左和上这两个位置是相对值，宽度大小是绝对值。

默认: width 1

height

以屏幕高度的某一比率设置元素的高度。

格式: height <value> 示例: height 0.25

大小是相对于屏幕大小而言的，所以0.25就是屏幕的四分之一。大小不是相对于父元素的大小；在窗口系统中左和上这两个位置是相对值，高度大小是绝对值。

默认: height 1

material

设置用于此元素的材质名。

格式: material <name> 示例: material Examples/TestMaterial

这里设置此元素将要使用的基本材质。每一类元素可能对此的解释都是不同的；例如，OGRE元素Panel把它当作面板的背景，而BorderPanel只将它解释为中心区域的材质。材质应当被定义在.material脚本中。

注意，在一个表层元素中使用材质会自动地禁用该材质上的光照和深度检测。因此，你不应该在表层上使用与真实的3D物体同样的材质。

默认: 无

caption

设置元素的文本标题。

格式: caption <string> 示例: caption This is a caption

不是所有的元素都支持标题，所以每个元素可以忽略这个属性。但是，对许多元素来说，为了使用起来跟简便，文本标题还是需要的。在GUI系统中，这是再普通不过的事了。

默认: 空白

rotation

设置元素的旋转。

格式: rotation <angle_in_degrees> <axis_x> <axis_y> <axis_z> 示例: rotation 30 0 0 1 默认: 无


文档:手册:1-4-0:3.4.2 标准表层元素 - OGRE 3D 中文

文档:手册:1-4-0:3.4.2 标准表层元素

3.4.2 标准表层元素

虽然OGRE的表层元素类和表层容器类被设计为是可供应用程序开发人员扩展的，但是有一些元素是Ogre本身自带的。包括：

  • Panel
  • BorderPanel
  • TextArea

这部分介绍了如何在一个.overlay脚本中定义它们的属性，你也可以在代码中改变这些属性。调用setParameter(paramname, value)定义属性。你可以通过StringConverter类将你要用的类型转换为字符串，或将字符串转换为你要的类型。

Panel（容器）

这是你可使用的最bog-standard容器。它是一块能够包含其他元素（或容器）的矩形区域，可以有背景也可以没有背景，随你的便。背景材质由材质属性决定，但是只有当透明处于关闭状态时，才会显示。

属性：

transparent <true|false>
如果设置为true那么面板就是透明的，且面板自己不需渲染，则它就被用来划分自己孩子的等级。
tiling <layer> <x_tile> <y_tile>
设置材质的纹理在整个面板上X和Y方向贴图的次数。<layer>是指纹理层，从0到此材质的纹理层数-1。依靠设置每层贴图，你可以为你的面板创建一些漂亮的多重贴图的背景，当你变化其中一层时，效果尤其好。
uv_coords <topleft_u> <topleft_v> <bottomright_u> <bottomright_v>
设置要用到这个面板上的纹理的坐标。

BorderPanel（容器）

这是一种稍微更高级的面板，用以替代单一的平板面板，有一个单独的可以随着面板调节大小的边框。为了做到这一点，它采用了一种类似在HTML表格中使用边框的方法：面板被分为9块区域进行渲染，以主材质渲染中心区域（如Panel）以及单独的边界材质渲染外部8个区域（四角和四边）。边角分开渲染的好处是边纹理可以被设计得笔直伸展而没有转角拐弯，意思就是说一个纹理可以用在任意大小的面板上。

属性：

border_size <left> <right> <top> <bottom>
每边边框按屏幕大小的比例尺寸。这令你可以按你的喜好设置不同尺寸的边框，或者你可以使用相同的数值4倍去创建一个固定尺寸的边框。
border_material <name>
用于边框的材质名。这个材质通常不同于用于中心区域的材质，因为中心区域经常是平铺的，也就是说你不能将边框区域放在中心区域那里。你必须将所有你需要的边角图像放到一个单独的纹理中。
border_topleft_uv <u1> <v1> <u2> <v2>
[及border_topright_uv，border_bottomleft_uv，border_bottomright_uv]；被用作边框的角落区域的纹理坐标。需要4个坐标，2个为区域的左上角，2个为区域的右下角。
border_left_uv <u1> <v1> <u2> <v2>
[及border_right_uv，border_top_uv，border_bottom_uv]；被用作边框的边区域纹理坐标。需要四个坐标，2个为左上角，2个为右下角。你应该注意设计一下纹理，以便左边和右边可以被垂直拉伸/压扁，而顶边和底边可以被水平拉伸/压扁，且无副作用。

文本区（元素）

这是一个可以用来渲染文本的普通元素。它使用可以用FontManager和FontClass类的代码定义的字体，或者事先预备的.fontdef文件。详情请参看字体定义部分。

属性：

font_name <name>
要使用的字体名。这个字体必须被定义在一个.fontdef文件中并确保在脚本使用时它是可用的。
char_height <height>
字母的高度占全屏高度的百分比。虽然因为OGRE支持比例字体字母宽度可能不尽相同，但是它会基于这个常量高度。
colour <red> <green> <blue>
渲染文字用的一个单色。通常，字体被定义成黑白单色；利用这一属性，你可以把字体弄上漂亮的颜色，让多重不同颜色的文本区域用上相同的纹理。颜色应当全都用0到1之间的值表示。如果你使用已经预先画好颜色的字体，那么你不必再使用这一属性。
colour_bottom <red> <green> <blue> / colour_top <red> <green> <blue>
作为单色的一种替换选择，你可以使文本从上到下使用不同的颜色，从而创造出一种非常漂亮的渐变效果。


文档:手册:1-4-0:3.5 字体定义脚本 - OGRE 3D 中文

文档:手册:1-4-0:3.5 字体定义脚本

3.5 字体定义脚本

Ogre使用基于纹理的字体渲染TextAreaOverlayElement。你也可以使用Font对象去实现你想要的目标。字体的最终格式是一个由字体生成的Material对象，以及一组"glyph"（字符轮廓）纹理坐标信息。

在OGRE中，你可以用两种方法得到字体:

1、利用一个艺术包或者字体生成工具自己设计一个字体纹理
2、让OGRE生成一个基于truetype字体的字体纹理

前一种方法给你最大的自由度，以及最棒的性能表现效果（从启动时间上看），但是，如果你想快速使用一个字体，而不愿自己生成纹理的话，后一种方法是更为方便的。建议使用后一种方法进行原形设计，而到了最后要完成最终一步时，在转成前一种方法。

所有字体定义被保存在.fontdef文件中，这些文件在开始启动时，由系统进行分析。每一个.fontdef文件可以包含多个字体定义。在.fontdef文件中的一个入口的基本格式是：

 <font_name>
 {
     type <image | truetype>
     source <image file | truetype font file>
     ...
     ... custom attributes depending on type
 }

使用一个现有字体纹理

如果有一个或多个艺术家与你一起工作，不要怀疑，他们可以为你制造出一个非常漂亮的字体纹理。OGRE支持全部色彩的字体纹理，或者保持黑白单色/灰阶以及使用TextArea的色彩特性。字体纹理总有一个alpha通道，最好是一个8位的alpha通道，就像TGA和PNG文件支持的那样，因为它可以得到更为漂亮的边界。要使用一个现有的纹理，你需要进行如下设置：

type image
这只是告诉OGRE，你想要一个预先画好的字体。
source <filename>
这是那个你想要调用的图片文件的名字。它会从标准TextureManager资源位置被装入，而且是任意OGRE支持的类型，尽管不推荐JPEG格式，因为缺少alpha而且是有损压缩。推荐PNG格式，它具备无损压缩和一个8位alpha通道的双重优点。
glyph <character> <u1> <v1> <u2> <v2>
这个是为指定的字提供纹理坐标。你必须为纹理中所有的每一个字，重复这一步骤。前两个数字是左上角的x和y坐标，后两个是右下角的x和y坐标。注意，你一定要使用等高的字，因为等比例字体，宽度可以有所不同。

一条给Windows用户的提示：建议使用（http://www.lmnopc.com/bitmapfontbuilder/），一个自由工具，可以用来生成纹理并且为你导出字符宽度，你可以在Tools文件夹下找到一个工具，将这个二进制的输出文件转换成'glyph'线条。

生成一个字体纹理

你也可以利用truetype字体生成一个字体纹理。不建议在成品中过多使用这个，因为每个字体渲染纹理都要花费几秒钟时间，增大载入时间。然而，不管怎样，它是一个非常好的快速得到你选择的字体的输出文本的方法。

下面是你需要提供的一些属性：

type truetype
告诉OGRE从一个字体里生成纹理。
source <ttf file>
要载入的ttf文件名。它将在普通资源位置和任何增加到FontManager中的资源位置搜索。
size <size_in_points>
按标准点计算要生成字体的大小。注意，这只影响字符在字体纹理中是多大，不影响在屏幕上显示的大小。你应当根据你期望渲染多大的字体来裁减这个的大小，因为生成一个庞大的纹理将导致字符在缩得很小的时候变得模糊（由于mipmapping），而且相反地，生成一个小字体会导致渲染大号文本时产生块状字。
resolution <dpi>
按每英寸中的点数计算的清晰度，与上面的point size关联使用以决定最终大小。一般是72 / 96 dpi。
antialias_colour <true|false>
这是一个可选项，默认是“false”。生成器会默认使用纹理的alpha分量对字体抗锯齿，如果你使用alpha混合渲染你的文本会看起来很好。无论你想在自己的代码中使用哪个基于混合的颜色，如：add或modulate，你都要设置这个选项为“true”，因此颜色值也是抗锯齿的。如果你设置这个为真，并且使用alpha混合，你会发现你的字体的边也是抗锯齿的，快速得到一个看上去很“细”的字体，因为不仅是alpha混合了边界，颜色也变淡了。如果有所怀疑，让这个选项保持默认“false”，也没关系。
code_points nn-nn [nn-nn] ..
这一指令允许你指定哪一个unicode编码点应当作为字符轮廓被生成为字体纹理。如果你不指定，编码点33-166将会默认被生成，覆盖基本的Latin 1 字符轮廓。如果你使用了这个标记，你应当指定一个包含编码点范围的独立空间列表，格式为“开始位置-结束位置”。数值必须是十进制数。

你也可以在运行时使用FontManager创建新字体。


文档:手册:1-4-0:4. Mesh 工具集 - OGRE 3D 中文

文档:手册:1-4-0:4. Mesh 工具集

4. 网格工具

这里有一些在OGRE有效的网格工具可以帮助你操作你的图形网格

  • 4.1 导出器（Exporters）
用于从模型生成器中得到数据并且导入到OGRE中去。
  • 4.2 XmlConverter（Xml转换器）
用于从XML转换网格数据和骨骼数据
  • 4.3 MeshUpgrader（网格数据更新器）
用于从OGRE其中之一的版本更新二进制网格数据到其他的版本中。


文档:手册:1-4-0:4.1 导出器（Exporters） - OGRE 3D 中文

文档:手册:1-4-0:4.1 导出器（Exporters）

From OGRE 3D 中文

4.1 Exporters

导出器是3D模型工具的插件用来写成网格数据和骨骼动画的文件格式可以在OGRE中被实时渲染。这些文件被导出器以.mesh和.skeleton形式生成。

为每一个模型工具编写制定的导出器是一个问题，尽管他们都使用一个由类MeshSerializer和SkeletonSerializer提供的通用工具集。他们同样通常要求你有自己的模型创建工具。

所有的导出器在这里都可以从源代码中创建，或者你可以从OGRE的web站点上下载预编译的版本。

一条关于OGRE的模型创建/动画的注意

这里有一些对于OGRE在创建一个动画模型时的规则：

  • 每个顶点你必须没有超过4的加权骨骼赋值。如果你超过了，OGRE将会删去最低的加权赋值并且重新规格化为其他权重。这些限制是由硬件混合局限性强加的。
  • 所有的的顶点都必须被分配到至少一个骨骼点上 -- 分配静态顶点到根部骨骼点。
  • 在动画开始和结束时最少每个骨骼点上必须有一个关键帧。

如果你创建的是非动画网格数据，因此你不需要关心上面所讲的内容。对于每个导出器所有的文档都提供了自身相关的介绍，同时在这里有一个在OGRE Wiki中受支持的模型创建工具列表http://www.ogre3d.org/wiki/index.php/Exporters.


文档:手册:1-4-0:4.2 XmlConverter - OGRE 3D 中文

文档:手册:1-4-0:4.2 XmlConverter

4.2 XmlConverter

这个OgreXmlConverter工具可以将二进制在.mesh和.skeleton文件与XML间进行转换，这是一个对于调试网格数据内容或者进行简单网格数据交换非常有用的工具 -- 由于XML简单的应用因此很多模型工具的网格数据导出器都导出为XML格式，同时OgreXmlConverter可以从XML生成一个二进制数据。除了它的简单性，OgreXmlConverter其它的优点是可以为网格数据生产附加的信息，像边界区域(bounding region)和level-of-detail缩放率。

语法：

     OgreXMLConverter sourcefile [destfile]
    sourcefile = 转换的文件名
     destfile   = 可选择写入的文件名。如果你不指定这些OGRE自始至终计算出拓展名同时如果资源内容
                    是XML那么就会生成为XML内容。例如test.mesh变成test.xml,如果根源内容是<mesh>
                 或者其他的XML文档那么test.xml变成test.mesh。

当转换XML到.mesh时，你将被提示(重)生成适合于网格数据的level-of-detail(LOD)信息 -- 如果你希望的话可以选择跳过这个部分，但是选择的话将允许你在网格数据读入到引擎中时减少网格数据自动生成的细节内容。引擎使用了一个复杂的算法去计算网格数据最佳的部分以减少对于很多因素的依赖，例如曲面的曲率、网格边缘、纹理边缘接缝、滤波组（smoothing groups ） -- 这些是经过仔细考虑过的，在真实场景中利用它可以让你的网格数据拥有更多的可伸缩性。


文档:手册:1-4-0:4.3 MeshUpgrader - OGRE 3D 中文

文档:手册:1-4-0:4.3 MeshUpgrader

4.3 MeshUpgrader

当二进制格式改变时这个工具提供给允许你去更新网格数据的功能 -- 即当某一时候我们修改它添加一个新的功能或者当你需要保存自己有用的东西到数据中去时。这个工具有一个非常简单的语法：

  OgreMeshUpgrade <oldmesh> <newmesh>

当一个新的版本需要这些时OGRE版本短信将会通知你。


文档:手册:1-4-0:5. 硬件缓存 - OGRE 3D 中文

文档:手册:1-4-0:5. 硬件缓存

顶点缓存、索引缓存和像素缓存都从HardwareBuffer类派生。从本质上来说硬件缓存只不过是一个普通的储存区域，并没有限定其储存数据的格式（顶点或其他），至于里面数据的用途完全取决于你对他们的使用方法，我们可以简单认为硬件缓存就如同我们通过“malloc”函数从内存中申请的空间——唯一不同的是硬件缓存的空间并不在内存中，而是存在于GPU或者AGP的储存区域（显存的两种类型）。


文档:手册:1-4-0:5.1 硬件缓存管理器 - OGRE 3D 中文

文档:手册:1-4-0:5.1 硬件缓存管理器

HardwareBufferManager类是一个用来创造几何体的工厂类型。大多数你自定义的几何体都需要通过这个类的实例来创建和销毁。它实现了单件模式，在系统初始化之后（换句话说在你调用Root::initialise方法之后），你可以通过HardwareBufferManager::getSingleton()方法来得到它的唯一实例；尽管你也可以通过一组通用的接口来创建物体，但我们提供这个类的原因是为了简化创建物体过程中固定不变的API调用。

例如：

VertexDeclaration* decl = HardwareBufferManager::getSingleton().createVertexDeclaration();

HardwareVertexBufferSharedPtr vbuf =
       HardwareBufferManager::getSingleton().createVertexBuffer(
              3*sizeof(Real), // size of one whole vertex 全部顶点的尺寸
              numVertices, // number of vertices 顶点的数量
              HardwareBuffer::HBU_STATIC_WRITE_ONLY, // usage 使用方法
              false); // no shadow buffer 不使用备份缓存

如果看不懂上面的细节也不用担心，我们会在之后的章节中详细介绍。唯一需要记住的是如果要建立缓存对象就一定要通过HardwareBufferManager类，而不要简单的通过“new”操作（因为大部分情况下这样做都不能正确的工作）。


文档:手册:1-4-0:5.2 缓存使用方法 - OGRE 3D 中文

文档:手册:1-4-0:5.2 缓存使用方法

在渲染场景的过程中硬件缓存中的储存介质可能会被争用，所以你需要谨慎的选择使用缓存时候的存取方式；管理缓存方法的依据包括是否需要规律（频繁）的更新缓存内容，以及是否需要从缓存中回写数据等。不论是建立索引缓存还是顶点缓存（请参考章节5.6 硬件顶点缓存和 5.7 硬件索引缓存），你都可以在构建的时候通过参数来决定具体的使用方法，这两种缓存都有一个相同的参数，被称为“用法（usage）”。

最理想的缓存（性能最优）是一个从来不需要更新并且也从来不需要回写的缓存。对于创建顶点缓存的createVertexBuffer和创建索引缓存的createIndexBuffer方法都拥有下面相同的“usage”参数。

HBU_STATIC

使用这个参数意味着你并不经常更新缓存，但有时候需要从缓存中读取数据。

HBU_STATIC_WRITE_ONLY

使用这个参数意味着你不需要经常更新缓存，并且你从不需要从缓存读取数据。不过如果你设置了使用备份缓存（请参考章节5.6 硬件顶点缓存）的话，你仍然可以从备份缓存中读取数据。

HBU_DYNAMIC

使用这个参数意味着你需要经常的更新缓存当中的数据，并且也希望能从里面读取数据。这是效率最低的缓存使用方法。

HBU_DYNAMIC_WRITE_ONLY

使用这个参数意味着你需要经常更新缓存，但你并不需要从缓存中读取数据。不过如果你设置了使用备份缓存（请参考章节5.3 备份缓存）的话，你仍然可以从备份缓存中读取数据。如果需要在每一帧更新缓存中的所有内容，你应该用HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE来代替这个参数，因为在某些平台上这样做能带来显著的性能提高。

HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE

使用这个参数意味着你需要频繁的全部更新缓存中的所有内容（大多数时候是在每一帧更新）。通过这个设置，系统将不会在意之前缓存中存在的内容，因为你将要在下一帧重新写入所有数据。在某些平台上这种方法将会带来性能的显著提高，因此当需要频繁更新的时候应该尽量考虑使用这个参数。注意，当你使用了这种缓存，当需要写入数据的时候应该通过HBL_DISCARD参数来给缓存加锁。

谨慎的选择缓存的使用方法可以让你从几何模型的处理中得到效率的优化。当需要频繁更新缓存的情况下，首先考虑是全部内容需要更新还是部分。如果是后者，尽量考虑使用多个缓存来保存数据，只把需要更新的缓存定义为HBU_DYNAMIC类型。

尽量选择有_WRITE_ONLY后缀的类型。这意味着你不能从缓存中直接读取数据，基于从缓存（显存）读取数据是非常耗时的过程，这样做是一个不错的选择。当你真的需要从缓存中回写数据的时候，可以考虑使用备份缓存来实现，我们将会在接下去的章节中介绍这个功能。


文档:手册:1-4-0:5.3 备份缓存 - OGRE 3D 中文

文档:手册:1-4-0:5.3 备份缓存

就像我们之前章节中讨论的一样，从缓存（显存）中回写数据是一个非常烂的主意。就算你有“死也要”从缓存中读取数据的情况，你也可以通过设置“备份缓存（shadowBuffer）”来代替直接从缓存中读取。当你在建立顶点缓存的createVertexBuffer方法中或者建立索引缓存的createIndexBuffer方法中设置备份缓存参数为“true”的时候，意味着引擎帮助你在内存中建立了一个硬件缓存的备份区域，这样就能让你可以像从内存中读取数据一样读取缓存数据。当你向显存中写入数据的时候，系统会首先更新内存中的备份数据，然后才会更新真正的硬件缓存，就如同一个独立的拷贝过程一样——使用这种技术会带来效率的而外开销。所以尽量不要使用它，除非真的需要。


文档:手册:1-4-0:5.4 缓存加锁 - OGRE 3D 中文

文档:手册:1-4-0:5.4 缓存加锁

在任何读取或者更新硬件缓存的时候，你需要预先“锁”上它。这个以帮助你实现两个功能——首先是告诉显示卡你需要对缓存取得所有权（对它的渲染队列产生影响），其次是得到一个你可以操作的缓存指针。请注意，如果你选择了可读的缓存类型（记住，其实你完全可以通过使用备份缓存来达到一样的功能），缓存中的内容会被拷贝至系统内存中用于你的使用。基于同样的原因，在你操作结束之后你需要对缓存进行“解锁”操作；如果之前进行了“锁”的操作，“解锁”会帮助你通知图形硬件数据更新。

锁类型参数

当你需要对换村进行写操作，你可以适用下列函数的其中一个：

//“锁”全部的缓存区域
pBuffer->lock(lockType);
//“锁”缓存中的一部分区域
pBuffer->lock(start, length, lockType);

其中第一个函数对整个缓存进行了“锁”操作，而第二个函数只“锁”了从“start”参数（字节偏移量）开始，“length”参数字节长度的部分。修改对缓存加“锁”的区域越少效率会越高，但并不等同于对之后更新缓存的时候，因为“锁”部分缓存意味着你无法正确使用HBL_DISCARD（清参看下面）。

锁类型（lockType）参数对你的应用程序性能会有很重要的影响，尤其是在你没有使用备份缓存的时候。

HBL_NORMAL

这种类型的“锁”允许从缓存中读取数据——同时这也是最差效率的一种类型，因为这种设置等同于允许你对显示卡进行任何操作。如果你没有使用备份缓存功能，这样做会导致缓存从显示卡到内存传送一个来回，如果你使用了备份缓存的话能让这种对程序效率的影响降至最低。

HBL_READ_ONLY

使用这种类型的“锁”意味着你只能从缓存中读取内容。使用这种操作的时候最好建立备份缓存，因为这样就能避免真正的从显示卡中读取数据。

HBL_DISCARD

使用这种类型的“锁”意味着你希望在每次操作时把缓存中所有的内容都丢弃。这样做暗示了你并不需要读取之前的数据——并且同时意味着对显示卡的当前渲染操作不会有任何性能影响，因为你已经承诺提供全新的数据。在没有使用备份缓存的时候应该尽量使用这种类型对缓存加“锁”，反之当你使用了备份缓存的时候就没什么大的必要了，使用一个备份缓存比每次锁住全部缓存效果要好，因为这样可以允许备份缓存当上载更新内容到真正的缓存的时候通过使用HBL_DISCARD。

HBL_NO_OVERWRITE

当因为只需要更新部分缓存导致无法使用HBL_DISCARD类型的时候，这种“锁”的类型就显得非常有用了。它告知显示卡你承诺在当前帧的渲染操作中不会对缓存中的任何部分进行修改。这种类型的“锁”和上一种“锁”一样，只在没有使用备份缓存的时候才有用处。

一旦你“锁”住了一个缓存，你就可以对返回的指针做任何你希望的操作（知识需要记住，不要对HBL_DISCARD类型的指针进行读操作，也不要对HBL_READ_ONLY类型的指针进行写操作）。如果针对不同类型缓存的内容进行修改，经参照章节5.6 硬件顶点缓存和章节5.7 硬件索引缓存。


文档:手册:1-4-0:5.5 缓存使用经验谈 - OGRE 3D 中文

文档:手册:1-4-0:5.5 缓存使用经验谈

缓存的构造和加锁之间存在相互作用，这种作用对执行效果有着重要的影响。下面给出一些相关提示：

  • 1．理论上最“完美”的缓存，是那种通过HBU_STATIC_WRITE_ONLY类型创建，但并不创建自身的备份缓存，并且只进行一次HBL_DISCARD的锁操作用于传入数据。之后永远不要去再次动它。
  • 2．如果你需要频繁更新缓存，就要对执行性能进行一些妥协。这时候使用HBU_DYNAMIC_WRITE_ONLY类型来创建缓存（仍然不要创建相应的备份缓存），之后通过HBL_DISCARD来进行全部缓存的锁操作，或者你不能对其全部加锁，那么可以考虑通过HBL_NO_OVERWRITE来锁住部分缓存。
  • 3．如果你真的又需要从缓存中读取数据的话，建立一个备份缓存。并确认通过HBL_READ_ONLY类型锁来进行读取，因为这样可以禁止在解锁的时候上载数据。你也可以把这一条联合上面两点来作为新的条款，在可能的时候尽量把缓存设为静态的——请记住 “_WRITE_ONLY”后缀只是针对真实的硬件缓存，如果拥有备份缓存，你仍然可以进行安全的读取操作。
  • 4．在对顶点的不同元素需要不同的使用模式的时候，把这些定点缓存元素拆分成不同的部分。不要通过指针更新大量的缓存定点数据，如果你只需要更新纹理坐标，那么就把纹理坐标单独放到一个缓存区域，然后把其他的元素拆分放置在HBU_STATIC_WRITE_ONLY类型的缓存区域中。


文档:手册:1-4-0:5.6 硬件顶点缓存 - OGRE 3D 中文

文档:手册:1-4-0:5.6 硬件顶点缓存

这一部分主要针对硬件缓存中的顶点内容进行重点讨论，对于硬件缓存的使用基础部分，包括创建和锁操作，请参照之前的章节5. 硬件缓存。


文档:手册:1-4-0:5.6.1 VertexData类 - OGRE 3D 中文

文档:手册:1-4-0:5.6.1 VertexData类

VertexData类保存了所有和顶点有关的信息。每次新的渲染操作都需要一个指向VertexData对象的指针，同时它也可以用被模型（Mesh）和子模型（SubMesh）来储存顶点位置、法线以及纹理坐标等数据。VertexData既可以被单独使用（被用来作为三角形流数据来渲染无索引的几何体），或者和索引数据结合来产生完整的顶点数据。

值得注意的是，你所使用的VertexData中几何体数据并不需要一定从应用程序中得到；你也可以自己凭空创建一个VertexData结构用来渲染。VertexData结构由一些指针类型的数据成员组成，因此这样做并不是什么难事。你可以选择任何一种你喜欢的方式来创建顶点缓存以及相应的声明信息，只要你保证它们能足够用来执行渲染操作就好了。

VertexData类中所包含的一些重要成员

  • vertexStart

顶点数据在缓存中开始的位置。通过这个成员可以允许你使用同用一个缓存来进行多个不同的渲染。

  • vertexCount

当前渲染组中所需要处理的顶点的数量。

  • vertexDeclaration

一个指向 VertexDeclaration对象的指针，用来标示输入顶点数据的格式；值得注意的是，这个数据通过VertexData来为你创建，具体细节请参照5.6.2 顶点声明。

  • vertexBufferBinding

一个指向VertexBufferBinding对象的指针，用来标示顶点缓存的来源-同样的，这个数据仍然是通过VertexData来为你创建。具体细节请参照5.6.3 顶点缓存绑定。


文档:手册:1-4-0:5.6.2 顶点声明 - OGRE 3D 中文

文档:手册:1-4-0:5.6.2 顶点声明

顶点声明定义了渲染屏幕上几何体所需要输入的顶点数据。基本上这意味着对于每一个顶点，你都需要填入一个数据集合到图形流水线被用于渲染工作，这个数据集合（会按照你所希望的方法）影响着渲染时候的具体表现。顶点声明中定义了缓存中顶点数据集合中的每个条目（称之为顶点元素，在OGRE中通过VertexElement类抽象），包括共享的和专用的具体元素。你所需要做的工作就是通过VertexDeclaration类型的实例来声明缓存的内容以确保它们有具体的含义。

如果你希望向VertexDeclaration对象的实例中增加新的元素，你可以通过addElement方法来完成这项工作。它所包含的参数包括：

  • source
这个参数告诉声明这个元素针对哪个缓存使用。请注意这个参数只是一个索引值，可以适用的范围从0开始到比顶点数据源的数量少1结束（比如有3个顶点缓存区域，索引范围从0到2）。具体相关细节清参照章节5.6.3 顶点缓存绑定。绑定可以把真实的缓存区域关联到具体的索引值上。通过这种方式来储存顶点元素（而不是通过缓存指针）允许你更容易的重新绑定顶点原，而不用改变声明的中的具体顶点格式。
  • offset
这个参数告诉声明这个元素在缓存中的每个顶点中具体的偏移量（bytes）。如果缓存中只有一个元素的话这个值可以填0，如果前面已经存在元素的话这个值会大一些。比较好的方法来理解这个参数就是：缓存中顶点数据里面当前元素前面声明的所有元素的尺寸。
  • type
这个参数被用来定义新元素的具体类型，同时包括它的尺寸。随着GPU变得越来越强大，这个参数的作用也日益重要。因为可编程顶点管线允许对输入和输出进行全面的控制，所以我们现在还不能确定是否将来的图形硬件会支持不是三个浮点数的空间位置数据。这个参数定义了元素相应的基本类型和尺寸，举例来说VET_FLOAT3代表了三个浮点数-而具体的含义又下面一个参数来确定。
  • semantic
这个参数定义了当前元素的具体 - GPU将使用这个参数来确定当前输入被用于什么地方，并且可编程顶点管线将要使用这个参数来确定具体要输入到哪个语义中去 。可以设置数据的语义包括“位置数据”、“法线数据”或者“纹理坐标数据”等等。你可以参照API参考书来得到关于配制这个参数的全部细节。
  • index
这个参数只会在你在同一个元素中配制了多个相同语义的元素是有产生作用。举例来说，如果你需要设置超过一个的纹理坐标数据，你就需要把第一个的索引设置为0，接下来的设置为1，并依次类推。

你可以重复的使用addElement方法，用来在顶点数据结构中添加多个元素。同时在VertexDeclaration类型中也提供了相应的查询声明中元素的方法 - 具体细节可以参考API参考书来使用。

需要考虑的部分

虽然理论上说，你可以完全控制顶点数据的内部格式。不过在实际的应用中仍然有一些限制，在早期支持DirectX的硬件里面的顶点数据中的元素规定了固定的顺序。对于任何针对DirectX 9之前的显示硬件而言，对顶点有如下的限制。

  • VertexElements的添加必须遵循下面的顺序，并且缓存中的元素也需要按照这个顺序排列：
1.位置信息（Positions）
2.绑定权重（Blending weights）
3.法线（Normals）
4.环境光颜色（Diffuse colours）
5.镜面光颜色（Specular colours）
6.纹理坐标（Texture coordinates）（从0开始，依次排列，并且不能有空隙）
  • 通过顶点元素（VertexElement）所配置的缓存中，不能有任何空隙存在。
  • 必须注意，不能设置两个顶点元素的缓存和偏移量交迭。

对于OpenGL和DirectX 9兼容的硬件而言，并没有前面提及的这些限制。在具体使用的时候，你会发现，就算不遵守上面的条款你仍然可以在OpenGL和DierctX9兼容的硬件上执行，但是放到老版本的显示卡上，运行早期版本的DirectX就会导致错误的产生。基于这个原因，如果你希望程序可以在更多的硬件上面运行，你应该尽量遵守上面所列出来的条款。


文档:手册:1-4-0:5.6.3 顶点缓存绑定 - OGRE 3D 中文

文档:手册:1-4-0:5.6.3 顶点缓存绑定

顶点缓存绑定指的是通过顶点声明来把顶点缓存和资源索引结合到一起。

创建顶点缓存

首先，让我们先看看怎么建立一个顶点缓存：

HardwareVertexBufferSharedPtr vbuf =
    HardwareBufferManager::getSingleton().createVertexBuffer(
        3*sizeof(Real), // size of one whole vertex
        numVertices, // number of vertices
        HardwareBuffer::HBU_STATIC_WRITE_ONLY, // usage
        false); // no shadow buffer

在这里我们看到，这是通过调用[文档:手册:1-4-0:5.1 硬件缓存管理器|硬件缓存管理器]来创建顶点缓存的，然后这方法返回给我们一个HardwareVertexBufferSharedPtr类的实例，而不是简单的原生指针。这是因为顶点缓存需要做引用计数工作——你可以把一个单独的顶点缓存作为资源应用到多个几何体片上，单纯的便准指针并不能完成这个工作，因为当没有引用计数的时候你无法知道是否还有什么地方在使用这个缓存，继而无法在合适的时候释放缓存。HardwareVertexBufferSharedPtr类通过引用计数来管理缓存的销毁工作，即档所有的HardwareVertexBufferSharedPtr实例都被销毁了之后，这个缓存也便自动被销毁了。

顶点缓存通过下列参数来创建:

  • vertexSize

整个一个顶点在缓存中的byte尺寸。一个定点可能会喊有很多不同的元素，根据你对定点声明的不同而决定一个定点的尺寸是不固定的。因此，你必须告诉管理器一个完整的定点的具体尺寸。在我们上面的例子中，我们使用了三个浮点数的大小作为定点的尺寸，这样我们就可以在每一个顶点缓存中放置一个标准的顶点位置坐标，也或者可以放置法线或者三维纹理的坐标。

  • numVertices

缓存中的顶点数量。记住，没有必要把所有顶点都一同使用，创建一个巨大的缓存区域在很多不同的几何体块之间共享是一件让人受益的事情，因为改变顶点缓存绑定是一个渲染状态的选择，因为改变顶点缓存的过程是一种渲染状态改变，这样可做可以使这个过程的代价见到最少。

  • usage

这个参数告诉系统你将如何使用这块缓存。请参照5.2 缓存使用方法。

  • useShadowBuffer

告知系统你是否需要一分系统内存的缓存拷贝，参照5.3 备份缓存。

绑定顶点缓存

第二个步骤就是榜定缓存到你所建立的资源索引上面去。通过下面的调用来实现：

vertexBufferBinding->setBinding(0, vbuf);

上面代码的执行结果就是把之前建造的顶点缓存榜定到更早之前创建的资源索引0上面，继而这里所有的顶点元素都可以通过资源索引0来得到他们在缓存中的数据。

同时Ogre也提供了通过绑定数据反过来找回缓存的方法，你可以参照API手册来得到具体的细节。


文档:手册:1-4-0:5.6.4 更新顶点缓存 - OGRE 3D 中文

文档:手册:1-4-0:5.6.4 更新顶点缓存

5.6.4 更新顶点缓存

更新顶点缓存的复杂性完全取决于之前如何配置里面的内容。你可以锁住一块缓存（参照5.4 缓存加锁），但是你写入的数据的方法需要依赖里面的具体内容。

让我们以一个非常简单的例子来说明。假设你有一块其中只有顶点位置的缓存，继而里面的内容对于每个定点来说只有三个浮点数据。如果你要向里面写入数据，只需要是用下面的代码：

Real* pReal = static_cast<Real*>(vbuf->lock(HardwareBuffer::HBL_DISCARD));

...然后你只要按照顺序写入每个顶点的三个实数坐标就可以了。如果你有更多的浮点数元素在里面，可能写入的过程会稍微复杂一些，但大体的方式是一样的，你只需要依次写入顶点中的不同元素。但是如果你有另外一种类型的定点元素在其中，或者你需要驱动元素自己去写入顶点数据？好的，这里在VertexElement类中提供一些有用的方法应该会帮的到你。

首先，你应该把锁住的缓存作为一个无符号的char*类型上面，而不是其它什么特殊的类型。然后，通过调用VertexDeclaration::findElementsBySource方法来得到顶点元素实例，对其调用VertexElement::baseVertexPointerToElement方法。这将会让你的到一个在缓存顶点中元素数据的偏移量，并且允许你用正确俄地类型来导入数据。下面提供了完整的例子：

// Get base pointer
unsigned char* pVert = static_cast<unsigned char*>(vbuf->lock(HardwareBuffer::HBL_READ_ONLY));
Real* pReal;
for (size_t v = 0; v < vertexCount; ++v)
{
    // Get elements
    VertexDeclaration::VertexElementList elems = decl->findElementsBySource(bufferIdx);
    VertexDeclaration::VertexElementList::iterator i, iend;
    for (i = elems.begin(); i != elems.end(); ++i)
    {
        VertexElement& elem = *i;
        if (elem.getSemantic() == VES_POSITION)
        {
            elem.baseVertexPointerToElement(pVert, &pReal);
            // write position using pReal

        }

        ...

    }
    pVert += vbuf->getVertexSize();
}
vbuf->unlock();

可以参照API手册来得到VertexDeclaration与VertexElement类型的所有方法的细节，来帮助你来管理顶点缓存的数据指针。


文档:手册:1-4-0:5.7 硬件索引缓存 - OGRE 3D 中文

文档:手册:1-4-0:5.7 硬件索引缓存

索引缓存被用于在渲染构造几何体的三角形的时候索引缓存中顶点数据所用，取代直接从顶点缓存中连续的读取数据。索引缓存比顶点缓存数据简单，里面所存的数据只是真正顶点数据的索引表，和顶点缓存一样，你也可以在多个几何体片段之间共享同一个索引缓存数据，因此对索引缓存建立和加锁的规则和顶点缓存相同，请参照5. 硬件缓存中相关的章节。


文档:手册:1-4-0:5.7.1 IndexData类 - OGRE 3D 中文

文档:手册:1-4-0:5.7.1 IndexData类

5.7.1 IndexData类

这个类中概述了渲染几何体索引集合所需要的信息。其中的成员包括：

  • indexStart
这个几何体片断所使用的第一个索引；这个成员对于在多个几何体片断中共享单独一个单独的索引缓存十分有用。
  • indexCount
这个可渲染物体中使用索引的数量。
  • indexBuffer
提供所需索引的具体索引缓存。

建立索引缓存

索引缓存和顶点缓存一样，也是通过硬件缓存管理器来创建（参照5.1章节），下面提供了具体调用的方法：

HardwareIndexBufferSharedPtr ibuf = HardwareBufferManager::getSingleton().
    createIndexBuffer(
        HardwareIndexBuffer::IT_16BIT, // type of index
        numIndexes, // number of indexes
        HardwareBuffer::HBU_STATIC_WRITE_ONLY, // usage
        false); // no shadow buffer

在重申一次，这里的返回值是一个对象而非简单的指针；这是为了提供给引用计数功能来实现自动销毁用的，这样做的目的是让一段缓存可以有多个引用。在创建索引缓存方法中的参数包括：

  • indexType
这里提供了两种不同的索引类型，16-bit和32-bit。这两种类型的索引缓存的使用方式完全一样，它们之间的区别在于能够索引顶点缓存地址的大小。如果你需要使用超过65526个以上的顶点数量，你就需要32-bit的索引了。注意，除非你真的对32-bit索引又需要，否则它会带来比16-bit大很多的空间浪费，而且在很多老的硬件上也不支持32-bit的索引。
  • numIndexes
缓存中索引的数量。和顶点缓存一样，尽量考虑建立一个可以供多个几何体片断共享使用的“大缓存”，这样可以让框架减少对多个缓存的切换。
  • usage

这个参数告诉系统你将如何使用这块缓存。请参照5.2 缓存使用方法。

  • useShadowBuffer

告知系统你是否需要一分系统内存的缓存拷贝，参照5.3 备份缓存。


文档:手册:1-4-0:5.7.2 更新索引缓存 - OGRE 3D 中文

文档:手册:1-4-0:5.7.2 更新索引缓存

5.7.2 更新索引缓存

只有在锁住缓存之后才能对索引缓存中的数据进行更新写入；可以参照5.4 缓存加锁来了解更多的细节。锁操作返回一个无类型的指针（void*），当使用时候必须要进行手动转换。对于16-bit类型的索引需要转换成unsigned short类型的指针，而对于32-bit类型来说需要转换成unsigned long类型的指针。例如

unsigned short* pIdx = static_cast<unsigned short*>(ibuf->lock(HardwareBuffer::HBL_DISCARD));

然后你就可以通过指针向缓存里面写入数据了，只是别忘了在写入结束后对缓存执行解锁操作！


文档:手册:1-4-0:5.8 硬件像素缓存 - OGRE 3D 中文

文档:手册:1-4-0:5.8 硬件像素缓存

5.8 硬件像素缓存

硬件像素缓存是一种储存在显示卡硬件内存中特殊图形数据的类型，通常被用来作为纹理使用。像素缓存可以用来保存一维、二维或者三维图形。一个纹理可以有一些这种缓存来组成。和顶点缓存与索引缓存不同，像素缓存并不能直接创建。当你创建一个纹理的时候，所需的顶点缓存会带着相应的数据被自动创建出来。


文档:手册:1-4-0:5.8.1 纹理 - OGRE 3D 中文

文档:手册:1-4-0:5.8.1 纹理

目录

  • 5.8.1 纹理
    • 1.1 创建一个纹理
    • 1.2 纹理使用
    • 1.3 得到一个PixelBuffer（像素缓存）

5.8.1 纹理

所谓纹理，就是一张可以应用在空间模型表面的图像。在Ogre中，纹理被描述成Texture resource类型.

创建一个纹理

纹理通过纹理管理器TextureManager创建。在大多数情况下都是直接从Ogre资源系统中的图片文件直接创建得来。但如果你在阅读着个章节的话，很可能是希望手动创建一个纹理的图像数据。这样的话你需要调用TextureManager::createManual方法:

   ptex = TextureManager::getSingleton().createManual(
   "MyManualTexture", // Name of texture
   "General", // Name of resource group in which the texture should be created
   TEX_TYPE_2D, // Texture type
   256, // Width
   256, // Height
   1, // Depth (Must be 1 for two dimensional textures)
   0, // Number of mipmaps
   PF_A8R8G8B8, // Pixel format
   TU_DYNAMIC_WRITE_ONLY // usage
);

在上面的例子中，我们创建了一个被称为MyManualTexture的纹理，并放置在资源组General中。这是一个二维矩形文理，宽度和高度均为256。拥有no mipmaps属性，内部像素格式为PF_A8R8G8B8，使用方法是TU_DYNAMIC_WRITE_ONLY。如果希望进一步了解不同文理类型，可以参照5.8.3 纹理类型。而更多关于像素格式的信息在5.8.4 像素格式。

纹理使用

如果希望了解更多的使用方法可以参照5.2 缓存使用方法章节，这里只是着重的介绍一下纹理自身所持有的特殊用法：

  • TU_AUTOMIPMAP
让图形硬件自动生成Mipmaps。这时候并没有制定具体的算法，但是你可以认为硬件使用了2x2 box filter算法来处理。
  • TU_RENDERTARGET
这个纹理是一个渲染目标。换句话说，你把一个目标渲染到这个纹理上。设置了这个标记将会忽略所有除了TU_AUTOMIPMAP之外的标记。
  • TU_DEFAULT
世界上这个一个混合了多种用法的标记，他等价于TU_AUTOMIPMAP | TU_STATIC_WRITE_ONLY。资源系统使用这个标记来处理从图片中读入的图像数据。

得到一个PixelBuffer（像素缓存）

一个纹理可以包含众多的PixelBuffer像素缓存，其中的每一个都对应着不同的mipmap等级和表面号码（face number）。我们已通过Texture对象的Texture::getBuffer(face, mipmap)方法来得到PixelBuffer实例，对于非立方、体贴图（no-cubemap）的纹理face需要设置为0值。而对于立方体贴图纹理face才会被用于表面的索引，关于立方体表面的细节可以参照5.8.3 纹理类型来了解更多。对于元素图像需要mipmap为0进行索引，第一个mpmap等级为1，以此类推。但当一个恩里使用了自动mipmap创建(TU_AUTOMIPMAP)的时候，只有等级0可以被使用，其他的细节都交给渲染API去处理。下面是一个使用getBuffer方法的简单例子：

   // Get the PixelBuffer for face 0, mipmap 0.
      HardwarePixelBufferSharedPtr ptr = tex->getBuffer(0,0);


文档:手册:1-4-0:5.8.2 更新像素缓存 - OGRE 3D 中文

文档:手册:1-4-0:5.8.2 更新像素缓存

5.8.2更新像素缓存

这里提供了两种不同的更新像素缓存的方法；其中一种很简单，另外一种稍微有一些难度，不过在某些场合会表现的高效率。不过不管是选择了哪一种方法，都需要借助PixelBox对象来帽徽缓存中的图像数据（可以参照像素盒)。

blitFromMemory

从像素缓存中得到图像的简单方法是通过调用HardwarePixelBuffer::blitFromMemory方法。这里获得一个PixelBox对象并帮助你进行所有必要的定点格式转换与缩放。例如，建立一个手动纹理并把一个图片放入里面，你将要采用以下代码：

 // Manually loads an image and puts the contents in a manually created texture
Image img;
img.load("elephant.png", "General");
// Create RGB texture with 5 mipmaps
TexturePtr tex = TextureManager::getSingleton().createManual(
   "elephant",
   "General",
   TEX_TYPE_2D,
   img.getWidth(), img.getHeight(),
   5, PF_X8R8G8B8);
// Copy face 0 mipmap 0 of the image to face 0 mipmap 0 of the texture.
tex->getBuffer(0,0)->blitFromMemory(img.getPixelBox(0,0));

直接对缓存加锁

另外一个高级的方法来从PixelBuffer（像素缓存）中得到图像数据的方法是对缓存加锁。通过对PixelBuffer加锁，你可以不管缓存的具体格式而直接的在GPU中存取其内容。

  /// Lock the buffer so we can write to it
buffer->lock(HardwareBuffer::HBL_DISCARD);
const PixelBox &pb = buffer->getCurrentLock();

/// Update the contents of pb here
/// Image data starts at pb.data and has format pb.format
/// Here we assume data.format is PF_X8R8G8B8 so we can address pixels as uint32.
uint32 *data = static_cast<uint32*>(pb.data);
size_t height = pb.getHeight();
size_t width = pb.getWidth();
size_t pitch = pb.rowPitch; // Skip between rows of image
for(size_t y=0; y<height; ++y)
{
    for(size_t x=0; x<width; ++x)
{
        // 0xRRGGBB -> fill the buffer with yellow pixels
        data[pitch*y + x] = 0x00FFFF00;
}
}

/// Unlock the buffer again (frees it for use by the GPU)
buffer->unlock();


文档:手册:1-4-0:5.8.3 纹理类型 - OGRE 3D 中文

文档:手册:1-4-0:5.8.3 纹理类型

5.8.3 纹理类型

当前的硬件支持四种不同的纹理类型，三种不同维度德纹理（一维、二维和三维）。第四中有些特殊。这四种类型的纹理是：

  • TEX_TYPE_1D
一维纹理，通过1D纹理坐标来索引。
  • TEX_TYPE_2D
二维纹理，通过2D纹理坐标来索引。
  • TEX_TYPE_3D
三维纹理，通过3D纹理坐标来索引。
  • TEX_TYPE_CUBE_MAP
立方体贴图(六个二维纹理，代表立方体的六个表面)，通过三维纹理坐标来索引。

立方体贴图纹理

立方体贴图纹理类型(TEX_TYPE_CUBE_MAP)是一个很灵类的纹理格式；一个立方体贴图由一系列六个二维图形表示，并以三为坐标系来所引起地址。

  • +X (表面0)
正x轴表面(右)。
  • -X (表面1)
负x轴表面(左).
  • +Y (表面2)

正y轴表面(上).

  • -Y (表面3)
负y轴表面(下).
  • +Z (表面4)
正z轴表面(前).
  • -Z (表面5)
负z轴表面(后).


文档:手册:1-4-0:5.8.4 像素格式 - OGRE 3D 中文

文档:手册:1-4-0:5.8.4 像素格式

5.8.4像素格式

像素格式描述了像素数据存储所用的格式。定义了像素在内存中的编码方式。下面的像素格式 (PF_*) 类型定义了：

  • 本地格式 (PF_A8R8G8B8 以及其他大量的不同的类型)
这意味着在内存中使用了本地储存方式（big endian或者little endian，包括16，24，，32位）的整形数据。同时意味着可以把PF_A8R8G8B8各式的图片看作一个32位的整形数组，在16进制表现为0xAARRGGBB。这些字母的意义我们在稍后会提供。
  • 位组格式Byte formats(PF_BYTE_*)
在这种格式下每个通道对应一个byte，通道在内存理的组织方式和格式名称定义的相同。例如PF_BYTE_RGBA格式的像素包含了四个byte，一个对应红色，一个绿色，一个蓝色，以及一个alpha通道。
  • Short格式(PF_SHORT_*)
在这种格式下每个通道对应一个unsigned short数据(16 bit整形)，通道在内存理的组织方式和格式名称定义的相同。例如PF_BYTE_RGBA格式的像素包含了四个unsigned short数据，一个对应红色，一个绿色，一个蓝色，以及一个alpha通道。
  • Float16 格式(PF_FLOAT16_*)
在这种格式下每个通道对应一个16 bit浮点数，通道在内存理的组织方式和格式名称定义的相同。例如PF_BYTE_RGBA格式的像素包含了四个16 bit浮点数数据，一个对应红色，一个绿色，一个蓝色，以及一个alpha通道。16 bit浮点数也被称为半浮点（half float），非常类似于IEEE 对32bit单精度浮点数标准，只不过它只有5个exponent位和10个mantissa位而已。值得注意，这并不是一个标准的C++数据，CPU对其支持也不够好，不过GPU却能如同处理32bit浮点数一样高效的处理它。
  • Float32格式(PF_FLOAT32_*)
在这种格式下每个通道对应一个32 bit浮点数，通道在内存理的组织方式和格式名称定义的相同。例如PF_BYTE_RGBA格式的像素包含了四个32 bit浮点数数据，一个对应红色，一个绿色，一个蓝色，以及一个alpha通道。再C++中，这个数据就是普通的float。just "float".
  • 压缩格式formats (PF_DXT[1-5])
S3TC压缩纹理格式，更多的细节清参照| Wikipedia (http://en.wikipedia.org/wiki/S3TC)

颜色通道

颜色通道中R,G,B,A,L 以及 X 的意义是：

  • R
红色成分，通常范围从0.0（没有红色）到1.0（全部的红色）。
  • G
绿色成分，通常范围从0.0（没有绿色）到1.0（全部的绿色）。
  • B
蓝色成分，通常范围从0.0（没有蓝色）到1.0（全部的蓝色）。
  • A
alpha（不透明度）成分，通常范围从0.0（完全透明）到1.0（不透明）。
  • L
亮度成分，通常范围从0.0（黑暗）到1.0（全白）。最终这个成分会被分散到RGB每个中完成最终的图像效果。
  • X
这个是被系统忽略的成分。

对于RGBL通道来说，默认的情况下设置为0。而Alpha痛悼却不同，在默认的情况下被设定为1，代表不透明。

全部的像素格式

当前版本的Ogre支持下列像素格式：

  • 位组格式
PF_BYTE_RGB, PF_BYTE_BGR, PF_BYTE_BGRA, PF_BYTE_RGBA, PF_BYTE_L, PF_BYTE_LA, PF_BYTE_A
  • Short格式
PF_SHORT_RGBA
  • Float16 格式
PF_FLOAT16_R, PF_FLOAT16_RGB, PF_FLOAT16_RGBA
  • Float32 格式
PF_FLOAT32_R, PF_FLOAT32_RGB, PF_FLOAT32_RGBA
  • 8 bit 本地格式
PF_L8, PF_A8, PF_A4L4, PF_R3G3B2
  • 16 bit 本地格式 '
PF_L16, PF_R5G6B5, PF_B5G6R5, PF_A4R4G4B4, PF_A1R5G5B5
  • 24 bit 本地格式
PF_R8G8B8, PF_B8G8R8
  • 32 bit 本地格式
PF_A8R8G8B8, PF_A8B8G8R8, PF_B8G8R8A8, PF_R8G8B8A8, PF_X8R8G8B8, PF_X8B8G8R8, PF_A2R10G10B10 PF_A2B10G10R10
  • 压缩格式
PF_DXT1, PF_DXT2, PF_DXT3, PF_DXT4, PF_DXT5


文档:手册:1-4-0:5.8.5 像素盒(Pixel boxes) - OGRE 3D 中文

文档:手册:1-4-0:5.8.5 像素盒(Pixel boxes)

From OGRE 3D 中文

5.8.5 像素盒(Pixel boxes)

Ogre中所有处理或者返回图像的方法都把图像数据封装在一个PixelBox对象中。每个PixelBox都是一种对CPU内存中像素的体积 (3D)，图像 (2D)或者是线的描述。它描述了内存中图像的位置和格式等信息，但是它本身并没有任何内存管理的工作和功能。代替通过内存指针来操作数据，像素盒中提供了通过深度（Z），高度（Y）以及宽度（X）来索引像素的方法，如果有一些维度没有被使用，就需要把它们设定为1。例如你需要处理一个一维的图像，你可以通过范围（width,1,1）来索引其中的像素。二维的图像通过（width,height,1）来索引。PixelBox类型拥有以下的成员：

  • data
内存中这个图像数据的首指针。
  • format
这个图像数据的像素格式(参照5.8.4 Pixel Formats) .
  • rowPitch
相邻两行最左边像素之间元素的数量，对于压缩格式来说，这个值总是等于getWidth()。
  • slicePitch
相邻两层最左上角像素之间元素的数量，对于压缩格式来说，这个值总是等于getWidth()*getHeight()。
  • left, top, right, bottom, front, back
盒子在三维空间的范围。注意到left，top以及front的边被包含进来，而right，bottom以及top的边没有被包含到这个空间中。left总是必须小于或者等于right，top总是必须小于或者等于bottom，front总是必须小于或者等于back。

里面同时还提供了一些有用的方法：

  • getWidth()
得到盒子的宽度
  • getHeight()
得到盒子的高度。对于一维图像来说这个值永远是1。
  • getDepth()
得到盒子的深度。对于一维和二维图像来说这个值永远是1。
  • setConsecutive()
设置rowPitch以及slicePitch，以便缓冲在内存中得到连续的数据。
  • getRowSkip()
得到两行之间的空隙长度，当行数据是连续的时候，这个值是0。
  • getSliceSkip()
得到两层之间的空隙长度，当蹭之间是连续的时候，这个值是0。
  • isConsecutive()
返回数据在内存中是否是连续的。
  • getConsecutiveSize()
得到这个图像在内存中使用连续数据的长度（单位是byte）。
  • getSubVolume(const Box &def)
返回一个PixelBox的子体积，并作为一个PixelBox。

对于更多的信息清参照API文档。


文档:手册:1-4-0:6. 外部纹理源 - OGRE 3D 中文

文档:手册:1-4-0:6. 外部纹理源

目录

  • 1 6. 外部纹理源
    • 1.1 介绍
    • 1.2 什么是外部纹理源？
    • 1.3 ExternalTextureSource类
    • 1.4 ExternalTextureSourceManager类
    • 1.5 纹理源材质脚本
    • 1.6 过程的简单图示

6. 外部纹理源

介绍

这个教程将会简略的介绍一下ExternalTextureSource和ExternalTextureSourceManager两个对象，它们之间的关系，和它们的插件是如何工作的。如果希望开发一个纹理源插件或者只是想了解一下这些系统是如何工作的，可以看一看ffmpegVideoSystem插件，再OGRE论坛上你也可以看到很多相关的讨论。

什么是外部纹理源？

什么是外部纹理源？答案是：一个纹理的来源可以使任何东西——png，bmp，jpeg等等。对于从普通的图片类型中载入纹理的工作仍然是Ogre本身来处理的，而对于从其它的纹理来源，包括mpeg/avi等电影格式文件，flash文件，实时产生的来源，用户自定义来源等，被称为外部纹理源。

如何再OGRE中合理的插入外部纹理源？简单的回答如下：不需要改变OGRE的任何部分，只要写一个支持新的插件来处理就好了。另外，OGRE的管理器通过StringInterface类来管理命令以及相应的参数，所以不用改变已有的材质脚本管理器来支持新的插件。如果你的插件中需要特殊的参数集合，只需要在参数字典（Parameter Dictionary）建立一个新的命令参数就可以实现了。我们可以参照ffmpegVideoSystem插件作为这方面应用的例子来学习。为了让这套系统正常的工作，需加入两个类型: ExternalTextureSource 以及 ExternalTextureSourceManager。

ExternalTextureSource类

你所构建的插件必须继承于ExternalTextureSource类。它提供了一个通用的框架(通过StringInterface类)和一个非常简单的计数功能。大部分普通的参数可以简单的通过TexturePlugInSource类型接口或者通过类型里面的StringInterface命令容器来处理。看起来似乎这里代码之间有重复的功能，但事实上字符串命令接口的使用可以可以让人和需要的新类型参数被轻易的增加。

基类提供了默认的命令参数包括：

  • 参数名："filename" 参数类型: Ogre::String 设置将要读入插件的文件名
  • 参数名："play_mode" 参数类型: Ogre::String 设置初始化播放插件的模式 - "play（播放）", "loop（循环）", "pause（暂停）"
  • 参数名："set_T_P_S" 参数类型: Ogre::String 被用来设置technique（技术）, pass（通路）, 以及texture unit（纹理单元） 在纹理上所应用的等级。举例来说：设置1等级的technique，2等级的pass，3等级的texture unit，这个字符串的内容就是"1 2 3".
  • 参数名："frames_per_second" 参数类型: Ogre::String 设置每秒的帧率（只能使用整形数据）

ExternalTextureSourceManager类

ExternalTextureSourceManager被用来跟踪载入的纹理源插件。同时它也被用来帮助纹理源从脚本中的创建。同时它也是你处理纹理源插件的接口。

下面我们来一步一步的使用ExternalTextureSourceManager来建立一个新的纹理：

注意：下面所展示的函数并不完全和真实的一样，为了更好的展示功能，函数所使用的参数被简化了一些。

  • 明显的，第一步骤自然是载入在plugin.cfg文件中配置的插件。
  • 把需要的插件设置为活动的，通过这个方法AdvancedTextureManager::getSingleton().SetCurrentPlugIn( String Type ); -- type 参数值的视插件注册时候使用的名称（比如"video", "flash", "whatever"等等)。
  • 注意：为了插件按照我们希望的方式工作，在这里需要设置其参数的值，通过调用AdvancedTextureManager::getSingleton().getCurrentPlugIn()->setParameter( String Param, String Value )方法来设置其参数/值；
  • 在设置完参数之后，只需要简单的调用AdvancedTextureManager::getSingleton().getCurrentPlugIn()->createDefinedTexture( sMaterialName )方法；就能创建一个使用给定材质名称的纹理。

管理器同时提供给我们一个用来删除纹理的方法：AdvancedTextureManager::DestroyAdvancedTexture( String sTextureName )；这个销毁方法通过材质名称广播来调用已经载入的插件来销毁纹理，谁创建的纹理由谁来销毁，其它的插件会忽略这个过程。换句话说，你只需要简单的调用销毁函数，具体的分派过程OGRE会帮助你来处理。同样的，在销毁纹理插件本身的时候它们也会清理所有其创建的纹理。

纹理源材质脚本

在我们前面提及过，定义和创建纹理源的过程可以放在材质脚本文件中来处理。这里提供一个材质脚本来定义纹理的例子——注意：这里的例子是基于ffmpegVideoSystem插件的参数。

material Example/MyVideoExample
{
    technique
    {
        pass
        {
            texture_unit
            {
                texture_source video
                {
                    filename mymovie.mpeg
                    play_mode play
                    sound_mode on
                }
            }
        }
    }
}

这里值得注意的是，在纹理源中定义的三个参数/值对中，前两个是在基类ExternalTextureSource中定义的，而第三个参数/值对在基类中并没有定义... 这个参数是ffmpegVideoPlugin插件自行向参数字典（param dictionary）中增加的... 这可以让我们了解扩这个系统的功能是很容易的一件事情。这里需要关注一下这行脚本： texture_source video。这一行被用来识别纹理单元是从那个插件中产生。这个参数决定了那个纹理插件被使用。在这个例子中，注册名为"video"的插件被使用来产生纹理。

过程的简单图示

在图示中我们使用了ffmpegVideoPlugin插件作为例子，不过所有的插件的注册和使用工作都使用相同的方式。这里需要注意的是纹理源插件在脚本处理之前已经被载入和注册了，但这并不意味着它们已经被初始化... 插件直到他们被设置为活动的时候才会执行初始化工作！这是为确保渲染系统在插件之前被设置而可被插件调用。


文档:手册:1-4-0:7. 阴影 - OGRE 3D 中文

文档:手册:1-4-0:7. 阴影

阴影是渲染一个真实场景的重要组成部分 — 他们可以给场景中的物体提供更加真实的感觉，同时还可以帮助用户更好的了解对象间的空间关系。然而，从3D渲染的角度来说，渲染阴影也是一个非常有挑战的事情，这也是目前很热门的一个研究课题。目前有很多渲染阴影的技术，它们没有一个是完美的，多少都有些优点和缺陷。基于这个原因，Ogre提供了多种阴影的实现，它们都有丰富的设置选项，你可以根据场景需要来选择一个最合适的技术。

阴影的实现本质上说分为两大类: 7.1 模板阴影 和 7.2 基于纹理的阴影。它们描述的是生成阴影的方式。另外，还有更多的方法把阴影渲染到场景中去: 7.3 调制阴影，这是把阴影区域变得更暗的方法，7.4 附加光照掩码，这是计算非阴影区域的光照贡献度的方法。你还可以 集成纹理阴影，它可以让你完全控制基于纹理阴影的应用程序，加入复杂的单遍阴影Shader。Ogre支持以上所有种类的组合。

启用阴影

缺省情况下，阴影是关闭的，下面介绍的是如何在普通场景中启用和配置它们。

  • 1. 在建立场景时，你的第一件事是使SceneManager的阴影技术有效。之所以这件事必须最先做完，是因为阴影技术会影响模型读取的方式。下面是示例:
mSceneMgr->setShadowTechnique(SHADOWTYPE_STENCIL_ADDITIVE);
  • 2. 创建一个或多个光源。注意不是所有的阴影技术都支持所有光源种类，你需要查看相关阴影技术的章节。如果某种光源不能投射阴影，你要用光源的setCastShadows(false)把它关掉。缺省情况这个值是true。
  • 3. 关闭那些不需要投射阴影的物体，可以用物体的setCastShadows(false)来实现这一点。缺省情况下所有的物体都会投射阴影。
  • 4. 设置投影的最远距离。出于性能方面的考虑，你可以用SceneManager::setShadowFarDistance来限制投影的最远距离。
  • 5. 关闭那些不需要接收阴影的材质。你可以通过Material::setReceiveShadows关掉阴影的接收，或者用材质的receive_shadows属性。这对一些自发光的材质是很有用的。另外请注意透明材质典型情况下是不会接收和投射阴影的。不过对一些例外情况，你可以参考 投射透明物体。

选择阴影

缺省情况下Ogre认为所有的不透明物体都可以投射和接收阴影（不过由于有些阴影技术可能不能同时支持两者，请先参考相关文档）。你可以用以下几种方法来关闭阴影:

  • 关闭光源的投影功能
调用Light::setCastsShadows(false) 这意味着这个光源不会再使任何物体产生阴影。
  • 关闭材质的阴影接收
调用Material::setReceiveShadows(false)可以让任何使用这种材质的物体不再接收阴影。
  • 关闭独立物体的阴影
调用MovableObject::setCastsShadows(false)可以关闭具体物体的阴影功能。
  • 关闭整个渲染队列的阴影
RenderQueueGroup::setShadowsEnabled(false)可以关闭整个渲染队列的投影和接收功能。这个功能很有用。因为为了保持组间的顺序，Ogre会对每个组进行设置光源的工作。Ogre会自动关闭某些渲染组的阴影功能，比如RENDER_QUEUE_BACKGROUND, RENDER_QUEUE_OVERLAY, RENDER_QUEUE_SKIES_EARLY 和 RENDER_QUEUE_SKIES_LATE。如果你使用了更多的渲染队列（缺省情况下，除了以上的队列以及一个“标准”队列以外，你不会使用到更多的队列，所以如果实在不理解这里的意思的话，就忽略它们吧），那么你需要明白每一组都会产生光源设置的消耗，所以如果有可能，请尽量的关闭阴影吧。


文档:手册:1-4-0:7.1 模版阴影 - OGRE 3D 中文

文档:手册:1-4-0:7.1 模版阴影

模板阴影是一种通过硬件的模板缓存来"标记"屏幕中区域的方法。这个标记被用来在后来的渲染中排除屏幕中的某些区域，进而可以通过这种方法来包含和排除阴影区域。在系统中通过SceneManager::setShadowTechnique方法来打开模板阴影技术，并传入参数SHADOWTYPE_STENCIL_ADDITIVE或者是SHADOWTYPE_STENCIL_MODULATIVE。因为模板只能用来标记区域的“打开”或者“关闭”两种属性，进而模板阴影只能产生“硬”边缘的阴影，即是那种在光线和黑暗之间轮廓及其清晰的阴影类型，这种技术无法产生柔性的边缘（半影）。

为了产生模板，我们需要应用“阴影体积”技术，这种技术通过从光源到投影物体的边缘来生成一个投影体积来实现。当这个体积覆盖了其他的物体的时候（包括投影体自身，进而支持了自投影技术），这些被覆盖的物体上面的模板缓存会被更新，在之后的操作中会根据这些模板缓存的结果来渲染光线和阴影。这些阴影最终的正确结果依赖于对7.3 调制阴影以及7.4 叠加光照掩码的使用。物体既可以投射出阴影，也可以接受阴影，进而这种技术可以对自投影具有良好的支持。

对于模板阴影来说，这是一种在较低等级硬件上可以实现自投影的简单技术，并且可以让你所产生的几何体在可控制的范围内。如果使用纹理阴影来产生自投影的结果，就需要依赖一些比较现代的图形硬件来支持（参照章节7.2 基于纹理的阴影）。基于这个原因，如果你希望可以在较老的硬件环境中实现正确的阴影结果，你可能就需要选择模板阴影技术来实现。

同时，模板阴影也具有很多不利的方面，尤其是在教现代的硬件环境中。因为模板阴影是一种几何层级上的技术，继而会花费更多的几何体数量作为代价，这就意味着你需要在你的模型中提供更多的细节信息以供使用。同样的，在处理阴影体积的时候也会带来几何体数量的开销。因此，对于现在应用程序中通过高精度模型来带来更好的视觉效果的同时，模板阴影就成了这时候效率的瓶颈。同时，模板阴影的视觉效果看起来颇显得不佳——场景中所有的阴影都只能使用僵硬的边缘，并且你无法对使用了shader的物体进行阴影操作，在这种情况下模板阴影就失效了。所以，如果你确定你的程序会跑在一个比较先进的硬件环境中的时候，你应该考虑使用纹理阴影（参照章节7.2 基于纹理的阴影）。否则的话可能要考虑很多模板阴影带来的问题了：

目录

  • 1 CPU的消耗
  • 2 过远的距离
  • 3 摄像机视截体远截面位置
  • 4 模型边列表
  • 5 轮廓边界（此段Aaron帮忙翻译的，谢谢）
  • 6 实际一些的情况
  • 7 Ogre对模板处理的优化

CPU的消耗

计算模型的阴影体积是一种昂贵的操作，并且它都是在CPU中进行计算的，而不是在GPU中进行硬件加速的计算工作。因此，如果你过多的使用这个特性的话，会造成一个应用程序中的CPU瓶颈。Ogre可以高效的的排除那些无法在视截体重投影的物体，但是这里也存在了一些相应的限制，包括数量、大小以及被拉伸过长的阴影（类似黄昏时候看到的被拉得很长的阴影），这些都很困难被高效的排除。尽量避免在一个物体周围排布过多的阴影投射，并尽量避免过长的阴影产生。如果你通过设置SceneManager“阴影距离参数”来，这样就可以通过直接排除那些投影过长的阴影体积来节省你的时间，只为那些更贴近物体的投影花费效率。最后，我们来考虑使用Ogre的Level-Of-Detail (LOD)特性的情况；你可以在程序代码中自动生成LOD信息用来使用（请参考API手册），或者也可以通过类似OgreXmlConverter或者OgreMeshUpgrader这种模型工具来离线生成这些模型LOD信息。甚至你可以使用自己手动创造的模型来提供LOD细节信息。不论你使用了那种方法，都会让远处使用LOD的模型节省很多处理阴影体积的效率。

过远的距离

当顶点着色程序无法使用的时候，Ogre只能提供一个有限距离的阴影体。如果有一个物体非常接近光源的时候，任何有限的阴影体都无法正确地描绘阴影。因此如果你不能确定你的程序一定能运行在支持顶点着色程序的硬件环境中，就尽可能不要让物体过分贴近光源。如果硬件环境支持顶点着色语言，Ogre可以通过顶点程序来处理无穷大的阴影体积（基于这个原因，在有顶点着色支持的硬件环境中不存在这个问题）。

当无法使用无穷远的阴影体积的时候，Ogre会使用有限的阴影体积来代替，对于点光源和聚光灯光源来说采用光线的衰弱的方法，而对于有向光通过直接修正阴影投射的距离。我们可以通过调用SceneManager::setShadowDirectionalLightExtrusionDistance方法来改变有向光修正的阴影长度。

摄像机视截体远截面位置

模板阴影体的效果极其依赖于远截面的剪裁。当我们打开模板阴影技术的时候，Ogre会把我们摄像机的远截的距离设为0—换句话说我们把远截面设置到了无穷远的位置（Camera::setFarClipDistance(0)）。这样做就避免了远截面把我们的阴影体削平一个头这样的问题，而这么做的小小代价是增加了深度精度的计算量。

模型边列表

模板阴影只能通过几何模型的“边列表”来运算得到。离线的导出工具可以自动的为你计算并保存这个列表（或者对于某些导出工具需要打开边列表的导出选项），但如果你是自己建立的模型（比如在程序中自动生成），你就需要在使用模板阴影之前产生边列表。对于离线的情况可以使用比如OgreMeshUpgrade或者OgreXmlConverter这类的工具产生，也可以通过调用Mesh::buildEdgeList方法来在使用的时候得到边列表。如果你使用的模型没有边列表信息，Ogre会断言这个模型不支持模板阴影技术。

轮廓边界（此段Aaron帮忙翻译的，谢谢）

模板遮蔽是要找到mesh网格的边界轮廓，并将它投影形成一定体积。意思就是，在光和阴影之间有一个产生阴影物体的明确边界。其中一面三角形的边面光，而另一面背光。这样当发生转变时，就在mesh网格周围形成了一个清晰的边界。当场景中提供的光很少或者根本没有光时，mesh网格有平滑的法线用以生成其下渲染的渐变光，轮廓边界可以被隐藏——mesh网格数越高，其工作效果越好。但是，如果场景中包含环境光，那么区别则相当明显。当使用7.3 Modulative Shadows时尤为突出，因为每个阴影区域的光照贡献并为纳入这个简化方法的计算之内，而且在使用调制模板阴影的场景中使用2个或者更多的光是不明智的；轮廓边界将会非常明显。附加的光不会因此而受到影响，因为每一个光都是被独立遮蔽的，也就是说，能够显示出轮廓边界的只有那唯一的环境光。

实际一些的情况

不要期待任何时候都可以通过硬件来得到完美的阴影算法和较高的效率。阴影本身是一个复杂和昂贵效率代价的技术，你应该通过一些合理的对灯光和物体的布局来限制和优化相应的计算；虽然表面上看来对于物体的布置没有什么限制，但是你需要了解这并不意味着“完全的自由”。

  • 尽量避免让物体非常接近（或者是穿过）光源 —— 虽然看起来这么做没什么大不了的，但对于没有顶点编程能力的机器而言会产生不良的后果。
  • 需要了解的是阴影体在被别的物体穿过的时候并不一定“可靠”，如果你放置一个不能投射阴影的物体（比如有隐藏特效的），在这个闭塞的物体的另外一面你仍然能看到阴影。
  • 通过SceneManager::setShadowFarDistance方法来限制阴影体的构造数量。
  • 通过LOD特性来减少远处阴影体的复杂程度。
  • 尽量避免过长的影子产生（比如黎明或者黄昏），否则的话会影响你的阴影体积剪裁的效率，并且会导致建立大量巨大距离的阴影体积。

Ogre对模板处理的优化

尽管如此，墨板阴影仍然是一种效果非常佳（尤其是在7.4 叠加光照掩码情况下），并且在你注意了上面提到的一些细节规则的时候，它会渲染得非常快。另外，Ogre引擎本身也对模板阴影做了一些内建的优化工作，用以帮助你产生的阴影尽量的高效快速。在这个章节中我们会介绍开发者和很多人感兴趣的Ogre内建优化过程。

  • 顶点程序推出
如同我们之前所提及到的，Ogre在支持顶点着色编程的硬件环境上（比如GeForce3，Radeon 8500或者更好的硬件），可以通过顶点着色语言来实现阴影体积的推出工作。这样做带来了两个明显的好处，其一是明显的运行速度的提高，其二是顶点程序可以推出在无穷远的顶点位置，而在固定功能渲染管线上来说是无法实现的（至少是在全部使用软件计算的情况下无法实现）。这可以实现非常棒的阴影体，并消除方向光带来的一半以上的三角形，因为所有点在无穷远的位置上都有一个单独的映射。
  • 剪裁测试优化
Ogre通过一个剪裁矩形来限制距离视口太过遥远的点光源/探照灯光源对模板阴影的影响，这样做节省了渲染模板阴影体的效率，特别是对那些距离很远的光源而言。
  • Z-Pass以及Z-Fail算法
Z-Fail是卡马克提出来的一种算法，通过这种算法可以让Ogre确保那些摄像机穿过阴影体积的时候渲染阴影的正确。然而，Z-Fail算法回比普通的Z-Pass算法花费更多的效率。所以Ogre只在必要的时候使用Z-Fail算法来确保渲染的正确性，在其他的时候尽可能的使用Z-Pass算法。
  • 双面模板（2-Sided stencilling）以及模板包装（stencil wrapping）
Ogre支持双面模板以及模板包装的扩展属性，这就允许可以让模板体积在单一渲染通路中渲染，而不用把阴影体积分成正面和背面进入两个渲染通路。虽然这么做并没有实质上的效率提高，仍然需要更新相同数量的模板，但是它可以让初期的设置等操作变得简单一些。
  • 自然的阴影剪裁
Ogre可以很漂亮的探测并处理灯光是否对视截体是否有影响，并且还能够处理物体是否投影进入整个视截体的情况。这就意味着我们不会浪费时间创建那些我们不需要的阴影几何体上面。因此把影子放置在很远的位置是一种很有效的减少模板阴影的方法，因为不管阴影体是否可见系统都会剔除那些比较远的阴影体，如果你很关心物体的阴影细节，这种实践是很有益的。


文档:手册:1-4-0:7.2 基于纹理的阴影 - OGRE 3D 中文

文档:手册:1-4-0:7.2 基于纹理的阴影

纹理阴影是通过以光源作为招眼点把投影体渲染到纹理上来得到，然后再把这个纹理投射到接受阴影的表面上来得到最终的结果。相对于7.1 模版阴影而言，纹理阴影的优势在于其极少的增加了集合体的细节，因此不用执行对每个三角形的计算。对渲染纹理阴影的大部分工作都放在图形硬件中执行，这就意味着在新的现实硬件上可以得到更好的性能，换句话说纹理阴影运算速度的进化超过了CPU的发展。另外的，纹理阴影的应用范围更加广泛——如果你喜欢可以把他们放入着色器中（你可以通过着色器的操作对整个阴影进行过滤而产生软阴影或者其他的效果）。基本上，绝大多数现代的图形引擎都会使用纹理阴影作为其首选阴影技术，这是因为其不仅非常强大，并且它的GPU执行代价也被分摊到不同的纹理通路中从而带来更高的效率。

不过纹理阴影也有其主要的不利因素，因为事实上所谓阴影的基础其事实就是一张纹理图，它拥有一个固定的像素数量，当纹理被拉长之后这些像素就变得很明显和突兀，这里有一些方法来改善这个缺点：

  • 选择一个“投影基础”
最简单的投射方法就是简单的从光源点通过标准的摄像机设置来渲染阴影投射体。但是这种方法的结果却不尽人意，因此有很多种其他种类的投射方法用以改善主摄像机投射法的质量。Ogre支持通过ShadowCameraSetup类型来插入“投影基础”，并提供了一些已经存在的操作——Uniform(最简单的投射方法)，Uniform Focussed（仍然采用了标准的摄像机投影，只不过是摄像机聚焦到主观察摄像机所观察的区域），LiSPSM (Light Space Perspective Shadow Mapping - 同时基于主观察摄像机聚焦并扭曲阴影的视截体)以及Plan Optimal (对一个独立的接收平面寻找最优的投影保真度)。
  • 过滤
相对于一次采样的简单方法，我们也可以通过多次采样的方法来改善阴影的糅合度以及平滑边缘。尽管对于采样的策略有很多种不同的模式，不过基于百分比渐近滤波(PCF)是一种比较常用的过滤方法。在我们提供的阴影演示程序中，使用了一种基于5-tap PCF混合的深度阴影贴图。
  • 使用一个更大一点的纹理
随着GPU速度和显存容量的提高，你可以采用更加巨大的纹理来进行阴影处理。

如果你可以很好的混合运用上面三种处理技巧，你可以得到一个非常高质量的阴影解决方案。另外一个问题是关于点光源的，这是因为对于阴影纹理来说，需要从光源的方向对纹理进行渲染，而对于全方向的光（换句话说就是点光源）需要对六个不同的方向进行渲染来处理全方位的阴影投射。基于这个原因，Ogre内部支持对于有向光源和聚光灯光源的纹理阴影；点光源只有在距离摄像机很远的位置上才能正确的工作，这是因为这时候点光源对于你的摄像机视截体来产生纹理阴影已经蜕化成了普通的聚光灯光源。

目录

  • 1 有向光光源
  • 2 聚光灯光源
  • 3 点光源
  • 4 阴影投射物体和阴影接收物体
  • 5 配置纹理阴影
    • 5.1 阴影纹理的最大数量
    • 5.2 阴影纹理的尺寸
    • 5.3 阴影的最大距离
    • 5.4 阴影纹理的偏移量（针对有向光光源）
    • 5.5 阴影淡出设置
  • 6 纹理阴影与顶点/片断编程
    • 6.1 定制摄像机
    • 6.2 集成纹理阴影(Integrated Texture Shadows)

有向光光源

从原理上来讲，有向光光源作为一个无穷远的光源，会把阴影投射满整个场景。不顾对于我们现在来说，只拥有一个有限大小的纹理，如果把平铺到整个无限大的空间中来，会让我们阴影的质量变得及其低下。Ogre使用了一种技巧来处理这种问题，它直接把有限的阴影纹理放置在摄像机正前方，并把阴影纹理随着摄像机的移动而移动（尽管会在小距离移动纹理的时候，会因为对于纹理的倍数缩放的近似值四舍五入产生类似“阴影抖动”的影响）。阴影具体的扩展范围，以及相对于摄像机的偏移量都是可以手动配置的（参照配置纹理阴影）。在阴影远处的边缘上，Ogre根据另外一个可以配置的参数把阴影渐渐淡化，因此远处的阴影看上去是柔和的样子。

聚光灯光源

显然聚光灯光源相对于有向光源更加容易被表现出来，这是因为一个有向光源本身就是一个视截体形状。Ogre对从聚光灯光源的位置朝向聚光灯方向渲染整个阴影作为聚光产生的阴影纹理；纹理摄像机的“可视范围”是根据聚光灯光源的衰减角度（falloff angles）来得到。另外，为了隐藏阴影纹理是一个矩形的样子，即让聚光灯产生阴影的边缘不至于太过明显，Ogre使用了另外一个纹理单元来表现阴影到外侧的过渡淡出，最终的结果是我们可以看到一个圆形的阴影范围被投射在聚光灯光源前面。

点光源

我们在上面谈及过，为了完全支持点光源的投影特性，我们需要提供多次渲染（比如6次序渲染的立方体渲染或者精度稍微低一些的两次渲染贴图）来进行相应的处理。不过我们采用了把点光源近似的作为聚光灯光源处理的策略，把点光源作为聚光灯从所在位置照亮整个视截体。不过这样做只有在点光源在视截体外面的时候才能正确的工作，所以并不是一个真正完美的解决方案，并且而外的这样做还会带来一些纹理的“抖动”。基于这些原因，我们建议尽量不要用点光源来投射纹理阴影。

阴影投射物体和阴影接收物体

为了打开纹理阴影，需要使用阴影技术包括SHADOWTYPE_TEXTURE_MODULATIVE或者SHADOWTYPE_TEXTURE_ADDITIVE；你可以在章节7.3 调制阴影与7.4 叠加光照掩码中找到相应的详细介绍。对于最廉价和简单的纹理阴影技术来说是没有使用深度信息的，而是仅仅渲染投射阴影的物体到一个纹理上作为普通的颜色数据应用到阴影接收物体上——这就意味着这种方法无法实现自投影的效果。如果你使用了自动的阴影效果，这就是纹理阴影默认的行为，一种和固定功能（没有使用着色语言的）相兼容（进而可以使用到较低等级的显示卡上面）的纹理阴影技术。你也可以使用着色语言作为技术的实现基础来处理阴影投射体和接收体的材质来实现更复杂的阴影算法，比如实现支持自投影的深度阴影贴图。OGRE在演示程序中给我们带来一个这样的例子，虽然这个实现只能保证在Shader Model 2图形硬件（或者更高）上面很好的运行。虽然对于使用了OpenGL接口的固定功能管线而言深度阴影贴图是可以直接使用的，不过对于Direct3D标准而言却不市内建的支持，所以使用着色与语言来实现的投射/接收材质更加通用一些。如果你决定使用了这个途径，调用SceneManager::setShadowTextureSelfShadow并把传入参数设置为“true”，来允许对自投影纹理阴影的支持。

如果你没有使用深度纹理阴影贴图，Ogre会把阴影投射体和接收体分成两个不同的组。通过简单的关掉物体的投射开关，你就能自动地把物体设置为阴影接收物体（你也可以通过在材质脚本中把receive_shadows设置为“false”来实现）。同样的，如果一个物体被设置成阴影投射体，那就意味着它无法接收其他物体投射的阴影。

配置纹理阴影

这里有一些对纹理阴影的设置，可以帮助你实现你需要的效果。

阴影纹理的最大数量

阴影纹理占用了纹理显存。为了避免阻塞渲染管线的效率，Ogre并没有在同一帧中对多个光源重复使用阴影纹理进行渲染。这就意味着每个光源都必须拥有自己的独立的阴影纹理。在具体的使用中，如果你使用了过多的光源，你应该需要避免带来过多的纹理消耗。

你可以通过手动关闭灯光的投影来限制产生纹理阴影的光源的数量。另外你也通过调用SceneManager::setShadowTextureCount方法来设置最大阴影纹理数量来限制。Ogre会在每一帧测定那些光源会影响视截体，并分配向应限制的纹理数量。对于光源采用先到先投影的策略，任何超过限定数量的光源会在当前Frame中被忽略。

注意，你可以通过调用SceneManager::setShadowTextureSettings方法来同时设定阴影纹理的尺寸和数量；这是一个很重要的特性，因为每次这类调用潜在的会销毁然后创造所有的纹理资源。

阴影纹理的尺寸

用来放置投射阴影的纹理的尺寸是可以改变的；使用巨大的纹理可以明显的提高你所使用的纹理阴影的质量，但是同时也带来巨大的耗费。我们可以通过调用SceneManager::setShadowTextureSize方法来改变纹理的尺寸——不过这里的限制是必须设置成为边长为2的n次方的正方形。需要知道每个阴影纹理都会消耗边长*边长*3个bytes的尺寸。

重要：如果你使用了GL渲染系统的话，只能在硬件支持了Frame Buffer Object (FBO)或者Pixel Buffer Object (PBO)扩展特性的情况下才能使用大于主窗口尺寸的阴影纹理（在任何维度上）。虽然大部分现代的硬件都已经能支持这些属性，不过在使用的时候仍然要注意有些比较老的硬件环境仍可能有这些问题——这时候你可以通过ogreRoot->getRenderSystem()->getCapabilities()->hasCapability(RSC_HWRENDER_TO_TEXTURE)方法来检查硬件环境是否有这个能力。如果硬件返回了false结果并使用了超过了主平面大小的阴影纹理尺寸，会导致产生一个空白的纹理阴影结果。

阴影的最大距离

决定阴影结束的距离；同时也是决定有向光投射纹理阴影距离的延展——你可以通过减少这个值或者增加纹理的尺寸来增加有向光产生纹理阴影的质量，所付出的代价分别是减少阴影终止的距离与耗费更多的显存。

阴影纹理的偏移量（针对有向光光源）

在有向光章节中我们提及过，对于有向光光源阴影的渲染允许我们使用一个单一的渲染来覆盖一大片阴影区域。这个偏移参数影响从摄像机位置到阴影中心的距离。增加这个值，更多的阴影就会被放置到摄像机前面，进而对你会变得“可用”，但是如果这个偏移量过大，也带来更大的机会让你在某些角度看到阴影纹理的边缘。你可以通过调用SceneManager::setShadowDirLightTextureOffset方法来设置这个参数，在默认的情况下这个值被设置成0.6。

阴影淡出设置

阴影在远距离进行了淡出的处理来保证不会让阴影边缘过于生硬。你可以通过调用SceneManager::setShadowTextureFadeStart与SceneManager::setShadowTextureFadeEnd方法来配置开始和结束的点来修正淡出的效果，作为距离的参数都是一个相对的比例值。因为我们使用了正方形纹理，但是淡出的边缘是一个圆形，这就导致我们尽量不要用1.0作为阴影的结束位置，否则会带来一个非常难看的生硬边缘。在默认的情况下这两个值分别被设置成为0.7和0.9，which serve most purposes but you can change them if you like.

纹理阴影与顶点/片断编程

当把一个阴影投射物体渲染到一个调制阴影纹理上的时候，Ogre会关闭所有的纹理，除了环境光之外所有的光源都会参照阴影颜色（阴影颜色）对最终的结果产生影响。而对于加成阴影，改为把投射物体渲染到白色和黑色纹理代替。这些对于固定渲染流程的材质技术的投射阴影物体来说已经足够用了，然而对于一个顶点程序来说Ogre没有了足够的控制。如果你在第一个渲染通路中使用了顶点着色技术，你就必须告知Ogre在渲染阴影投射体的时候具体使用那个顶点程序；参照阴影和顶点程序。

定制摄像机

在我们之前提到过，对阴影纹理有很大限制的就是纹理本身的解析度是有限的，并且当阴影纹理像素大于屏幕的像素的时候，纹理的映射可能会导致产生混淆现象。为了解决这个问题，你可以通过制定另外一个继承于ShadowCameraSetup的类型作为新的映射基础。在默认的版本下我们使用DefaultShadowCameraSetup作为一个简单的视截体映射来处理点光源和聚光灯光源，对于有向光源采用正交式截锥体来处理。这里同时也提供了名为PlaneOptimalShadowCameraSetup的类型来专门映射到一个平面上，当你的阴影主要的投射到一个平面上的时候会给你带来更佳的效果。其他的设置类型（例如你可以创建一个透视图或者不等边四边形的阴影贴图版本）可以在运行的时候插入到系统中来，可以针对某一个特别的光源也可以对整个场景管理器。

集成纹理阴影(Integrated Texture Shadows)

相对于模板阴影来说，纹理阴影有一个主要的优势——这些数据可以被标准的着色器引用并处理。同时默认的阴影模型（SHADOWTYPE_TEXTURE_MODULATIVE以及SHADOWTYPE_TEXTURE_ADDITIVE）会自动的为你把阴影渲染出来，他的不利因素是会带来很多附加在我们材质上面的额外负担，更多的场景中渲染通路的使用。而外的，你不能对阴影的成分有很多的控制。

这里存在“集成”的纹理阴影设置。对于两种纹理阴影类型都存在另外一种被称为SHADOWTYPE_TEXTURE_MODULATIVE_INTEGRATED或者SHADOWTYPE_TEXTURE_ADDITIVE_INTEGRATED的版本，当采用了这两种类型之后，系统将不会直接为你渲染阴影，取而代之的是在渲染场景阴影接收物体的时候建立纹理阴影并期待你按照自己的需求去使用。如果你使用了这种类型设置，你需要在每一个材质上计算阴影接收的过程，而相应带来的好处是你拥有对对阴影纹理使用的全部控制。更深层的优点是你可以在这种环境下执行更复杂的着色过程，得到阴影计算，这时就有可能使用一些更深入的方法；并且因为你了解你具体需要多少数据量而不用全部得到，进而你能使用更少的渲染通路去处理这些信息。当你使用了这些阴影处理手段的一种，对于加成阴影和调制阴影的唯一却别就是阴影纹理投射的颜色（对于调制阴影是阴影颜色值，而对于加成阴影是简单的黑色）—— 在实际的计算过程中，所有处理接收阴影的问题都交给了你自己。没有调制渲染通路的分离过程，也没有把你的材质分成环境光/每个光源/贴花等部分——所有需要处理的事情都需要在你最初提供的原始材质中处理（如果你喜欢可以把调制分成每个通路或者每个光源进行迭代，但这并不是必需的）。

如果你希望在材质脚本中处理这些阴影纹理相关的事情，可以在{texture_unit}标记范围中通过'content_type shadow'标签来驱动。通过这项标签暗示这是一个阴影纹理基础，会在相同的通路中被使用多次，从light_start设置或者light-based通路进行迭代，灯光的索引值需要大于0。

上一章节： 7.1 模版阴影
下一章节：7.3 调制阴影


文档:手册:1-4-0:7.3 调制阴影 - OGRE 3D 中文

文档:手册:1-4-0:7.3 调制阴影

调制阴影的工作方式是暗化已经渲染完场景的颜色。首先，场景会正常的渲染所有接受阴影的物体；然后对每一个光源执行调制过程，把场景变暗；最后渲染那些不接收阴影的物体。

这里有两种不同的调制阴影技术；以模板为基础的（参照7.1 模版阴影:SHADOWTYPE_STENCIL_MODULATIVE）以及以纹理为基础的（参照7.2 基于纹理的阴影:SHADOWTYPE_TEXTURE_MODULATIVE）。调制阴影并不是正确的光学模型，所以阴影的黑暗区域是相同的深度，进而不考虑光线进入阴影区域的数量。然而，向对于那些更加“真实”的阴影技术而言（比如加成光照遮罩），调制阴影具有吸引人的高效率，并且他可以很好的结合那些采用“预烘焙（pre-baked）”技术的静态光（诸如预先计算好的光线贴图），而加成光线产生的阴影却不能。而使用调制阴影需要注意的问题是：当光源过多的时候，会产生过分黑的阴影（阴影不断的重叠，并不符合真正的物理特性），另外使用模板阴影的时候会因为每个影子边缘过分清晰而导致阴影不真实(参照Silhouette Edge)。

阴影颜色

我们可以通过调用SceneManager::setShadowColour方法来设置阴影变暗场景所使用的颜色；在默认的情况下系统使用了深灰色（进而可以让被覆盖德区域仍然保留一部分颜色）。

注意如果你使用了纹理阴影，你需要额外的设置集成纹理阴影(Integrated Texture Shadows)，否则就要使用分离的渲染通路来渲染场景中的阴影。基于这个原因“调制”之后阴影技术的外观只是简单的对颜色产生了影响。


文档:手册:1-4-0:7.4 加成光照遮罩 - OGRE 3D 中文

文档:手册:1-4-0:7.4 加成光照遮罩

使用加成光照叠加的方法渲染阴影，本质上就是依照产生阴影的灯光的数量，对场景进行多次渲染，每次渲染的时候把此光源阴影的地方留黑，然后最终把这些渲染结果依次叠加，这样所有的光照各自的影响再最终的场景中表现出来，阴影就自然的产生。这种方法的好处是更接近真实的光学原理，继而能得到更逼真地渲染果。同时所带来的却带也更加明显：更多的渲染通路。

你可能在一些技术文档（或者游戏开发杂志）上面看到过，渲染这种接近现实的光照需要处理很多的渲染通路。做为一个易用的图形引擎，Ogre已经把你从这些繁琐的细节中拯救出来。你可以使用我们平时用的材质来处理这些细节，为了实现加成（Additive）的计算（不论是否使用可编程管线）。Ogre都会把你的渲染通路产分成三种不同的类型：

  1. 环境光照通路：即使场景中没有任何可以投影的物体，Ogre也会使用唯一的环境光通路来设置深度缓存并把环境光和辐射光应用到这个场景中，在这个渲染通路只有被环境光影响的纹理才会被渲染。
  2. 慢反射光和镜面反射光通路：这个通路为每个光源进行一次渲染，而这个光源所无法照射的地方（阴影）不会被渲染，这个通路中没有被阴影影响的部分和其他通路中的渲染结果混合（scene_blend add）。重申一下，除了那些影响光照的纹理（比如法线贴图）之外，这里的通路不会渲染任何纹理。
  3. 贴花通路：这个通路负责巴最终的纹理作为“贴花”渲染到场景中来，并通过之前渲染的环境光以及漫反射和镜面反射光通路来调整最终渲染结果。

在实际的应用中，很少有真正的只需要上述其中一类通路的时候。对于每一个Technique，Ogre会帮助我们把已经定义好的材质通路编译成不同的通路以适应不同的需要。例如，我们提供了一个非常简单的材质脚本：

material TestIllumination
{
    technique
    {
        pass
        {
            ambient 0.5 0.2 0.2
            diffuse 1 0 0
            specular 1 0.8 0.8 15
            texture_unit
            {
                texture grass.png
            }
        }
    }
}

Ogre会把它拆分成三个不同的光照通路，等价于下面的脚本：

material TestIlluminationSplitIllumination
{
    technique
    {
        // Ambient pass
        pass
        {
            ambient 0.5 0.2 0.2
            diffuse 0 0 0
            specular 0 0 0
        }

        // Diffuse / specular pass
        pass
        {
            scene_blend add
            iteration once_per_light
            diffuse 1 0 0
            specular 1 0.8 0.8 15
        }

        // Decal pass
        pass
        {
            scene_blend modulate
            lighting off
            texture_unit
            {
                texture grass.png
            }
        }
    }
}

就像你上面所看到的，尽管是一个及其简单的材质，采用了阴影技术之后也需要拆分成至少三个渲染通路，对于一个普通的场景最终需要的数量是（光源的数量+2）个渲染通路。虽然你仍然可以使用最初定义的材质，Ogre会帮助你处理其他的细节。但是你需要清楚的是，每当你是用一个通路的时候都会根据不同的灯光类型（环境光vs漫反射光/镜面反射光）被拆分成几倍的渲染通路和纹理单元。主要的好处是即使你没有通过标签来在材质中分别定义不同类型的通路你也可以得到所有的光照行为的全部多通路，继而意味着你可以保留以前的材质定义到我们处理更现实的光照技术中使用。

通路分类和顶点程序

Ogre在不改变你的材质定义的情况下可以很好的分类和拆分你的渲染通路用于处理加成光照工作所使用。然而，有一种另外的情况，那就是如果你使用了顶点编程的情况下。当你的渲染过程使用了顶点着色语言，所谓的环境光、漫反射光以及镜面反射光都失去了意义，因为如何使用他们是你在顶点程序中决定的，这时候Ogre无法了解他们到底在顶点程序中被你用作了哪些工作，这时候需要你来告知。

在实际使用的中这是一个非常简单的过程。虽然你可能使用了一个非常复杂并拥有很多自定制过程的顶点着色彻骨，但这些通路仍然可以被简单的划分为上面列出三种不同类型的纹理。你所要做的只是简单的告知Ogre你讲要把它们作为环境光，漫反射光，镜面反射光或者自辐射光，这和我们没有使用顶点程序时候一样。当然，对于你将要使用的顶点程序而言，这些使一些无关紧要的设置，但是它可以给Ogre指出当前的通路是被顶点用于那部分光照处理。Ogre会根据这个信息对通路进行分类工作——这个工作是在顶点程序之外进行的（换句话说，当你更改顶点着色程序的时候，这里也需要跟着修改）。

这里需要注意的是，在处理漫反射光/镜面反射光的通路的时候，Ogre会检查你是否设置了通路对每一个光源运行一次（iteration once_per_light）。如果是这样的话，这个通路不会做任何改变，包括其中的顶点着色程序以及片断着色程序。否则当你没有在这个通路中设置这个属性，Ogre会场时把每个光源的部分分离出去，同时这样做会关掉片断着色程序，因此当没有设置“iteration once_per_light”属性的时候，也就意味着片断程序只是简单的执行贴花工作（decal work），而不用为每个光源单独运行。

明确的，当你使用了加成光照遮罩技术作为处理阴影技术的时候，你需要确保对支持可编程的渲染通路进行了家当的设置，以便于给系统做出正确的分类。同时，也要注意到，当你决定不使用加成光照技术的时候，当前材质也能够很好的正确的被处理，这里需要遵守的法则是你需要确保相同的材质能在所有的光照模型中正确的使用，下面我们提供一个被正确处理光照通路分类的可编程材质。

// Per-pixel normal mapping Any number of lights, diffuse and specular
material Examples/BumpMapping/MultiLightSpecular
{

    technique
    {
        // Base ambient pass
        pass
        {
            // ambient only, not needed for rendering, but as information
            // to lighting pass categorisation routine
            ambient 1 1 1
            diffuse 0 0 0
            specular 0 0 0 0
            // Really basic vertex program
            vertex_program_ref Ogre/BasicVertexPrograms/AmbientOneTexture
            {
                param_named_auto worldViewProj worldviewproj_matrix
                param_named_auto ambient ambient_light_colour
            }

        }
        // Now do the lighting pass
        // NB we don't do decal texture here because this is repeated per light
        pass
        {
            // set ambient off, not needed for rendering, but as information
            // to lighting pass categorisation routine
            ambient 0 0 0
            // do this for each light
            iteration once_per_light

            scene_blend add

            // Vertex program reference
            vertex_program_ref Examples/BumpMapVPSpecular
            {
                param_named_auto lightPosition light_position_object_space 0
                param_named_auto eyePosition camera_position_object_space
                param_named_auto worldViewProj worldviewproj_matrix
            }

            // Fragment program
            fragment_program_ref Examples/BumpMapFPSpecular
            {
                param_named_auto lightDiffuse light_diffuse_colour 0
                param_named_auto lightSpecular light_specular_colour 0
            }

            // Base bump map
            texture_unit
            {
                texture NMBumpsOut.png
                colour_op replace
            }
            // Normalisation cube map
            texture_unit
            {
                cubic_texture nm.png combinedUVW
                tex_coord_set 1
                tex_address_mode clamp
            }
            // Normalisation cube map #2
            texture_unit
            {
                cubic_texture nm.png combinedUVW
                tex_coord_set 1
                tex_address_mode clamp
            }
        }

        // Decal pass
        pass
        {
            lighting off
            // Really basic vertex program
            vertex_program_ref Ogre/BasicVertexPrograms/AmbientOneTexture
            {
                param_named_auto worldViewProj worldviewproj_matrix
                param_named ambient float4 1 1 1 1
            }
            scene_blend dest_colour zero
            texture_unit
            {
                texture RustedMetal.jpg
            }

        }
    }
}

注意，如果你使用了纹理阴影的话还可以通过集成纹理阴影(Integrated Texture Shadows)进行一些相应的设置。这样就允许你通定义一个投射阴影光源的数量上限来过减少你的渲染通路。基于这个原因，“加成”技术只会影响阴影纹理的颜色，并且不论你是否喜欢，他都会把这个阴影纹理混合到你的阴影接收者上面。

静态光照

先不论它有多强，加成阴影技术有一个附件的限制；它们没有与在场景中预计算的静态光做很好地混合。这是因为它们基于这样的原理：阴影是不染光的，而且由于在场景中的静态光已经涵有光和阴影的区域了，加成阴影不能以去除亮度来创建新的阴影。因此，若你使用了加成阴影技术，你要么使用这种技术来专门作为你的光照方案（并且你可以拿它与逐像素光照混合，以此创建很是令人印象深刻的动态光照方案），要么使用集成化材质阴影(Integerated Texture Shadows)来与你选择的最为贴切之静态光混合。


文档:手册:1-4-0:8. 动画 - OGRE 3D 中文

文档:手册:1-4-0:8. 动画

Ogre提供了相当灵活的脚本系统，通过它可以做各种各样的应用。

  • 8.1 骨骼动画

运用骨骼结构来定义网格数据。

  • 8.3 顶点动画

保存顶点的快照来决定网格数据如何改变。

  • 8.4 场景节点动画

根据预先定义的路径来操作场景节点上挂接的实体的运动产生动画效果。

  • 8.5 数值动画

Ogre提供扩展的类来根据任何值产生动画效果。


文档:手册:1-4-0:8.1 骨骼动画 - OGRE 3D 中文

文档:手册:1-4-0:8.1 骨骼动画

骨骼动画是根据网格数据中的骨骼信息来产生动画效果，一般是根据顶点上绑定的骨骼信息轮询确定模式的顶点。另一个叫法是骨骼蒙皮。骨骼动画一般是通过3d建模工具完成的。OGRE提供导出工具，来将建模工具制作的骨骼动画导出为引擎可以应用的格式。参见 4.1 Exporters。

骨骼动画的等级和种类比较多，并不是所有的引擎和模型制作工具都可以支持。OGRE支持下列特征的骨骼动画：

  • 1 每个网格可以定义一个独立骨骼动画。
  • 2 每个骨骼动画可以支持无限的骨骼。
  • 3 作用于骨骼上的反向动力。
  • 4 每个骨骼集可以定义多个名称的动画。
  • 5 每个骨骼动画可以有多个关键帧。
  • 6 关键帧之间的线性或者是样条插值。
  • 7 一个顶点可以关联多个骨骼，并且可以被赋予权重，用来做融合。
  • 8 通过权值融合，多个动画可以在同一时刻被作用于一个网格数据。

骨骼和动画信息被保存在以.skeleton结尾的文件中，可以通过OGRE的exporters导出。当创建一个基于某个mesh的实体的时间，如果mesh上有动画信息，那么相应的.skeleton文件会被自动加载。之后就可以根据8.2节介绍的动画状态来操作实体了。骨骼动画可以用软件实现，也可以用shaders（硬件蒙皮）实现。总体来说，第二种方式比较好，因为这将以部分cpu的工作交给了gpu，并且顶点数据不需要每帧都去更新。对大型的，细节非常多的模型非常有用。通过指定带有顶点program的材质脚本可以实现硬件蒙皮。更多的信息可以参考顶点program实现硬件蒙皮。骨骼动画可以和顶点动画相结合。参考8.3.3


文档:手册:1-4-0:8.2 动画状态 - OGRE 3D 中文

文档:手册:1-4-0:8.2 动画状态

当创建一个带有动画的实体的时间，需要创建对每个动画创建一个叫动画状态的对象来控制实体动画的状态。

通过相同的动画状态可操作多个动画实体。通过Entity::getAnimationState可以获得一个指向AnimationState的指针。

随后就可以在frameStarted事件中，通过该指针的方法来更新动画。在操作动画状态之前，必须使用setEnabled方法使其生效，可以通过适当的方法来设置动画的权重和位置信息。动画状态有一个addTime方法，可以持续的设置动画的位置信息，并且可以自动循环。 addTime的参数可以是正数，也可以是负数（用来反转动画）。


文档:手册:1-4-0:8.3 顶点动画 - OGRE 3D 中文

文档:手册:1-4-0:8.3 顶点动画

顶点动画直接利用顶点的运动信息来产生动画。每个轨迹对应于一个VertexData的实例。顶点动画的数据存储于.mesh文件中。实际上，有两种顶点动画。

  • 8.3.1 变形动画
变形动画和骨骼动画相比，在技术上比较简单。它根据动画的关键帧时间线插入相应的网格数据。
  • 8.3.2 姿态动画
姿态动画根据不同的权重和对顶点数据的偏移融合不同的姿态，来产生最后的结果。在面部动画中，姿态动画应用比较广泛。

其中，变形动画和姿态动画可以采用相同的方法实现。但是在OGRE中，对两种动画做了区别对待。如果你对这些不关心的话，那么你可以跳过下面的内容。

变形动画利用一系列的顶点数据快照来产生动画。由于是基于快照并且在帧间只是做简单的线性插值，所以速度非常快。其缺点是不支持多动画的融合。如果你需要动画融合的话，可以根据不同情况采用骨骼动画或者是姿态动画。对于一个完整网格数据的动画，可以采用骨骼动画。对于多个网格数据，可以采用姿态动画。例如，面部表情动画就可以采用姿态动画。在顶点shader中，变形动画只需要两个顶点buffer，一个是最原始的位置buffer，另一个是插值因子。变形动画中，每个轨迹对应于一个独立的顶点数据。

姿态动画稍微有点复杂。和变形动画一样，姿态动画每个轨迹也代表一个独立的顶点数据，不同的是，每帧对应于一个或者多个姿态，每个姿态都有其影响等级。一个姿态是对基本顶点数据的一个偏移，并不一定是对所有的顶点数据都进行偏移。姿态动画可以做动画融合，不论是在一个动画轨迹中，或者是在不同的动画间。这些特征都非常适用于面部表情动画。

例如，你定义了一个基于顶点数据的面部模型和一系列姿态信息，每个姿态信息表示面部的语音位置。接下来你可以基于这个顶点数据定义一个叫做 SayHello的面部动画。这个动画包含一系列关键帧。每个关键帧代表了不同的面部位置信息。所以，对于不同的面部动画，每种姿态只有一个实例，但是在不同的动画中可以根据需要来引用不同的姿态。这样就可以很容易的建立一个语音动画系统。

姿态动画的缺点是不容易建立，以面部动画为例，对于每个面部位置信息需要建立单独的姿态用来在关键帧中引用。同时姿态动画，对于空间要求比较高。一般需要存储基本数据和每个姿态对应的数据来做融合。所以你如果用GPU来做动画实现的话，你必须时刻注意同一时刻有多少姿态进行融合。通过在脚本中加入includes_pose_animation ，可以定义vertex program中支持的最大数目，请参考Pose Animation in Vertex Programs。综上所述，将顶点动画分为两类，对我们非常有利。变形动画不能和姿态动画或者是其它的变形动画进行融合，但是可以和骨骼动画融合。姿态动画可以和其它姿态动画以及骨骼动画融合。同时所有的变形动画可以转换成姿态动画，但是反过来不成立。

每个轨迹应用一个子类型子类型是在轨迹这个层次，而不是在动画和网格这一层次。如果一个网格被分为子网格，那么每个子网格可以有自己的姿态动画或者是变形动画。比如，对于一个复杂的角色模型，可能既需要骨骼动画又需要面部表情动画，那么可以将头部网格拆分。每个子网格有自己的几何数据，这就可以将骨骼动画应用于子网格，而姿态动画只应用于头部网格。如果应用软件方式实现顶点动画，那么必须手动实现对顶点数据的分配等。应用OGRE的导出工具，可以自动组织。在Ogre::Mesh的接口中，有Ogre::VertexData::reorganiseBuffers() 和Ogre::VertexDeclaration::getAutoOrganisedDeclaration()两种方法，具体请参考API手册。


文档:手册:1-4-0:8.3.1 变形(Morph)动画 - OGRE 3D 中文

文档:手册:1-4-0:8.3.1 变形(Morph)动画

变形动画在每帧中存储顶点位置信息的快照，然后在帧间插值。当骨骼动画不能应用的情况下，采用变形动画。一般来说，当实体的结构和形状发生完全变化的时间，采用变形动画。

因为采用绝对信息，所以基于同一顶点数据的多个变形动画不能融合。当对同一顶点数据，有多个变形动画的时间，只有最后一个变形动画才起作用。由此可以看出，权重对变形动画没有任何意义。

变形动画可以通过硬件实现，请参考Morph Animation in Vertex Programs。


文档:手册:1-4-0:8.3.2 姿态(Pose)动画 - OGRE 3D 中文

文档:手册:1-4-0:8.3.2 姿态(Pose)动画

8.3.2 姿态动画

姿态动画允许你绑定多个潜在的在不同的影响层上顶点姿态到final vertex state。它一般用于面部动画，在每个面部动画被置于一个分离动画的地方，影响(层)要么与从一个表达式到另一个的绑定，要么做完全的表达式混合，如果每个姿态仅作用于脸的的部分。

为了能这么做，姿态动画使用一个参考姿态集，这个姿态集被定义在网格上，被表达为到原顶点数据的偏移。这不要求每个顶点拥有一个偏移 -- 那些顶点不被单独保留。当以软件方式绑定时，这些顶点被完全忽略 -- 当以硬件方式绑定（要有一个顶点入口给每个顶点）时，每个顶点零偏移，这些顶点是在自动化创建时没有被注意到地。

你只要定义一次姿态，就可以在动画中查到它们。每个姿态动画轨迹查找一单个几何体集合(是网格的共享几何体，或是子网格上的专有几何体)，而且在此轨迹中的每个关键帧可以查到一个或更多的姿态，每个姿态有它自己拥有的影响层。被应用到整个动画的权也缩放着这些影响成。你能定义许多关键帧，它们使姿态的绑定随时间而转变。关键帧被表示在邻居关键帧时，它在一个关键帧中的姿态的缺少，使得为了能插值被作为0影响。

你应该小心一次有多少个姿态被使用。当你在硬件上用姿态动画（见Pose Animation in Vertex Programs），每个活动姿态要求另一个被加到着色器上的顶点缓冲。而当姿态动画在软件上时，就可以占用更多的时间，使用更多的活动姿态。记住，如果在一个关键帧里你有2个姿态时，同时在接下来的关键帧里姿态数量不为2，那就意味着在这两个帧间插值时，有4个活动关键帧。

你可以把姿态动画与骨骼动画混合，见8.3.3 Combining Skeletal and Vertex Animation，并且你也能硬件加速用顶点着色器做绑定的应用程序，见Pose Animation in Vertex Programs。


文档:手册:1-4-0:8.3.3 骨骼动画与顶点动画的混合 - OGRE 3D 中文

文档:手册:1-4-0:8.3.3 骨骼动画与顶点动画的混合

在相同的实体在同一时刻，骨骼动画和顶点动画（也可以是其它子类型）可以同时使用（参考8.2 动画状态）。那些在顶点上的效果被首先应用到基网格模型上，而骨骼动画被应用到这个结果上。举例来说：这就允许你在一个角色的面部动画用在塑造顶点动画，同时进行主要的移动动画用在骨骼动画上。

组合这两种动画，从用户的角度来看是一种极其简单的工作。概括来讲，当时用这个特性的时候，只需要关注下面这两方面：

混合硬件皮肤

对于复杂的角色，通过硬件上面的定点着色程序来实现硬件蒙皮是一个非常好的想法，具体相关的细节，可以参考: 顶点程序中的骨骼动画，顶点程序中的变形动画，顶点程序中的姿势动画。

当混合各种类型的动画时，你的顶点程序必须都支持这两种需要被混合到网格上的动画的类型，否则硬件皮肤会被禁止掉。你应该实现与在OGRE里做的那种相同方式的动画，例如：先做顶点动画，然后应用骨骼动画到其结果上。记住，变形动画的实现传递2个绝对的开始（from）和结束（to）关键帧的即时缓冲，连同一单个参数，用于做线性插入，同时造型动画传递基本顶点数据来加上‘n’这个造型偏移缓冲值，和参数换的‘n’权值。

[编辑]

子网格模型的分离

若你只需做混合顶点动画和骨骼动画到你的网格模型的一小部分上，例如：脸，为了减少计算负载，你可以分离你的网格成两部分，一个要被混合，而另一个不这么做。记住这也会减少顶点缓冲的使用，因为顶点关键帧/造型缓冲也会更小。例如，你使用硬件皮肤，你应该实现两个分离的顶点程序，一个做骨骼动画，一个做骨骼动画和顶点动画。


文档:手册:1-4-0:8.4 场景节点动画 - OGRE 3D 中文

文档:手册:1-4-0:8.4 场景节点动画

为了做场景结点运动的动画，场景结点动画从场景管理器中创建，它使得与与之关联的对象自动的随着一起移动。你能在演示Demo_CameraTrack中看到照相机的轨迹行为，也可以在Demo_Fresnel的池塘中看鱼如何移动的。

在主要的部分，场景结点动画与在骨骼动画中的基本骨骼的代码非常相似，在使用SceneManager::createAnimation创建主动画后，你能为你要动画化的每个SceneNode创建对应的一个NodeAnimationTrack，并创建关键帧来控制位置、方向和线性插值或是曲线的缩放。你也可以与骨骼/顶点动画相同的方式，使用8.2 动画状态。否则你需要包含来自与SceneManager的状态，来取代来自独立实体的状态。动画被自动应用到每一帧上，或是使用高级的在SceneManager上的_applySceneAnimations()方法来被应用。设置场景动画之接口的完整细节见API参考。


文档:手册:1-4-0:8.5 数值动画 - OGRE 3D 中文

文档:手册:1-4-0:8.5 数值动画

从制定的动画类型分离，你也能使用动画到AnimableObject接口上被暴露的任何值的后面。

可动画的对象（AnimableObject）

AnimableObject是一个抽象接口，任何类可以扩展它，为了提供到大量AnimableValues的访问。AnimableObject抓着一份可动画的属性“词典”，这些属性可以被getAnimableValueNames方法枚举，并且当它的createAnimableValue方法被调用时，返回一个到值对象的引用，这个值对象形成通用动画接口和下面指定的对象属性间的桥。

一个例子就是Light类。他扩展了AnimableObject，并且提供AnimabelValues给像"diffuseColor"and"attenuation"样的属性。动画轨迹可以为这些值而被创建，并且这个光上面的属性可以在脚本里被改变。还有其它对象，包括你自定义的对象在内，它们可以以相同的方式扩充这个接口，以此提供动画支持给它们的属性。

可动画的值（AnimableValue ）

当实现自定义的可动画化的属性时，你必须也实现大量的在AnimableValue上的方法 -- 它们主要是被标记为未实现的。不存在简单的纯虚方法，因为你只要实现这个供你正在动画的值的类型的方法。此外，参见在Light演示里的示例是如何做到这些的。


翻译人员

1. 介绍--zotin
2. 核心对象 ninjacatii
3. 脚本--杨延平
4. Mesh 工具集--Eraser 78
5. 硬件缓存--免费打工仔
6. 外部纹理源--免费打工仔
7.1 模版阴影--免费打工仔
8. 动画到 8.3.1 变形(Morph)动画 --Swisel
8.3.2 姿态(Pose)动画 到 8.5 数值动画 CornerZhang

在这里感谢以上翻译人员，拿出休息的时间来翻译。
此致敬礼


如果您的浏览器没有自动跳转,请点击这里