转:Ogre的MaterialSystem分析
1. Mesh 、SubMesh、SubEntity和Entity
所有的Mesh对象是由SubMesh构成的,每个SubMesh代表了Mesh对象的一部分,该部分只能使用一种Meterial。如果一个Mesh只采用一种Material,那么它可能只包含一个SubMesh。
当基于Mesh创建出一个Entity时,该Entity由多个SubEntity构建而成, SubEntity与Mesh中的SubMesh一一对应。可以通过调用Entity::getSubEntity方法获得SubEntity。一旦得到SubEntity的指针,通过调用setMaterialName方法改变其Material。通过这种方法,可以改变所创建的Entity的默认Materials,从而使创建出来的Entity与众不同。
class SubMesh
{
RenderOperation::OperationType operationType;
VertexData *vertexData;
IndexData *indexData;
String mMaterialName;
};
通过代码可以看到SubMesh是保存顶点和顶点索引的类。
class Mesh: public Resource
{
typedef std::vector<SubMesh*> SubMeshList;
SubMeshList mSubMeshList;
}
通过代码可以看到Mesh是收集SubMesh的类。
class SubEntity: public Renderable
{
String mMaterialName;
MaterialPtr mpMaterial;
SubMesh* mSubMesh;
}
通过代码可以看到SubEntity与SubMesh和Material是一一对应的。
class Entity: public MovableObject, public Resource::Listener
{
MeshPtr mMesh;
typedef std::vector<SubEntity*> SubEntityList;
SubEntityList mSubEntityList;
}
通过代码可以看到Entity是收集SubEntity和Mesh的类。
Entity的可渲染属性:Entity是由SubEntity组成的,SubEntity是从Renderable继承而来,所以Entity是可渲染的。
Entity的可移动属性:Entity是从MovableObject继承而来,所以Entity是可移动的。
概括的来说,Entity和SubEntity是物体渲染特性的入口,而Mesh与SubMesh是物体结构特性(几何体数据)的入口。
2. Technique、Scheme 、Pass和Texture Unit
Technique和Scheme
可以说技术和方案是Ogre引擎材质中最强大和活跃的两个特性。
在Ogre中,每个材质中都至少包含了一种“技术”实现,这种实现允许你对不同性能显示卡和硬件平台使用不同的材质属性组合。简而言之,技术就是“一种对物体的渲染方法”。通常来说对具体适用哪个渲染技术是由Ogre引擎自动甄选出来的(根据硬件性能、方案以及细节等级等信息),但是如果你希望的话也可以在代码中完全控制这个过程。
“方案”是Ogre使用的高级话题之一,事实上它是一个渲染技术集合的描述。举例来说,你可能有三个不同的技术方案:高质量,中等质量,低质量。在游戏运行的时候,允许用户通过选择这三个方案中的任意一个来确定在游戏中具体使用的渲染技术集合。
Ogre在渲染的时候,会有一个自动甄选所需渲染技术的固定流程:首先过滤掉那些不在当前方案中的所有技术(默认情况下当前方案是“Default”);然后选择适配当前细节等级(LoD)的那些;最后在剩下的当中挑选当前硬件环境中可以执行的最优技术(最好效果的)。当Ogre找不到任何一个可以使用的渲染技术时,就会把物体渲染成单调的白色表面。换句话说,如果你看到了一片雪白,就要检讨一下你对材质的配置了。另外在默认的情况下,材质中所有技术的细节等级(LoD)都被设置成为0,也就是最高的细节等级。换句话说,Ogre总是在尽可能的帮助你选择最优材质技术。
似乎技术和方案会带来很多复杂的处理细节。但在实际的执行过程中,你只要在材质脚本中提供了充足的内容,Ogre就会接替你来管理这些琐碎的细节。当然如果你喜欢,也可以用代码完成脚本所进行的工作。
Pass
在Ogre中通路是最基本的渲染单位,同时也是可渲染对象(Renderable)用来标示自己渲染状态的基本单元。每个可渲染对象都会有自己的材质,Ogre在材质中甄选出最适合当前应用的技术实现。然后把当前技术中所有的“通路”依次放入图形硬件的渲染通路中。顾名思义,Ogre材质中的“通路”对应于图形硬件中“渲染通路”的概念。也就是说当前技术中如果包含了3个通路,那么在绘制是用这个材质的模型的时候,在每一帧就要进行3次渲染。
在实际的使用中,通路里面还有“纹理单元(texture unit)”的定义,你可以在一个通路中定义任意数量的纹理单元,当然一个不用也是没问题的。
Texture Unit
在Ogre对材质的定义中,纹理单元的概念对应于图形硬件中的纹理采样(texture sampler)。为了运行Ogre程序,至少需要一个硬件纹理采样支持。不过这并不是什么大问题,因为现代的图形硬件基本上都会有多个纹理采样,因此我们可以在一次渲染通路的执行中,同时处理多个纹理单元。
顾名思义,纹理单元里都会包含一张纹理。你可以直接用硬盘中的图片文件,也可以通过实时的渲染来得到,甚至可以通过一个视频流来动态生成纹理图案。在Ogre中并没有对通路中纹理单元的数量进行限制,这是因为Ogre能根据图形硬件能力动态拆分通路(这里假设没有使用硬件着色程序)。具体点说,如果你的图形硬件只能同时处理4个纹理采样,但是应用程序却使用了一个6纹理单元的通路。这时候Ogre会自动的把这个6纹理通路拆分成两个分别两次进行渲染,不过虽然最后的渲染结果和预期的一样,但是仍然是通过两次渲染通路来实现的,对效率的影响不言自明。
材质的组成
在下图中,展示了Ogre的材质之中各种组成成分之间的关系。一份完整的材质至少有一种技术实现,每种技术实现中至少要有一个渲染通路。从图示中看到材质中包含了N种的技术实现,而在真正的渲染时,只会有一种技术被激活并进入渲染过程(选择激活技术的工作一般交给Ogre自动完成)。
图6-2:在Ogre中,材质,技术以及通路之间的关系