(版本:TGEA1.0.3)
1. 基本概念
参见<TGEA中材质的使用>
2. 核心类
2.1. MaterialPropertyMap
MaterialPropertyMap是一个单件,存储了所有Material与纹理的映射信息。具体参Material与MaterialPropertyMap类说明。以下详细分析下MaterialPropertyMap:
图3-2 MaterialPropertyMap UML图
数据成员:
l Vector<MapEntry> mMapEntries;
这个向量中的每个元素都维护了一个材质对象的映射信息。
MapEntry的功能参MapEntry类的说明。
l StringTableEntry name
为模型文件中存储的纹理信息,材质即是要和这个纹理对应。称之为纹理名(texture tag)。
l materialName
存储的为脚本中的Material对象名。
成员函数:
l bool addMapping(S32,char**)
创建一个新的MapEntry,并赋值。
2.2. MapEntry
MapEntry的UML如下:
图3-3 MapEntry UML图
l StringTableEntry name
为模型文件中存储的纹理信息,材质即是要和这个纹理对应。称之为texture tag。
l materialName
存储的为脚本中的Material对象名。
2.3. MaterialList
MaterialList维护了一个模型上所带的所有材质,UML图如下:
图3-4 MaterialList UML图
数据成员:
l Vector<MatInstance *> mMatInstList
存储这个模型的所有的MatInstance, MatInstance才是真正的存储材质的对象。Material只是对它的一个包装。存储的为材质名。
l VectorPtr<char *> mMaterialNames
存储这个模型的所有texture tag,即纹理名。
这两个向量的元素是一一对应的,即存储了脚本中的材质对象与模型的纹理的映射信息。
成员函数:
l void mapMaterials()
进行材质与纹理的映射。
2.4. MatInstance
图3-5 MatInstance
成员函数:
l void processMaterial()
处理材质关于渲染的各种属性。重要语句如下:
mMaxStages = getNumStages();
for( U32 i=0; i<mMaxStages; i++ )
{
GFXShaderFeatureData fd;
determineFeatures( i, fd );
if( fd.codify() )
{
createPasses( fd, i );
}
}
关于stage,stage在TGEA中的概念类似于DirectX中的“pass”,即多道渲染。对同一个面片使用多个不同的shader进行渲染,最终将多次渲染的结果合成。
在材质脚本中已经指定了各道stage的渲染属性。在processMaterial中对针对每道stage生成相应的shader。
l void determineFeatures( U32 stageNum, GFXShaderFeatureData &fd )
根据stage的标号来决定这道stage的shaderFeature。以下详细解释:
例如有材质的对象定义:
new Material(SphereGlow)
{
mapTo = sphere_metal;
baseTex[0] = "~/data/shapes/test/blobtex1";
emissive[0] = true;
glow[0] = true;
};
可以看到,下标为0的指定了0道stage的渲染特性。这些特性指定了最终的渲染效果。在引擎中这样的每个特性称为shader feature,这些特性是存储在Material类中。
可以看到determineFeatures()只接受了stage的标号。却没有任何的feature信息。他是如何创建这道stage相应的shaderfeature呢。
关键在于GFXShaderFeatureData结构中的一个枚举量:
enum
{
RTLighting = 0, // realtime lighting
TexAnim,
BaseTex,
DynamicLight,
DynamicLightDual,
DynamicLightMask,
DynamicLightAttenuateBackFace,
SelfIllumination,
LightMap,
LightNormMap,
BumpMap,
DetailMap,
ExposureX2,
ExposureX4,
EnvMap,
CubeMap,
// BumpCubeMap,
// Refraction,
PixSpecular,
VertSpecular,
Fog, // keep fog last feature
NumFeatures,
};
可见在此枚举上shader feature是按顺序排列的。共19个。
在determineFeatures()函数中,有如下循环:
for( U32 i=0; i<GFXShaderFeatureData::NumFeatures; i++ ){
。。。。。。
}
在这里就依次判断材质中否具有这19个shader feature。最近再将具有的feature存入fd中。
l void createPasses( GFXShaderFeatureData &fd, U32 stageNum )
根据传入shaderfeature fd,调用addPass来创建shader。
关于这个函数应该注意的是:creatrePasses()函数会根据shaderFeature的数目来决定创建shader的数目。因为受硬件性能所显,每个shader能执行的语句及使用的硬件寄存器(主要是纹理寄存器)有限,因此一个fd所包含的feature有时需要多个shader才能完成。TGEA记录每个feature要使用的寄存器数量,当fd中的feature使用的寄在器数量超过Shader Model支持的数量后,就会开始创建shader。而后继续处理fd中别的feature。
l void addPass( RenderPassData &rpd, U32 &texIndex, GFXShaderFeatureData &fd,U32 stageNum )
调用GFX开始创建shader。GFX为TGEA的抽象图形层,封装了底层图形API,具体见第4章,第7章。
3. 流程
Materials模块的功能主要有:第一,完成材质与模型的对应.这样引擎才知道渲染模型时使用相应的材质;第二,利用脚本中材质对象的定义生成相应的shader。以下按照流程来分析,流程为两个部分组成:
1 Material::onAdd()起,功能为将材质映射信息存入MaterialPropertyMap。
2 TSStatic::onAdd()起,从MaterialPropertyMap中读出映射信息,完成材质与模型的映射。并调用ShaderGen模块来生成shader。
3.1. Material::onAdd()开始
当引擎载入脚本代码执行时,对脚本对象会调用引擎中相应对象的onAdd函数,Material对象引起的流程如下:
在materials/material.cpp中:
Material::onAdd()
àMaterial::mapMaterial()
àMaterialPropertyMap::addMapping()
这段代码的作用是将材质与模型的映射信息存入MaterialPropertyMap。
3.2. TSStatic::onAdd()开始
当引擎载入脚本代码执行时,对脚本对象会调用引擎中相应对象的onAdd函数,对象引起的流程如下:
在game/ tsStatic.cpp中:
TSStatic::onAdd()
àmshape=ResouceManager->load(mshapeName)
àmshapeInstance= new TSShapeInstance()
àTSShapeInstance::buildInstanceData()
à TSShapeInstance:: setMaterialList(mShape->materialList)
à mMaterialList->mapMaterials()
à TSShapeInstance::initMatInstance()
àMatInstance::init()
àMatInstance::ProcessMaterial()
具体如下:
l 前三句为加载模型。具体见模型系统。
l TSShapeInstance::setMaterialList(mShape->materialList):使用mShape的材质列表(实质上是texture tag),因为一个模型会带很多的纹理,每张纹理都要对应一个材质,所以实际上一个模型要对应许多材质.因此需要用一个列表来存储所有的材质信息.给TSShapeInstance的mMaterialList赋值。
l mMaterialList->mapMaterials():从Map中读出映射信息并赋值,完成材质映射信息的填充。
l TSShapeInstance::initMatInstance():初始化材质列表。
l MatInstance::init():对材质列表中每个材质进行被始化。
l MatInstance::ProcessMaterial():处理材质的各种属性,并根据这些属性调用ShaderGen创建shader。