地形
ogre过去在地形的支持上很少,过去只是让你导入一个高度图,然后在上面放一层基本纹理和一细节纹理,在1.7版本的Ogre后,里面单独加入了terrain的模块,在地形的支持上已经非常强大,关于新版Ogre的地形的资料少之又少,我花了好几天经过反复试验根系摸了一下,总结一下新版Ogre的地形使用
1.设置摄像机的远剪裁面为无限远
if (root->getRenderSystem()->getCapabilities()->hasCapability(Ogre::RSC_INFINITE_FAR_PLANE))
{
cam->setFarClipDistance(0); // enable infinite far clip distance if we can
}
2.设置TerrainGlobalOptions,这是一个表示地形的总体特性的类,他可以设置地形的一些特征,首先你需要new出来一个
mTerrainGlobals=new TerrainGlobalOptions();
然后设置一些必要的特征
mTerrainGlobals->setMaxPixelError(8);
这个值越小地形越精确,效率越低
在地形的渲染中。Ogre提供了一种组合贴图的渲染,就是在较远的地方使用一种贴图混合简单光影的方式来代替实际的纹理,这有很多应用:
1是这样可以再较远的地方不使用精细的纹理生成,提高效率
2是你可以使用这个特性实现游戏中照亮与黑暗的效果
下面是设置这方面的参数,首先设置在多远处开始使用组合贴图
mTerrainGlobals->setCompositeMapDistance(100);
然后设置产生组合贴图的光线方向
mTerrainGlobals->setLightMapDirection(Ogre::Vector3(0,-1,0));
设置组合贴图的光影颜色
mTerrainGlobals->setCompositeMapAmbient(smgr->getAmbientLight());
mTerrainGlobals->setCompositeMapDiffuse(ColourValue::Black);
例如上面的参数设置,就会在你的摄像机周围100范围内看到地形,而之外则是渐变到黑,这样就是游戏中只照亮你周围的效果
3.设置地形组
在Ogre中,地形是以组的形式出现的,一个地形组中有多个地形实例,一个组中的地形拥有相同的纹理,相同的高度图,并很方便在他们之间平滑连接,ogre中代表地形组的类是TerrainGroup,代表一个地形实例的类是Terrain
首先我们需要new产生一个地形组
mTerrainGroup=new TerrainGroup(场景管理器直至,地形的朝向, 地形顶点数的大小, 地形面积的大小);
Ogre手册中关于后两个参数说的很不通俗,经过试验,是这样的,第一个是顶点数目(要为2^n+1),最后一个是地形的空间尺寸(边长)
设置地形的原点位置
mTerrainGroup->setOrigin(Ogre::Vector3::ZERO);
然后设置地形的一些具体属性,通过Ogre::Terrain::ImportData& defaultimp = mTerrainGroup->getDefaultImportSettings()得到一个Terrain::ImportData类实例,然后修改它
defaultimp.inputScale = 600;//这是对导入数据(高度图)的高度值的缩放,这个属性很重要,我们知道高度图上的高度在图像的尺度上的范围是0-1(0为全黑),所以默认下,地形的高度将在0-1范围内(这基本比平原还平原),所以要使用这个值来对原始图片上的像素值相乘,也就是这个值越大,地势越陡峭
新版orge的地形的纹理贴附是这样的,他允许地形上有几个纹理层次(数目取决与你的硬件),标记位0层,1层..n层,默认情况下你只能见到第0层,我们可以设置n+1层对之前n层纹理混合结果的混合方式,如果不混合,就只能看到0层,首先你要定义这些层的纹理是什么,纹理的大小
defaultimp.layerList.resize(3);//设置有几层纹理
例如设置第0层
defaultimp.layerList[0].worldSize = 2500;//设置该层纹理的空间大小
defaultimp.layerList[0].textureNames.push_back("2.jpg");//设置该层纹理的贴图
defaultimp.layerList[0].textureNames.push_back("dirt_grayrocky_normalheight.dds");//设置该层纹理的法向贴图
4。定义好每层纹理后,我们要使用地形组产生地形实例
首先导入高度图
Ogre::Image img;
img.load("terrain.png", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
然后使用下面这个函数生个一个地形实例
mTerrainGroup->defineTerrain(x, y, &img);
地形组是指一个二维网格的地形群,上面这个函数是指在地形组这个网格的(X Y)处使用这个高度图产生一个地形实例,在ogre中每个地形实例都是方形的,所以如果你想产生矩形地形就需要产生多个地形实例,如在(0,0)和(0,1)处产生两个
5 在产生了地形实例后,我们需要对地形的纹理层进行我们想要的混合方式,这不就等于你在地形上铺东西
用地形组的迭代器访问每一个地形实例
混合的原理机制是这样的,对于每一个纹理层,都有一个保存每个像素的alpha混合值的值,可以通过Ogre::TerrainLayerBlendMap* blendMap1 = terrain->getLayerBlendMap(1)来获取第1层的这个混合数据,初始情况下都是0,也就是说默认情况下第1层对第0层的混合是0,那样你就只能看到0层,你可以通过修改这个数据来直接修改混合方式,这就像两张图像做混合,而每张混合图像代表了整个这个地形实例的表面图片,为了得到这个图像的边长,可以使用terrain->getLayerBlendMapSize(); 你还可以使用blendMap1->convertImageToTerrainSpace(x, y, &tx, &ty)来得到混合图像空间上(x,y)的那个像素对应的地形实例空间上的坐标。
最修改了混合值之后,你需要使用
blendMap1->dirty();
blendMap1->update();
来更新
6最后我们调用mTerrainGroup->freeTemporaryResources();来做一些清理工作
当然在程序执行完毕我们需要清理掉mTerrainGroup和 mTerrainGlobals;
这就是新版Ogre的地形,虽然比之前的操作要复杂的多,我还真的琢磨了好几天,但是可以实现非常好的地形效果,而纹理层见的混合可以制造各种纹理贴附的地形效果,大家试试看
- 天空
说了地,再说天,ogre有三种表现天空的方法,skybox skydome skyplane
skybox
就是一种cube mapping
使用:
mSceneMgr->setSkyBox(true, "Examples/SpaceSkyBox", 5000, false);
其中参数1代表是否绘制
参数2代表这个cube mapping的材质
参数3代表天距离你多远
其中参数4代表是否先绘制天空盒,如果后绘制,他将在地形的上层
skydome
这是将一个纹理图片弯曲一下从几个方向拼成一个天,最上面中心可能会有拼痕
使用
mSceneMgr->setSkyDome(true, "Examples/CloudySky", 5, 8);
这里面的材质就是一张普通图片
skyplane
就简单将一张图片放在头顶代表天,适用四周有群山等遮挡看不到地平线的时候
这三种越来越简单,当然效率越来越高
雾
ogre中雾的使用很简单,你需要在被雾影响的物体绘制前调用雾的绘制:
mSceneMgr->setFog(Ogre::FOG_EXP, fadeColour, 0.005);
这里面第一个参数是雾计算的数学模型,有线性和指数型
第二个是雾的颜色,注意你需要将视口的背景颜色也设置成此颜色
后面是一些在具体数学模型下的参数
这里面要注意,如果你需要完全看清天空,就需要将天空的距离设置的比武的最近距离要近,否则雾会遮挡天空,尽管事实是这样,而有时却并非如此。
还有雾不仅可以是雾,变一变颜色,可以变成烟、黑暗或者某种恐怖的场景~