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

本文深入探讨Ogre引擎中的Material内嵌类TextureLayer,详细讲解纹理的定义、使用及其在材质脚本加载过程中的角色。虽然材质的Load及材质脚本不在此篇涵盖,但整体内容对理解Ogre的材质系统至关重要。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先是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以及材质脚本
不在本篇涉及范围内

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值