Ogre源码分析与学习笔记-3 材质

来源:互联网 发布:java小程序代码 编辑:程序博客网 时间:2024/06/07 00:54

首先是Material::TextureLayer, 这是Material的一个内嵌类, 定义了一个纹理

class _OgreExport TextureLayer{//Ogre支持多种纹理效果, 包括:ET_BUMP_MAP, ET_ENVIRONMENT_MAP, ET_SCROLL, ET_ROTATE, ET_TRANSFORMEffectMap 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_CLAMPTextureAddressingMode mAddressMode;                //blend, 用来控制本层纹理和上一层纹理的混合方式LayerBlendModeEx colourBlendMode;SceneBlendFactor colourBlendFallbackSrc;SceneBlendFactor colourBlendFallbackDest;LayerBlendModeEx alphaBlendMode;//判断当前纹理是不是一个空纹理, 一般发生在load图片失败, 或者其他一些非致命错误后bool mIsBlank;//定义纹理是立即被load, 还是以后被loadbool 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 SceneManagerstatic 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_FLATShadeOptions mShadeOptions;/// Texture filtering//纹理过滤方式, Ogre支持双线过滤, 三线过滤, 以及各向异性过滤TextureFilterOptions mTextureFiltering;// texture anisotropy levelint mMaxAniso;//-------------------------------------------------------------------------    // Fogbool 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 layersint 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 materialFogMode 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 materialnewFogMode = mat->getFogMode();newFogColour = mat->getFogColour();newFogStart = mat->getFogStart();newFogEnd = mat->getFogEnd();newFogDensity = mat->getFogDensity();}else{// New fog params from scenenewFogMode = 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 layersint texLayer = mat->getNumTextureLayers() - numLayersLeft;int thisUnitsRequested = numLayersLeft;int texUnits = mDestRenderSystem->_getNumTextureUnits();#if OGRE_TEST_MULTIPASS == 1texUnits = 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 unitslastUsedFallback = 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 unitmDestRenderSystem->_disableTextureUnit(unit);}else{Material::TextureLayer* pTex = mat->getTextureLayer(texLayer);// We still have texture layers to put in this unitif (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 blendlastUsedFallback = true;// Copy texture layer info and set custom blendingMaterial::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 settingsmDestRenderSystem->_setTextureUnitSettings(unit, newTex);}else{if (lastUsedFallback){// Ensure that fallback alpha on bottom layer does not mask out alpha on this layerpTex->setAlphaOperation(LBX_ADD);}// Standard issuemDestRenderSystem->_setTextureUnitSettings(unit, *pTex);}numLayersLeft--;}}// 设置一些跟纹理无关的纹理参数// 从这里可以看出Ogre的Material不光包括通常意义上的材质参数// 也包括一些可以作用在材质上, 或者改变材质属性的参数// 因此从某种意义上说, Ogre的Material更类似于一个"Shader"// Set up non-texture related material settings// Depth buffer settingsif (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 modeif (firstTime || lastMat.getCullingMode() != mat->getCullingMode()){mDestRenderSystem->_setCullingMode(mat->getCullingMode());}// Dynamic lighting enabledif (firstTime || lastMat.getLightingEnabled() != mat->getLightingEnabled()){mDestRenderSystem->setLightingEnabled(mat->getLightingEnabled());}// Shadingif (firstTime || lastMat.getShadingMode() != mat->getShadingMode()){mDestRenderSystem->setShadingType(mat->getShadingMode());}// Texture filteringif (firstTime || lastMat.getTextureFiltering() != mat->getTextureFiltering()){mDestRenderSystem->setTextureFiltering(mat->getTextureFiltering());}// anisotropyif (firstTime || lastMat.getAnisotropy() != mat->getAnisotropy()){mDestRenderSystem->_setAnisotropy(mat->getAnisotropy());}firstTime = false;// Copy material settings from last renderlastMat = *mat;lastNumTexUnitsUsed = unit;return numLayersLeft;}


另外还有两部分跟材质相关的内容:
材质的Load以及材质脚本
不在本篇涉及范围内