Ogre中资源有以下几种:Texture、Compositor、Font、GpuProgram、Material、Mesh、Skeleton、BspLevel
本文聚焦于材质资源Material。DirectX、Opengl中的材质含义为物体的光学属性,如高光和漫反射光的颜色等。但在Ogre中,材质类所包含的概念更大,涵盖了纹理等设置的信息。从某种意思上来说,Ogre中的Material更接近于Shader 的概念。
Ogre中的材质资源相关头文件如下:
OgreMaterial.h
OgreMaterialManager.h
OgrePass.h
OgreTechnique.h
Material、Technique和Pass的UML关系图如下
从图中可以看出,Ogre中的材质是按三个层次来管理的。
最底层的是Pass(通路),Pass是Ogre最基本的绘制单元。
管理Pass的是Technique(技术),Technique是一组用来绘制一个特定材质的方法。
管理Technique的就是Material了,Material封装了对于一个物体而言的所有可视效果。
下面就逐一来解读下Ogre的材质结构。
(1)Pass
在Ogre中,Pass是最基本的绘制单元,同时也是Renderable(可绘制对象)用来标识自己绘制状态的基本单元。
Pass中与自身在材质结构中相关的成员变量有
Technique* mParent; unsigned short mIndex; // pass index String mName; // optional name for the pass uint32 mHash; // pass hash bool mHashDirtyQueued; // needs to be dirtied when next loaded
mParent是指向父类Technique的指针。
index用来表示,在父类的pass集合中,自身的序列号。
生成的hash是用来对pass分组排序的。需要提高绘制效率,我们就需要安排尽可能高效的绘制批次(batching)。为了减少绘制批次,我们具有相同绘制状态的绘制请求一起进行。对pass的合理组合,是有效地提高绘制效率的手段。
Pass的成员变量非常多,绝大部分都是绘制状态的设置。
大致有以下几类:
(2)Technique
Technique是对Pass的集中管理,在Technique中,引入了硬件的考量。也就是说,Pass的设置能否在当前硬件上运行,Technique会给出考量后的结果。比如:在一个Pass中,所请求的纹理单元过多了,那么Technique就会自动地进行Pass的分割,使得Pass能够符合硬件的运行要求。
Technique的主要数据结构有
typedef vector<Pass*>::type Passes; /// List of primary passes Passes mPasses;
这是所管理的Pass集合。
/// LOD level unsigned short mLodIndex; /// Scheme unsigned short mSchemeIndex;
Lod和Scheme是上层Material用来区分不同Technique的度量方式。
还有两个比较重要的数据结构体GPUVendorRule和GPUDeviceNameRule。
顾名思义,从硬件获取的信息,通过这两个struct保存,并在编译Pass的过程中使用。
(3)Material
Material是管理的Technique的类,主要通过设定Scheme(方案)来进行度量。这里Scheme更符合我们平时对于绘制质量的理解,比如:高质量,中等质量,低质量等。划分好Scheme后,我们就可以把相应的Technique归入其中的一类,在切换Scheme的时候,就可以使用相应的Technique来进行绘制了。
还有一个度量就是Lod(细节等级)。有了相应的Scheme之后,在Technique执行时还需要考虑Lod的影响,根据视点与物体的距离来选择相应的Technique,是Ogre提供的材质绘制策略。
上述这两个度量的数据结构如下:
typedef map<unsigned short, Technique*>::type LodTechniques; typedef map<unsigned short, LodTechniques*>::type BestTechniquesBySchemeList;
LodTechniques是将距离与相应的Technique进行绑定。
BestTechniquesBySchemeList则是将Scheme与相应的LodTechniques绑定。
Material中管理Technique的数据结构如下:
typedef vector<Technique*>::type Techniques; /// All techniques, supported and unsupported Techniques mTechniques; /// Supported techniques of any sort Techniques mSupportedTechniques;
可以看到,Material保存两份Technique的集合,mTechniques是当资源导入以后就保存的一份集合。而mSupportedTechniques则在每次编译之前清空,根据当前硬件的环境要求,来选择硬件支持的Technique。
还值得一提的是,在Pass、Technique和Material中,大部分的成员函数就是用来设置Pass中的绘制状态。设置的过程往往是从上至下传递的,也就是从Material->Technique->Pass的流程进行设置。当底层有需要进行重新编译的请求,都会发送给Material,然后再从Material至下,一步一步地编译所有材质资源。
(4)MaterialManager
继承自ResourceManager,对Material进行管理。主要实现了对纹理过滤的设置、Scheme的管理,设置相应的监听等操作。还负责读取材质脚本、初始化材质资源。