首先是Material::TextureLayer, 这是Material的一个内嵌类, 定义了一个纹理
class _OgreExport TextureLayer
{
//Ogre支持多种纹理效果, 包括:ET_BUMP_MAP, ET_ENVIRONMENT_MAP, ET_SCROLL, ET_ROTATE, ET_TRANSFORM
EffectMap mEffects;
//Ogre 支持纹理动画, 就是在模型不变的前提下, 更换纹理, 产生一个平面动画的效果, 下面几个参数是关于平面动画的:
/// Number of frames of animation, or frames making up cubic
//帧数
int mNumFrames;
/// The xurrent animation frame.
//当前帧数, 动画演示时使用
int mCurrentFrame;
/// Duration of animation in seconds
//每帧间隔
Real mAnimDuration;
//Controller是一个通用类, 用来计算每一帧会变化的量.
//Controller可以做时间插值, 位置插值, 像素插值等等
//在这里用mAnimController计算动画时间, 插值出当前的动画是第几帧
Controller* mAnimController;
//Ogre支持Cube texture
//Cube texture是一个组合纹理, 它使用6张图片来对应一个立方体的六个面
//通过视线和法线计算出的反射光线来查询CubeMap, 可以创建一个真实的反射镜面体
//通过视线和法线计算出的折射光线来查询CubeMap, 可以创建一个透明体.
//Cube texture可以用来绘制天空盒(skyboxes), 或用来模拟反射效果
bool mCubic;
//纹理单元?
int textureCoordSetIndex;
//纹理模式, 对应于OpenGL的GL_REPEAT, GL_MIRRORED_REPEAT, GL_CLAMP
TextureAddressingMode mAddressMode;
//blend, 用来控制本层纹理和上一层纹理的混合方式
LayerBlendModeEx colourBlendMode;
SceneBlendFactor colourBlendFallbackSrc;
SceneBlendFactor colourBlendFallbackDest;
LayerBlendModeEx alphaBlendMode;
//判断当前纹理是不是一个空纹理, 一般发生在load图片失败, 或者其他一些非致命错误后
bool mIsBlank;
//定义纹理是立即被load, 还是以后被load
bool mDeferLoad;
//是否计算纹理矩阵
//可以动态改变纹理矩阵, 从而改变纹理坐标, 使用这种方法可以制作一些特殊效果, 比如滚动的纹理等等.
//纹理矩阵可以直接设置, 也可以通过一些纹理变换函数改变, 比如setTextureScale(), setTextureRotate()等
bool mRecalcTexMatrix;
Real mUMod, mVMod;
Real mUScale, mVScale;
Real mRotate;
Matrix4 mTexModMatrix;
//alpha 测试函数, 详情见OpenGL的alpha测试
CompareFunction mAlphaRejectFunc;
unsigned char mAlphaRejectVal;
// Animation, will be set up as Controllers
//animation使用, 被Controllers自动设置
Real mUScrollAnim, mVScrollAnim;
Real mRotateAnim;
/// Texture layer filtering
//纹理滤波方式
TextureFilterOptions mTextureLayerFiltering;
//Texture layer anisotropy
//各向异性
int mMaxAniso;
};
然后是纹理本身
class Material
{
// Colour properties
//纹理的颜色属性, 环境光, 散射光, 镜面光等等
ColourValue mAmbient;
ColourValue mDiffuse;
ColourValue mSpecular;
ColourValue mEmissive;
Real mShininess;
//-------------------------------------------------------------------------
/// Default material settings - set up by SceneManager
static Material* mDefaultSettings;
//-------------------------------------------------------------------------
// Blending factors
//混合因子, 用于多个纹理的混合
SceneBlendFactor mSourceBlendFactor;
SceneBlendFactor mDestBlendFactor;
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
// Depth buffer settings
//深度缓冲控制
bool mDepthCheck;
bool mDepthWrite;
CompareFunction mDepthFunc;
ushort mDepthBias;
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
// Culling mode
//裁切控制
CullingMode mCullMode;
ManualCullingMode mManualCullMode;
//-------------------------------------------------------------------------
/// Lighting enabled?
//光照控制
bool mLightingEnabled;
/// Shading options
//对应GL_SMOOTH, GL_FLAT
ShadeOptions mShadeOptions;
/// Texture filtering
//纹理过滤方式, Ogre支持双线过滤, 三线过滤, 以及各向异性过滤
TextureFilterOptions mTextureFiltering;
// texture anisotropy level
int mMaxAniso;
//-------------------------------------------------------------------------
// Fog
bool mFogOverride;
FogMode mFogMode;
ColourValue mFogColour;
Real mFogStart;
Real mFogEnd;
Real mFogDensity;
//-------------------------------------------------------------------------
/** If true, loading of textures and setting up controllers is deferred
until the 'load' method is called.
*/
bool mDeferLoad;
/// Number of texture layers
int mNumTextureLayers;
};
然后是纹理的使用
//纹理的使用通过SceneManager::setMaterial来做, 主要是使用Material的各种属性来设置RenderSystem的状态
//一般来说, RenderSystem状态的切换的效率都不高, 因此, 要做到尽量少的切换状态
//并且进行分组排序, 使用同样状态的Material一块使用
int SceneManager::setMaterial(Material* mat, int numLayersLeft)
{
static bool firstTime = true;
static bool lastUsedFallback = false;
static int lastNumTexUnitsUsed = 0;
static Material lastMat; // Last material settings, to minimise render state changes
// Recent changes: eliminated the need to copy all material settings to set with RenderSystem
// Now only issues required render state changes to the render system for maximum performance
// Set surface properties
// 为了提高效率, 如果当前设置的纹理和前一个纹理的颜色一样, 就不做任何改变
if (firstTime || mat->_compareSurfaceParams(lastMat) == false)
{
ColourValue a, b, c, d;
a = mat->getAmbient();
b = mat->getDiffuse();
c = mat->getSpecular();
d = mat->getSelfIllumination();
mDestRenderSystem->_setSurfaceParams( a, b, c, d, mat->getShininess() );
}
// Set global blending, play it safe if last one was fallback
//设置混合方式, 网上资料一大堆
if (firstTime || lastUsedFallback ||
(lastMat.getSourceBlendFactor() != mat->getSourceBlendFactor() ||
lastMat.getDestBlendFactor() != mat->getDestBlendFactor()))
{
mDestRenderSystem->_setSceneBlending(mat->getSourceBlendFactor(), mat->getDestBlendFactor());
}
//雾设置
// Fog
// New fog params can either be from scene or from material
FogMode newFogMode;
ColourValue newFogColour;
Real newFogStart, newFogEnd, newFogDensity;
static FogMode oldFogMode;
static ColourValue oldFogColour;
static Real oldFogStart, oldFogEnd, oldFogDensity;
if (mat->getFogOverride())
{
// New fog params from material
newFogMode = mat->getFogMode();
newFogColour = mat->getFogColour();
newFogStart = mat->getFogStart();
newFogEnd = mat->getFogEnd();
newFogDensity = mat->getFogDensity();
}
else
{
// New fog params from scene
newFogMode = mFogMode;
newFogColour = mFogColour;
newFogStart = mFogStart;
newFogEnd = mFogEnd;
newFogDensity = mFogDensity;
}
if (firstTime || newFogMode != oldFogMode || newFogColour != oldFogColour ||
newFogStart != oldFogStart || newFogEnd != oldFogEnd ||
newFogDensity != oldFogDensity)
{
mDestRenderSystem->_setFog(newFogMode, newFogColour, newFogDensity, newFogStart, newFogEnd);
oldFogMode = newFogMode;
oldFogColour = newFogColour;
oldFogStart = newFogStart;
oldFogEnd = newFogEnd;
oldFogDensity = newFogDensity;
}
//纹理, Ogre支持多重纹理, 以及纹理混合
// 这里, 主要使用RenderSystem::_setTextureUnitSettings()来设置纹理, 包括:
// 1. 绑定纹理: _setTexture ->glBindTexture
// 2. 设置纹理坐标: _setTextureCoordSet()
// 3. 设置纹理滤波: _setTextureLayerFiltering()
// 4. 设置各向异性: _setTextureLayerAnisotropy()
// 5. 多重纹理的混合: _setTextureBlendMode()
// 6. 纹理效果
// ...
// Texture layers
int texLayer = mat->getNumTextureLayers() - numLayersLeft;
int thisUnitsRequested = numLayersLeft;
int texUnits = mDestRenderSystem->_getNumTextureUnits();
#if OGRE_TEST_MULTIPASS == 1
texUnits = 1;
#endif
// Iterate over texture units, set them up to the higher of the last texturing units used and the current to be used
// but no higher than the number of units
lastUsedFallback = false;
int unit;
for (unit = 0;
(unit < lastNumTexUnitsUsed || unit < thisUnitsRequested) && unit < texUnits;
++unit, ++texLayer)
{
if (unit >= thisUnitsRequested)
{
// We've run out of texture layers before we ran out of units to set
// Turn off the texturing for this unit
mDestRenderSystem->_disableTextureUnit(unit);
}
else
{
Material::TextureLayer* pTex = mat->getTextureLayer(texLayer);
// We still have texture layers to put in this unit
if (unit == 0 && thisUnitsRequested > 0 && thisUnitsRequested < mat->getNumTextureLayers())
{
// We're on the second (or more) leg of a multipass render
// because remaining layers is not the total number
// So we need to use the multipass fallback and override first texture layer blend
lastUsedFallback = true;
// Copy texture layer info and set custom blending
Material::TextureLayer newTex = *pTex;
// Set multitexture blend to NO blend (avoids any modulation with material colour)
newTex.setColourOperation(LBO_REPLACE);
// Set scene blending to colour blending equivalent (fallback)
mDestRenderSystem->_setSceneBlending(pTex->getColourBlendFallbackSrc(), pTex->getColourBlendFallbackDest());
// Set texture unit settings
// NB rendersystem will know to only change relevant settings
mDestRenderSystem->_setTextureUnitSettings(unit, newTex);
}
else
{
if (lastUsedFallback)
{
// Ensure that fallback alpha on bottom layer does not mask out alpha on this layer
pTex->setAlphaOperation(LBX_ADD);
}
// Standard issue
mDestRenderSystem->_setTextureUnitSettings(unit, *pTex);
}
numLayersLeft--;
}
}
// 设置一些跟纹理无关的纹理参数
// 从这里可以看出Ogre的Material不光包括通常意义上的材质参数
// 也包括一些可以作用在材质上, 或者改变材质属性的参数
// 因此从某种意义上说, Ogre的Material更类似于一个"Shader"
// Set up non-texture related material settings
// Depth buffer settings
if (firstTime || lastMat.getDepthFunction() != mat->getDepthFunction())
{
mDestRenderSystem->_setDepthBufferFunction(mat->getDepthFunction());
}
if (firstTime || lastMat.getDepthCheckEnabled() != mat->getDepthCheckEnabled())
{
mDestRenderSystem->_setDepthBufferCheckEnabled(mat->getDepthCheckEnabled());
}
if (firstTime || lastMat.getDepthWriteEnabled() != mat->getDepthWriteEnabled())
{
mDestRenderSystem->_setDepthBufferWriteEnabled(mat->getDepthWriteEnabled());
}
if (firstTime || lastMat.getDepthBias() != mat->getDepthBias())
{
mDestRenderSystem->_setDepthBias(mat->getDepthBias());
}
// Culling mode
if (firstTime || lastMat.getCullingMode() != mat->getCullingMode())
{
mDestRenderSystem->_setCullingMode(mat->getCullingMode());
}
// Dynamic lighting enabled
if (firstTime || lastMat.getLightingEnabled() != mat->getLightingEnabled())
{
mDestRenderSystem->setLightingEnabled(mat->getLightingEnabled());
}
// Shading
if (firstTime || lastMat.getShadingMode() != mat->getShadingMode())
{
mDestRenderSystem->setShadingType(mat->getShadingMode());
}
// Texture filtering
if (firstTime || lastMat.getTextureFiltering() != mat->getTextureFiltering())
{
mDestRenderSystem->setTextureFiltering(mat->getTextureFiltering());
}
// anisotropy
if (firstTime || lastMat.getAnisotropy() != mat->getAnisotropy())
{
mDestRenderSystem->_setAnisotropy(mat->getAnisotropy());
}
firstTime = false;
// Copy material settings from last render
lastMat = *mat;
lastNumTexUnitsUsed = unit;
return numLayersLeft;
}
另外还有两部分跟材质相关的内容:
材质的Load以及材质脚本
不在本篇涉及范围内